diff options
author | Michele Marchetto <michele@cvs.openbsd.org> | 2009-03-06 18:39:14 +0000 |
---|---|---|
committer | Michele Marchetto <michele@cvs.openbsd.org> | 2009-03-06 18:39:14 +0000 |
commit | 79bf2b9529b10783102a038860f4a2e6a9b1dd37 (patch) | |
tree | 377d3d6341c062a6745966eddd9e5c522563e204 | |
parent | 2e5aaa812e944ad785bdcdae37e63e836ee8c6da (diff) |
Make RDE aware of multicast group members per interface. This is needed to
make unicast routing decisions.
ok claudio@
-rw-r--r-- | usr.sbin/dvmrpd/dvmrpd.h | 10 | ||||
-rw-r--r-- | usr.sbin/dvmrpd/group.c | 30 | ||||
-rw-r--r-- | usr.sbin/dvmrpd/igmp.h | 6 | ||||
-rw-r--r-- | usr.sbin/dvmrpd/interface.c | 3 | ||||
-rw-r--r-- | usr.sbin/dvmrpd/rde.c | 101 | ||||
-rw-r--r-- | usr.sbin/dvmrpd/rde.h | 7 | ||||
-rw-r--r-- | usr.sbin/dvmrpd/rde_mfc.c | 18 | ||||
-rw-r--r-- | usr.sbin/dvmrpd/rde_srt.c | 38 |
8 files changed, 182 insertions, 31 deletions
diff --git a/usr.sbin/dvmrpd/dvmrpd.h b/usr.sbin/dvmrpd/dvmrpd.h index f8f7d8a9f4f..40923a8e221 100644 --- a/usr.sbin/dvmrpd/dvmrpd.h +++ b/usr.sbin/dvmrpd/dvmrpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dvmrpd.h,v 1.13 2009/01/20 01:35:34 todd Exp $ */ +/* $OpenBSD: dvmrpd.h,v 1.14 2009/03/06 18:39:13 michele Exp $ */ /* * Copyright (c) 2004, 2005, 2006 Esben Norby <norby@openbsd.org> @@ -111,6 +111,8 @@ enum imsg_type { IMSG_MFC_DEL, IMSG_NEIGHBOR_UP, IMSG_NEIGHBOR_DOWN, + IMSG_GROUP_ADD, + IMSG_GROUP_DEL, IMSG_FLASH_UPDATE, IMSG_FLASH_UPDATE_DS }; @@ -184,6 +186,11 @@ struct group { int state; }; +struct rde_group { + TAILQ_ENTRY(rde_group) entry; + struct in_addr rde_group; +}; + struct mfc { struct in_addr origin; struct in_addr group; @@ -202,6 +209,7 @@ struct iface { time_t uptime; LIST_HEAD(, nbr) nbr_list; TAILQ_HEAD(, group) group_list; + TAILQ_HEAD(, rde_group) rde_group_list; struct rr_head rr_list; char name[IF_NAMESIZE]; diff --git a/usr.sbin/dvmrpd/group.c b/usr.sbin/dvmrpd/group.c index 99bb35b7fbd..8fe979090db 100644 --- a/usr.sbin/dvmrpd/group.c +++ b/usr.sbin/dvmrpd/group.c @@ -1,4 +1,4 @@ -/* $OpenBSD: group.c,v 1.1 2006/06/01 14:12:20 norby Exp $ */ +/* $OpenBSD: group.c,v 1.2 2009/03/06 18:39:13 michele Exp $ */ /* * Copyright (c) 2006 Esben Norby <norby@openbsd.org> @@ -58,15 +58,15 @@ struct { } grp_fsm[] = { /* current state event that happened action(s) to take resulting state */ /* querier fsm */ - {GRP_STA_NO_MEMB_PRSNT, GRP_EVT_V2_REPORT_RCVD, {GRP_ACT_ADD_ROUTE, + {GRP_STA_NO_MEMB_PRSNT, GRP_EVT_V2_REPORT_RCVD, {GRP_ACT_ADD_GROUP, GRP_ACT_START_TMR, GRP_ACT_END}, GRP_STA_MEMB_PRSNT}, - {GRP_STA_NO_MEMB_PRSNT, GRP_EVT_V1_REPORT_RCVD, {GRP_ACT_ADD_ROUTE, + {GRP_STA_NO_MEMB_PRSNT, GRP_EVT_V1_REPORT_RCVD, {GRP_ACT_ADD_GROUP, GRP_ACT_START_TMR, GRP_ACT_START_V1_HOST_TMR, GRP_ACT_END}, GRP_STA_MEMB_PRSNT}, - {GRP_STA_MEMB_PRSNT, GRP_EVT_TMR_EXPIRED, {GRP_ACT_DEL_ROUTE, + {GRP_STA_MEMB_PRSNT, GRP_EVT_TMR_EXPIRED, {GRP_ACT_DEL_GROUP, GRP_ACT_END}, GRP_STA_NO_MEMB_PRSNT}, {GRP_STA_MEMB_PRSNT, GRP_EVT_V2_REPORT_RCVD, {GRP_ACT_START_TMR, GRP_ACT_END}, 0}, @@ -80,7 +80,7 @@ struct { {GRP_STA_CHECK_MEMB, GRP_EVT_V2_REPORT_RCVD, {GRP_ACT_START_TMR, GRP_ACT_END}, GRP_STA_MEMB_PRSNT}, - {GRP_STA_CHECK_MEMB, GRP_EVT_TMR_EXPIRED, {GRP_ACT_DEL_ROUTE, + {GRP_STA_CHECK_MEMB, GRP_EVT_TMR_EXPIRED, {GRP_ACT_DEL_GROUP, GRP_ACT_CLR_RETRANS_TMR, GRP_ACT_END}, GRP_STA_NO_MEMB_PRSNT}, {GRP_STA_CHECK_MEMB, GRP_EVT_RETRANS_TMR_EXP,{GRP_ACT_SEND_GRP_QUERY, @@ -97,11 +97,11 @@ struct { GRP_ACT_END}, 0}, {GRP_STA_V1_MEMB_PRSNT, GRP_EVT_V2_REPORT_RCVD, {GRP_ACT_START_TMR, GRP_ACT_END}, 0}, - {GRP_STA_V1_MEMB_PRSNT, GRP_EVT_TMR_EXPIRED, {GRP_ACT_DEL_ROUTE, + {GRP_STA_V1_MEMB_PRSNT, GRP_EVT_TMR_EXPIRED, {GRP_ACT_DEL_GROUP, GRP_ACT_END}, GRP_STA_NO_MEMB_PRSNT}, /* non querier fsm */ - {GRP_STA_NO_MEMB_PRSNT, GRP_EVT_REPORT_RCVD, {GRP_ACT_ADD_ROUTE, + {GRP_STA_NO_MEMB_PRSNT, GRP_EVT_REPORT_RCVD, {GRP_ACT_ADD_GROUP, GRP_ACT_START_TMR, GRP_ACT_END}, GRP_STA_MEMB_PRSNT}, {GRP_STA_MEMB_PRSNT, GRP_EVT_REPORT_RCVD, {GRP_ACT_START_TMR, @@ -122,8 +122,8 @@ const char * const group_action_names[] = { "START RETRANSMISSION TIMER", "START V1 HOST TIMER", "SEND GROUP QUERY", - "ADD ROUTE", - "DEL ROUTE", + "ADD GROUP", + "DEL GROUP", "CLEAR RETRANSMISSION TIMER", "NOTHING" }; @@ -182,18 +182,18 @@ group_fsm(struct group *group, enum group_event event) case GRP_ACT_SEND_GRP_QUERY: ret = send_igmp_query(group->iface, group); break; - case GRP_ACT_ADD_ROUTE: + case GRP_ACT_ADD_GROUP: mfc.origin.s_addr = 0; mfc.group = group->addr; - mfc.ifindex = group->iface->ifindex; /* XXX fixme */ - dvmrpe_imsg_compose_rde(IMSG_MFC_ADD, 0, 0, &mfc, + mfc.ifindex = group->iface->ifindex; + dvmrpe_imsg_compose_rde(IMSG_GROUP_ADD, 0, 0, &mfc, sizeof(mfc)); break; - case GRP_ACT_DEL_ROUTE: + case GRP_ACT_DEL_GROUP: mfc.origin.s_addr = 0; mfc.group = group->addr; - mfc.ifindex = group->iface->ifindex; /* XXX fixme */ - dvmrpe_imsg_compose_rde(IMSG_MFC_DEL, 0, 0, &mfc, + mfc.ifindex = group->iface->ifindex; + dvmrpe_imsg_compose_rde(IMSG_GROUP_DEL, 0, 0, &mfc, sizeof(mfc)); break; case GRP_ACT_CLR_RETRANS_TMR: diff --git a/usr.sbin/dvmrpd/igmp.h b/usr.sbin/dvmrpd/igmp.h index 81165ee67c0..ea1dcc88c0c 100644 --- a/usr.sbin/dvmrpd/igmp.h +++ b/usr.sbin/dvmrpd/igmp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: igmp.h,v 1.1 2006/06/01 14:12:20 norby Exp $ */ +/* $OpenBSD: igmp.h,v 1.2 2009/03/06 18:39:13 michele Exp $ */ /* * Copyright (c) 2005, 2006 Esben Norby <norby@openbsd.org> @@ -102,8 +102,8 @@ enum group_action { GRP_ACT_START_RETRANS_TMR, GRP_ACT_START_V1_HOST_TMR, GRP_ACT_SEND_GRP_QUERY, - GRP_ACT_ADD_ROUTE, - GRP_ACT_DEL_ROUTE, + GRP_ACT_ADD_GROUP, + GRP_ACT_DEL_GROUP, GRP_ACT_CLR_RETRANS_TMR, GRP_ACT_NOTHING }; diff --git a/usr.sbin/dvmrpd/interface.c b/usr.sbin/dvmrpd/interface.c index 492dfbbff11..28331ec8b73 100644 --- a/usr.sbin/dvmrpd/interface.c +++ b/usr.sbin/dvmrpd/interface.c @@ -1,4 +1,4 @@ -/* $OpenBSD: interface.c,v 1.7 2009/01/20 01:35:34 todd Exp $ */ +/* $OpenBSD: interface.c,v 1.8 2009/03/06 18:39:13 michele Exp $ */ /* * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> @@ -173,6 +173,7 @@ if_new(struct kif *kif) LIST_INIT(&iface->nbr_list); TAILQ_INIT(&iface->group_list); + TAILQ_INIT(&iface->rde_group_list); strlcpy(iface->name, kif->ifname, sizeof(iface->name)); if ((ifr = calloc(1, sizeof(*ifr))) == NULL) diff --git a/usr.sbin/dvmrpd/rde.c b/usr.sbin/dvmrpd/rde.c index 4492e3e14c1..b46c8421bde 100644 --- a/usr.sbin/dvmrpd/rde.c +++ b/usr.sbin/dvmrpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.10 2009/01/27 08:53:47 michele Exp $ */ +/* $OpenBSD: rde.c,v 1.11 2009/03/06 18:39:13 michele Exp $ */ /* * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org> @@ -283,13 +283,39 @@ rde_dispatch_imsg(int fd, short event, void *bula) memcpy(&rn, imsg.data, sizeof(rn)); if (rde_nbr_new(imsg.hdr.peerid, &rn) == NULL) - fatalx("rde_rispatch_imsg: " + fatalx("rde_dispatch_imsg: " "neighbor already exists"); break; case IMSG_NEIGHBOR_DOWN: rde_nbr_del(rde_nbr_find(imsg.hdr.peerid)); break; + case IMSG_GROUP_ADD: + if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(mfc)) + fatalx("invalid size of OE request"); + memcpy(&mfc, imsg.data, sizeof(mfc)); + + iface = if_find_index(mfc.ifindex); + if (iface == NULL) { + fatalx("rde_dispatch_imsg: " + "cannot find matching interface"); + } + + rde_group_list_add(iface, mfc.group); + break; + case IMSG_GROUP_DEL: + if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(mfc)) + fatalx("invalid size of OE request"); + memcpy(&mfc, imsg.data, sizeof(mfc)); + + iface = if_find_index(mfc.ifindex); + if (iface == NULL) { + fatalx("rde_dispatch_imsg: " + "cannot find matching interface"); + } + + rde_group_list_remove(iface, mfc.group); + break; default: log_debug("rde_dispatch_msg: unexpected imsg %d", imsg.hdr.type); @@ -392,3 +418,74 @@ rde_nbr_del(struct rde_nbr *nbr) free(nbr); } + +/* rde group functions */ +void +rde_group_list_add(struct iface *iface, struct in_addr group) +{ + struct rde_group *rdegrp; + + /* validate group id */ + if (!IN_MULTICAST(htonl(group.s_addr))) { + log_debug("rde_group_list_add: interface %s, %s is not a " + "multicast address", iface->name, + inet_ntoa(group)); + return; + } + + if (rde_group_list_find(iface, group)) + return; + + rdegrp = calloc(1, sizeof(*rdegrp)); + if (rdegrp == NULL) + fatal("rde_group_list_add"); + + rdegrp->rde_group.s_addr = group.s_addr; + + TAILQ_INSERT_TAIL(&iface->rde_group_list, rdegrp, entry); + + log_debug("rde_group_list_add: interface %s, group %s", iface->name, + inet_ntoa(rdegrp->rde_group)); + + return; +} + +int +rde_group_list_find(struct iface *iface, struct in_addr group) +{ + struct rde_group *rdegrp = NULL; + + /* validate group id */ + if (!IN_MULTICAST(htonl(group.s_addr))) { + log_debug("rde_group_list_find: interface %s, %s is not a " + "multicast address", iface->name, + inet_ntoa(group)); + return (0); + } + + TAILQ_FOREACH(rdegrp, &iface->rde_group_list, entry) { + if (rdegrp->rde_group.s_addr == group.s_addr) + return (1); + } + + return (0); +} + +void +rde_group_list_remove(struct iface *iface, struct in_addr group) +{ + struct rde_group *rg; + + if (TAILQ_EMPTY(&iface->rde_group_list)) + fatalx("rde_group_list_remove: group does not exist"); + + for(rg = TAILQ_FIRST(&iface->rde_group_list); rg != NULL; + rg = TAILQ_NEXT(rg, entry)) { + if (rg->rde_group.s_addr == group.s_addr) { + log_debug("group_list_remove: interface %s, group %s", + iface->name, inet_ntoa(rg->rde_group)); + TAILQ_REMOVE(&iface->rde_group_list, rg, entry); + free(rg); + } + } +} diff --git a/usr.sbin/dvmrpd/rde.h b/usr.sbin/dvmrpd/rde.h index 78e85b58bec..6410932dbdd 100644 --- a/usr.sbin/dvmrpd/rde.h +++ b/usr.sbin/dvmrpd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.10 2009/02/03 16:21:19 michele Exp $ */ +/* $OpenBSD: rde.h,v 1.11 2009/03/06 18:39:13 michele Exp $ */ /* * Copyright (c) 2005, 2006 Esben Norby <norby@openbsd.org> @@ -81,6 +81,10 @@ pid_t rde(struct dvmrpd_conf *, int [2], int [2], int [2]); int rde_imsg_compose_parent(int, pid_t, void *, u_int16_t); int rde_imsg_compose_dvmrpe(int, u_int32_t, pid_t, void *, u_int16_t); +void rde_group_list_add(struct iface *, struct in_addr); +int rde_group_list_find(struct iface *, struct in_addr); +void rde_group_list_remove(struct iface *, struct in_addr); + /* rde_mfc.c */ void mfc_init(void); int mfc_compare(struct mfc_node *, struct mfc_node *); @@ -92,6 +96,7 @@ void mfc_dump(pid_t); void mfc_update(struct mfc *); void mfc_delete(struct mfc *); void mfc_update_source(struct rt_node *); +int mfc_check_members(struct rt_node *, struct iface *); /* rde_srt.c */ void rt_init(void); diff --git a/usr.sbin/dvmrpd/rde_mfc.c b/usr.sbin/dvmrpd/rde_mfc.c index 85e738255bd..6d3bc508839 100644 --- a/usr.sbin/dvmrpd/rde_mfc.c +++ b/usr.sbin/dvmrpd/rde_mfc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_mfc.c,v 1.3 2009/02/03 16:21:19 michele Exp $ */ +/* $OpenBSD: rde_mfc.c,v 1.4 2009/03/06 18:39:13 michele Exp $ */ /* * Copyright (c) 2006 Esben Norby <norby@openbsd.org> @@ -259,3 +259,19 @@ mfc_delete(struct mfc *nmfc) /* XXX notify parent */ } + +int +mfc_check_members(struct rt_node *rn, struct iface *iface) +{ + struct mfc_node *mn; + + RB_FOREACH(mn, mfc_tree, &mfc) { + if (mn->origin.s_addr == rn->prefix.s_addr) { + if (rde_group_list_find(iface, mn->group) + != NULL) + return (1); + } + } + + return (0); +} diff --git a/usr.sbin/dvmrpd/rde_srt.c b/usr.sbin/dvmrpd/rde_srt.c index 5a633455da8..27fbfbb2234 100644 --- a/usr.sbin/dvmrpd/rde_srt.c +++ b/usr.sbin/dvmrpd/rde_srt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_srt.c,v 1.17 2009/02/03 16:21:19 michele Exp $ */ +/* $OpenBSD: rde_srt.c,v 1.18 2009/03/06 18:39:13 michele Exp $ */ /* * Copyright (c) 2005, 2006 Esben Norby <norby@openbsd.org> @@ -518,9 +518,24 @@ srt_delete_ds(struct rt_node *rn, struct ds_nbr *ds_nbr, struct iface *iface) free(ds_nbr); rn->ds_cnt[iface->ifindex]--; - /* XXX */ - if (!rn->ds_cnt[iface->ifindex]) - rn->ttls[iface->ifindex] = 0; + /* We are not the designated forwarder for this source on this + interface. Keep things as they currently are */ + if (rn->adv_rtr[iface->ifindex].addr.s_addr != iface->addr.s_addr) + return; + + /* There are still downstream dependent router for this source + Keep things as they currently are */ + if (rn->ds_cnt[iface->ifindex]) + return; + + /* There are still group members for this source on this iface + Keep things as they currently are */ + if (!mfc_check_members(rn, iface)) + return; + + /* Remove interface from the downstream list */ + rn->ttls[iface->ifindex] = 0; + mfc_update_source(rn); } void @@ -528,11 +543,20 @@ srt_expire_nbr(struct in_addr addr, struct iface *iface) { struct ds_nbr *ds; struct rt_node *rn; + u_int32_t ifindex = iface->ifindex; RB_FOREACH(rn, rt_tree, &rt) { - ds = srt_find_ds(rn, addr.s_addr); - if (ds) - srt_delete_ds(rn, ds, iface); + if (rn->adv_rtr[ifindex].addr.s_addr == addr.s_addr) { + rn->adv_rtr[ifindex].addr.s_addr = + iface->addr.s_addr; + rn->adv_rtr[ifindex].metric = rn->cost; + /* XXX: delete all routes learned from this nbr */ + } else if (rn->adv_rtr[ifindex].addr.s_addr == + iface->addr.s_addr) { + ds = srt_find_ds(rn, addr.s_addr); + if (ds) + srt_delete_ds(rn, ds, iface); + } } } |