summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pimd/pim_cmd.c17
-rw-r--r--pimd/pim_msdp.c236
-rw-r--r--pimd/pim_msdp.h4
-rw-r--r--pimd/pim_msdp_packet.c25
-rw-r--r--pimd/pim_register.c1
-rw-r--r--pimd/pim_rp.c15
-rw-r--r--pimd/pim_upstream.c25
-rw-r--r--pimd/pim_upstream.h5
8 files changed, 302 insertions, 26 deletions
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 5b5bf8235d..03856bdfcf 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -1603,6 +1603,10 @@ json_object_pim_upstream_add (json_object *json, struct pim_upstream *up)
if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
json_object_boolean_true_add(json, "sourceStream");
+
+ /* XXX: need to print ths flag in the plain text display as well */
+ if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
+ json_object_boolean_true_add(json, "sourceMsdp");
}
static void pim_show_upstream(struct vty *vty, u_char uj)
@@ -5294,13 +5298,14 @@ ip_msdp_show_sa(struct vty *vty, u_char uj)
char grp_str[INET_ADDRSTRLEN];
char rp_str[INET_ADDRSTRLEN];
char timebuf[PIM_MSDP_UPTIME_STRLEN];
+ char spt_str[2];
int64_t now;
if (uj) {
// XXX: blah
return;
} else {
- vty_out(vty, "Source Group RP Uptime%s", VTY_NEWLINE);
+ vty_out(vty, "Source Group RP SPT Uptime%s", VTY_NEWLINE);
for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {
now = pim_time_monotonic_sec();
pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime);
@@ -5308,11 +5313,17 @@ ip_msdp_show_sa(struct vty *vty, u_char uj)
pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
if (sa->flags & PIM_MSDP_SAF_LOCAL) {
strcpy(rp_str, "local");
+ strcpy(spt_str, "-");
} else {
pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str));
+ if (sa->up) {
+ strcpy(spt_str, "y");
+ } else {
+ strcpy(spt_str, "n");
+ }
}
- vty_out(vty, "%-15s %15s %15s %8s%s",
- src_str, grp_str, rp_str, timebuf, VTY_NEWLINE);
+ vty_out(vty, "%-15s %15s %15s %3s %8s%s",
+ src_str, grp_str, rp_str, spt_str, timebuf, VTY_NEWLINE);
}
}
}
diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c
index d8237469c8..8e933222c6 100644
--- a/pimd/pim_msdp.c
+++ b/pimd/pim_msdp.c
@@ -82,6 +82,7 @@ pim_msdp_sa_timer_expiry_log(struct pim_msdp_sa *sa, const char *timer_str)
static int
pim_msdp_sa_adv_timer_cb(struct thread *t)
{
+ msdp->sa_adv_timer = NULL;
if (PIM_DEBUG_MSDP_INTERNAL) {
zlog_debug("MSDP SA advertisment timer expired");
}
@@ -107,6 +108,7 @@ pim_msdp_sa_state_timer_cb(struct thread *t)
struct pim_msdp_sa *sa;
sa = THREAD_ARG(t);
+ sa->sa_state_timer = NULL;
if (PIM_DEBUG_MSDP_EVENTS) {
pim_msdp_sa_timer_expiry_log(sa, "state");
@@ -125,6 +127,134 @@ pim_msdp_sa_state_timer_setup(struct pim_msdp_sa *sa, bool start)
}
}
+static void
+pim_msdp_sa_upstream_del(struct pim_msdp_sa *sa)
+{
+ struct pim_upstream *up = sa->up;
+ if (!up) {
+ return;
+ }
+
+ sa->up = NULL;
+ /* XXX: we can't pull the plug on an active flow even if the SA entry is
+ * removed. so ideally we want to start the kat in parallel and let the
+ * entry age out; but running the kat has fatal consequences. need to
+ * check with Donald on the best way to go abt this */
+ if (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags)) {
+ PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(up->flags);
+ pim_upstream_del(up, __PRETTY_FUNCTION__);
+ }
+
+ if (PIM_DEBUG_MSDP_EVENTS) {
+ char key_str[PIM_MSDP_SA_KEY_STRLEN];
+ pim_msdp_sa_key_dump(sa, key_str, sizeof(key_str), true);
+ zlog_debug("%s de-referenced SPT", key_str);
+ }
+}
+
+static bool
+pim_msdp_sa_upstream_add_ok(struct pim_msdp_sa *sa, struct pim_upstream *xg_up)
+{
+ if (sa->flags & PIM_MSDP_SAF_LOCAL) {
+ /* if there is a local reference we should NEVER use it for setting up
+ * SPTs otherwise we will get stuck in a simple circular deadlock */
+ return false;
+ }
+
+ if (!(sa->flags & PIM_MSDP_SAF_PEER)) {
+ /* SA should have been rxed from a peer */
+ return false;
+ }
+ /* check if we are RP */
+ if (!I_am_RP(sa->sg.grp)) {
+ return false;
+ }
+
+ /* check if we have a (*, G) with a non-empty immediate OIL */
+ if (!xg_up) {
+ struct prefix_sg sg;
+
+ memset(&sg, 0, sizeof(sg));
+ sg.grp = sa->sg.grp;
+
+ xg_up = pim_upstream_find(&sg);
+ }
+ if (!xg_up || (xg_up->join_state != PIM_UPSTREAM_JOINED)) {
+ /* join desired will be true for such (*, G) entries so we will
+ * just look at join_state and let the PIM state machine do the rest of
+ * the magic */
+ return false;
+ }
+
+ return true;
+}
+
+/* Upstream add evaluation needs to happen everytime -
+ * 1. Peer reference is added or removed.
+ * 2. Local reference is added or removed.
+ * 3. The RP for a group changes.
+ * 4. joinDesired for the associated (*, G) changes
+ * 5. associated (*, G) is removed - this seems like a bit redundant
+ * (considering #4); but just in case an entry gets nuked without
+ * upstream state transition
+ * */
+static void
+pim_msdp_sa_upstream_update(struct pim_msdp_sa *sa,
+ struct pim_upstream *xg_up, const char *ctx)
+{
+ struct pim_upstream *up;
+ char key_str[PIM_MSDP_SA_KEY_STRLEN];
+
+ if (PIM_DEBUG_MSDP_EVENTS || PIM_DEBUG_MSDP_INTERNAL) {
+ pim_msdp_sa_key_dump(sa, key_str, sizeof(key_str), true);
+ }
+
+ if (PIM_DEBUG_MSDP_INTERNAL) {
+ zlog_debug("%s upstream update on %s", key_str, ctx);
+ }
+
+ if (!pim_msdp_sa_upstream_add_ok(sa, xg_up)) {
+ pim_msdp_sa_upstream_del(sa);
+ return;
+ }
+
+ if (sa->up) {
+ /* nothing to do */
+ return;
+ }
+
+ up = pim_upstream_find(&sa->sg);
+ if (up && (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags))) {
+ /* somehow we lost track of the upstream ptr? best log it */
+ sa->up = up;
+ if (PIM_DEBUG_MSDP_EVENTS) {
+ zlog_debug("%s SPT reference missing", key_str);
+ }
+ return;
+ }
+
+ /* RFC3618: "RP triggers a (S, G) join event towards the data source
+ * as if a JP message was rxed addressed to the RP itself." */
+ up = pim_upstream_add(&sa->sg, NULL /* iif */,
+ PIM_UPSTREAM_FLAG_MASK_SRC_MSDP,
+ __PRETTY_FUNCTION__);
+
+ sa->up = up;
+ if (up) {
+ /* update inherited oil */
+ pim_upstream_inherited_olist(up);
+ /* should we also start the kat in parallel? we will need it when the
+ * SA ages out */
+ if (PIM_DEBUG_MSDP_EVENTS) {
+ zlog_debug("%s referenced SPT", key_str);
+ }
+ } else {
+ if (PIM_DEBUG_MSDP_EVENTS) {
+ zlog_debug("%s SPT reference failed", key_str);
+ }
+ }
+}
+
/* release all mem associated with a sa */
static void
pim_msdp_sa_free(struct pim_msdp_sa *sa)
@@ -137,8 +267,6 @@ pim_msdp_sa_new(struct prefix_sg *sg, struct in_addr rp)
{
struct pim_msdp_sa *sa;
- pim_msdp_enable();
-
sa = XCALLOC(MTYPE_PIM_MSDP_SA, sizeof(*sa));
if (!sa) {
zlog_err("%s: PIM XCALLOC(%zu) failure",
@@ -194,6 +322,10 @@ pim_msdp_sa_add(struct prefix_sg *sg, struct in_addr rp)
static void
pim_msdp_sa_del(struct pim_msdp_sa * sa)
{
+ /* this is somewhat redundant - still want to be careful not to leave
+ * stale upstream references */
+ pim_msdp_sa_upstream_del(sa);
+
/* stop timers */
pim_msdp_sa_state_timer_setup(sa, false /* start */);
@@ -243,6 +375,7 @@ pim_msdp_sa_deref(struct pim_msdp_sa *sa, enum pim_msdp_sa_flags flags)
}
sa->flags &= ~flags;
+ pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "sa-deref");
if (!(sa->flags & PIM_MSDP_SAF_REF)) {
pim_msdp_sa_del(sa);
}
@@ -275,6 +408,10 @@ pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg,
sa->peer = mp->peer;
/* start/re-start the state timer to prevent cache expiry */
pim_msdp_sa_state_timer_setup(sa, true /* start */);
+ /* We re-evaluate SA "SPT-trigger" everytime we hear abt it from a
+ * peer. XXX: If this becomes too much of a periodic overhead we
+ * can make it event based */
+ pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "peer-ref");
} else {
if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) {
sa->flags |= PIM_MSDP_SAF_LOCAL;
@@ -282,8 +419,9 @@ pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg,
if (PIM_DEBUG_MSDP_EVENTS) {
zlog_debug("%s added locally", key_str);
}
- /* send an immeidate SA update to peers */
+ /* send an immediate SA update to peers */
pim_msdp_pkt_sa_tx_one(sa);
+ pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "local-ref");
}
sa->flags &= ~PIM_MSDP_SAF_STALE;
}
@@ -338,28 +476,100 @@ pim_msdp_sa_local_setup(void)
}
}
-/* whenever the RP changes we need to re-evaluate the "local"
- * SA-cache */
-/* XXX: need to call this from thr right places. also needs more testing */
+/* whenever the RP changes we need to re-evaluate the "local" SA-cache */
+/* XXX: needs to be tested */
void
pim_msdp_i_am_rp_changed(void)
{
struct listnode *sanode;
struct pim_msdp_sa *sa;
+ if (!(msdp->flags & PIM_MSDPF_ENABLE)) {
+ /* if the feature is not enabled do nothing */
+ return;
+ }
+
+ if (PIM_DEBUG_MSDP_INTERNAL) {
+ zlog_debug("MSDP i_am_rp changed");
+ }
+
/* mark all local entries as stale */
for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {
- sa->flags |= PIM_MSDP_SAF_STALE;
+ if (sa->flags & PIM_MSDP_SAF_LOCAL) {
+ sa->flags |= PIM_MSDP_SAF_STALE;
+ }
}
/* re-setup local SA entries */
pim_msdp_sa_local_setup();
- /* purge stale SA entries */
for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {
+ /* purge stale SA entries */
if (sa->flags & PIM_MSDP_SAF_STALE) {
+ /* clear the stale flag; the entry may be kept even after
+ * "local-deref" */
+ sa->flags &= ~PIM_MSDP_SAF_STALE;
pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL);
}
+ /* also check if we can still influence SPT */
+ pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "rp-change");
+ }
+}
+
+/* We track the join state of (*, G) entries. If G has sources in the SA-cache
+ * we need to setup or teardown SPT when the JoinDesired status changes for
+ * (*, G) */
+void
+pim_msdp_up_join_state_changed(struct pim_upstream *xg_up)
+{
+ struct listnode *sanode;
+ struct pim_msdp_sa *sa;
+
+ if (PIM_DEBUG_MSDP_INTERNAL) {
+ zlog_debug("MSDP join state changed for %s", pim_str_sg_dump(&xg_up->sg));
+ }
+
+ /* If this is not really an XG entry just move on */
+ if ((xg_up->sg.src.s_addr != INADDR_ANY) ||
+ (xg_up->sg.grp.s_addr == INADDR_ANY)) {
+ return;
+ }
+
+ /* XXX: Need to maintain SAs per-group to avoid all this unnecessary
+ * walking */
+ for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {
+ if (sa->sg.grp.s_addr != xg_up->sg.grp.s_addr) {
+ continue;
+ }
+ pim_msdp_sa_upstream_update(sa, xg_up, "up-jp-change");
+ }
+}
+
+/* XXX: Need to maintain SAs per-group to avoid all this unnecessary
+ * walking */
+void
+pim_msdp_up_xg_del(struct prefix_sg *sg)
+{
+ struct listnode *sanode;
+ struct pim_msdp_sa *sa;
+
+ if (PIM_DEBUG_MSDP_INTERNAL) {
+ zlog_debug("MSDP %s del", pim_str_sg_dump(sg));
+ }
+
+ /* If this is not really an XG entry just move on */
+ if ((sg->src.s_addr != INADDR_ANY) ||
+ (sg->grp.s_addr == INADDR_ANY)) {
+ return;
+ }
+
+ /* XXX: Need to maintain SAs per-group to avoid all this unnecessary
+ * walking */
+ for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {
+ if (sa->sg.grp.s_addr != sg->grp.s_addr) {
+ continue;
+ }
+ pim_msdp_sa_upstream_update(sa, NULL /* xg */, "up-jp-change");
}
}
@@ -536,6 +746,12 @@ pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state)
}
}
+ if (PIM_DEBUG_MSDP_INTERNAL) {
+ char key_str[PIM_MSDP_PEER_KEY_STRLEN];
+
+ pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), false);
+ zlog_debug("%s pim_msdp_peer_stop_tcp_conn", key_str);
+ }
/* stop read and write threads */
PIM_MSDP_PEER_READ_OFF(mp);
PIM_MSDP_PEER_WRITE_OFF(mp);
@@ -594,6 +810,7 @@ pim_msdp_peer_hold_timer_cb(struct thread *t)
struct pim_msdp_peer *mp;
mp = THREAD_ARG(t);
+ mp->hold_timer = NULL;
if (PIM_DEBUG_MSDP_EVENTS) {
pim_msdp_peer_timer_expiry_log(mp, "hold");
@@ -627,6 +844,7 @@ pim_msdp_peer_ka_timer_cb(struct thread *t)
struct pim_msdp_peer *mp;
mp = THREAD_ARG(t);
+ mp->ka_timer = NULL;
if (PIM_DEBUG_MSDP_EVENTS) {
pim_msdp_peer_timer_expiry_log(mp, "ka");
@@ -636,7 +854,6 @@ pim_msdp_peer_ka_timer_cb(struct thread *t)
pim_msdp_peer_ka_timer_setup(mp, true /* start */);
return 0;
}
-/* XXX: reset this anytime a message is sent to the peer */
static void
pim_msdp_peer_ka_timer_setup(struct pim_msdp_peer *mp, bool start)
{
@@ -690,6 +907,7 @@ pim_msdp_peer_cr_timer_cb(struct thread *t)
struct pim_msdp_peer *mp;
mp = THREAD_ARG(t);
+ mp->cr_timer = NULL;
if (PIM_DEBUG_MSDP_EVENTS) {
pim_msdp_peer_timer_expiry_log(mp, "connect-retry");
diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h
index 2af453f689..5e13b33b5b 100644
--- a/pimd/pim_msdp.h
+++ b/pimd/pim_msdp.h
@@ -81,6 +81,8 @@ struct pim_msdp_sa {
#define PIM_MSDP_SA_HOLD_TIME ((3*60)+30)
struct thread *sa_state_timer; // 5.6
int64_t uptime;
+
+ struct pim_upstream *up;
};
enum pim_msdp_peer_flags {
@@ -193,4 +195,6 @@ void pim_msdp_sa_local_add(struct prefix_sg *sg);
void pim_msdp_sa_local_del(struct prefix_sg *sg);
void pim_msdp_i_am_rp_changed(void);
bool pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp);
+void pim_msdp_up_join_state_changed(struct pim_upstream *xg_up);
+void pim_msdp_up_xg_del(struct prefix_sg *sg);
#endif
diff --git a/pimd/pim_msdp_packet.c b/pimd/pim_msdp_packet.c
index d6b4765714..bc6156325f 100644
--- a/pimd/pim_msdp_packet.c
+++ b/pimd/pim_msdp_packet.c
@@ -150,14 +150,17 @@ pim_msdp_write(struct thread *thread)
struct stream *s;
int num;
enum pim_msdp_tlv type;
+ int work_cnt = 0;
+ char key_str[PIM_MSDP_PEER_KEY_STRLEN];
mp = THREAD_ARG(thread);
mp->t_write = NULL;
if (PIM_DEBUG_MSDP_INTERNAL) {
- char key_str[PIM_MSDP_PEER_KEY_STRLEN];
-
pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), false);
+ }
+
+ if (PIM_DEBUG_MSDP_INTERNAL) {
zlog_debug("%s pim_msdp_write", key_str);
}
if (mp->fd < 0) {
@@ -176,7 +179,7 @@ pim_msdp_write(struct thread *thread)
return 0;
}
- sockopt_cork (mp->fd, 1);
+ sockopt_cork(mp->fd, 1);
/* Nonblocking write until TCP output buffer is full */
do
@@ -190,8 +193,12 @@ pim_msdp_write(struct thread *thread)
num = write(mp->fd, STREAM_PNT(s), writenum);
if (num < 0) {
/* write failed either retry needed or error */
- if (ERRNO_IO_RETRY(errno))
+ if (ERRNO_IO_RETRY(errno)) {
+ if (PIM_DEBUG_MSDP_INTERNAL) {
+ zlog_debug("%s pim_msdp_write io retry", key_str);
+ }
break;
+ }
/* XXX:revisit; reset TCP connection */
pim_msdp_peer_reset_tcp_conn(mp, "pkt-tx-failed");
@@ -202,9 +209,6 @@ pim_msdp_write(struct thread *thread)
/* Partial write */
stream_forward_getp(s, num);
if (PIM_DEBUG_MSDP_INTERNAL) {
- char key_str[PIM_MSDP_PEER_KEY_STRLEN];
-
- pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), false);
zlog_debug("%s pim_msdp_partial_write", key_str);
}
break;
@@ -230,12 +234,17 @@ pim_msdp_write(struct thread *thread)
/* packet sent delete it. */
pim_msdp_pkt_delete(mp);
+ ++work_cnt;
/* XXX - may need to pause if we have done too much work in this
* loop */
} while ((s = stream_fifo_head(mp->obuf)) != NULL);
pim_msdp_write_proceed_actions(mp);
- sockopt_cork (mp->fd, 0);
+ sockopt_cork(mp->fd, 0);
+
+ if (PIM_DEBUG_MSDP_INTERNAL) {
+ zlog_debug("%s pim_msdp_write wrote %d packets", key_str, work_cnt);
+ }
return 0;
}
diff --git a/pimd/pim_register.c b/pimd/pim_register.c
index e012115e37..3058df1af4 100644
--- a/pimd/pim_register.c
+++ b/pimd/pim_register.c
@@ -352,6 +352,7 @@ pim_register_recv (struct interface *ifp,
{
zlog_debug ("Received Register(%s), for which I have no path back", pim_str_sg_dump (&upstream->sg));
}
+ pim_upstream_unset_created_by_upstream(upstream);
pim_upstream_del (upstream, __PRETTY_FUNCTION__);
return 1;
}
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c
index 817837afbf..1bd48798c6 100644
--- a/pimd/pim_rp.c
+++ b/pimd/pim_rp.c
@@ -40,6 +40,7 @@
#include "pim_sock.h"
#include "pim_memory.h"
#include "pim_iface.h"
+#include "pim_msdp.h"
struct rp_info
{
@@ -226,6 +227,7 @@ pim_rp_find_match_group (struct prefix *group)
static void
pim_rp_refresh_group_to_rp_mapping()
{
+ pim_msdp_i_am_rp_changed();
}
void
@@ -509,6 +511,7 @@ pim_rp_check_rp (struct in_addr old, struct in_addr new)
{
struct listnode *node;
struct rp_info *rp_info;
+ bool i_am_rp_changed = false;
if (qpim_rp_list == NULL)
return;
@@ -529,14 +532,24 @@ pim_rp_check_rp (struct in_addr old, struct in_addr new)
if (new.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr)
{
- rp_info->i_am_rp = 1;
+ if (!rp_info->i_am_rp) {
+ i_am_rp_changed = true;
+ }
+ rp_info->i_am_rp = 1;
}
if (old.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr)
{
+ if (rp_info->i_am_rp) {
+ i_am_rp_changed = true;
+ }
rp_info->i_am_rp = 0;
}
}
+
+ if (i_am_rp_changed) {
+ pim_msdp_i_am_rp_changed();
+ }
}
/*
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index 2596f8c6e1..2abf0b296f 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -119,7 +119,7 @@ pim_upstream_set_created_by_upstream(struct pim_upstream *up)
pim_msdp_sa_local_add(&up->sg);
}
-static void
+void
pim_upstream_unset_created_by_upstream(struct pim_upstream *up)
{
PIM_UPSTREAM_FLAG_UNSET_CREATED_BY_UPSTREAM(up->flags);
@@ -169,6 +169,8 @@ static void upstream_channel_oil_detach(struct pim_upstream *up)
void
pim_upstream_del(struct pim_upstream *up, const char *name)
{
+ bool notify_msdp = false;
+
if (PIM_DEBUG_PIM_TRACE)
{
zlog_debug ("%s: Delete (%s) ref count: %d",
@@ -187,10 +189,20 @@ pim_upstream_del(struct pim_upstream *up, const char *name)
THREAD_OFF(up->t_ka_timer);
THREAD_OFF(up->t_rs_timer);
+ if (up->join_state == PIM_UPSTREAM_JOINED) {
+ pim_joinprune_send (up->rpf.source_nexthop.interface,
+ up->rpf.rpf_addr.u.prefix4,
+ up, 0);
+ if (up->sg.src.s_addr == INADDR_ANY) {
+ /* if a (*, G) entry in the joined state is being deleted we
+ * need to notify MSDP */
+ notify_msdp = true;
+ }
+ }
+
if (up->sg.src.s_addr != INADDR_ANY)
wheel_remove_item (pim_upstream_sg_wheel, up);
- pim_msdp_sa_local_del(&up->sg);
pim_upstream_remove_children (up);
pim_mroute_del (up->channel_oil);
upstream_channel_oil_detach(up);
@@ -212,6 +224,9 @@ pim_upstream_del(struct pim_upstream *up, const char *name)
listnode_delete (pim_upstream_list, up);
hash_release (pim_upstream_hash, up);
+ if (notify_msdp) {
+ pim_msdp_up_xg_del(&up->sg);
+ }
pim_upstream_free(up);
}
@@ -465,6 +480,7 @@ pim_upstream_switch(struct pim_upstream *up,
{
int old_fhr = PIM_UPSTREAM_FLAG_TEST_FHR(up->flags);
forward_on(up);
+ pim_msdp_up_join_state_changed(up);
if (pim_upstream_could_register (up))
{
PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
@@ -487,6 +503,8 @@ pim_upstream_switch(struct pim_upstream *up,
}
else {
forward_off(up);
+ if (old_state == PIM_UPSTREAM_JOINED)
+ pim_msdp_up_join_state_changed(up);
pim_joinprune_send(up->rpf.source_nexthop.interface,
up->rpf.rpf_addr.u.prefix4,
up,
@@ -925,9 +943,6 @@ pim_upstream_keep_alive_timer (struct thread *t)
pim_mroute_del (up->channel_oil);
THREAD_OFF (up->t_ka_timer);
THREAD_OFF (up->t_rs_timer);
- THREAD_OFF (up->t_join_timer);
- pim_joinprune_send (up->rpf.source_nexthop.interface, up->rpf.rpf_addr.u.prefix4,
- up, 0);
PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM (up->flags);
if (PIM_UPSTREAM_FLAG_TEST_CREATED_BY_UPSTREAM(up->flags))
{
diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h
index 7f8c0c99cb..a073125021 100644
--- a/pimd/pim_upstream.h
+++ b/pimd/pim_upstream.h
@@ -34,6 +34,7 @@
#define PIM_UPSTREAM_FLAG_MASK_SRC_PIM (1 << 4)
#define PIM_UPSTREAM_FLAG_MASK_SRC_STREAM (1 << 5)
#define PIM_UPSTREAM_FLAG_MASK_CREATED_BY_UPSTREAM (1 << 6)
+#define PIM_UPSTREAM_FLAG_MASK_SRC_MSDP (1 << 7)
#define PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
#define PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
@@ -42,6 +43,7 @@
#define PIM_UPSTREAM_FLAG_TEST_SRC_PIM(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_PIM)
#define PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
#define PIM_UPSTREAM_FLAG_TEST_CREATED_BY_UPSTREAM(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_CREATED_BY_UPSTREAM)
+#define PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
#define PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
#define PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
@@ -50,6 +52,7 @@
#define PIM_UPSTREAM_FLAG_SET_SRC_PIM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_PIM)
#define PIM_UPSTREAM_FLAG_SET_SRC_STREAM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
#define PIM_UPSTREAM_FLAG_SET_CREATED_BY_UPSTREAM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_CREATED_BY_UPSTREAM)
+#define PIM_UPSTREAM_FLAG_SET_SRC_MSDP(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
#define PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
#define PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
@@ -58,6 +61,7 @@
#define PIM_UPSTREAM_FLAG_UNSET_SRC_PIM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_PIM)
#define PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
#define PIM_UPSTREAM_FLAG_UNSET_CREATED_BY_UPSTREAM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_CREATED_BY_UPSTREAM)
+#define PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
enum pim_upstream_state {
PIM_UPSTREAM_NOTJOINED,
@@ -164,4 +168,5 @@ void pim_upstream_find_new_rpf (void);
void pim_upstream_init (void);
void pim_upstream_terminate (void);
void pim_upstream_set_created_by_upstream(struct pim_upstream *up);
+void pim_upstream_unset_created_by_upstream(struct pim_upstream *up);
#endif /* PIM_UPSTREAM_H */