From 781a1745c0908e54e44c761f32b6f7936d6c1a04 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 19 Jan 2017 12:09:26 -0500 Subject: [PATCH] pimd: Fixup tracking of where we got OIF's from. This commit does these three things: 1) Add code to 'show ip pim state' to show where OIF's got their decision to include that interface 2) Add code in pim_mroute_[add|del] to display what we think we are adding to the kernel 3) Add code to properly track where we got the incoming request from and to appropriately not remove a OIL if we have state still Ticket: CM-14034 Signed-off-by: Donald Sharp Reviewed-by: Don Slice Reviewed-by: Chirag Shah --- pimd/pim_cmd.c | 29 ++++++++++++++++++------ pimd/pim_ifchannel.c | 14 ++++++------ pimd/pim_mroute.c | 23 ++++++++----------- pimd/pim_oil.c | 54 ++++++++++++++++++++++++++++++++------------ pimd/pim_oil.h | 9 ++++++-- pimd/pim_upstream.c | 6 ++++- 6 files changed, 90 insertions(+), 45 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 7dc1aeccb..8f3e2cb3e 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1367,7 +1367,8 @@ pim_show_state(struct vty *vty, const char *src_or_group, const char *group, u_c if (uj) { json = json_object_new_object(); } else { - vty_out(vty, "%sSource Group IIF OIL%s", VTY_NEWLINE, VTY_NEWLINE); + vty_out(vty, "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G)"); + vty_out(vty, "%sInstalled Source Group IIF OIL%s", VTY_NEWLINE, VTY_NEWLINE); } for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { @@ -1379,9 +1380,6 @@ pim_show_state(struct vty *vty, const char *src_or_group, const char *group, u_c struct interface *ifp_in; first_oif = 1; - if (!c_oil->installed) - continue; - pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, grp_str, sizeof(grp_str)); pim_inet4_dump("", c_oil->oil.mfcc_origin, src_str, sizeof(src_str)); ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); @@ -1426,7 +1424,8 @@ pim_show_state(struct vty *vty, const char *src_or_group, const char *group, u_c json_object_object_add(json_source, in_ifname, json_ifp_in); } } else { - vty_out(vty, "%-15s %-15s %-5s ", + vty_out(vty, "%-9d %-15s %-15s %-7s ", + c_oil->installed, src_str, grp_str, ifp_in->name); @@ -1455,16 +1454,25 @@ pim_show_state(struct vty *vty, const char *src_or_group, const char *group, u_c json_object_string_add(json_ifp_out, "group", grp_str); json_object_string_add(json_ifp_out, "inboundInterface", in_ifname); json_object_string_add(json_ifp_out, "outboundInterface", out_ifname); + json_object_int_add(json_ifp_out, "installed", c_oil->installed); json_object_object_add(json_ifp_in, out_ifname, json_ifp_out); } else { if (first_oif) { first_oif = 0; - vty_out(vty, "%s", out_ifname); + vty_out(vty, "%s(%c%c%c%c)", out_ifname, + (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) ? 'I' : ' ', + (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) ? 'J' : ' ', + (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) ? 'S' : ' ', + (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) ? '*' : ' '); } else - vty_out(vty, ",%s", out_ifname); + vty_out(vty, ", %s(%c%c%c%c)", out_ifname, + (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) ? 'I' : ' ', + (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) ? 'J' : ' ', + (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) ? 'S' : ' ', + (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) ? '*' : ' ' ); } } @@ -2963,6 +2971,9 @@ static void show_mroute(struct vty *vty, u_char uj) if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) json_object_boolean_true_add(json_ifp_out, "protocolSource"); + if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) + json_object_boolean_true_add(json_ifp_out, "protocolInherited"); + json_object_string_add(json_ifp_out, "inboundInterface", in_ifname); json_object_int_add(json_ifp_out, "iVifI", c_oil->oil.mfcc_parent); json_object_string_add(json_ifp_out, "outboundInterface", out_ifname); @@ -2987,6 +2998,10 @@ static void show_mroute(struct vty *vty, u_char uj) strcpy(proto, "SRC"); } + if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) { + strcpy(proto, "STAR"); + } + vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s%s", src_str, grp_str, diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 07318791e..8d2de3c87 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -153,7 +153,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) struct listnode *up_node; for (ALL_LIST_ELEMENTS_RO (ch->upstream->sources, up_node, child)) - pim_channel_del_oif (child->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_PIM); + pim_channel_del_oif (child->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); } } @@ -270,7 +270,7 @@ void pim_ifchannel_ifjoin_switch(const char *caller, continue; if (!pim_upstream_evaluate_join_desired (child)) - pim_channel_del_oif (c_oil, ch->interface, PIM_OIF_FLAG_PROTO_PIM); + pim_channel_del_oif (c_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); /* * If the S,G has no if channel and the c_oil still @@ -278,7 +278,7 @@ void pim_ifchannel_ifjoin_switch(const char *caller, * if channel. So remove it. */ if (!ch && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) - pim_channel_del_oif (c_oil, ch->interface, PIM_OIF_FLAG_PROTO_PIM); + pim_channel_del_oif (c_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); } } if (ch->ifjoin_state == PIM_IFJOIN_JOIN) @@ -292,7 +292,7 @@ void pim_ifchannel_ifjoin_switch(const char *caller, if (pim_upstream_evaluate_join_desired (child)) { - pim_channel_add_oif (child->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_PIM); + pim_channel_add_oif (child->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); pim_upstream_switch (child, PIM_UPSTREAM_JOINED); } } @@ -964,7 +964,7 @@ void pim_ifchannel_local_membership_add(struct interface *ifp, if (pim_upstream_evaluate_join_desired (child)) { - pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_STAR); pim_upstream_switch (child, PIM_UPSTREAM_JOINED); } } @@ -1008,7 +1008,7 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, up->sg_str, ifp->name, child->sg_str); if (c_oil && !pim_upstream_evaluate_join_desired (child)) - pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR); /* * If the S,G has no if channel and the c_oil still @@ -1016,7 +1016,7 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, * if channel. So remove it. */ if (!chchannel && c_oil && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) - pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR); } } delete_on_noinfo(ch); diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index dfd22b702..05d08b6e9 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -812,13 +812,10 @@ int pim_mroute_add(struct channel_oil *c_oil, const char *name) if (PIM_DEBUG_MROUTE) { - struct prefix_sg sg; - - sg.src = c_oil->oil.mfcc_origin; - sg.grp = c_oil->oil.mfcc_mcastgrp; - - zlog_debug("%s(%s), Added Route: %s to mroute table", - __PRETTY_FUNCTION__, name, pim_str_sg_dump(&sg)); + char buf[1000]; + zlog_debug("%s(%s), Added Route: %s", + __PRETTY_FUNCTION__, name, + pim_channel_oil_dump (c_oil, buf, sizeof(buf))); } c_oil->installed = 1; @@ -850,14 +847,12 @@ int pim_mroute_del (struct channel_oil *c_oil, const char *name) if (PIM_DEBUG_MROUTE) { - struct prefix_sg sg; - - sg.src = c_oil->oil.mfcc_origin; - sg.grp = c_oil->oil.mfcc_mcastgrp; - - zlog_debug("%s(%s), Deleted Route: %s from mroute table", - __PRETTY_FUNCTION__, name, pim_str_sg_dump(&sg)); + char buf[1000]; + zlog_debug("%s(%s), Deleted Route: %s", + __PRETTY_FUNCTION__, name, + pim_channel_oil_dump (c_oil, buf, sizeof(buf))); } + c_oil->installed = 0; return 0; diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 0cebe4735..4c5eff488 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -36,6 +36,31 @@ struct list *pim_channel_oil_list = NULL; struct hash *pim_channel_oil_hash = NULL; +char * +pim_channel_oil_dump (struct channel_oil *c_oil, char *buf, size_t size) +{ + struct prefix_sg sg; + int i; + + memset (buf, 0, size); + sg.src = c_oil->oil.mfcc_origin; + sg.grp = c_oil->oil.mfcc_mcastgrp; + sprintf(buf, "%s IIF: %d, OIFS: ", + pim_str_sg_dump (&sg), c_oil->oil.mfcc_parent); + + for (i = 0 ; i < MAXVIFS ; i++) + { + if (c_oil->oil.mfcc_ttls[i] != 0) + { + char buf1[10]; + sprintf(buf1, "%d ", i); + strcat(buf, buf1); + } + } + + return buf; +} + static int pim_channel_oil_compare (struct channel_oil *c1, struct channel_oil *c2) { @@ -353,25 +378,26 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, } /* Allow other protocol to request subscription of same interface to - channel (S,G) multiple times, by silently ignoring further - requests */ + * channel (S,G), we need to note this information + */ if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & PIM_OIF_FLAG_PROTO_ANY) { + channel_oil->oif_creation[pim_ifp->mroute_vif_index] = pim_time_monotonic_sec(); + channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask; /* Check the OIF really exists before returning, and only log warning otherwise */ if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) { - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: new protocol mask %u requested nonexistent OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - proto_mask, oif->name, pim_ifp->mroute_vif_index, - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index], - source_str, group_str); - } + { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); + pim_inet4_dump("", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); + zlog_warn("%s %s: new protocol mask %u requested nonexistent OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, + proto_mask, oif->name, pim_ifp->mroute_vif_index, + channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index], + source_str, group_str); + } } return 0; diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index 143cfb794..6b96750ad 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -29,13 +29,16 @@ * IGMP - Learned from IGMP * PIM - Learned from PIM * SOURCE - Learned from Source multicast packet received + * STAR - Inherited */ #define PIM_OIF_FLAG_PROTO_IGMP (1 << 0) #define PIM_OIF_FLAG_PROTO_PIM (1 << 1) -#define PIM_OIF_FLAG_PROTO_SOURCE (2 << 1) +#define PIM_OIF_FLAG_PROTO_SOURCE (1 << 2) +#define PIM_OIF_FLAG_PROTO_STAR (1 << 3) #define PIM_OIF_FLAG_PROTO_ANY (PIM_OIF_FLAG_PROTO_IGMP | \ PIM_OIF_FLAG_PROTO_PIM | \ - PIM_OIF_FLAG_PROTO_SOURCE) + PIM_OIF_FLAG_PROTO_SOURCE | \ + PIM_OIF_FLAG_PROTO_STAR) /* * We need a pimreg vif id from the kernel. @@ -96,4 +99,6 @@ int pim_channel_del_oif (struct channel_oil *c_oil, uint32_t proto_mask); int pim_channel_oil_empty (struct channel_oil *c_oil); + +char *pim_channel_oil_dump (struct channel_oil *c_oil, char *buf, size_t size); #endif /* PIM_OIL_H */ diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index fbb7d84a2..4ae49c0fd 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1288,7 +1288,11 @@ pim_upstream_inherited_olist_decide (struct pim_upstream *up) if (pim_upstream_evaluate_join_desired_interface (up, ch)) { - pim_channel_add_oif (up->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_PIM); + int flag = PIM_OIF_FLAG_PROTO_PIM; + + if (ch->sg.src.s_addr == INADDR_ANY && ch->upstream != up) + flag = PIM_OIF_FLAG_PROTO_STAR; + pim_channel_add_oif (up->channel_oil, ch->interface, flag); output_intf++; } } -- 2.39.2