From e355e30fcbe03b35dede323d7307ac38eb6f7479 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 20 Oct 2015 06:00:02 -0700 Subject: [PATCH] pimd: Fixup kernel callbacks to handle them better This patch sets up the handling of the 3 basic kernel callbacks: IGMPMSG_WRONGVIF - When a multicast message comes in the wrong vif IGMPMSG_NOCACHE - There is no multicast route associated with a received(S,G) IGMPMSG_WHOLEPKT - There is no outgoing interface for a packet. The code's debugs are cleaned up to be covered by debug statements Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 248 ++++++++++++++++++++++++++-------------------- 1 file changed, 141 insertions(+), 107 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 2f04323db2..f0830c1e7b 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -61,135 +61,169 @@ static int pim_mroute_set(int fd, int enable) return 0; } -int pim_mroute_msg(int fd, const char *buf, int buf_size) +static const char *igmpmsgtype2str[IGMPMSG_WHOLEPKT + 1] = { + "", + "NOCACHE", + "WRONGVIF", + "WHOLEPKT", }; + +static int +pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg, + const char *src_str, const char *grp_str) { - struct interface *ifp; - const struct ip *ip_hdr; - const struct igmpmsg *msg; - const char *upcall; - char src_str[100]; - char grp_str[100]; + return 0; +} - ip_hdr = (const struct ip *) buf; +static int +pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const struct igmpmsg *msg, + const char *src_str, const char *grp_str) +{ + return 0; +} - /* kernel upcall must have protocol=0 */ - if (ip_hdr->ip_p) { - /* this is not a kernel upcall */ -#ifdef PIM_UNEXPECTED_KERNEL_UPCALL - zlog_warn("%s: not a kernel upcall proto=%d msg_size=%d", - __PRETTY_FUNCTION__, ip_hdr->ip_p, buf_size); -#endif - return 0; - } +static int +pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *msg, + const char *src_str, const char *grp_str) +{ + struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; - msg = (const struct igmpmsg *) buf; + /* + Send Assert(S,G) on iif as response to WRONGVIF kernel upcall. - switch (msg->im_msgtype) { - case IGMPMSG_NOCACHE: upcall = "NOCACHE"; break; - case IGMPMSG_WRONGVIF: upcall = "WRONGVIF"; break; - case IGMPMSG_WHOLEPKT: upcall = "WHOLEPKT"; break; - default: upcall = ""; - } - ifp = pim_if_find_by_vif_index(msg->im_vif); - pim_inet4_dump("", msg->im_src, src_str, sizeof(src_str)); - pim_inet4_dump("", msg->im_dst, grp_str, sizeof(grp_str)); - - if (msg->im_msgtype == IGMPMSG_WRONGVIF) { - struct pim_ifchannel *ch; - struct pim_interface *pim_ifp; - - /* - Send Assert(S,G) on iif as response to WRONGVIF kernel upcall. - - RFC 4601 4.8.2. PIM-SSM-Only Routers - - iif is the incoming interface of the packet. - if (iif is in inherited_olist(S,G)) { - send Assert(S,G) on iif - } - */ + RFC 4601 4.8.2. PIM-SSM-Only Routers + + iif is the incoming interface of the packet. + if (iif is in inherited_olist(S,G)) { + send Assert(S,G) on iif + } + */ + if (!ifp) { if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: WRONGVIF from fd=%d for (S,G)=(%s,%s) on %s vifi=%d", + zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) could not find input interface for input_vif_index=%d", __PRETTY_FUNCTION__, - fd, - src_str, - grp_str, - ifp ? ifp->name : "", - msg->im_vif); + src_str, grp_str, msg->im_vif); } + return -1; + } - if (!ifp) { - zlog_warn("%s: WRONGVIF (S,G)=(%s,%s) could not find input interface for input_vif_index=%d", - __PRETTY_FUNCTION__, - src_str, grp_str, msg->im_vif); - return -1; + pim_ifp = ifp->info; + if (!pim_ifp) { + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) multicast not enabled on interface %s", + __PRETTY_FUNCTION__, + src_str, grp_str, ifp->name); } + return -2; + } - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: WRONGVIF (S,G)=(%s,%s) multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); - return -2; + ch = pim_ifchannel_find(ifp, msg->im_src, msg->im_dst); + if (!ch) { + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) could not find channel on interface %s", + __PRETTY_FUNCTION__, + src_str, grp_str, ifp->name); } + return -3; + } - ch = pim_ifchannel_find(ifp, msg->im_src, msg->im_dst); - if (!ch) { - zlog_warn("%s: WRONGVIF (S,G)=(%s,%s) could not find channel on interface %s", - __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); - return -3; - } + /* + RFC 4601: 4.6.1. (S,G) Assert Message State Machine + + Transitions from NoInfo State + + An (S,G) data packet arrives on interface I, AND + CouldAssert(S,G,I)==TRUE An (S,G) data packet arrived on an + downstream interface that is in our (S,G) outgoing interface + list. We optimistically assume that we will be the assert + winner for this (S,G), and so we transition to the "I am Assert + Winner" state and perform Actions A1 (below), which will + initiate the assert negotiation for (S,G). + */ - /* - RFC 4601: 4.6.1. (S,G) Assert Message State Machine - - Transitions from NoInfo State - - An (S,G) data packet arrives on interface I, AND - CouldAssert(S,G,I)==TRUE An (S,G) data packet arrived on an - downstream interface that is in our (S,G) outgoing interface - list. We optimistically assume that we will be the assert - winner for this (S,G), and so we transition to the "I am Assert - Winner" state and perform Actions A1 (below), which will - initiate the assert negotiation for (S,G). - */ - - if (ch->ifassert_state != PIM_IFASSERT_NOINFO) { - zlog_warn("%s: WRONGVIF (S,G)=(%s,%s) channel is not on Assert NoInfo state for interface %s", - __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); - return -4; + if (ch->ifassert_state != PIM_IFASSERT_NOINFO) { + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) channel is not on Assert NoInfo state for interface %s", + __PRETTY_FUNCTION__, + src_str, grp_str, ifp->name); } + return -4; + } - if (!PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { - zlog_warn("%s: WRONGVIF (S,G)=(%s,%s) interface %s is not downstream for channel", - __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); - return -5; + if (!PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) interface %s is not downstream for channel", + __PRETTY_FUNCTION__, + src_str, grp_str, ifp->name); } + return -5; + } - if (assert_action_a1(ch)) { - zlog_warn("%s: WRONGVIF (S,G)=(%s,%s) assert_action_a1 failure on interface %s", - __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); - return -6; + if (assert_action_a1(ch)) { + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) assert_action_a1 failure on interface %s", + __PRETTY_FUNCTION__, + src_str, grp_str, ifp->name); } + return -6; + } + + return 0; +} + +int pim_mroute_msg(int fd, const char *buf, int buf_size) +{ + struct interface *ifp; + const struct ip *ip_hdr; + const struct igmpmsg *msg; + char src_str[100] = ""; + char grp_str[100] = ""; + ip_hdr = (const struct ip *) buf; + + /* kernel upcall must have protocol=0 */ + if (ip_hdr->ip_p) { + /* this is not a kernel upcall */ + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: not a kernel upcall proto=%d msg_size=%d", + __PRETTY_FUNCTION__, ip_hdr->ip_p, buf_size); + } return 0; - } /* IGMPMSG_WRONGVIF */ - - zlog_warn("%s: kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%s,%s) on %s vifi=%d", - __PRETTY_FUNCTION__, - upcall, - msg->im_msgtype, - ip_hdr->ip_p, - fd, - src_str, - grp_str, - ifp ? ifp->name : "", - msg->im_vif); + } + + msg = (const struct igmpmsg *) buf; + + ifp = pim_if_find_by_vif_index(msg->im_vif); + + if (PIM_DEBUG_PIM_TRACE) { + pim_inet4_dump("", msg->im_src, src_str, sizeof(src_str)); + pim_inet4_dump("", msg->im_dst, grp_str, sizeof(grp_str)); + zlog_warn("%s: kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%s,%s) on %s vifi=%d", + __PRETTY_FUNCTION__, + igmpmsgtype2str[msg->im_msgtype], + msg->im_msgtype, + ip_hdr->ip_p, + fd, + src_str, + grp_str, + ifp ? ifp->name : "", + msg->im_vif); + } + + switch (msg->im_msgtype) { + case IGMPMSG_WRONGVIF: + return pim_mroute_msg_wrongvif(fd, ifp, msg, src_str, grp_str); + break; + case IGMPMSG_NOCACHE: + return pim_mroute_msg_nocache(fd, ifp, msg, src_str, grp_str); + break; + case IGMPMSG_WHOLEPKT: + return pim_mroute_msg_wholepkt(fd, ifp, msg, src_str, grp_str); + break; + default: + break; + } return 0; } -- 2.39.5