summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichele Marchetto <michele@cvs.openbsd.org>2009-03-06 18:39:14 +0000
committerMichele Marchetto <michele@cvs.openbsd.org>2009-03-06 18:39:14 +0000
commit79bf2b9529b10783102a038860f4a2e6a9b1dd37 (patch)
tree377d3d6341c062a6745966eddd9e5c522563e204
parent2e5aaa812e944ad785bdcdae37e63e836ee8c6da (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.h10
-rw-r--r--usr.sbin/dvmrpd/group.c30
-rw-r--r--usr.sbin/dvmrpd/igmp.h6
-rw-r--r--usr.sbin/dvmrpd/interface.c3
-rw-r--r--usr.sbin/dvmrpd/rde.c101
-rw-r--r--usr.sbin/dvmrpd/rde.h7
-rw-r--r--usr.sbin/dvmrpd/rde_mfc.c18
-rw-r--r--usr.sbin/dvmrpd/rde_srt.c38
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);
+ }
}
}