From 7667c5568fdff287ad124e6d6d39653da2241968 Mon Sep 17 00:00:00 2001 From: anuradhak Date: Tue, 8 Nov 2016 10:34:31 -0800 Subject: [PATCH] pim-msdp: part-3: use SA cache for setting up SPTs 1. Added a new MSDP source reference flag for creating (S,G) entries based on the SA-cache. The RFC recommends treating as SA like rxing a (S, G) join (which is a bit different then treating like a traffic stream). 2. SA-SPT is only setup if we are RP for the group and a corresponding (*,G) exists with a non-empty OIL. 3. When an SA is moved we need to let the SPT live if it is active (this change will come in a subsequent CL). Testing done: 1. SA first; SPT setup whenever (*, G) comes around. 2. (*, G) first. As soon as SA is added SPT is setup. 3. (*, G) del with valid SA entries around. Ticket: CM-13306 Signed-off-by: Anuradha Karuppiah Acked-by: Donald Sharp --- pimd/pim_cmd.c | 17 ++- pimd/pim_msdp.c | 236 +++++++++++++++++++++++++++++++++++++++-- pimd/pim_msdp.h | 4 + pimd/pim_msdp_packet.c | 25 +++-- pimd/pim_register.c | 1 + pimd/pim_rp.c | 15 ++- pimd/pim_upstream.c | 25 ++++- pimd/pim_upstream.h | 5 + 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("", 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("", 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 */ -- 2.39.5