From: Donald Sharp Date: Thu, 23 Mar 2017 01:07:57 +0000 (-0400) Subject: pimd: Allow SPT switchover X-Git-Tag: frr-3.0-rc0~84^2~2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=850a9f99b8e4ba6e043a75c28d25c9cb092770c5;p=mirror%2Ffrr.git pimd: Allow SPT switchover This allows SPT switchover for S,G upon receipt of packets on the LHR. 1) When we create a *,G from a IGMP Group Report, install the *,G route with the pimreg device on the OIL. 2) When a packet hits the LHR that matches the *,G, we will get a WHOLEPKT callback from the kernel and if we cannot find the S,G, that means we have matched it on the LHR via the *,G mroute. Create the S,G start the KAT and run inherited_olist. 3) When the S,G times out, safely remove the S,G via the KAT expiry 4) When the *,G is removed, remove any S,G associated with it via the LHR flag. Signed-off-by: Donald Sharp --- diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index e6b4ba92a9..e1697960e4 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -1006,6 +1006,7 @@ pim_ifchannel_local_membership_add(struct interface *ifp, pim_upstream_switch (child, PIM_UPSTREAM_JOINED); } } + pim_channel_add_oif(up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); } return 1; diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 2fb243b9bd..cfbd07ede0 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -200,6 +200,23 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf) up = pim_upstream_find(&sg); if (!up) { + struct prefix_sg star = sg; + star.src.s_addr = INADDR_ANY; + + up = pim_upstream_find(&star); + + if (up && PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) + { + up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_LHR, __PRETTY_FUNCTION__); + pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); + pim_upstream_inherited_olist (up); + pim_upstream_switch(up, PIM_UPSTREAM_JOINED); + + if (PIM_DEBUG_MROUTE) + zlog_debug ("%s: Creating %s upstream on LHR", + __PRETTY_FUNCTION__, up->sg_str); + return 0; + } if (PIM_DEBUG_MROUTE_DETAIL) { zlog_debug("%s: Unable to find upstream channel WHOLEPKT%s", __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 172d0d21c9..3e81aaf496 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -198,7 +198,20 @@ pim_upstream_del(struct pim_upstream *up, const char *name) upstream_channel_oil_detach(up); if (up->sources) - list_delete (up->sources); + { + struct listnode *node, *nnode; + struct pim_upstream *child; + for (ALL_LIST_ELEMENTS (up->sources, node, nnode, child)) + { + if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(child->flags)) + { + PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(child->flags); + pim_upstream_del(child, __PRETTY_FUNCTION__); + } + } + + list_delete (up->sources); + } up->sources = NULL; /* @@ -1083,26 +1096,31 @@ pim_upstream_keep_alive_timer (struct thread *t) up->t_ka_timer = NULL; if (I_am_RP (up->sg.grp)) - { - pim_br_clear_pmbr (&up->sg); - /* - * We need to do more here :) - * But this is the start. - */ - } + { + pim_br_clear_pmbr (&up->sg); + /* + * We need to do more here :) + * But this is the start. + */ + } /* source is no longer active - pull the SA from MSDP's cache */ pim_msdp_sa_local_del(&up->sg); /* if entry was created because of activity we need to deref it */ if (PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) - { - pim_upstream_fhr_kat_expiry(up); - if (PIM_DEBUG_TRACE) - zlog_debug ("kat expired on %s; remove stream reference", up->sg_str); - PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags); - pim_upstream_del(up, __PRETTY_FUNCTION__); - } + { + pim_upstream_fhr_kat_expiry(up); + if (PIM_DEBUG_TRACE) + zlog_debug ("kat expired on %s; remove stream reference", up->sg_str); + PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags); + pim_upstream_del(up, __PRETTY_FUNCTION__); + } + else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) + { + PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(up->flags); + pim_upstream_del(up, __PRETTY_FUNCTION__); + } return 0; } @@ -1633,25 +1651,28 @@ pim_upstream_sg_running (void *arg) return; } - if (pim_upstream_kat_start_ok(up)) { - /* Add a source reference to the stream if - * one doesn't already exist */ - if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) + if (pim_upstream_kat_start_ok(up)) { - if (PIM_DEBUG_TRACE) - zlog_debug ("source reference created on kat restart %s", up->sg_str); + /* Add a source reference to the stream if + * one doesn't already exist */ + if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) + { + if (PIM_DEBUG_TRACE) + zlog_debug ("source reference created on kat restart %s", up->sg_str); - pim_upstream_ref(up, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM); - PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); - pim_upstream_fhr_kat_start(up); + pim_upstream_ref(up, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM); + PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); + pim_upstream_fhr_kat_start(up); + } + pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); } + else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); - } if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) - { - pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface); - } + { + pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface); + } return; } diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 6f7556f323..94bc5a55b9 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -34,6 +34,8 @@ #define PIM_UPSTREAM_FLAG_MASK_SRC_STREAM (1 << 5) #define PIM_UPSTREAM_FLAG_MASK_SRC_MSDP (1 << 6) #define PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE (1 << 7) +#define PIM_UPSTREAM_FLAG_MASK_SRC_LHR (1 << 8) +#define PIM_UPSTREAM_FLAG_ALL 0xFFFFFFFF #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) @@ -43,6 +45,7 @@ #define PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) #define PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) #define PIM_UPSTREAM_FLAG_TEST_SEND_SG_RPT_PRUNE(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE) +#define PIM_UPSTREAM_FLAG_TEST_SRC_LHR(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_LHR) #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) @@ -52,6 +55,7 @@ #define PIM_UPSTREAM_FLAG_SET_SRC_STREAM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) #define PIM_UPSTREAM_FLAG_SET_SRC_MSDP(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) #define PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE) +#define PIM_UPSTREAM_FLAG_SET_SRC_LHR(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_LHR) #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) @@ -61,6 +65,7 @@ #define PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) #define PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) #define PIM_UPSTREAM_FLAG_UNSET_SEND_SG_RPT_PRUNE(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE) +#define PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_LHR) enum pim_upstream_state { PIM_UPSTREAM_NOTJOINED,