diff options
author | Sarita Patra <saritap@vmware.com> | 2020-03-02 09:55:22 +0100 |
---|---|---|
committer | Sarita Patra <saritap@vmware.com> | 2020-03-17 05:54:34 +0100 |
commit | 9443810eef5d2de2d932600cf058ee030baa6d47 (patch) | |
tree | 9e0b775f7f75f89f74444f99265a3aa97fa7c7bc | |
parent | Merge pull request #5985 from Naveenaidu/5984-cleanup-is_selfroute (diff) | |
download | frr-9443810eef5d2de2d932600cf058ee030baa6d47.tar.xz frr-9443810eef5d2de2d932600cf058ee030baa6d47.zip |
pimd: fix OIL not removed after IGMP prune
Issue: Client1------LHR-----(int-1)RP(int-2)------client2
Client2 send IGMP join for group G.
Client1 send IGMP join for group G.
verify show ip mroute in RP, will have 2 OIL.
Client2 send IGMP leave.
Verify show ip mroute in RP, will still have 2.
Root cause: When RP receives IGMP join from client2, it creates
a (s,g) channel oil and add the interface int-2 into oil list and
set the flag PIM_OIF_FLAG_PROTO_IGMP to int-2
Client1 send IGMP join, LHR will send a (*,G) join to RP. RP will
add the interface int-1 into the oil list of (s,g) channel_oil and
will set the flag PIM_OIF_FLAG_PROTO_IGMP and PIM_OIF_FLAG_PROTO_PIM
to the int-1 and set PIM_OIF_FLAG_PROTO_PIM to int-2 as well. It is
happening because of the pim_upstream_inherited_olist_decide() and
forward_on() get all the oil and update the flag wrongly.
So now when client 2 sends IGMP prune, RP will not remove the int-2
from oil list since both PIM_OIF_FLAG_PROTO_PIM & PIM_OIF_FLAG_PROTO_IGMP
are set, it just unset the flag PIM_OIF_FLAG_PROTO_IGMP.
Fix: Introduced new flags in if_channel, PIM_IF_FLAG_MASK_PROTO_PIM
& PIM_IF_FLAG_MASK_PROTO_IGMP. If a if_channel is created because of
pim join or pim (s,g,rpt) prune received, then set the flag
PIM_IF_FLAG_MASK_PROTO_PIM. If a if_channel is created becuase of IGMP
join received, then set the flag PIM_IF_FLAG_MASK_PROTO_IGMP.
When an interface needs to be added into the oil list check if
PIM_IF_FLAG_MASK_PROTO_PIM or PIM_IF_FLAG_MASK_PROTO_IGMP is set, then
update oil flag accordingly.
Signed-off-by: Sarita Patra <saritap@vmware.com>
-rw-r--r-- | pimd/pim_cmd.c | 5 | ||||
-rw-r--r-- | pimd/pim_ifchannel.c | 6 | ||||
-rw-r--r-- | pimd/pim_ifchannel.h | 19 | ||||
-rw-r--r-- | pimd/pim_upstream.c | 8 | ||||
-rw-r--r-- | pimd/pim_zebra.c | 7 |
5 files changed, 40 insertions, 5 deletions
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index abc154896..cf3637c4f 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1706,7 +1706,10 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp, pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags)); if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) json_object_int_add(json_row, "SGRpt", 1); - + if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags)) + json_object_int_add(json_row, "protocolPim", 1); + if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags)) + json_object_int_add(json_row, "protocolIgmp", 1); json_object_object_get_ex(json_iface, ch_grp_str, &json_grp); if (!json_grp) { json_grp = json_object_new_object(); diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 44d4ee719..70e06ccc4 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -628,6 +628,12 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, up->dualactive_ifchannel_count, up->flags); } + if (up_flags == PIM_UPSTREAM_FLAG_MASK_SRC_PIM) + PIM_IF_FLAG_SET_PROTO_PIM(ch->flags); + + if (up_flags == PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) + PIM_IF_FLAG_SET_PROTO_IGMP(ch->flags); + if (PIM_DEBUG_PIM_TRACE) zlog_debug("%s: ifchannel %s(%s) is created ", __func__, ch->sg_str, ch->interface->name); diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 3d5cbd8ec..425622b79 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -69,7 +69,7 @@ struct pim_assert_metric { #define PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(flags) ((flags) &= ~PIM_IF_FLAG_MASK_ASSERT_TRACKING_DESIRED) /* - * Flat to tell us if the ifchannel is (S,G,rpt) + * Flag to tell us if the ifchannel is (S,G,rpt) */ #define PIM_IF_FLAG_MASK_S_G_RPT (1 << 2) #define PIM_IF_FLAG_TEST_S_G_RPT(flags) ((flags) & PIM_IF_FLAG_MASK_S_G_RPT) @@ -77,6 +77,23 @@ struct pim_assert_metric { #define PIM_IF_FLAG_UNSET_S_G_RPT(flags) ((flags) &= ~PIM_IF_FLAG_MASK_S_G_RPT) /* + * Flag to tell us if the ifchannel is proto PIM + */ +#define PIM_IF_FLAG_MASK_PROTO_PIM (1 << 3) +#define PIM_IF_FLAG_TEST_PROTO_PIM(flags) ((flags)&PIM_IF_FLAG_MASK_PROTO_PIM) +#define PIM_IF_FLAG_SET_PROTO_PIM(flags) ((flags) |= PIM_IF_FLAG_MASK_PROTO_PIM) +#define PIM_IF_FLAG_UNSET_PROTO_PIM(flags) \ + ((flags) &= ~PIM_IF_FLAG_MASK_PROTO_PIM) +/* + * Flag to tell us if the ifchannel is proto IGMP + */ +#define PIM_IF_FLAG_MASK_PROTO_IGMP (1 << 4) +#define PIM_IF_FLAG_TEST_PROTO_IGMP(flags) ((flags)&PIM_IF_FLAG_MASK_PROTO_IGMP) +#define PIM_IF_FLAG_SET_PROTO_IGMP(flags) \ + ((flags) |= PIM_IF_FLAG_MASK_PROTO_IGMP) +#define PIM_IF_FLAG_UNSET_PROTO_IGMP(flags) \ + ((flags) &= ~PIM_IF_FLAG_MASK_PROTO_IGMP) +/* Per-interface (S,G) state */ struct pim_ifchannel { diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index efa58c1b1..07f8315a1 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1794,10 +1794,16 @@ int pim_upstream_inherited_olist_decide(struct pim_instance *pim, continue; if (pim_upstream_evaluate_join_desired_interface(up, ch, starch)) { - int flag = PIM_OIF_FLAG_PROTO_PIM; + int flag = 0; if (!ch) flag = PIM_OIF_FLAG_PROTO_STAR; + else { + if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags)) + flag = PIM_OIF_FLAG_PROTO_IGMP; + if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags)) + flag |= PIM_OIF_FLAG_PROTO_PIM; + } pim_channel_add_oif(up->channel_oil, ifp, flag, __func__); diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index e791500ed..8355c2099 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -835,7 +835,7 @@ void igmp_source_forward_stop(struct igmp_source *source) void pim_forward_start(struct pim_ifchannel *ch) { struct pim_upstream *up = ch->upstream; - uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; + uint32_t mask = 0; if (PIM_DEBUG_PIM_TRACE) { char source_str[INET_ADDRSTRLEN]; @@ -853,9 +853,12 @@ void pim_forward_start(struct pim_ifchannel *ch) inet_ntoa(up->upstream_addr)); } - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) + if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags)) mask = PIM_OIF_FLAG_PROTO_IGMP; + if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags)) + mask |= PIM_OIF_FLAG_PROTO_PIM; + pim_channel_add_oif(up->channel_oil, ch->interface, mask, __func__); } |