From 8f483f924eb7cdb07a1bf200bdcde2332ee9758f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 12 Jul 2016 21:40:35 -0400 Subject: [PATCH 001/386] pimd: Create pim_encode_addr_group Create the ability to encode the group address in a message. Signed-off-by: Donald Sharp --- pimd/pim_tlv.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++-- pimd/pim_tlv.h | 3 ++ 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index 38f6de9fea..f441e043a7 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -97,8 +97,8 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf, #define ucast_ipv4_encoding_len (2 + sizeof(struct in_addr)) -static int -pim_encode_unicast_address (uint8_t *buf, struct prefix *p) +int +pim_encode_addr_ucast (uint8_t *buf, struct prefix *p) { switch (p->family) { @@ -116,6 +116,79 @@ pim_encode_unicast_address (uint8_t *buf, struct prefix *p) } } +#define group_ipv4_encoding_len (4 + sizeof (struct in_addr)) + +/* + * Encoded-Group addresses take the following format: + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Addr Family | Encoding Type |B| Reserved |Z| Mask Len | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Group multicast Address + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+... + * + * Addr Family + * Described above. + * + * Encoding Type + * Described above. + * + * [B]idirectional PIM + * Indicates the group range should use Bidirectional PIM [13]. + * For PIM-SM defined in this specification, this bit MUST be zero. + * + * Reserved + * Transmitted as zero. Ignored upon receipt. + * + * Admin Scope [Z]one + * indicates the group range is an admin scope zone. This is used + * in the Bootstrap Router Mechanism [11] only. For all other + * purposes, this bit is set to zero and ignored on receipt. + * + * Mask Len + * The Mask length field is 8 bits. The value is the number of + * contiguous one bits that are left justified and used as a mask; + * when combined with the group address, it describes a range of + * groups. It is less than or equal to the address length in bits + * for the given Address Family and Encoding Type. If the message + * is sent for a single group, then the Mask length must equal the + * address length in bits for the given Address Family and Encoding + * Type (e.g., 32 for IPv4 native encoding, 128 for IPv6 native + * encoding). + * + * Group multicast Address + * Contains the group address. + */ +int +pim_encode_addr_group (uint8_t *buf, afi_t afi, int bidir, int scope, struct in_addr group) +{ + uint8_t flags = 0; + + flags |= bidir << 8; + flags |= scope; + + switch (afi) + { + case AFI_IP: + *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV4; + ++buf; + *(uint8_t *)buf = 0; + ++buf; + *(uint8_t *)buf = flags; + ++buf; + *(uint8_t *)buf = 32; + ++buf; + memcpy (buf, &group, sizeof (struct in_addr)); + return group_ipv4_encoding_len; + break; + default: + return 0; + break; + } +} + uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend, struct list *ifconnected) @@ -145,7 +218,7 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, if ((curr + ucast_ipv4_encoding_len) > buf_pastend) return 0; - l_encode = pim_encode_unicast_address (curr, p); + l_encode = pim_encode_addr_ucast (curr, p); curr += l_encode; option_len += l_encode; } diff --git a/pimd/pim_tlv.h b/pimd/pim_tlv.h index 8556e931ab..586d989684 100644 --- a/pimd/pim_tlv.h +++ b/pimd/pim_tlv.h @@ -111,6 +111,9 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, uint16_t option_len, const uint8_t *tlv_curr); +int pim_encode_addr_ucast (uint8_t *buf, struct prefix *p); +int pim_encode_addr_group (uint8_t *buf, afi_t afi, int bidir, int scope, struct in_addr group); + int pim_parse_addr_ucast (struct prefix *p, const uint8_t *buf, int buf_size); From 3d7765d7417b0552fb4d6356742dc68428bf3d4b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 14 Jul 2016 09:05:34 -0400 Subject: [PATCH 002/386] pimd: Fixup some dead code Remove some dead code. Signed-off-by: Donald Sharp --- pimd/pim_iface.c | 3 +-- pimd/pim_igmpv3.c | 3 +-- pimd/pim_mroute.c | 30 +++++------------------------- pimd/pim_pim.c | 3 +-- pimd/pim_sock.c | 3 +-- pimd/pim_ssmpingd.c | 6 ++---- pimd/pim_str.c | 3 +-- 7 files changed, 12 insertions(+), 39 deletions(-) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index a8a1d08805..6739ce17be 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -1119,14 +1119,13 @@ int pim_if_igmp_join_del(struct interface *ifp, } if (close(ij->sock_fd)) { - int e = errno; char group_str[100]; char source_str[100]; pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); zlog_warn("%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s", __PRETTY_FUNCTION__, - ij->sock_fd, group_str, source_str, ifp->name, e, safe_strerror(e)); + ij->sock_fd, group_str, source_str, ifp->name, errno, safe_strerror(errno)); /* warning only */ } listnode_delete(pim_ifp->igmp_join_list, ij); diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index 7300e6c6b4..05d2699ff7 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -1710,7 +1710,6 @@ void pim_igmp_send_membership_query(struct igmp_group *group, sent = sendto(fd, query_buf, msg_size, MSG_DONTWAIT, (struct sockaddr *)&to, tolen); if (sent != (ssize_t) msg_size) { - int e = errno; char dst_str[100]; char group_str[100]; pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); @@ -1719,7 +1718,7 @@ void pim_igmp_send_membership_query(struct igmp_group *group, zlog_warn("%s: sendto() failure to %s on %s: group=%s msg_size=%zd: errno=%d: %s", __PRETTY_FUNCTION__, dst_str, ifname, group_str, msg_size, - e, safe_strerror(e)); + errno, safe_strerror(errno)); } else { zlog_warn("%s: sendto() partial to %s on %s: group=%s msg_size=%zd: sent=%zd", diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 56f49d62f5..41672b1b19 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -50,20 +50,12 @@ static int pim_mroute_set(int fd, int enable) err = setsockopt(fd, IPPROTO_IP, opt, &opt, opt_len); if (err) { - int e = errno; zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,%s=%d): errno=%d: %s", __FILE__, __PRETTY_FUNCTION__, - fd, enable ? "MRT_INIT" : "MRT_DONE", opt, e, safe_strerror(e)); - errno = e; + fd, enable ? "MRT_INIT" : "MRT_DONE", opt, errno, safe_strerror(errno)); return -1; } -#if 0 - zlog_info("%s %s: setsockopt(fd=%d,IPPROTO_IP,MRT_INIT,opt=%d): ok", - __FILE__, __PRETTY_FUNCTION__, - fd, opt); -#endif - return 0; } @@ -452,8 +444,6 @@ int pim_mroute_socket_enable() qpim_mroute_socket_creation = pim_time_monotonic_sec(); mroute_read_on(); - zassert(PIM_MROUTE_IS_ENABLED); - return 0; } @@ -477,8 +467,6 @@ int pim_mroute_socket_disable() mroute_read_off(); qpim_mroute_socket_fd = -1; - zassert(PIM_MROUTE_IS_DISABLED); - return 0; } @@ -524,15 +512,13 @@ int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, unsigned ch err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_VIF, (void*) &vc, sizeof(vc)); if (err) { char ifaddr_str[100]; - int e = errno; pim_inet4_dump("", ifaddr, ifaddr_str, sizeof(ifaddr_str)); zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_VIF,vif_index=%d,ifaddr=%s,flag=%d): errno=%d: %s", __FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd, ifp->ifindex, ifaddr_str, flags, - e, safe_strerror(e)); - errno = e; + errno, safe_strerror(errno)); return -2; } @@ -555,12 +541,10 @@ int pim_mroute_del_vif(int vif_index) err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_VIF, (void*) &vc, sizeof(vc)); if (err) { - int e = errno; zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_VIF,vif_index=%d): errno=%d: %s", __FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd, vif_index, - e, safe_strerror(e)); - errno = e; + errno, safe_strerror(errno)); return -2; } @@ -598,12 +582,10 @@ int pim_mroute_add(struct channel_oil *c_oil) c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = orig; if (err) { - int e = errno; zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_MFC): errno=%d: %s", __FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd, - e, safe_strerror(e)); - errno = e; + errno, safe_strerror(errno)); return -2; } @@ -626,12 +608,10 @@ int pim_mroute_del (struct channel_oil *c_oil) err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_MFC, &c_oil->oil, sizeof(c_oil->oil)); if (err) { - int e = errno; zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_MFC): errno=%d: %s", __FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd, - e, safe_strerror(e)); - errno = e; + errno, safe_strerror(errno)); return -2; } diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 0dfd39cd16..c1b9e04e23 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -495,14 +495,13 @@ int pim_msg_send(int fd, sent = sendto(fd, pim_msg, pim_msg_size, MSG_DONTWAIT, (struct sockaddr *)&to, tolen); if (sent != (ssize_t) pim_msg_size) { - int e = errno; char dst_str[100]; pim_inet4_dump("", dst, dst_str, sizeof(dst_str)); if (sent < 0) { zlog_warn("%s: sendto() failure to %s on %s: fd=%d msg_size=%d: errno=%d: %s", __PRETTY_FUNCTION__, dst_str, ifname, fd, pim_msg_size, - e, safe_strerror(e)); + errno, safe_strerror(errno)); } else { zlog_warn("%s: sendto() partial to %s on %s: fd=%d msg_size=%d: sent=%zd", diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index 231efd0f22..3eeda040b1 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -267,7 +267,6 @@ int pim_socket_join_source(int fd, ifindex_t ifindex, const char *ifname) { if (pim_igmp_join_source(fd, ifindex, group_addr, source_addr)) { - int e = errno; char group_str[100]; char source_str[100]; pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); @@ -275,7 +274,7 @@ int pim_socket_join_source(int fd, ifindex_t ifindex, zlog_warn("%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s", __PRETTY_FUNCTION__, fd, group_str, source_str, ifindex, ifname, - e, safe_strerror(e)); + errno, safe_strerror(errno)); return -1; } diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c index fba563a6f8..3f494d112d 100644 --- a/pimd/pim_ssmpingd.c +++ b/pimd/pim_ssmpingd.c @@ -197,12 +197,11 @@ static void ssmpingd_delete(struct ssmpingd_sock *ss) THREAD_OFF(ss->t_sock_read); if (close(ss->sock_fd)) { - int e = errno; char source_str[100]; pim_inet4_dump("", ss->source_addr, source_str, sizeof(source_str)); zlog_warn("%s: failure closing ssmpingd sock_fd=%d for source %s: errno=%d: %s", __PRETTY_FUNCTION__, - ss->sock_fd, source_str, e, safe_strerror(e)); + ss->sock_fd, source_str, errno, safe_strerror(errno)); /* warning only */ } @@ -221,14 +220,13 @@ static void ssmpingd_sendto(struct ssmpingd_sock *ss, sent = sendto(ss->sock_fd, buf, len, MSG_DONTWAIT, (struct sockaddr *)&to, tolen); if (sent != len) { - int e = errno; char to_str[100]; pim_inet4_dump("", to.sin_addr, to_str, sizeof(to_str)); if (sent < 0) { zlog_warn("%s: sendto() failure to %s,%d: fd=%d len=%d: errno=%d: %s", __PRETTY_FUNCTION__, to_str, ntohs(to.sin_port), ss->sock_fd, len, - e, safe_strerror(e)); + errno, safe_strerror(errno)); } else { zlog_warn("%s: sendto() partial to %s,%d: fd=%d len=%d: sent=%d", diff --git a/pimd/pim_str.c b/pimd/pim_str.c index 3a8353cd8c..ee9c74fa36 100644 --- a/pimd/pim_str.c +++ b/pimd/pim_str.c @@ -35,9 +35,8 @@ void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, int buf_ int save_errno = errno; if (!inet_ntop(AF_INET, &addr, buf, buf_size)) { - int e = errno; zlog_warn("pim_inet4_dump: inet_ntop(AF_INET,buf_size=%d): errno=%d: %s", - buf_size, e, safe_strerror(e)); + buf_size, errno, safe_strerror(errno)); if (onfail) snprintf(buf, buf_size, "%s", onfail); } From 6352a6cf233bc4aa840d037df5d69fcd99a7470d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 14 Jul 2016 09:09:39 -0400 Subject: [PATCH 003/386] pimd: Set correct parameters to pim_register_stop_send Setup the pim_register_stop_send function to take the correct parameters. Signed-off-by: Donald Sharp --- pimd/pim_register.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index ce3ac1a433..fe805841dc 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -65,8 +65,9 @@ pim_check_is_my_ip_address (struct in_addr dest_addr) } static void -pim_register_stop_send (struct in_addr src) +pim_register_stop_send (struct in_addr source, struct in_addr group, struct in_addr originator) { + zlog_debug ("Send Register Stop"); return; } @@ -205,8 +206,6 @@ pim_register_recv (struct interface *ifp, */ #define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4 ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN); - //hlen = (ip_hdr->ip_hl << 2) | PIM_MSG_REGISTER_LEN; - //msg = (uint8_t *)tlv_buf + hlen; source = ip_hdr->ip_src; group = ip_hdr->ip_dst; @@ -221,7 +220,7 @@ pim_register_recv (struct interface *ifp, if (pimbr.s_addr == pim_br_unknown.s_addr) pim_br_set_pmbr(source, group, src_addr); else if (src_addr.s_addr != pimbr.s_addr) { - pim_register_stop_send(src_addr); + pim_register_stop_send(source, group, src_addr); if (PIM_DEBUG_PIM_PACKETS) zlog_debug("%s: Sending register-Stop to %s and dropping mr. packet", __func__, "Sender"); @@ -235,12 +234,15 @@ pim_register_recv (struct interface *ifp, * If we don't have a place to send ignore the packet */ if (!upstream) - return 1; + { + pim_register_stop_send (source, group, src_addr); + return 1; + } if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || ((SwitchToSptDesired(source, group)) && (inherited_olist(source, group) == NULL))) { - pim_register_stop_send(src_addr); + pim_register_stop_send(source, group, src_addr); sentRegisterStop = 1; } @@ -274,7 +276,7 @@ pim_register_recv (struct interface *ifp, //inherited_olist(S,G,rpt) } } else { - pim_register_stop_send(src_addr); + pim_register_stop_send(source, group, src_addr); } return 1; From 13c2408c1d3fdf1c5b259e94eaa4aeb02523fd5d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 14 Jul 2016 10:12:25 -0400 Subject: [PATCH 004/386] pimd: Send Register-Stop from RP The RP now has the ability to send a register stop message to the originator of the packet in order to tell it to stop encapsulating packets to the RP. Signed-off-by: Donald Sharp --- pimd/pim_register.c | 54 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index fe805841dc..233db88d3e 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -24,6 +24,7 @@ #include "log.h" #include "if.h" #include "thread.h" +#include "prefix.h" #include "pimd.h" #include "pim_mroute.h" @@ -39,6 +40,7 @@ #include "pim_oil.h" #include "pim_zebra.h" #include "pim_join.h" +#include "pim_util.h" struct thread *send_test_packet_timer = NULL; @@ -65,10 +67,48 @@ pim_check_is_my_ip_address (struct in_addr dest_addr) } static void -pim_register_stop_send (struct in_addr source, struct in_addr group, struct in_addr originator) +pim_register_stop_send (struct interface *ifp, struct in_addr source, + struct in_addr group, struct in_addr originator) { - zlog_debug ("Send Register Stop"); - return; + struct pim_interface *pinfo; + unsigned char buffer[3000]; + unsigned int b1length = 0; + unsigned int length; + uint8_t *b1; + struct prefix p; + + memset (buffer, 0, 3000); + b1 = (uint8_t *)buffer + PIM_MSG_REGISTER_STOP_LEN; + + length = pim_encode_addr_group (b1, AFI_IP, 0, 0, group); + b1length += length; + b1 += length; + + p.family = AF_INET; + p.u.prefix4 = source; + p.prefixlen = 32; + length = pim_encode_addr_ucast (b1, &p); + b1length += length; + + pim_msg_build_header (buffer, b1length + PIM_MSG_REGISTER_STOP_LEN, PIM_MSG_TYPE_REG_STOP); + + pinfo = (struct pim_interface *)ifp->info; + if (!pinfo) + { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug ("%s: No pinfo!\n", __PRETTY_FUNCTION__); + return; + } + if (pim_msg_send (pinfo->pim_sock_fd, originator, + buffer, b1length + PIM_MSG_REGISTER_STOP_LEN, + ifp->name)) + { + if (PIM_DEBUG_PIM_TRACE) + { + zlog_debug ("%s: could not send PIM register stop message on interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + } } void @@ -220,7 +260,7 @@ pim_register_recv (struct interface *ifp, if (pimbr.s_addr == pim_br_unknown.s_addr) pim_br_set_pmbr(source, group, src_addr); else if (src_addr.s_addr != pimbr.s_addr) { - pim_register_stop_send(source, group, src_addr); + pim_register_stop_send (ifp, source, group, src_addr); if (PIM_DEBUG_PIM_PACKETS) zlog_debug("%s: Sending register-Stop to %s and dropping mr. packet", __func__, "Sender"); @@ -235,14 +275,14 @@ pim_register_recv (struct interface *ifp, */ if (!upstream) { - pim_register_stop_send (source, group, src_addr); + pim_register_stop_send (ifp, source, group, src_addr); return 1; } if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || ((SwitchToSptDesired(source, group)) && (inherited_olist(source, group) == NULL))) { - pim_register_stop_send(source, group, src_addr); + pim_register_stop_send (ifp, source, group, src_addr); sentRegisterStop = 1; } @@ -276,7 +316,7 @@ pim_register_recv (struct interface *ifp, //inherited_olist(S,G,rpt) } } else { - pim_register_stop_send(source, group, src_addr); + pim_register_stop_send (ifp, source, group, src_addr); } return 1; From 4dffc8807e4c265002247d19dad4275308b6d818 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 14 Jul 2016 10:30:37 -0400 Subject: [PATCH 005/386] pimd: Refactor pim message receive We were using a variety of techniques to handle incoming pim packets. Refactor to use a switch statement to handle the incoming packets. Also add the ability to notice that we are getting a register stop. Signed-off-by: Donald Sharp --- pimd/pim_pim.c | 91 ++++++++++++++++++++++----------------------- pimd/pim_register.c | 7 ++++ pimd/pim_register.h | 1 + 3 files changed, 52 insertions(+), 47 deletions(-) diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index c1b9e04e23..f0db822cb4 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -208,60 +208,57 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) pim_version, pim_type, pim_msg_len, checksum); } - if (pim_type == PIM_MSG_TYPE_REG_STOP || - pim_type == PIM_MSG_TYPE_BOOTSTRAP || - pim_type == PIM_MSG_TYPE_GRAFT || - pim_type == PIM_MSG_TYPE_GRAFT_ACK || - pim_type == PIM_MSG_TYPE_CANDIDATE) + switch (pim_type) { + case PIM_MSG_TYPE_HELLO: + return pim_hello_recv (ifp, + ip_hdr->ip_src, + pim_msg + PIM_MSG_HEADER_LEN, + pim_msg_len - PIM_MSG_HEADER_LEN); + break; + case PIM_MSG_TYPE_REGISTER: + return pim_register_recv (ifp, + ip_hdr->ip_dst, + ip_hdr->ip_src, + pim_msg + PIM_MSG_HEADER_LEN, + pim_msg_len - PIM_MSG_HEADER_LEN); + break; + case PIM_MSG_TYPE_REG_STOP: + return pim_register_stop_recv (); + break; + case PIM_MSG_TYPE_JOIN_PRUNE: + neigh = pim_neighbor_find(ifp, ip_hdr->ip_src); + if (!neigh) { + zlog_warn("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", + __FILE__, __PRETTY_FUNCTION__, + pim_type, src_str, ifp->name); + return -1; + } + return pim_joinprune_recv(ifp, neigh, + ip_hdr->ip_src, + pim_msg + PIM_MSG_HEADER_LEN, + pim_msg_len - PIM_MSG_HEADER_LEN); + break; + case PIM_MSG_TYPE_ASSERT: + neigh = pim_neighbor_find(ifp, ip_hdr->ip_src); + if (!neigh) { + zlog_warn("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", + __FILE__, __PRETTY_FUNCTION__, + pim_type, src_str, ifp->name); + return -1; + } + return pim_assert_recv(ifp, neigh, + ip_hdr->ip_src, + pim_msg + PIM_MSG_HEADER_LEN, + pim_msg_len - PIM_MSG_HEADER_LEN); + break; + default: if (PIM_DEBUG_PIM_PACKETS) { zlog_debug("Recv PIM packet type %d which is not currently understood", pim_type); } return -1; } - - if (pim_type == PIM_MSG_TYPE_HELLO) { - return pim_hello_recv(ifp, - ip_hdr->ip_src, - pim_msg + PIM_MSG_HEADER_LEN, - pim_msg_len - PIM_MSG_HEADER_LEN); - } else if (pim_type == PIM_MSG_TYPE_REGISTER) { - return pim_register_recv(ifp, - ip_hdr->ip_dst, - ip_hdr->ip_src, - pim_msg + PIM_MSG_HEADER_LEN, - pim_msg_len - PIM_MSG_HEADER_LEN); - } - - neigh = pim_neighbor_find(ifp, ip_hdr->ip_src); - if (!neigh) { - zlog_warn("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", - __FILE__, __PRETTY_FUNCTION__, - pim_type, src_str, ifp->name); - return -1; - } - - switch (pim_type) { - case PIM_MSG_TYPE_JOIN_PRUNE: - return pim_joinprune_recv(ifp, neigh, - ip_hdr->ip_src, - pim_msg + PIM_MSG_HEADER_LEN, - pim_msg_len - PIM_MSG_HEADER_LEN); - break; - case PIM_MSG_TYPE_ASSERT: - return pim_assert_recv(ifp, neigh, - ip_hdr->ip_src, - pim_msg + PIM_MSG_HEADER_LEN, - pim_msg_len - PIM_MSG_HEADER_LEN); - break; - default: - zlog_warn("%s %s: unsupported PIM message type=%d from %s on %s", - __FILE__, __PRETTY_FUNCTION__, - pim_type, src_str, ifp->name); - break; - } - return -1; } diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 233db88d3e..a3e63f0285 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -111,6 +111,13 @@ pim_register_stop_send (struct interface *ifp, struct in_addr source, } } +int +pim_register_stop_recv (void) +{ + zlog_debug ("Received Register Stop"); + return 0; +} + void pim_register_send (const struct ip *ip_hdr, struct pim_rpf *rpg) { diff --git a/pimd/pim_register.h b/pimd/pim_register.h index 039c0006e0..4749480b9d 100644 --- a/pimd/pim_register.h +++ b/pimd/pim_register.h @@ -35,6 +35,7 @@ void pim_register_send_test_packet_start (struct in_addr source, struct in_addr group, uint32_t pps); +int pim_register_stop_recv (void); int pim_register_recv (struct interface *ifp, struct in_addr dest_addr, struct in_addr src_addr, From 2ddab288813b4bf66fff05505143b8f9f7982fbc Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 14 Jul 2016 17:16:42 -0400 Subject: [PATCH 006/386] pimd: Add decision point to send register message When we receive a register stop we will have created a timer for this. As such if the t_rs_timer pointer will be non-NULL at this point. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 7 ++++++- pimd/pim_upstream.h | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 41672b1b19..bf996a738b 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -194,7 +194,12 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf, return 0; } - pim_register_send((const struct ip *)(buf + sizeof(struct ip)), rpg); + /* + * If we've received a register suppress + */ + if (!up->t_rs_timer) + pim_register_send((const struct ip *)(buf + sizeof(struct ip)), rpg); + return 0; } diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index ea44707c54..71a4c85f18 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -100,6 +100,13 @@ struct pim_upstream { struct thread *t_join_timer; + /* + * RST(S,G) + */ + struct thread *t_rs_timer; +#define PIM_REGISTER_SUPPRESSION_PERIOD (60) +#define PIM_REGISTER_PROBE_PERIOD (5) + /* * KAT(S,G) */ From 59ba0ac3e6631f1eebc35bdc1581c17ee43bc7f0 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 14 Jul 2016 17:19:00 -0400 Subject: [PATCH 007/386] pimd: Fix use of 0 for NULL pimd uses allot of 0's to represent NULL. Not a good programming practice. Signed-off-by: Donald Sharp --- pimd/pim_assert.c | 2 +- pimd/pim_iface.c | 10 +++++----- pimd/pim_ifchannel.c | 16 ++++++++-------- pimd/pim_igmp.c | 14 +++++++------- pimd/pim_neighbor.c | 4 ++-- pimd/pim_pim.c | 13 ++++++------- pimd/pim_static.c | 16 ++++++++-------- pimd/pimd.c | 16 ++++++++-------- 8 files changed, 45 insertions(+), 46 deletions(-) diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index d3df6a1102..590a7e1da5 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -552,7 +552,7 @@ static int on_assert_timer(struct thread *t) src_str, grp_str, ifp->name); } - ch->t_ifassert_timer = 0; + ch->t_ifassert_timer = NULL; switch (ch->ifassert_state) { case PIM_IFASSERT_I_AM_WINNER: diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 6739ce17be..65b51d2b56 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -111,10 +111,10 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim) PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp->options); #endif - pim_ifp->igmp_join_list = 0; - pim_ifp->igmp_socket_list = 0; - pim_ifp->pim_neighbor_list = 0; - pim_ifp->pim_ifchannel_list = 0; + pim_ifp->igmp_join_list = NULL; + pim_ifp->igmp_socket_list = NULL; + pim_ifp->pim_neighbor_list = NULL; + pim_ifp->pim_ifchannel_list = NULL; pim_ifp->pim_generation_id = 0; /* list of struct igmp_sock */ @@ -187,7 +187,7 @@ void pim_if_delete(struct interface *ifp) XFREE(MTYPE_PIM_INTERFACE, pim_ifp); - ifp->info = 0; + ifp->info = NULL; } void pim_if_update_could_assert(struct interface *ifp) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index abfa5cc2b7..a3d827f1e0 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -202,14 +202,14 @@ static struct pim_ifchannel *pim_ifchannel_new(struct interface *ifp, zlog_err("%s: could not attach upstream (S,G)=(%s,%s) on interface %s", __PRETTY_FUNCTION__, src_str, grp_str, ifp->name); - return 0; + return NULL; } ch = XMALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch)); if (!ch) { zlog_err("%s: PIM XMALLOC(%zu) failure", __PRETTY_FUNCTION__, sizeof(*ch)); - return 0; + return NULL; } ch->flags = 0; @@ -220,8 +220,8 @@ static struct pim_ifchannel *pim_ifchannel_new(struct interface *ifp, ch->local_ifmembership = PIM_IFMEMBERSHIP_NOINFO; ch->ifjoin_state = PIM_IFJOIN_NOINFO; - ch->t_ifjoin_expiry_timer = 0; - ch->t_ifjoin_prune_pending_timer = 0; + ch->t_ifjoin_expiry_timer = NULL; + ch->t_ifjoin_prune_pending_timer = NULL; ch->ifjoin_creation = 0; ch->ifassert_my_metric = pim_macro_ch_my_assert_metric_eval(ch); @@ -230,7 +230,7 @@ static struct pim_ifchannel *pim_ifchannel_new(struct interface *ifp, ch->ifassert_winner.s_addr = 0; /* Assert state */ - ch->t_ifassert_timer = 0; + ch->t_ifassert_timer = NULL; reset_ifassert_state(ch); if (pim_macro_ch_could_assert_eval(ch)) PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); @@ -363,7 +363,7 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, __PRETTY_FUNCTION__, src_str, grp_str, ifp->name); - return 0; + return NULL; } static void ifjoin_to_noinfo(struct pim_ifchannel *ch) @@ -381,7 +381,7 @@ static int on_ifjoin_expiry_timer(struct thread *t) ch = THREAD_ARG(t); zassert(ch); - ch->t_ifjoin_expiry_timer = 0; + ch->t_ifjoin_expiry_timer = NULL; zassert(ch->ifjoin_state == PIM_IFJOIN_JOIN); @@ -431,7 +431,7 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) ch = THREAD_ARG(t); zassert(ch); - ch->t_ifjoin_prune_pending_timer = 0; + ch->t_ifjoin_prune_pending_timer = NULL; zassert(ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING); diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 3b63b10e0d..189f40ff51 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -171,7 +171,7 @@ static int pim_igmp_other_querier_expire(struct thread *t) ifaddr_str); } - igmp->t_other_querier_timer = 0; + igmp->t_other_querier_timer = NULL; /* We are the current querier, then @@ -212,7 +212,7 @@ void pim_igmp_other_querier_timer_on(struct igmp_sock *igmp) else { /* We are the current querier, then stop sending general queries: - igmp->t_igmp_query_timer = 0; + igmp->t_igmp_query_timer = NULL; */ pim_igmp_general_query_off(igmp); } @@ -864,7 +864,7 @@ void pim_igmp_general_query_on(struct igmp_sock *igmp) startup_mode ? "startup" : "non-startup", igmp->fd); } - igmp->t_igmp_query_timer = 0; + igmp->t_igmp_query_timer = NULL; zassert(!igmp->t_igmp_query_timer); THREAD_TIMER_ON(master, igmp->t_igmp_query_timer, pim_igmp_general_query, @@ -956,7 +956,7 @@ static void igmp_read_on(struct igmp_sock *igmp) zlog_debug("Scheduling READ event on IGMP socket fd=%d", igmp->fd); } - igmp->t_igmp_read = 0; + igmp->t_igmp_read = NULL; zassert(!igmp->t_igmp_read); THREAD_READ_ON(master, igmp->t_igmp_read, pim_igmp_read, igmp, igmp->fd); } @@ -1202,9 +1202,9 @@ static struct igmp_sock *igmp_sock_new(int fd, igmp->fd = fd; igmp->interface = ifp; igmp->ifaddr = ifaddr; - igmp->t_igmp_read = 0; - igmp->t_igmp_query_timer = 0; - igmp->t_other_querier_timer = 0; /* no other querier present */ + igmp->t_igmp_read = NULL; + igmp->t_igmp_query_timer = NULL; + igmp->t_other_querier_timer = NULL; /* no other querier present */ igmp->querier_robustness_variable = pim_ifp->igmp_default_robustness_variable; igmp->sock_creation = pim_time_monotonic_sec(); diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index 7e7cbc0d11..90fdc35473 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -222,7 +222,7 @@ static int on_neighbor_timer(struct thread *t) neigh->holdtime, src_str, ifp->name); } - neigh->t_expire_timer = 0; + neigh->t_expire_timer = NULL; snprintf(msg, sizeof(msg), "%d-sec holdtime expired", neigh->holdtime); pim_neighbor_delete(ifp, neigh, msg); @@ -313,7 +313,7 @@ static struct pim_neighbor *pim_neighbor_new(struct interface *ifp, neigh->dr_priority = dr_priority; neigh->generation_id = generation_id; neigh->prefix_list = addr_list; - neigh->t_expire_timer = 0; + neigh->t_expire_timer = NULL; neigh->interface = ifp; pim_neighbor_timer_reset(neigh, holdtime); diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index f0db822cb4..60bba9e9ba 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -377,7 +377,7 @@ static void pim_sock_read_on(struct interface *ifp) zlog_debug("Scheduling READ event on PIM socket fd=%d", pim_ifp->pim_sock_fd); } - pim_ifp->t_pim_sock_read = 0; + pim_ifp->t_pim_sock_read = NULL; zassert(!pim_ifp->t_pim_sock_read); THREAD_READ_ON(master, pim_ifp->t_pim_sock_read, pim_sock_read, ifp, pim_ifp->pim_sock_fd); @@ -430,9 +430,9 @@ void pim_sock_reset(struct interface *ifp) pim_ifp->pim_sock_fd = -1; pim_ifp->pim_sock_creation = 0; - pim_ifp->t_pim_sock_read = 0; + pim_ifp->t_pim_sock_read = NULL; - pim_ifp->t_pim_hello_timer = 0; + pim_ifp->t_pim_hello_timer = NULL; pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD; pim_ifp->pim_default_holdtime = -1; /* unset: means 3.5 * pim_hello_period */ pim_ifp->pim_triggered_hello_delay = PIM_DEFAULT_TRIGGERED_HELLO_DELAY; @@ -634,7 +634,7 @@ static int on_pim_hello_send(struct thread *t) /* * Schedule next hello */ - pim_ifp->t_pim_hello_timer = 0; + pim_ifp->t_pim_hello_timer = NULL; hello_resched(ifp); /* @@ -701,9 +701,8 @@ void pim_hello_restart_triggered(struct interface *ifp) } THREAD_OFF(pim_ifp->t_pim_hello_timer); - pim_ifp->t_pim_hello_timer = 0; + pim_ifp->t_pim_hello_timer = NULL; } - zassert(!pim_ifp->t_pim_hello_timer); random_msec = random() % (triggered_hello_delay_msec + 1); @@ -741,7 +740,7 @@ int pim_sock_add(struct interface *ifp) return -2; } - pim_ifp->t_pim_sock_read = 0; + pim_ifp->t_pim_sock_read = NULL; pim_ifp->pim_sock_creation = pim_time_monotonic_sec(); /* diff --git a/pimd/pim_static.c b/pimd/pim_static.c index 5882142b32..98c74caab5 100644 --- a/pimd/pim_static.c +++ b/pimd/pim_static.c @@ -80,11 +80,11 @@ static struct static_route *static_route_new(unsigned int iif, int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr group, struct in_addr source) { - struct listnode *node = 0; - struct static_route *s_route = 0; - struct static_route *original_s_route = 0; - struct pim_interface *pim_iif = iif ? iif->info : 0; - struct pim_interface *pim_oif = oif ? oif->info : 0; + struct listnode *node = NULL; + struct static_route *s_route = NULL; + struct static_route *original_s_route = NULL; + struct pim_interface *pim_iif = iif ? iif->info : NULL; + struct pim_interface *pim_oif = oif ? oif->info : NULL; ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; @@ -228,9 +228,9 @@ int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr group, struct in_addr source) { - struct listnode *node = 0; - struct listnode *nextnode = 0; - struct static_route *s_route = 0; + struct listnode *node = NULL; + struct listnode *nextnode = NULL; + struct static_route *s_route = NULL; struct pim_interface *pim_iif = iif ? iif->info : 0; struct pim_interface *pim_oif = oif ? oif->info : 0; ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; diff --git a/pimd/pimd.c b/pimd/pimd.c index 91d8d56afc..4ec9023f0a 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -47,21 +47,21 @@ struct thread_master *master = NULL; uint32_t qpim_debugs = 0; int qpim_mroute_socket_fd = -1; int64_t qpim_mroute_socket_creation = 0; /* timestamp of creation */ -struct thread *qpim_mroute_socket_reader = 0; +struct thread *qpim_mroute_socket_reader = NULL; int qpim_mroute_oif_highest_vif_index = -1; -struct list *qpim_channel_oil_list = 0; +struct list *qpim_channel_oil_list = NULL; int qpim_t_periodic = PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */ -struct list *qpim_upstream_list = 0; -struct zclient *qpim_zclient_update = 0; -struct zclient *qpim_zclient_lookup = 0; +struct list *qpim_upstream_list = NULL; +struct zclient *qpim_zclient_update = NULL; +struct zclient *qpim_zclient_lookup = NULL; struct pim_assert_metric qpim_infinite_assert_metric; long qpim_rpf_cache_refresh_delay_msec = 10000; -struct thread *qpim_rpf_cache_refresher = 0; +struct thread *qpim_rpf_cache_refresher = NULL; int64_t qpim_rpf_cache_refresh_requests = 0; int64_t qpim_rpf_cache_refresh_events = 0; int64_t qpim_rpf_cache_refresh_last = 0; struct in_addr qpim_inaddr_any; -struct list *qpim_ssmpingd_list = 0; +struct list *qpim_ssmpingd_list = NULL; struct in_addr qpim_ssmpingd_group_addr; int64_t qpim_scan_oil_events = 0; int64_t qpim_scan_oil_last = 0; @@ -69,7 +69,7 @@ int64_t qpim_mroute_add_events = 0; int64_t qpim_mroute_add_last = 0; int64_t qpim_mroute_del_events = 0; int64_t qpim_mroute_del_last = 0; -struct list *qpim_static_route_list = 0; +struct list *qpim_static_route_list = NULL; struct pim_rpf qpim_rp = { .rpf_addr.s_addr = INADDR_NONE }; int32_t qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; From d7259eac8b7c5f9f7d0f5f04adf1b2c98dd50fa9 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 17 Jul 2016 19:45:16 -0400 Subject: [PATCH 008/386] pimd: create pim_upstream_state2str Allow update of show command to understant all pim upstream states. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 2 +- pimd/pim_upstream.c | 23 ++++++++++++++++++++++- pimd/pim_upstream.h | 5 ++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index e50837ebed..b595d337e7 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -996,7 +996,7 @@ static void pim_show_upstream(struct vty *vty) up->rpf.source_nexthop.interface->name, src_str, grp_str, - up->join_state == PIM_UPSTREAM_JOINED ? "Jnd" : "NtJnd", + pim_upstream_state2str (up), uptime, join_timer, up->ref_count, diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 8267885756..8f1b019808 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -415,7 +415,7 @@ struct pim_upstream *pim_upstream_find(struct in_addr source_addr, } } - return 0; + return NULL; } struct pim_upstream *pim_upstream_add(struct in_addr source_addr, @@ -784,3 +784,24 @@ pim_upstream_switch_to_spt_desired (struct in_addr source, struct in_addr group) { return 0; } + +const char * +pim_upstream_state2str (struct pim_upstream *up) +{ + switch (up->join_state) + { + case PIM_UPSTREAM_NOTJOINED: + return "NtJnd"; + break; + case PIM_UPSTREAM_JOINED: + return "Jnd"; + break; + case PIM_UPSTREAM_JOIN_PENDING: + return "JPend"; + break; + case PIM_UPSTREAM_PRUNE: + return "Prune"; + break; + } + return "Unkwn"; +} diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 71a4c85f18..1ae3893d47 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -69,7 +69,9 @@ enum pim_rpf_result { enum pim_upstream_state { PIM_UPSTREAM_NOTJOINED, - PIM_UPSTREAM_JOINED + PIM_UPSTREAM_JOINED, + PIM_UPSTREAM_JOIN_PENDING, + PIM_UPSTREAM_PRUNE, }; enum pim_upstream_sptbit { @@ -148,4 +150,5 @@ void pim_upstream_keep_alive_timer_start (struct pim_upstream *up, uint32_t time int pim_upstream_switch_to_spt_desired (struct in_addr source, struct in_addr group); #define SwitchToSptDesired(S,G) pim_upstream_switch_to_spt_desired ((S), (G)) +const char *pim_upstream_state2str (struct pim_upstream *up); #endif /* PIM_UPSTREAM_H */ From 887fa0149fbba33c702c949b9e0072faa53c98fb Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 17 Jul 2016 19:51:56 -0400 Subject: [PATCH 009/386] pimd: Add pim_channel_del_oif For a given interface remove the interface from the list of outgoing interfaces for a mroute and reinstall it into the kernel. Signed-off-by: Donald Sharp --- pimd/pim_oil.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++ pimd/pim_oil.h | 3 ++ 2 files changed, 89 insertions(+) diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 96f9ef2b62..d072c73dd8 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -142,6 +142,92 @@ void pim_channel_oil_del(struct channel_oil *c_oil) } } +int +pim_channel_del_oif (struct channel_oil *channel_oil, + struct interface *oif, + uint32_t proto_mask) +{ + struct pim_interface *pim_ifp; + + zassert (channel_oil); + zassert (oif); + + pim_ifp = oif->info; + + if (PIM_DEBUG_MROUTE) + { + char group_str[100]; + char source_str[100]; + 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: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d", + __FILE__, __PRETTY_FUNCTION__, + source_str, group_str, + proto_mask, oif->name, pim_ifp->mroute_vif_index); + } + + /* + * Don't do anything if we've been asked to remove a source + * that is not actually on it. + */ + if (!(channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask)) + { + if (PIM_DEBUG_MROUTE) + { + char group_str[100]; + char source_str[100]; + 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: no existing protocol mask %u(%u) for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, + proto_mask, channel_oil->oif_flags[pim_ifp->mroute_vif_index], + oif->name, pim_ifp->mroute_vif_index, + channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index], + source_str, group_str); + } + return 0; + } + + channel_oil->oif_flags[pim_ifp->mroute_vif_index] &= ~proto_mask; + + if (channel_oil->oif_flags[pim_ifp->mroute_vif_index]) + { + if (PIM_DEBUG_MROUTE) + { + char group_str[100]; + char source_str[100]; + 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: other protocol masks remain for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, + oif->name, pim_ifp->mroute_vif_index, + channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index], + source_str, group_str); + } + return 0; + } + + channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0; + + if (pim_mroute_add (channel_oil)) { + if (PIM_DEBUG_MROUTE) + { + char group_str[100]; + char source_str[100]; + 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: could not remove output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, + oif->name, pim_ifp->mroute_vif_index, + source_str, group_str); + } + return -1; + } + + return 0; +} + + int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif, uint32_t proto_mask) diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index c63c026c0f..0edb50787e 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -87,5 +87,8 @@ void pim_channel_oil_del(struct channel_oil *c_oil); int pim_channel_add_oif(struct channel_oil *c_oil, struct interface *oif, uint32_t proto_mask); +int pim_channel_del_oif (struct channel_oil *c_oil, + struct interface *oif, + uint32_t proto_mask); #endif /* PIM_OIL_H */ From b100a4f5b943acd92b3166058b0a718afa27280c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 17 Jul 2016 20:18:33 -0400 Subject: [PATCH 010/386] pimd: Add null_register bit to pim_register_send When sending a pim register message to an RP, we need the ability to set the null bit in the message. This adds the ability to do so. Additionally we need to switch the ip_hdr to a const uint8_t *buf because pim_register_send really shouldn't know or care about the fact it's a 'struct ip'. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 2 +- pimd/pim_register.c | 12 ++++++------ pimd/pim_register.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index bf996a738b..83a3b1045d 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -198,7 +198,7 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf, * If we've received a register suppress */ if (!up->t_rs_timer) - pim_register_send((const struct ip *)(buf + sizeof(struct ip)), rpg); + pim_register_send((uint8_t *)buf + sizeof(struct ip), ntohs (ip_hdr->ip_len), rpg, 0); return 0; } diff --git a/pimd/pim_register.c b/pimd/pim_register.c index a3e63f0285..2876dec83f 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -119,13 +119,12 @@ pim_register_stop_recv (void) } void -pim_register_send (const struct ip *ip_hdr, struct pim_rpf *rpg) +pim_register_send (const uint8_t *buf, int buf_size, struct pim_rpf *rpg, int null_register) { unsigned char buffer[3000]; unsigned char *b1; struct pim_interface *pinfo; struct interface *ifp; - uint32_t plen; ifp = rpg->source_nexthop.interface; pinfo = (struct pim_interface *)ifp->info; @@ -135,17 +134,18 @@ pim_register_send (const struct ip *ip_hdr, struct pim_rpf *rpg) } memset(buffer, 0, 3000); + b1 = buffer + PIM_MSG_HEADER_LEN; + *b1 |= null_register << 31; b1 = buffer + PIM_MSG_REGISTER_LEN; - plen = ntohs(ip_hdr->ip_len); - memcpy(b1, (const unsigned char *)ip_hdr, plen); + memcpy(b1, (const unsigned char *)buf, buf_size); - pim_msg_build_header(buffer, plen + PIM_MSG_REGISTER_LEN, PIM_MSG_TYPE_REGISTER); + pim_msg_build_header(buffer, buf_size + PIM_MSG_REGISTER_LEN, PIM_MSG_TYPE_REGISTER); if (pim_msg_send(pinfo->pim_sock_fd, rpg->rpf_addr, buffer, - plen + PIM_MSG_REGISTER_LEN, + buf_size + PIM_MSG_REGISTER_LEN, ifp->name)) { if (PIM_DEBUG_PIM_TRACE) { zlog_debug("%s: could not send PIM register message on interface %s", diff --git a/pimd/pim_register.h b/pimd/pim_register.h index 4749480b9d..3de1557966 100644 --- a/pimd/pim_register.h +++ b/pimd/pim_register.h @@ -41,6 +41,6 @@ int pim_register_recv (struct interface *ifp, struct in_addr src_addr, uint8_t *tlv_buf, int tlv_buf_size); -void pim_register_send (const struct ip *msg, struct pim_rpf *rpg); +void pim_register_send (const uint8_t *buf, int buf_size, struct pim_rpf *rpg, int null_register); #endif From 627ed2a3b7880018f452b3abeb9610793b5c6446 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 18 Jul 2016 09:47:19 -0400 Subject: [PATCH 011/386] pimd: Create register stop timer for DR When a register stop is received, create the register stop timer and associated state machine. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 86 +++++++++++++++++++++++++++++++++++++++++++++ pimd/pim_upstream.h | 2 ++ 2 files changed, 88 insertions(+) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 8f1b019808..066fbc4721 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -46,6 +46,7 @@ #include "pim_macro.h" #include "pim_rp.h" #include "pim_br.h" +#include "pim_register.h" static void join_timer_start(struct pim_upstream *up); static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up); @@ -805,3 +806,88 @@ pim_upstream_state2str (struct pim_upstream *up) } return "Unkwn"; } + +static int +pim_upstream_register_stop_timer (struct thread *t) +{ + struct pim_upstream *up; + struct pim_rpf *rpg; + struct ip ip_hdr; + + up = THREAD_ARG (t); + + up->t_rs_timer = NULL; + + if (PIM_DEBUG_TRACE) + { + char src_str[100]; + char grp_str[100]; + + pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); + pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); + zlog_debug ("%s: (S,G)=(%s,%s) upstream register stop timer %d", + __PRETTY_FUNCTION__, src_str, grp_str, up->join_state); + } + + switch (up->join_state) + { + case PIM_UPSTREAM_JOIN_PENDING: + up->join_state = PIM_UPSTREAM_JOINED; + break; + case PIM_UPSTREAM_PRUNE: + up->join_state = PIM_UPSTREAM_JOIN_PENDING; + pim_upstream_start_register_stop_timer (up, 1); + + rpg = RP (up->group_addr); + memset (&ip_hdr, 0, sizeof (struct ip)); + ip_hdr.ip_p = PIM_IP_PROTO_PIM; + ip_hdr.ip_hl = 5; + ip_hdr.ip_v = 4; + ip_hdr.ip_src = up->source_addr; + ip_hdr.ip_dst = up->group_addr; + ip_hdr.ip_len = 20; + // checksum is broken + pim_register_send ((uint8_t *)&ip_hdr, sizeof (struct ip), rpg, 1); + pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); + break; + default: + break; + } + + return 0; +} + +void +pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_register) +{ + uint32_t time; + + if (up->t_rs_timer) + { + THREAD_TIMER_OFF (up->t_rs_timer); + up->t_rs_timer = NULL; + } + + if (!null_register) + { + uint32_t lower = (0.5 * PIM_REGISTER_SUPPRESSION_PERIOD); + uint32_t upper = (1.5 * PIM_REGISTER_SUPPRESSION_PERIOD); + time = lower + (random () % (upper - lower + 1)) - PIM_REGISTER_PROBE_PERIOD; + } + else + time = PIM_REGISTER_PROBE_PERIOD; + + if (PIM_DEBUG_TRACE) + { + char src_str[100]; + char grp_str[100]; + + pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); + pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); + zlog_debug ("%s: (S,G)=(%s,%s) Starting upstream register stop timer %d", + __PRETTY_FUNCTION__, src_str, grp_str, time); + } + THREAD_TIMER_ON (master, up->t_rs_timer, + pim_upstream_register_stop_timer, + up, time); +} diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 1ae3893d47..222e30b4ba 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -150,5 +150,7 @@ void pim_upstream_keep_alive_timer_start (struct pim_upstream *up, uint32_t time int pim_upstream_switch_to_spt_desired (struct in_addr source, struct in_addr group); #define SwitchToSptDesired(S,G) pim_upstream_switch_to_spt_desired ((S), (G)) +void pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_register); + const char *pim_upstream_state2str (struct pim_upstream *up); #endif /* PIM_UPSTREAM_H */ From 792f4d29adabe9679de8088869d32d623ffadaa5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 18 Jul 2016 09:52:45 -0400 Subject: [PATCH 012/386] pimd: Properly initialize and delete t_rs_timer Ensure that we properly initialize and stop the t_rs_timer. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 066fbc4721..87f6089b28 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -68,6 +68,7 @@ void pim_upstream_delete(struct pim_upstream *up) { THREAD_OFF(up->t_join_timer); THREAD_OFF(up->t_ka_timer); + THREAD_OFF(up->t_rs_timer); upstream_channel_oil_detach(up); @@ -379,6 +380,7 @@ static struct pim_upstream *pim_upstream_new(struct in_addr source_addr, up->ref_count = 1; up->t_join_timer = NULL; up->t_ka_timer = NULL; + up->t_rs_timer = NULL; up->join_state = 0; up->state_transition = pim_time_monotonic_sec(); up->channel_oil = NULL; From 64a70f46c331d05a0e99ffc7f250019f61d68082 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 15 Jul 2016 09:42:57 -0400 Subject: [PATCH 013/386] pimd: Remove unneeded function. Remove the prune_echo function as that it just took some data and passed it into another function. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index a3d827f1e0..a95f48550b 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -391,33 +391,6 @@ static int on_ifjoin_expiry_timer(struct thread *t) return 0; } -static void prune_echo(struct interface *ifp, - struct in_addr source_addr, - struct in_addr group_addr) -{ - struct pim_interface *pim_ifp; - struct in_addr neigh_dst_addr; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - neigh_dst_addr = pim_ifp->primary_address; - - if (PIM_DEBUG_PIM_EVENTS) { - char source_str[100]; - char group_str[100]; - char neigh_dst_str[100]; - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", neigh_dst_addr, neigh_dst_str, sizeof(neigh_dst_str)); - zlog_debug("%s: sending PruneEcho(S,G)=(%s,%s) to upstream=%s on interface %s", - __PRETTY_FUNCTION__, source_str, group_str, neigh_dst_str, ifp->name); - } - - pim_joinprune_send(ifp, neigh_dst_addr, source_addr, group_addr, - 0 /* boolean: send_join=false (prune) */); -} - static int on_ifjoin_prune_pending_timer(struct thread *t) { struct pim_ifchannel *ch; @@ -448,7 +421,8 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) /* from here ch may have been deleted */ if (send_prune_echo) - prune_echo(ifp, ch_source, ch_group); + pim_joinprune_send (ifp, pim_ifp->primary_address, + ch_source, ch_group, 0); return 0; } From 535db05b574cf0f71d94242a3464768cf08daf06 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 15 Jul 2016 11:03:15 -0400 Subject: [PATCH 014/386] pimd: Refactor ifchannel creation. Remove unnecessary function. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 141 +++++++++++++++++++------------------------ 1 file changed, 63 insertions(+), 78 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index a95f48550b..d3855d5d76 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -182,74 +182,6 @@ void reset_ifassert_state(struct pim_ifchannel *ch) qpim_infinite_assert_metric); } -static struct pim_ifchannel *pim_ifchannel_new(struct interface *ifp, - struct in_addr source_addr, - struct in_addr group_addr) -{ - struct pim_ifchannel *ch; - struct pim_interface *pim_ifp; - struct pim_upstream *up; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - up = pim_upstream_add(source_addr, group_addr, NULL); - if (!up) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", group_addr, grp_str, sizeof(grp_str)); - zlog_err("%s: could not attach upstream (S,G)=(%s,%s) on interface %s", - __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); - return NULL; - } - - ch = XMALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch)); - if (!ch) { - zlog_err("%s: PIM XMALLOC(%zu) failure", - __PRETTY_FUNCTION__, sizeof(*ch)); - return NULL; - } - - ch->flags = 0; - ch->upstream = up; - ch->interface = ifp; - ch->source_addr = source_addr; - ch->group_addr = group_addr; - ch->local_ifmembership = PIM_IFMEMBERSHIP_NOINFO; - - ch->ifjoin_state = PIM_IFJOIN_NOINFO; - ch->t_ifjoin_expiry_timer = NULL; - ch->t_ifjoin_prune_pending_timer = NULL; - ch->ifjoin_creation = 0; - - ch->ifassert_my_metric = pim_macro_ch_my_assert_metric_eval(ch); - ch->ifassert_winner_metric = pim_macro_ch_my_assert_metric_eval (ch); - - ch->ifassert_winner.s_addr = 0; - - /* Assert state */ - ch->t_ifassert_timer = NULL; - reset_ifassert_state(ch); - if (pim_macro_ch_could_assert_eval(ch)) - PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); - else - PIM_IF_FLAG_UNSET_COULD_ASSERT(ch->flags); - - if (pim_macro_assert_tracking_desired_eval(ch)) - PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(ch->flags); - else - PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); - - /* Attach to list */ - listnode_add(pim_ifp->pim_ifchannel_list, ch); - - zassert(IFCHANNEL_NOINFO(ch)); - - return ch; -} - struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, struct in_addr source_addr, struct in_addr group_addr) @@ -345,7 +277,9 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, struct in_addr source_addr, struct in_addr group_addr) { + struct pim_interface *pim_ifp; struct pim_ifchannel *ch; + struct pim_upstream *up; char src_str[100]; char grp_str[100]; @@ -353,17 +287,68 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, if (ch) return ch; - ch = pim_ifchannel_new(ifp, source_addr, group_addr); - if (ch) - return ch; - - pim_inet4_dump("", source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", group_addr, grp_str, sizeof(grp_str)); - zlog_warn("%s: pim_ifchannel_new() failure for (S,G)=(%s,%s) on interface %s", - __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); + pim_ifp = ifp->info; + zassert(pim_ifp); - return NULL; + up = pim_upstream_add(source_addr, group_addr, NULL); + if (!up) { + char src_str[100]; + char grp_str[100]; + pim_inet4_dump("", source_addr, src_str, sizeof(src_str)); + pim_inet4_dump("", group_addr, grp_str, sizeof(grp_str)); + zlog_err("%s: could not attach upstream (S,G)=(%s,%s) on interface %s", + __PRETTY_FUNCTION__, + src_str, grp_str, ifp->name); + return NULL; + } + + ch = XMALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch)); + if (!ch) { + pim_inet4_dump("", source_addr, src_str, sizeof(src_str)); + pim_inet4_dump("", group_addr, grp_str, sizeof(grp_str)); + zlog_warn("%s: pim_ifchannel_new() failure for (S,G)=(%s,%s) on interface %s", + __PRETTY_FUNCTION__, + src_str, grp_str, ifp->name); + + return NULL; + } + + ch->flags = 0; + ch->upstream = up; + ch->interface = ifp; + ch->source_addr = source_addr; + ch->group_addr = group_addr; + ch->local_ifmembership = PIM_IFMEMBERSHIP_NOINFO; + + ch->ifjoin_state = PIM_IFJOIN_NOINFO; + ch->t_ifjoin_expiry_timer = NULL; + ch->t_ifjoin_prune_pending_timer = NULL; + ch->ifjoin_creation = 0; + + ch->ifassert_my_metric = pim_macro_ch_my_assert_metric_eval(ch); + ch->ifassert_winner_metric = pim_macro_ch_my_assert_metric_eval (ch); + + ch->ifassert_winner.s_addr = 0; + + /* Assert state */ + ch->t_ifassert_timer = NULL; + reset_ifassert_state(ch); + if (pim_macro_ch_could_assert_eval(ch)) + PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); + else + PIM_IF_FLAG_UNSET_COULD_ASSERT(ch->flags); + + if (pim_macro_assert_tracking_desired_eval(ch)) + PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(ch->flags); + else + PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); + + /* Attach to list */ + listnode_add(pim_ifp->pim_ifchannel_list, ch); + + zassert(IFCHANNEL_NOINFO(ch)); + + return ch; } static void ifjoin_to_noinfo(struct pim_ifchannel *ch) From 566387390f7d9eaf29c7ec103101e3397d8758ac Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 15 Jul 2016 15:42:09 -0400 Subject: [PATCH 015/386] pimd: First Schwag at pim_register_stop Implement the pim_register_stop state machine. There are still a few bugs still but this is enough to get us rolling a bit more. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 4 ++++ pimd/pim_ifchannel.h | 3 ++- pimd/pim_mroute.c | 8 ++++++-- pimd/pim_pim.c | 3 ++- pimd/pim_register.c | 42 +++++++++++++++++++++++++++++++++++------- pimd/pim_register.h | 3 ++- pimd/pim_upstream.c | 39 ++++++++++++++++++++++++--------------- pimd/pim_upstream.h | 3 +++ 8 files changed, 78 insertions(+), 27 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index d3855d5d76..15dd682a50 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -148,6 +148,7 @@ const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state) { switch (ifjoin_state) { case PIM_IFJOIN_NOINFO: return "NOINFO"; + case PIM_IFJOIN_JOIN_PIMREG: return "REGT"; case PIM_IFJOIN_JOIN: return "JOIN"; case PIM_IFJOIN_PRUNE_PENDING: return "PRUNEP"; } @@ -627,6 +628,8 @@ void pim_ifchannel_join_add(struct interface *ifp, THREAD_OFF(ch->t_ifjoin_prune_pending_timer); pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN); break; + case PIM_IFJOIN_JOIN_PIMREG: + zlog_warn("Received Incorrect new state"); } zassert(!IFCHANNEL_NOINFO(ch)); @@ -660,6 +663,7 @@ void pim_ifchannel_prune(struct interface *ifp, switch (ch->ifjoin_state) { case PIM_IFJOIN_NOINFO: case PIM_IFJOIN_PRUNE_PENDING: + case PIM_IFJOIN_JOIN_PIMREG: /* nothing to do */ break; case PIM_IFJOIN_JOIN: diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index e6f1c2947c..5f488ddc0f 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -37,7 +37,8 @@ enum pim_ifmembership { enum pim_ifjoin_state { PIM_IFJOIN_NOINFO, PIM_IFJOIN_JOIN, - PIM_IFJOIN_PRUNE_PENDING + PIM_IFJOIN_PRUNE_PENDING, + PIM_IFJOIN_JOIN_PIMREG, }; enum pim_ifassert_state { diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 83a3b1045d..c13f2cbba4 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -36,6 +36,7 @@ #include "pim_rp.h" #include "pim_oil.h" #include "pim_register.h" +#include "pim_ifchannel.h" /* GLOBAL VARS */ extern struct zebra_privs_t pimd_privs; @@ -93,6 +94,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg const char *src_str, const char *grp_str) { struct pim_interface *pim_ifp = ifp->info; + struct pim_ifchannel *ch; struct pim_upstream *up; struct pim_rpf *rpg; @@ -149,8 +151,10 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg return 0; } up->channel_oil->cc.pktcnt++; - - pim_channel_add_oif(up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_SOURCE); + up->fhr = 1; + ch = pim_ifchannel_add (pim_regiface, msg->im_src, msg->im_dst); + pim_ifchannel_ifjoin_switch (__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN_PIMREG); + up->join_state = PIM_UPSTREAM_JOINED; return 0; } diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 60bba9e9ba..5f5b2dd5ec 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -224,7 +224,8 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) pim_msg_len - PIM_MSG_HEADER_LEN); break; case PIM_MSG_TYPE_REG_STOP: - return pim_register_stop_recv (); + return pim_register_stop_recv (pim_msg + PIM_MSG_HEADER_LEN, + pim_msg_len - PIM_MSG_HEADER_LEN); break; case PIM_MSG_TYPE_JOIN_PRUNE: neigh = pim_neighbor_find(ifp, ip_hdr->ip_src); diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 2876dec83f..c8d0174116 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -112,9 +112,41 @@ pim_register_stop_send (struct interface *ifp, struct in_addr source, } int -pim_register_stop_recv (void) +pim_register_stop_recv (uint8_t *buf, int buf_size) { - zlog_debug ("Received Register Stop"); + struct pim_upstream *upstream = NULL; + struct prefix source; + struct prefix group; + int l; + + if (PIM_DEBUG_PACKETS) + pim_pkt_dump ("Received Register Stop", buf, buf_size); + + l = pim_parse_addr_group (&group, buf, buf_size); + buf += l; + buf_size -= l; + l = pim_parse_addr_ucast (&source, buf, buf_size); + upstream = pim_upstream_find (source.u.prefix4, group.u.prefix4); + if (!upstream) + { + return 0; + } + + switch (upstream->join_state) + { + case PIM_UPSTREAM_NOTJOINED: + case PIM_UPSTREAM_PRUNE: + return 0; + break; + case PIM_UPSTREAM_JOINED: + case PIM_UPSTREAM_JOIN_PENDING: + upstream->join_state = PIM_UPSTREAM_PRUNE; + pim_upstream_start_register_stop_timer (upstream, 0); + pim_channel_del_oif (upstream->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); + return 0; + break; + } + return 0; } @@ -313,11 +345,7 @@ pim_register_recv (struct interface *ifp, upstream->rpf.rpf_addr.s_addr = source.s_addr; upstream->channel_oil->oil.mfcc_origin = source; pim_scan_individual_oil (upstream->channel_oil); - pim_joinprune_send(upstream->rpf.source_nexthop.interface, - upstream->rpf.source_nexthop.mrib_nexthop_addr, - upstream->source_addr, - upstream->group_addr, - 1); + pim_upstream_send_join (upstream); //decapsulate and forward the iner packet to //inherited_olist(S,G,rpt) diff --git a/pimd/pim_register.h b/pimd/pim_register.h index 3de1557966..8ab24b7137 100644 --- a/pimd/pim_register.h +++ b/pimd/pim_register.h @@ -35,7 +35,8 @@ void pim_register_send_test_packet_start (struct in_addr source, struct in_addr group, uint32_t pps); -int pim_register_stop_recv (void); +int pim_register_stop_recv (uint8_t *buf, int buf_size); + int pim_register_recv (struct interface *ifp, struct in_addr dest_addr, struct in_addr src_addr, diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 87f6089b28..4f2c2d0eaa 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -82,25 +82,34 @@ void pim_upstream_delete(struct pim_upstream *up) pim_upstream_free(up); } -static void send_join(struct pim_upstream *up) +void +pim_upstream_send_join (struct pim_upstream *up) { - zassert(up->join_state == PIM_UPSTREAM_JOINED); - - if (PIM_DEBUG_PIM_TRACE) { + char src_str[100]; + char grp_str[100]; + char rpf_str[100]; + pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); + pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); + pim_inet4_dump("", up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); + zlog_debug ("%s: RPF'(%s,%s)=%s(%s) for Interface %s", __PRETTY_FUNCTION__, + src_str, grp_str, rpf_str, pim_upstream_state2str (up), + up->rpf.source_nexthop.interface->name); if (PIM_INADDR_IS_ANY(up->rpf.rpf_addr)) { - char src_str[100]; - char grp_str[100]; - char rpf_str[100]; - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); - pim_inet4_dump("", up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); - zlog_warn("%s: can't send join upstream: RPF'(%s,%s)=%s", - __PRETTY_FUNCTION__, - src_str, grp_str, rpf_str); + zlog_debug("%s: can't send join upstream: RPF'(%s,%s)=%s", + __PRETTY_FUNCTION__, + src_str, grp_str, rpf_str); /* warning only */ } } + + /* + * In the case of a FHR we will not have anyone to send this to. + */ + if (up->fhr) + return; + + zassert(up->join_state == PIM_UPSTREAM_JOINED); /* send Join(S,G) to the current upstream neighbor */ pim_joinprune_send(up->rpf.source_nexthop.interface, @@ -118,7 +127,7 @@ static int on_join_timer(struct thread *t) up = THREAD_ARG(t); zassert(up); - send_join(up); + pim_upstream_send_join (up); up->t_join_timer = NULL; join_timer_start(up); @@ -334,7 +343,7 @@ static void pim_upstream_switch(struct pim_upstream *up, if (new_state == PIM_UPSTREAM_JOINED) { forward_on(up); - send_join(up); + pim_upstream_send_join (up); join_timer_start(up); } else { diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 222e30b4ba..5e7d6114df 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -87,6 +87,7 @@ enum pim_upstream_sptbit { See RFC 4601: 4.5.7. Sending (S,G) Join/Prune Message */ struct pim_upstream { + int fhr; struct in_addr upstream_addr;/* Who we are talking to */ struct in_addr source_addr; /* (S,G) source key */ struct in_addr group_addr; /* (S,G) group key */ @@ -152,5 +153,7 @@ int pim_upstream_switch_to_spt_desired (struct in_addr source, struct in_addr gr void pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_register); +void pim_upstream_send_join (struct pim_upstream *up); + const char *pim_upstream_state2str (struct pim_upstream *up); #endif /* PIM_UPSTREAM_H */ From 0e6ae42582d49e12f0343f43d32d5332396f28ed Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 15 Jul 2016 15:47:13 -0400 Subject: [PATCH 016/386] pimd: Fix PACKETDUMP compile errors. signed-off-by: Donald Sharp --- pimd/pim_register.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index c8d0174116..d6c8fecd9f 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -119,7 +119,7 @@ pim_register_stop_recv (uint8_t *buf, int buf_size) struct prefix group; int l; - if (PIM_DEBUG_PACKETS) + if (PIM_DEBUG_PIM_PACKETDUMP_RECV) pim_pkt_dump ("Received Register Stop", buf, buf_size); l = pim_parse_addr_group (&group, buf, buf_size); From 36d9e7dcea547443ef25e5a8d308691f50099568 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 16 Jul 2016 02:45:33 -0400 Subject: [PATCH 017/386] pimd: Use XCALLOC instead of XMALLOC Ensure that all data structures start out as 0 filled. Signed-off-by: Donald Sharp --- pimd/pim_iface.c | 8 ++++---- pimd/pim_igmp.c | 8 ++++---- pimd/pim_igmpv3.c | 4 ++-- pimd/pim_neighbor.c | 4 ++-- pimd/pim_ssmpingd.c | 4 ++-- pimd/pim_upstream.c | 4 ++-- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 65b51d2b56..584aebb1d4 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -80,9 +80,9 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim) zassert(ifp); zassert(!ifp->info); - pim_ifp = XMALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp)); + pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp)); if (!pim_ifp) { - zlog_err("PIM XMALLOC(%zu) failure", sizeof(*pim_ifp)); + zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_ifp)); return 0; } @@ -997,13 +997,13 @@ static struct igmp_join *igmp_join_new(struct interface *ifp, return 0; } - ij = XMALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij)); + ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij)); if (!ij) { char group_str[100]; char source_str[100]; pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - zlog_err("%s: XMALLOC(%zu) failure for IGMP group %s source %s on interface %s", + zlog_err("%s: XCALLOC(%zu) failure for IGMP group %s source %s on interface %s", __PRETTY_FUNCTION__, sizeof(*ij), group_str, source_str, ifp->name); close(join_fd); diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 189f40ff51..0f141d4fc6 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -1184,9 +1184,9 @@ static struct igmp_sock *igmp_sock_new(int fd, fd, inet_ntoa(ifaddr), ifp->name); } - igmp = XMALLOC(MTYPE_PIM_IGMP_SOCKET, sizeof(*igmp)); + igmp = XCALLOC(MTYPE_PIM_IGMP_SOCKET, sizeof(*igmp)); if (!igmp) { - zlog_warn("%s %s: XMALLOC() failure", + zlog_warn("%s %s: XCALLOC() failure", __FILE__, __PRETTY_FUNCTION__); return 0; } @@ -1392,9 +1392,9 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, of INCLUDE and an empty source list. */ - group = XMALLOC(MTYPE_PIM_IGMP_GROUP, sizeof(*group)); + group = XCALLOC(MTYPE_PIM_IGMP_GROUP, sizeof(*group)); if (!group) { - zlog_warn("%s %s: XMALLOC() failure", + zlog_warn("%s %s: XCALLOC() failure", __FILE__, __PRETTY_FUNCTION__); return 0; /* error, not found, could not create */ } diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index 05d2699ff7..2738a9ca5c 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -495,9 +495,9 @@ source_new (struct igmp_group *group, group->group_igmp_sock->interface->name); } - src = XMALLOC(MTYPE_PIM_IGMP_GROUP_SOURCE, sizeof(*src)); + src = XCALLOC(MTYPE_PIM_IGMP_GROUP_SOURCE, sizeof(*src)); if (!src) { - zlog_warn("%s %s: XMALLOC() failure", + zlog_warn("%s %s: XCALLOC() failure", __FILE__, __PRETTY_FUNCTION__); return 0; /* error, not found, could not create */ } diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index 90fdc35473..749390595a 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -298,9 +298,9 @@ static struct pim_neighbor *pim_neighbor_new(struct interface *ifp, pim_ifp = ifp->info; zassert(pim_ifp); - neigh = XMALLOC(MTYPE_PIM_NEIGHBOR, sizeof(*neigh)); + neigh = XCALLOC(MTYPE_PIM_NEIGHBOR, sizeof(*neigh)); if (!neigh) { - zlog_err("%s: PIM XMALLOC(%zu) failure", + zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, sizeof(*neigh)); return 0; } diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c index 3f494d112d..0bab8b6586 100644 --- a/pimd/pim_ssmpingd.c +++ b/pimd/pim_ssmpingd.c @@ -364,11 +364,11 @@ static struct ssmpingd_sock *ssmpingd_new(struct in_addr source_addr) return 0; } - ss = XMALLOC(MTYPE_PIM_SSMPINGD, sizeof(*ss)); + ss = XCALLOC(MTYPE_PIM_SSMPINGD, sizeof(*ss)); if (!ss) { char source_str[100]; pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - zlog_err("%s: XMALLOC(%zu) failure for ssmpingd source %s", + zlog_err("%s: XCALLOC(%zu) failure for ssmpingd source %s", __PRETTY_FUNCTION__, sizeof(*ss), source_str); close(sock_fd); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 4f2c2d0eaa..3b533d27fe 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -367,9 +367,9 @@ static struct pim_upstream *pim_upstream_new(struct in_addr source_addr, struct pim_upstream *up; enum pim_rpf_result rpf_result; - up = XMALLOC(MTYPE_PIM_UPSTREAM, sizeof(*up)); + up = XCALLOC(MTYPE_PIM_UPSTREAM, sizeof(*up)); if (!up) { - zlog_err("%s: PIM XMALLOC(%zu) failure", + zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, sizeof(*up)); return NULL; } From 7643f0a1c651b84ff26a661cd6b7de806fe7fb3c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 16 Jul 2016 04:49:32 -0400 Subject: [PATCH 018/386] pimd: Refactor pim message type to an enum Change the pim message type to an enum and add the ability to output a string based upon message type. Signed-off-by: Donald Sharp --- pimd/pim_pim.c | 27 +++++++++++++++++++++++---- pimd/pim_pim.h | 20 +++++++++++--------- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 5f5b2dd5ec..b3e4eddc28 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -46,6 +46,25 @@ static int on_pim_hello_send(struct thread *t); static int pim_hello_send(struct interface *ifp, uint16_t holdtime); +static +const char *pim_pim_msgtype2str (enum pim_msg_type type) +{ + switch (type) + { + case PIM_MSG_TYPE_HELLO: return "HELLO"; + case PIM_MSG_TYPE_REGISTER: return "REGISTER"; + case PIM_MSG_TYPE_REG_STOP: return "REGSTOP"; + case PIM_MSG_TYPE_JOIN_PRUNE: return "JP"; + case PIM_MSG_TYPE_BOOTSTRAP: return "BOOT"; + case PIM_MSG_TYPE_ASSERT: return "ASSERT"; + case PIM_MSG_TYPE_GRAFT: return "GRAFT"; + case PIM_MSG_TYPE_GRAFT_ACK: return "GACK"; + case PIM_MSG_TYPE_CANDIDATE: return "CANDIDATE"; + } + + return "UNKNOWN"; +} + static void sock_close(struct interface *ifp) { struct pim_interface *pim_ifp = ifp->info; @@ -121,7 +140,7 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) uint8_t *pim_msg; int pim_msg_len; uint8_t pim_version; - uint8_t pim_type; + enum pim_msg_type pim_type; uint16_t pim_checksum; /* received checksum */ uint16_t checksum; /* computed checksum */ struct pim_neighbor *neigh; @@ -203,9 +222,9 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) } if (PIM_DEBUG_PIM_PACKETS) { - zlog_debug("Recv PIM packet from %s to %s on %s: ttl=%d pim_version=%d pim_type=%d pim_msg_size=%d checksum=%x", - src_str, dst_str, ifp->name, ip_hdr->ip_ttl, - pim_version, pim_type, pim_msg_len, checksum); + zlog_debug("Recv PIM %s packet from %s to %s on %s: ttl=%d pim_version=%d pim_msg_size=%d checksum=%x", + pim_pim_msgtype2str (pim_type), src_str, dst_str, ifp->name, + ip_hdr->ip_ttl, pim_version, pim_msg_len, checksum); } switch (pim_type) diff --git a/pimd/pim_pim.h b/pimd/pim_pim.h index 4b378fb2c3..e3559a2d97 100644 --- a/pimd/pim_pim.h +++ b/pimd/pim_pim.h @@ -40,15 +40,17 @@ #define PIM_DEFAULT_CAN_DISABLE_JOIN_SUPPRESSION (0) /* boolean */ #define PIM_DEFAULT_T_PERIODIC (60) /* RFC 4601: 4.11. Timer Values */ -#define PIM_MSG_TYPE_HELLO (0) -#define PIM_MSG_TYPE_REGISTER (1) -#define PIM_MSG_TYPE_REG_STOP (2) -#define PIM_MSG_TYPE_JOIN_PRUNE (3) -#define PIM_MSG_TYPE_BOOTSTRAP (4) -#define PIM_MSG_TYPE_ASSERT (5) -#define PIM_MSG_TYPE_GRAFT (6) -#define PIM_MSG_TYPE_GRAFT_ACK (7) -#define PIM_MSG_TYPE_CANDIDATE (8) +enum pim_msg_type { + PIM_MSG_TYPE_HELLO = 0, + PIM_MSG_TYPE_REGISTER, + PIM_MSG_TYPE_REG_STOP, + PIM_MSG_TYPE_JOIN_PRUNE, + PIM_MSG_TYPE_BOOTSTRAP, + PIM_MSG_TYPE_ASSERT, + PIM_MSG_TYPE_GRAFT, + PIM_MSG_TYPE_GRAFT_ACK, + PIM_MSG_TYPE_CANDIDATE +}; #define PIM_MSG_HDR_OFFSET_VERSION(pim_msg) (pim_msg) #define PIM_MSG_HDR_OFFSET_TYPE(pim_msg) (pim_msg) From 7f0c1c5fddb665b8c1315908213843cf2da1ae1e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 16 Jul 2016 08:23:22 -0400 Subject: [PATCH 019/386] pimd: change string to JOINPRUNE Change the JP message string to JOINPRUNE. Signed-off-by: Donald Sharp --- pimd/pim_pim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index b3e4eddc28..6b8478424b 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -54,7 +54,7 @@ const char *pim_pim_msgtype2str (enum pim_msg_type type) case PIM_MSG_TYPE_HELLO: return "HELLO"; case PIM_MSG_TYPE_REGISTER: return "REGISTER"; case PIM_MSG_TYPE_REG_STOP: return "REGSTOP"; - case PIM_MSG_TYPE_JOIN_PRUNE: return "JP"; + case PIM_MSG_TYPE_JOIN_PRUNE: return "JOINPRUNE"; case PIM_MSG_TYPE_BOOTSTRAP: return "BOOT"; case PIM_MSG_TYPE_ASSERT: return "ASSERT"; case PIM_MSG_TYPE_GRAFT: return "GRAFT"; From 7fcdfb34acd927d5ea15e871f6627385a3eac5d9 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 16 Jul 2016 08:27:24 -0400 Subject: [PATCH 020/386] pimd: Make pim_upstream_switch non static Allow pim_upstream_switch to be called from outside of pim_upstream.c Also change the assert to an if test to just correctly stop the timer. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 11 +++++------ pimd/pim_upstream.h | 2 ++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 3b533d27fe..a2f34d24e9 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -318,8 +318,9 @@ static void forward_off(struct pim_upstream *up) } /* scan iflist */ } -static void pim_upstream_switch(struct pim_upstream *up, - enum pim_upstream_state new_state) +void +pim_upstream_switch(struct pim_upstream *up, + enum pim_upstream_state new_state) { enum pim_upstream_state old_state = up->join_state; @@ -353,13 +354,11 @@ static void pim_upstream_switch(struct pim_upstream *up, up->source_addr, up->group_addr, 0 /* prune */); - zassert(up->t_join_timer); - THREAD_OFF(up->t_join_timer); + if (up->t_join_timer) + THREAD_OFF(up->t_join_timer); } - } - static struct pim_upstream *pim_upstream_new(struct in_addr source_addr, struct in_addr group_addr, struct interface *incoming) diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 5e7d6114df..78206e8db7 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -155,5 +155,7 @@ void pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_r void pim_upstream_send_join (struct pim_upstream *up); +void pim_upstream_switch (struct pim_upstream *up, enum pim_upstream_state new_state); + const char *pim_upstream_state2str (struct pim_upstream *up); #endif /* PIM_UPSTREAM_H */ From 5e08fee1e1da3fb6f3e56af12ffdf16400bfa49b Mon Sep 17 00:00:00 2001 From: vivek Date: Thu, 21 Jul 2016 08:50:17 -0700 Subject: [PATCH 021/386] zebra: API to locate client structure based on protocol Signed-off-by: Vivek Venkatraman Reviewed-by: Donald Sharp Ticket: Reviewed By: CCR-4968 Testing Done: Tested with subsequent patch(es) --- zebra/zserv.c | 15 +++++++++++++++ zebra/zserv.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/zebra/zserv.c b/zebra/zserv.c index b7e45d8df1..a92efa027f 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -2371,6 +2371,21 @@ zebra_show_client_brief (struct vty *vty, struct zserv *client) } +struct zserv * +zebra_find_client (u_char proto) +{ + struct listnode *node, *nnode; + struct zserv *client; + + for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) + { + if (client->proto == proto) + return client; + } + + return NULL; +} + /* Display default rtm_table for all clients. */ DEFUN (show_table, diff --git a/zebra/zserv.h b/zebra/zserv.h index a0434d299b..d17a28eb6a 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -176,4 +176,6 @@ extern void zserv_create_header(struct stream *s, uint16_t cmd, vrf_id_t vrf_id) extern void zserv_nexthop_num_warn(const char *, const struct prefix *, const unsigned int); extern int zebra_server_send_message(struct zserv *client); +extern struct zserv *zebra_find_client (u_char proto); + #endif /* _ZEBRA_ZEBRA_H */ From 9fd309db2d88eeba9d2828fb5fe47516f51cbec1 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 22 Jul 2016 09:26:30 -0400 Subject: [PATCH 022/386] pimd: Start switchover to using a PRUNE (S,G) for uninteresting streams When we receive a register for a (S,G) that we have no interest in prune it off and send the register stop. Signed-off-by: Donald Sharp --- pimd/pim_register.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index d6c8fecd9f..8c9e6c7810 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -313,6 +313,12 @@ pim_register_recv (struct interface *ifp, * If we don't have a place to send ignore the packet */ if (!upstream) + { + upstream = pim_upstream_add (source, group, ifp); + pim_upstream_switch (upstream, PIM_UPSTREAM_PRUNE); + } + + if (upstream->join_state == PIM_UPSTREAM_PRUNE) { pim_register_stop_send (ifp, source, group, src_addr); return 1; From f6a1dc2ca74705ccf9fc68784ab4a1b39835cf9c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 22 Jul 2016 10:19:32 -0400 Subject: [PATCH 023/386] pimd: Fix join in register to use correct nexthop pim was sending the join from the RP towards the FHR with a address that was the source instead of the nexthop. This join was treated as a non-local and nothing was done with it. Ticket: CM-11945 Signed-off-by: Donald Sharp --- pimd/pim_register.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 8c9e6c7810..bb05ba1c68 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -348,7 +348,7 @@ pim_register_recv (struct interface *ifp, upstream->upstream_addr, NULL); upstream->rpf.source_nexthop.interface = ifp; upstream->source_addr.s_addr = source.s_addr; - upstream->rpf.rpf_addr.s_addr = source.s_addr; + upstream->rpf.rpf_addr = upstream->rpf.source_nexthop.mrib_nexthop_addr; upstream->channel_oil->oil.mfcc_origin = source; pim_scan_individual_oil (upstream->channel_oil); pim_upstream_send_join (upstream); From e945ee80d35e4cce29ec87c1717db0597f8e6af4 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 22 Jul 2016 05:58:08 -0400 Subject: [PATCH 024/386] lib: Setup prefix.h to allow it to store (s,g) We need the ability to store the (s,g) in a struct prefix. This will allow us to consolidate some duplicated code in pimd as well as set us up to switch from a link list to a table to store (s,g) state. Signed-off-by: Donald Sharp --- lib/prefix.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/prefix.h b/lib/prefix.h index 85488ccea7..4878fcfdd2 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -83,6 +83,11 @@ struct prefix struct in_addr adv_router; } lp; struct ethaddr prefix_eth; /* AF_ETHERNET */ + struct + { + struct in_addr src; + struct in_addr grp; + } sg; u_char val[8]; uintptr_t ptr; } u __attribute__ ((aligned (8))); From 99064df9e385acc466ea8b4ee9f53709d0df9b55 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 22 Jul 2016 08:01:43 -0400 Subject: [PATCH 025/386] pimd: Convert ifchannel to using a prefix to store (s,g) Convert ifchannel to use a prefix to store (s,g) information. Additionally create pim_str_sg_dump function to output data when using debugs. Signed-off-by: Donald Sharp --- pimd/pim_assert.c | 113 ++++++++++++------------------------------- pimd/pim_cmd.c | 24 ++++----- pimd/pim_ifchannel.c | 32 ++++++------ pimd/pim_ifchannel.h | 4 +- pimd/pim_macro.c | 48 +++++------------- pimd/pim_str.c | 13 +++++ pimd/pim_str.h | 3 ++ pimd/pim_zebra.c | 12 ++--- 8 files changed, 96 insertions(+), 153 deletions(-) diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index 590a7e1da5..63f4e33868 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -56,31 +56,23 @@ void pim_ifassert_winner_set(struct pim_ifchannel *ch, if (PIM_DEBUG_PIM_EVENTS) { if (ch->ifassert_state != new_state) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); - zlog_debug("%s: (S,G)=(%s,%s) assert state changed from %s to %s on interface %s", - __PRETTY_FUNCTION__, - src_str, grp_str, - pim_ifchannel_ifassert_name(ch->ifassert_state), - pim_ifchannel_ifassert_name(new_state), - ch->interface->name); + zlog_debug("%s: (S,G)=%s assert state changed from %s to %s on interface %s", + __PRETTY_FUNCTION__, + pim_str_sg_dump (&ch->sg), + pim_ifchannel_ifassert_name(ch->ifassert_state), + pim_ifchannel_ifassert_name(new_state), + ch->interface->name); } if (winner_changed) { - char src_str[100]; - char grp_str[100]; char was_str[100]; char winner_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); pim_inet4_dump("", ch->ifassert_winner, was_str, sizeof(was_str)); pim_inet4_dump("", winner, winner_str, sizeof(winner_str)); - zlog_debug("%s: (S,G)=(%s,%s) assert winner changed from %s to %s on interface %s", - __PRETTY_FUNCTION__, - src_str, grp_str, - was_str, winner_str, ch->interface->name); + zlog_debug("%s: (S,G)=%s assert winner changed from %s to %s on interface %s", + __PRETTY_FUNCTION__, + pim_str_sg_dump (&ch->sg), + was_str, winner_str, ch->interface->name); } } /* PIM_DEBUG_PIM_EVENTS */ @@ -140,13 +132,9 @@ static void if_could_assert_do_a1(const char *caller, { if (PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { if (assert_action_a1(ch)) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); - zlog_warn("%s: %s: (S,G)=(%s,%s) assert_action_a1 failure on interface %s", + zlog_warn("%s: %s: (S,G)=%s assert_action_a1 failure on interface %s", __PRETTY_FUNCTION__, caller, - src_str, grp_str, ch->interface->name); + pim_str_sg_dump (&ch->sg), ch->interface->name); /* log warning only */ } } @@ -460,7 +448,7 @@ static int pim_assert_do(struct pim_ifchannel *ch, } pim_msg_size = pim_assert_build_msg(pim_msg, sizeof(pim_msg), ifp, - ch->group_addr, ch->source_addr, + ch->sg.u.sg.grp, ch->sg.u.sg.src, metric.metric_preference, metric.route_metric, metric.rpt_bit_flag); @@ -482,13 +470,9 @@ static int pim_assert_do(struct pim_ifchannel *ch, pim_hello_require(ifp); if (PIM_DEBUG_PIM_TRACE) { - char source_str[100]; - char group_str[100]; - pim_inet4_dump("", ch->source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("", ch->group_addr, group_str, sizeof(group_str)); - zlog_debug("%s: to %s: (S,G)=(%s,%s) pref=%u metric=%u rpt_bit=%u", + zlog_debug("%s: to %s: (S,G)=%s pref=%u metric=%u rpt_bit=%u", __PRETTY_FUNCTION__, - ifp->name, source_str, group_str, + ifp->name, pim_str_sg_dump (&ch->sg), metric.metric_preference, metric.route_metric, PIM_FORCE_BOOLEAN(metric.rpt_bit_flag)); @@ -525,7 +509,7 @@ static int pim_assert_cancel(struct pim_ifchannel *ch) metric.rpt_bit_flag = 0; metric.metric_preference = PIM_ASSERT_METRIC_PREFERENCE_MAX; metric.route_metric = PIM_ASSERT_ROUTE_METRIC_MAX; - metric.ip_address = ch->source_addr; + metric.ip_address = ch->sg.u.sg.src; return pim_assert_do(ch, metric); } @@ -543,13 +527,9 @@ static int on_assert_timer(struct thread *t) zassert(ifp); if (PIM_DEBUG_PIM_TRACE) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); - zlog_debug("%s: (S,G)=(%s,%s) timer expired on interface %s", + zlog_debug("%s: (S,G)=%s timer expired on interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); + pim_str_sg_dump (&ch->sg), ifp->name); } ch->t_ifassert_timer = NULL; @@ -564,13 +544,9 @@ static int on_assert_timer(struct thread *t) break; default: { - char source_str[100]; - char group_str[100]; - pim_inet4_dump("", ch->source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("", ch->group_addr, group_str, sizeof(group_str)); - zlog_warn("%s: (S,G)=(%s,%s) invalid assert state %d on interface %s", + zlog_warn("%s: (S,G)=%s invalid assert state %d on interface %s", __PRETTY_FUNCTION__, - source_str, group_str, ch->ifassert_state, ifp->name); + pim_str_sg_dump (&ch->sg), ch->ifassert_state, ifp->name); } } @@ -587,13 +563,9 @@ static void assert_timer_off(struct pim_ifchannel *ch) if (PIM_DEBUG_PIM_TRACE) { if (ch->t_ifassert_timer) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); - zlog_debug("%s: (S,G)=(%s,%s) cancelling timer on interface %s", + zlog_debug("%s: (S,G)=%s cancelling timer on interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); + pim_str_sg_dump (&ch->sg), ifp->name); } } THREAD_OFF(ch->t_ifassert_timer); @@ -612,13 +584,9 @@ static void pim_assert_timer_set(struct pim_ifchannel *ch, assert_timer_off(ch); if (PIM_DEBUG_PIM_TRACE) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); - zlog_debug("%s: (S,G)=(%s,%s) starting %u sec timer on interface %s", + zlog_debug("%s: (S,G)=%s starting %u sec timer on interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, interval, ifp->name); + pim_str_sg_dump(&ch->sg), interval, ifp->name); } THREAD_TIMER_ON(master, ch->t_ifassert_timer, @@ -650,13 +618,9 @@ int assert_action_a1(struct pim_ifchannel *ch) pim_ifp = ifp->info; if (!pim_ifp) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); - zlog_warn("%s: (S,G)=(%s,%s) multicast not enabled on interface %s", + zlog_warn("%s: (S,G)=%s multicast not enabled on interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); + pim_str_sg_dump (&ch->sg), ifp->name); return -1; /* must return since pim_ifp is used below */ } @@ -668,13 +632,9 @@ int assert_action_a1(struct pim_ifchannel *ch) zassert(ch->ifassert_state == PIM_IFASSERT_I_AM_WINNER); /* a3 requirement */ if (assert_action_a3(ch)) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); - zlog_warn("%s: (S,G)=(%s,%s) assert_action_a3 failure on interface %s", + zlog_warn("%s: (S,G)=%s assert_action_a3 failure on interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); + pim_str_sg_dump (&ch->sg), ifp->name); /* warning only */ } @@ -719,14 +679,9 @@ static int assert_action_a3(struct pim_ifchannel *ch) pim_assert_timer_reset(ch); if (pim_assert_send(ch)) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); - - zlog_warn("%s: (S,G)=(%s,%s) failure sending assert on interface %s", + zlog_warn("%s: (S,G)=%s failure sending assert on interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, ch->interface->name); + pim_str_sg_dump (&ch->sg), ch->interface->name); return -1; } @@ -748,13 +703,9 @@ static int assert_action_a3(struct pim_ifchannel *ch) void assert_action_a4(struct pim_ifchannel *ch) { if (pim_assert_cancel(ch)) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); - zlog_warn("%s: failure sending AssertCancel(%s,%s) on interface %s", + zlog_warn("%s: failure sending AssertCancel%s on interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, ch->interface->name); + pim_str_sg_dump (&ch->sg), ch->interface->name); /* log warning only */ } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index b595d337e7..726a033343 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -178,9 +178,9 @@ static void pim_show_assert(struct vty *vty) char uptime[10]; char timer[10]; - pim_inet4_dump("", ch->source_addr, + pim_inet4_dump("", ch->sg.u.sg.src, ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->group_addr, + pim_inet4_dump("", ch->sg.u.sg.grp, ch_grp_str, sizeof(ch_grp_str)); pim_inet4_dump("", ch->ifassert_winner, winner_str, sizeof(winner_str)); @@ -236,9 +236,9 @@ static void pim_show_assert_internal(struct vty *vty) char ch_src_str[100]; char ch_grp_str[100]; - pim_inet4_dump("", ch->source_addr, + pim_inet4_dump("", ch->sg.u.sg.src, ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->group_addr, + pim_inet4_dump("", ch->sg.u.sg.grp, ch_grp_str, sizeof(ch_grp_str)); vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s%s", ifp->name, @@ -284,9 +284,9 @@ static void pim_show_assert_metric(struct vty *vty) am = pim_macro_spt_assert_metric(&ch->upstream->rpf, pim_ifp->primary_address); - pim_inet4_dump("", ch->source_addr, + pim_inet4_dump("", ch->sg.u.sg.src, ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->group_addr, + pim_inet4_dump("", ch->sg.u.sg.grp, ch_grp_str, sizeof(ch_grp_str)); pim_inet4_dump("", am.ip_address, addr_str, sizeof(addr_str)); @@ -337,9 +337,9 @@ static void pim_show_assert_winner_metric(struct vty *vty) am = &ch->ifassert_winner_metric; - pim_inet4_dump("", ch->source_addr, + pim_inet4_dump("", ch->sg.u.sg.src, ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->group_addr, + pim_inet4_dump("", ch->sg.u.sg.grp, ch_grp_str, sizeof(ch_grp_str)); pim_inet4_dump("", am->ip_address, addr_str, sizeof(addr_str)); @@ -394,9 +394,9 @@ static void pim_show_membership(struct vty *vty) char ch_src_str[100]; char ch_grp_str[100]; - pim_inet4_dump("", ch->source_addr, + pim_inet4_dump("", ch->sg.u.sg.src, ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->group_addr, + pim_inet4_dump("", ch->sg.u.sg.grp, ch_grp_str, sizeof(ch_grp_str)); vty_out(vty, "%-9s %-15s %-15s %-15s %-10s%s", @@ -727,9 +727,9 @@ static void pim_show_join(struct vty *vty) char expire[10]; char prune[10]; - pim_inet4_dump("", ch->source_addr, + pim_inet4_dump("", ch->sg.u.sg.src, ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->group_addr, + pim_inet4_dump("", ch->sg.u.sg.grp, ch_grp_str, sizeof(ch_grp_str)); pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation); diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 15dd682a50..2c34f1b72f 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -126,8 +126,8 @@ void pim_ifchannel_ifjoin_switch(const char *caller, if (PIM_DEBUG_PIM_EVENTS) { char src_str[100]; char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); + pim_inet4_dump("", ch->sg.u.sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", ch->sg.u.sg.grp, grp_str, sizeof(grp_str)); zlog_debug("PIM_IFCHANNEL_%s: (S,G)=(%s,%s) on interface %s", ((new_state == PIM_IFJOIN_NOINFO) ? "DOWN" : "UP"), src_str, grp_str, ch->interface->name); @@ -209,8 +209,8 @@ struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { if ( - (source_addr.s_addr == ch->source_addr.s_addr) && - (group_addr.s_addr == ch->group_addr.s_addr) + (source_addr.s_addr == ch->sg.u.sg.src.s_addr) && + (group_addr.s_addr == ch->sg.u.sg.grp.s_addr) ) { return ch; } @@ -228,8 +228,8 @@ static void ifmembership_set(struct pim_ifchannel *ch, if (PIM_DEBUG_PIM_EVENTS) { char src_str[100]; char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); + pim_inet4_dump("", ch->sg.u.sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", ch->sg.u.sg.grp, grp_str, sizeof(grp_str)); zlog_debug("%s: (S,G)=(%s,%s) membership now is %s on interface %s", __PRETTY_FUNCTION__, src_str, grp_str, @@ -317,8 +317,8 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, ch->flags = 0; ch->upstream = up; ch->interface = ifp; - ch->source_addr = source_addr; - ch->group_addr = group_addr; + ch->sg.u.sg.src = source_addr; + ch->sg.u.sg.grp = group_addr; ch->local_ifmembership = PIM_IFMEMBERSHIP_NOINFO; ch->ifjoin_state = PIM_IFJOIN_NOINFO; @@ -400,8 +400,8 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1); /* Save (S,G) */ - ch_source = ch->source_addr; - ch_group = ch->group_addr; + ch_source = ch->sg.u.sg.src; + ch_group = ch->sg.u.sg.grp; ifjoin_to_noinfo(ch); /* from here ch may have been deleted */ @@ -759,8 +759,8 @@ void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch) if (PIM_DEBUG_PIM_EVENTS) { char src_str[100]; char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); + pim_inet4_dump("", ch->sg.u.sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", ch->sg.u.sg.grp, grp_str, sizeof(grp_str)); zlog_debug("%s: CouldAssert(%s,%s,%s) changed from %d to %d", __PRETTY_FUNCTION__, src_str, grp_str, ch->interface->name, @@ -803,8 +803,8 @@ void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch) char grp_str[100]; char old_addr_str[100]; char new_addr_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); + pim_inet4_dump("", ch->sg.u.sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", ch->sg.u.sg.grp, grp_str, sizeof(grp_str)); pim_inet4_dump("", ch->ifassert_my_metric.ip_address, old_addr_str, sizeof(old_addr_str)); pim_inet4_dump("", my_metric_new.ip_address, new_addr_str, sizeof(new_addr_str)); zlog_debug("%s: my_assert_metric(%s,%s,%s) changed from %u,%u,%u,%s to %u,%u,%u,%s", @@ -839,8 +839,8 @@ void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch) if (PIM_DEBUG_PIM_EVENTS) { char src_str[100]; char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); + pim_inet4_dump("", ch->sg.u.sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", ch->sg.u.sg.grp, grp_str, sizeof(grp_str)); zlog_debug("%s: AssertTrackingDesired(%s,%s,%s) changed from %d to %d", __PRETTY_FUNCTION__, src_str, grp_str, ch->interface->name, diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 5f488ddc0f..747ee39bf2 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -26,6 +26,7 @@ #include #include "if.h" +#include "prefix.h" #include "pim_upstream.h" @@ -73,8 +74,7 @@ struct pim_assert_metric { Per-interface (S,G) state */ struct pim_ifchannel { - struct in_addr source_addr; /* (S,G) source key */ - struct in_addr group_addr; /* (S,G) group key */ + struct prefix sg; struct interface *interface; /* backpointer to interface */ uint32_t flags; diff --git a/pimd/pim_macro.c b/pimd/pim_macro.c index 39098df526..ea9fc3b063 100644 --- a/pimd/pim_macro.c +++ b/pimd/pim_macro.c @@ -102,13 +102,9 @@ int pim_macro_ch_lost_assert(const struct pim_ifchannel *ch) ifp = ch->interface; if (!ifp) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); - zlog_warn("%s: (S,G)=(%s,%s): null interface", + zlog_warn("%s: (S,G)=%s: null interface", __PRETTY_FUNCTION__, - src_str, grp_str); + pim_str_sg_dump (&ch->sg)); return 0; /* false */ } @@ -118,13 +114,9 @@ int pim_macro_ch_lost_assert(const struct pim_ifchannel *ch) pim_ifp = ifp->info; if (!pim_ifp) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); - zlog_warn("%s: (S,G)=(%s,%s): multicast not enabled on interface %s", + zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); + pim_str_sg_dump (&ch->sg), ifp->name); return 0; /* false */ } @@ -159,13 +151,9 @@ int pim_macro_chisin_pim_include(const struct pim_ifchannel *ch) struct pim_interface *pim_ifp = ch->interface->info; if (!pim_ifp) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); - zlog_warn("%s: (S,G)=(%s,%s): multicast not enabled on interface %s", + zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, ch->interface->name); + pim_str_sg_dump (&ch->sg), ch->interface->name); return 0; /* false */ } @@ -227,13 +215,9 @@ int pim_macro_ch_could_assert_eval(const struct pim_ifchannel *ch) ifp = ch->interface; if (!ifp) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); - zlog_warn("%s: (S,G)=(%s,%s): null interface", + zlog_warn("%s: (S,G)=%s: null interface", __PRETTY_FUNCTION__, - src_str, grp_str); + pim_str_sg_dump (&ch->sg)); return 0; /* false */ } @@ -388,25 +372,17 @@ int pim_macro_assert_tracking_desired_eval(const struct pim_ifchannel *ch) ifp = ch->interface; if (!ifp) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); - zlog_warn("%s: (S,G)=(%s,%s): null interface", + zlog_warn("%s: (S,G)=%s: null interface", __PRETTY_FUNCTION__, - src_str, grp_str); + pim_str_sg_dump (&ch->sg)); return 0; /* false */ } pim_ifp = ifp->info; if (!pim_ifp) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", ch->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->group_addr, grp_str, sizeof(grp_str)); - zlog_warn("%s: (S,G)=(%s,%s): multicast not enabled on interface %s", + zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, ch->interface->name); + pim_str_sg_dump (&ch->sg), ch->interface->name); return 0; /* false */ } diff --git a/pimd/pim_str.c b/pimd/pim_str.c index ee9c74fa36..2d647876f6 100644 --- a/pimd/pim_str.c +++ b/pimd/pim_str.c @@ -43,3 +43,16 @@ void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, int buf_ errno = save_errno; } + +char * +pim_str_sg_dump (const struct prefix *sg) +{ + char src_str[100]; + char grp_str[100]; + static char sg_str[200]; + + pim_inet4_dump ("", sg->u.sg.src, src_str, sizeof(src_str)); + pim_inet4_dump ("", sg->u.sg.grp, grp_str, sizeof(grp_str)); + snprintf (sg_str, 200, "(%s,%s)", src_str, grp_str); + return sg_str; +} diff --git a/pimd/pim_str.h b/pimd/pim_str.h index 925f17f732..ea84362699 100644 --- a/pimd/pim_str.h +++ b/pimd/pim_str.h @@ -27,6 +27,9 @@ #include #include +#include + void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, int buf_size); +char *pim_str_sg_dump (const struct prefix *sg); #endif diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 1822de2299..bda5dd6845 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -1130,8 +1130,8 @@ void pim_forward_start(struct pim_ifchannel *ch) char group_str[100]; char upstream_str[100]; - pim_inet4_dump("", ch->source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("", ch->group_addr, group_str, sizeof(group_str)); + pim_inet4_dump("", ch->sg.u.sg.src, source_str, sizeof(source_str)); + pim_inet4_dump("", ch->sg.u.sg.grp, group_str, sizeof(group_str)); pim_inet4_dump("", up->upstream_addr, upstream_str, sizeof(upstream_str)); zlog_debug("%s: (S,G)=(%s,%s) oif=%s(%s)", __PRETTY_FUNCTION__, @@ -1175,8 +1175,8 @@ void pim_forward_stop(struct pim_ifchannel *ch) if (PIM_DEBUG_PIM_TRACE) { char source_str[100]; char group_str[100]; - pim_inet4_dump("", ch->source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("", ch->group_addr, group_str, sizeof(group_str)); + pim_inet4_dump("", ch->sg.u.sg.src, source_str, sizeof(source_str)); + pim_inet4_dump("", ch->sg.u.sg.grp, group_str, sizeof(group_str)); zlog_debug("%s: (S,G)=(%s,%s) oif=%s", __PRETTY_FUNCTION__, source_str, group_str, ch->interface->name); @@ -1185,8 +1185,8 @@ void pim_forward_stop(struct pim_ifchannel *ch) if (!up->channel_oil) { char source_str[100]; char group_str[100]; - pim_inet4_dump("", ch->source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("", ch->group_addr, group_str, sizeof(group_str)); + pim_inet4_dump("", ch->sg.u.sg.src, source_str, sizeof(source_str)); + pim_inet4_dump("", ch->sg.u.sg.grp, group_str, sizeof(group_str)); zlog_warn("%s: (S,G)=(%s,%s) oif=%s missing channel OIL", __PRETTY_FUNCTION__, source_str, group_str, ch->interface->name); From 05e451f828dce67a38ffb234258cfb10660619d7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 22 Jul 2016 08:57:20 -0400 Subject: [PATCH 026/386] pimd: Refactor s,g information to struct prefix in pim_upstream.h This change allows us to pass the (s,g) state around as a prefix. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 16 +++--- pimd/pim_ifchannel.c | 8 ++- pimd/pim_join.c | 27 ++++------ pimd/pim_join.h | 3 +- pimd/pim_mroute.c | 6 ++- pimd/pim_oil.c | 34 +++++------- pimd/pim_oil.h | 3 +- pimd/pim_register.c | 2 +- pimd/pim_rpf.c | 34 ++++-------- pimd/pim_upstream.c | 120 +++++++++++++------------------------------ pimd/pim_upstream.h | 6 ++- pimd/pim_zebra.c | 67 ++++++++---------------- 12 files changed, 111 insertions(+), 215 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 726a033343..e8323ff08a 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -987,8 +987,8 @@ static void pim_show_upstream(struct vty *vty) char uptime[10]; char join_timer[10]; - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); + pim_inet4_dump("", up->sg.u.sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", up->sg.u.sg.grp, grp_str, sizeof(grp_str)); pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer), up->t_join_timer); @@ -1028,8 +1028,8 @@ static void pim_show_join_desired(struct vty *vty) for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, chnode, ch)) { struct pim_upstream *up = ch->upstream; - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); + pim_inet4_dump("", up->sg.u.sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", up->sg.u.sg.grp, grp_str, sizeof(grp_str)); vty_out(vty, "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s%s", ifp->name, @@ -1064,8 +1064,8 @@ static void pim_show_upstream_rpf(struct vty *vty) rpf = &up->rpf; - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); + pim_inet4_dump("", up->sg.u.sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", up->sg.u.sg.grp, grp_str, sizeof(grp_str)); pim_inet4_dump("", rpf->source_nexthop.mrib_nexthop_addr, rpf_nexthop_str, sizeof(rpf_nexthop_str)); pim_inet4_dump("", rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); @@ -1141,8 +1141,8 @@ static void pim_show_rpf(struct vty *vty) const char *rpf_ifname; struct pim_rpf *rpf = &up->rpf; - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); + pim_inet4_dump("", up->sg.u.sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", up->sg.u.sg.grp, grp_str, sizeof(grp_str)); pim_inet4_dump("", rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); pim_inet4_dump("", rpf->source_nexthop.mrib_nexthop_addr, rib_nexthop_str, sizeof(rib_nexthop_str)); diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 2c34f1b72f..cf2cc99f58 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -383,8 +383,7 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) int send_prune_echo; /* boolean */ struct interface *ifp; struct pim_interface *pim_ifp; - struct in_addr ch_source; - struct in_addr ch_group; + struct prefix sg; zassert(t); ch = THREAD_ARG(t); @@ -400,15 +399,14 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1); /* Save (S,G) */ - ch_source = ch->sg.u.sg.src; - ch_group = ch->sg.u.sg.grp; + sg = ch->sg; ifjoin_to_noinfo(ch); /* from here ch may have been deleted */ if (send_prune_echo) pim_joinprune_send (ifp, pim_ifp->primary_address, - ch_source, ch_group, 0); + &sg, 0); return 0; } diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 3852b423f0..75f484e577 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -272,8 +272,7 @@ int pim_joinprune_recv(struct interface *ifp, int pim_joinprune_send(struct interface *ifp, struct in_addr upstream_addr, - struct in_addr source_addr, - struct in_addr group_addr, + struct prefix *sg, int send_join) { struct pim_interface *pim_ifp; @@ -295,30 +294,22 @@ int pim_joinprune_send(struct interface *ifp, } if (PIM_DEBUG_PIM_TRACE) { - char source_str[100]; - char group_str[100]; char dst_str[100]; - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", upstream_addr, dst_str, sizeof(dst_str)); - zlog_debug("%s: sending %s(S,G)=(%s,%s) to upstream=%s on interface %s", + zlog_debug("%s: sending %s(S,G)=%s to upstream=%s on interface %s", __PRETTY_FUNCTION__, send_join ? "Join" : "Prune", - source_str, group_str, dst_str, ifp->name); + pim_str_sg_dump (sg), dst_str, ifp->name); } if (PIM_INADDR_IS_ANY(upstream_addr)) { if (PIM_DEBUG_PIM_TRACE) { - char source_str[100]; - char group_str[100]; char dst_str[100]; - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", upstream_addr, dst_str, sizeof(dst_str)); - zlog_debug("%s: %s(S,G)=(%s,%s): upstream=%s is myself on interface %s", + zlog_debug("%s: %s(S,G)=%s: upstream=%s is myself on interface %s", __PRETTY_FUNCTION__, send_join ? "Join" : "Prune", - source_str, group_str, dst_str, ifp->name); + pim_str_sg_dump (sg), dst_str, ifp->name); } return 0; } @@ -368,10 +359,10 @@ int pim_joinprune_send(struct interface *ifp, remain = pastend - pim_msg_curr; pim_msg_curr = pim_msg_addr_encode_ipv4_group(pim_msg_curr, remain, - group_addr); + sg->u.sg.grp); if (!pim_msg_curr) { char group_str[100]; - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); + pim_inet4_dump("", sg->u.sg.grp, group_str, sizeof(group_str)); zlog_warn("%s: failure encoding group address %s: space left=%d", __PRETTY_FUNCTION__, group_str, remain); return -5; @@ -397,10 +388,10 @@ int pim_joinprune_send(struct interface *ifp, remain = pastend - pim_msg_curr; pim_msg_curr = pim_msg_addr_encode_ipv4_source(pim_msg_curr, remain, - source_addr); + sg->u.sg.src); if (!pim_msg_curr) { char source_str[100]; - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); + pim_inet4_dump("", sg->u.sg.src, source_str, sizeof(source_str)); zlog_warn("%s: failure encoding source address %s: space left=%d", __PRETTY_FUNCTION__, source_str, remain); return -7; diff --git a/pimd/pim_join.h b/pimd/pim_join.h index 37ec0f4525..994b0e47e3 100644 --- a/pimd/pim_join.h +++ b/pimd/pim_join.h @@ -36,8 +36,7 @@ int pim_joinprune_recv(struct interface *ifp, int pim_joinprune_send(struct interface *ifp, struct in_addr upstream_addr, - struct in_addr source_addr, - struct in_addr group_addr, + struct prefix *sg, int send_join); #endif /* PIM_JOIN_H */ diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index c13f2cbba4..aeb49f770c 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -97,6 +97,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg struct pim_ifchannel *ch; struct pim_upstream *up; struct pim_rpf *rpg; + struct prefix sg; rpg = RP(msg->im_dst); /* @@ -127,6 +128,8 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg __PRETTY_FUNCTION__, grp_str, src_str); } + sg.u.sg.src = msg->im_src; + sg.u.sg.grp = msg->im_dst; up = pim_upstream_add(msg->im_src, msg->im_dst, ifp); if (!up) { if (PIM_DEBUG_PIM_TRACE) { @@ -139,8 +142,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg pim_upstream_keep_alive_timer_start (up, PIM_KEEPALIVE_PERIOD); - up->channel_oil = pim_channel_oil_add(msg->im_dst, - msg->im_src, + up->channel_oil = pim_channel_oil_add(&sg, pim_ifp->mroute_vif_index); if (!up->channel_oil) { if (PIM_DEBUG_PIM_TRACE) { diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index d072c73dd8..2b26b54e08 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -50,8 +50,7 @@ static void pim_channel_oil_delete(struct channel_oil *c_oil) pim_channel_oil_free(c_oil); } -static struct channel_oil *channel_oil_new(struct in_addr group_addr, - struct in_addr source_addr, +static struct channel_oil *channel_oil_new(struct prefix *sg, int input_vif_index) { struct channel_oil *c_oil; @@ -60,13 +59,9 @@ static struct channel_oil *channel_oil_new(struct in_addr group_addr, ifp_in = pim_if_find_by_vif_index(input_vif_index); if (!ifp_in) { /* warning only */ - char group_str[100]; - char source_str[100]; - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: (S,G)=(%s,%s) could not find input interface for input_vif_index=%d", + zlog_warn("%s: (S,G)=%s could not find input interface for input_vif_index=%d", __PRETTY_FUNCTION__, - source_str, group_str, input_vif_index); + pim_str_sg_dump (sg), input_vif_index); } c_oil = XCALLOC(MTYPE_PIM_CHANNEL_OIL, sizeof(*c_oil)); @@ -75,8 +70,8 @@ static struct channel_oil *channel_oil_new(struct in_addr group_addr, return 0; } - c_oil->oil.mfcc_mcastgrp = group_addr; - c_oil->oil.mfcc_origin = source_addr; + c_oil->oil.mfcc_mcastgrp = sg->u.sg.grp; + c_oil->oil.mfcc_origin = sg->u.sg.src; c_oil->oil.mfcc_parent = input_vif_index; c_oil->oil_ref_count = 1; c_oil->installed = 0; @@ -86,13 +81,12 @@ static struct channel_oil *channel_oil_new(struct in_addr group_addr, return c_oil; } -static struct channel_oil *pim_add_channel_oil(struct in_addr group_addr, - struct in_addr source_addr, +static struct channel_oil *pim_add_channel_oil(struct prefix *sg, int input_vif_index) { struct channel_oil *c_oil; - c_oil = channel_oil_new(group_addr, source_addr, input_vif_index); + c_oil = channel_oil_new(sg, input_vif_index); if (!c_oil) { zlog_warn("PIM XCALLOC(%zu) failure", sizeof(*c_oil)); return 0; @@ -103,34 +97,32 @@ static struct channel_oil *pim_add_channel_oil(struct in_addr group_addr, return c_oil; } -static struct channel_oil *pim_find_channel_oil(struct in_addr group_addr, - struct in_addr source_addr) +static struct channel_oil *pim_find_channel_oil(struct prefix *sg) { struct listnode *node; struct channel_oil *c_oil; for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) { - if ((group_addr.s_addr == c_oil->oil.mfcc_mcastgrp.s_addr) && - (source_addr.s_addr == c_oil->oil.mfcc_origin.s_addr)) + if ((sg->u.sg.grp.s_addr == c_oil->oil.mfcc_mcastgrp.s_addr) && + (sg->u.sg.src.s_addr == c_oil->oil.mfcc_origin.s_addr)) return c_oil; } return 0; } -struct channel_oil *pim_channel_oil_add(struct in_addr group_addr, - struct in_addr source_addr, +struct channel_oil *pim_channel_oil_add(struct prefix *sg, int input_vif_index) { struct channel_oil *c_oil; - c_oil = pim_find_channel_oil(group_addr, source_addr); + c_oil = pim_find_channel_oil(sg); if (c_oil) { ++c_oil->oil_ref_count; return c_oil; } - return pim_add_channel_oil(group_addr, source_addr, input_vif_index); + return pim_add_channel_oil(sg, input_vif_index); } void pim_channel_oil_del(struct channel_oil *c_oil) diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index 0edb50787e..c16e42efdb 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -79,8 +79,7 @@ struct channel_oil { }; void pim_channel_oil_free(struct channel_oil *c_oil); -struct channel_oil *pim_channel_oil_add(struct in_addr group_addr, - struct in_addr source_addr, +struct channel_oil *pim_channel_oil_add(struct prefix *sg, int input_vif_index); void pim_channel_oil_del(struct channel_oil *c_oil); diff --git a/pimd/pim_register.c b/pimd/pim_register.c index bb05ba1c68..003b8a1bd0 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -347,7 +347,7 @@ pim_register_recv (struct interface *ifp, pim_nexthop_lookup (&upstream->rpf.source_nexthop, upstream->upstream_addr, NULL); upstream->rpf.source_nexthop.interface = ifp; - upstream->source_addr.s_addr = source.s_addr; + upstream->sg.u.sg.src.s_addr = source.s_addr; upstream->rpf.rpf_addr = upstream->rpf.source_nexthop.mrib_nexthop_addr; upstream->channel_oil->oil.mfcc_origin = source; pim_scan_individual_oil (upstream->channel_oil); diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 11d8464486..6802997076 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -151,13 +151,9 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, rpf->rpf_addr = pim_rpf_find_rpf_addr(up); if (PIM_INADDR_IS_ANY(rpf->rpf_addr) && PIM_DEBUG_PIM_EVENTS) { /* RPF'(S,G) not found */ - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); - zlog_debug("%s %s: RPF'(%s,%s) not found: won't send join upstream", + zlog_debug("%s %s: RPF'%s not found: won't send join upstream", __FILE__, __PRETTY_FUNCTION__, - src_str, grp_str); + pim_str_sg_dump (&up->sg)); /* warning only */ } @@ -165,15 +161,11 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, if (nexthop_mismatch(&rpf->source_nexthop, &save_nexthop)) { if (PIM_DEBUG_PIM_EVENTS) { - char src_str[100]; - char grp_str[100]; char nhaddr_str[100]; - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); pim_inet4_dump("", rpf->source_nexthop.mrib_nexthop_addr, nhaddr_str, sizeof(nhaddr_str)); - zlog_debug("%s %s: (S,G)=(%s,%s) source nexthop now is: interface=%s address=%s pref=%d metric=%d", + zlog_debug("%s %s: (S,G)=%s source nexthop now is: interface=%s address=%s pref=%d metric=%d", __FILE__, __PRETTY_FUNCTION__, - src_str, grp_str, + pim_str_sg_dump (&up->sg), rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "", nhaddr_str, rpf->source_nexthop.mrib_metric_preference, @@ -189,13 +181,9 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, if (save_nexthop.interface != rpf->source_nexthop.interface) { if (PIM_DEBUG_PIM_EVENTS) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); - zlog_debug("%s %s: (S,G)=(%s,%s) RPF_interface(S) changed from %s to %s", + zlog_debug("%s %s: (S,G)=%s RPF_interface(S) changed from %s to %s", __FILE__, __PRETTY_FUNCTION__, - src_str, grp_str, + pim_str_sg_dump (&up->sg), save_nexthop.interface ? save_nexthop.interface->name : "", rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : ""); /* warning only */ @@ -239,20 +227,16 @@ static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up) struct in_addr rpf_addr; if (!up->rpf.source_nexthop.interface) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); - zlog_warn("%s: missing RPF interface for upstream (S,G)=(%s,%s)", + zlog_warn("%s: missing RPF interface for upstream (S,G)=%s", __PRETTY_FUNCTION__, - src_str, grp_str); + pim_str_sg_dump (&up->sg)); rpf_addr.s_addr = PIM_NET_INADDR_ANY; return rpf_addr; } rpf_ch = pim_ifchannel_find(up->rpf.source_nexthop.interface, - up->source_addr, up->group_addr); + up->sg.u.sg.src, up->sg.u.sg.grp); if (rpf_ch) { if (rpf_ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { return rpf_ch->ifassert_winner; diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index a2f34d24e9..2f16226f01 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -86,19 +86,15 @@ void pim_upstream_send_join (struct pim_upstream *up) { if (PIM_DEBUG_PIM_TRACE) { - char src_str[100]; - char grp_str[100]; char rpf_str[100]; - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); pim_inet4_dump("", up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); - zlog_debug ("%s: RPF'(%s,%s)=%s(%s) for Interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, rpf_str, pim_upstream_state2str (up), + zlog_debug ("%s: RPF'%s=%s(%s) for Interface %s", __PRETTY_FUNCTION__, + pim_str_sg_dump (&up->sg), rpf_str, pim_upstream_state2str (up), up->rpf.source_nexthop.interface->name); if (PIM_INADDR_IS_ANY(up->rpf.rpf_addr)) { - zlog_debug("%s: can't send join upstream: RPF'(%s,%s)=%s", + zlog_debug("%s: can't send join upstream: RPF'%s=%s", __PRETTY_FUNCTION__, - src_str, grp_str, rpf_str); + pim_str_sg_dump (&up->sg), rpf_str); /* warning only */ } } @@ -114,8 +110,7 @@ pim_upstream_send_join (struct pim_upstream *up) /* send Join(S,G) to the current upstream neighbor */ pim_joinprune_send(up->rpf.source_nexthop.interface, up->rpf.rpf_addr, - up->source_addr, - up->group_addr, + &up->sg, 1 /* join */); } @@ -138,14 +133,10 @@ static int on_join_timer(struct thread *t) static void join_timer_start(struct pim_upstream *up) { if (PIM_DEBUG_PIM_EVENTS) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); - zlog_debug("%s: starting %d sec timer for upstream (S,G)=(%s,%s)", + zlog_debug("%s: starting %d sec timer for upstream (S,G)=%s", __PRETTY_FUNCTION__, qpim_t_periodic, - src_str, grp_str); + pim_str_sg_dump (&up->sg)); } zassert(!up->t_join_timer); @@ -165,14 +156,10 @@ static void pim_upstream_join_timer_restart_msec(struct pim_upstream *up, int interval_msec) { if (PIM_DEBUG_PIM_EVENTS) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); - zlog_debug("%s: restarting %d msec timer for upstream (S,G)=(%s,%s)", + zlog_debug("%s: restarting %d msec timer for upstream (S,G)=%s", __PRETTY_FUNCTION__, interval_msec, - src_str, grp_str); + pim_str_sg_dump (&up->sg)); } THREAD_OFF(up->t_join_timer); @@ -194,28 +181,20 @@ void pim_upstream_join_suppress(struct pim_upstream *up, join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer); if (PIM_DEBUG_PIM_TRACE) { - char src_str[100]; - char grp_str[100]; char rpf_str[100]; - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); pim_inet4_dump("", rpf_addr, rpf_str, sizeof(rpf_str)); - zlog_debug("%s %s: detected Join(%s,%s) to RPF'(S,G)=%s: join_timer=%ld msec t_joinsuppress=%ld msec", + zlog_debug("%s %s: detected Join%s to RPF'(S,G)=%s: join_timer=%ld msec t_joinsuppress=%ld msec", __FILE__, __PRETTY_FUNCTION__, - src_str, grp_str, + pim_str_sg_dump (&up->sg), rpf_str, join_timer_remain_msec, t_joinsuppress_msec); } if (join_timer_remain_msec < t_joinsuppress_msec) { if (PIM_DEBUG_PIM_TRACE) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); - zlog_debug("%s %s: suppressing Join(S,G)=(%s,%s) for %ld msec", + zlog_debug("%s %s: suppressing Join(S,G)=%s for %ld msec", __FILE__, __PRETTY_FUNCTION__, - src_str, grp_str, t_joinsuppress_msec); + pim_str_sg_dump (&up->sg), t_joinsuppress_msec); } pim_upstream_join_timer_restart_msec(up, t_joinsuppress_msec); @@ -233,27 +212,19 @@ void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label, t_override_msec = pim_if_t_override_msec(up->rpf.source_nexthop.interface); if (PIM_DEBUG_PIM_TRACE) { - char src_str[100]; - char grp_str[100]; char rpf_str[100]; - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); pim_inet4_dump("", rpf_addr, rpf_str, sizeof(rpf_str)); - zlog_debug("%s: to RPF'(%s,%s)=%s: join_timer=%ld msec t_override=%d msec", + zlog_debug("%s: to RPF'%s=%s: join_timer=%ld msec t_override=%d msec", debug_label, - src_str, grp_str, rpf_str, + pim_str_sg_dump (&up->sg), rpf_str, join_timer_remain_msec, t_override_msec); } if (join_timer_remain_msec > t_override_msec) { if (PIM_DEBUG_PIM_TRACE) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); - zlog_debug("%s: decreasing (S,G)=(%s,%s) join timer to t_override=%d msec", + zlog_debug("%s: decreasing (S,G)=%s join timer to t_override=%d msec", debug_label, - src_str, grp_str, + pim_str_sg_dump (&up->sg), t_override_msec); } @@ -330,14 +301,10 @@ pim_upstream_switch(struct pim_upstream *up, up->state_transition = pim_time_monotonic_sec(); if (PIM_DEBUG_PIM_EVENTS) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); - zlog_debug("%s: PIM_UPSTREAM_%s: (S,G)=(%s,%s)", + zlog_debug("%s: PIM_UPSTREAM_%s: (S,G)=%s", __PRETTY_FUNCTION__, ((new_state == PIM_UPSTREAM_JOINED) ? "JOINED" : "NOTJOINED"), - src_str, grp_str); + pim_str_sg_dump (&up->sg)); } pim_upstream_update_assert_tracking_desired(up); @@ -351,8 +318,7 @@ pim_upstream_switch(struct pim_upstream *up, forward_off(up); pim_joinprune_send(up->rpf.source_nexthop.interface, up->rpf.rpf_addr, - up->source_addr, - up->group_addr, + &up->sg, 0 /* prune */); if (up->t_join_timer) THREAD_OFF(up->t_join_timer); @@ -373,7 +339,7 @@ static struct pim_upstream *pim_upstream_new(struct in_addr source_addr, return NULL; } - up->source_addr = source_addr; + up->sg.u.sg.src = source_addr; if (!pim_rp_set_upstream_addr (&up->upstream_addr, source_addr)) { if (PIM_DEBUG_PIM_TRACE) @@ -383,7 +349,7 @@ static struct pim_upstream *pim_upstream_new(struct in_addr source_addr, return NULL; } - up->group_addr = group_addr; + up->sg.u.sg.grp = group_addr; up->flags = 0; up->ref_count = 1; up->t_join_timer = NULL; @@ -418,9 +384,9 @@ struct pim_upstream *pim_upstream_find(struct in_addr source_addr, struct pim_upstream *up; for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, up_node, up)) { - if (group_addr.s_addr == up->group_addr.s_addr) { - if ((up->source_addr.s_addr == INADDR_ANY) || - (source_addr.s_addr == up->source_addr.s_addr)) { + if (group_addr.s_addr == up->sg.u.sg.grp.s_addr) { + if ((up->sg.u.sg.src.s_addr == INADDR_ANY) || + (source_addr.s_addr == up->sg.u.sg.src.s_addr)) { return up; } } @@ -563,16 +529,12 @@ void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr) if (PIM_DEBUG_PIM_TRACE) { char neigh_str[100]; - char src_str[100]; - char grp_str[100]; char rpf_addr_str[100]; pim_inet4_dump("", neigh_addr, neigh_str, sizeof(neigh_str)); - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); pim_inet4_dump("", up->rpf.rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); - zlog_debug("%s: matching neigh=%s against upstream (S,G)=(%s,%s) joined=%d rpf_addr=%s", + zlog_debug("%s: matching neigh=%s against upstream (S,G)=%s joined=%d rpf_addr=%s", __PRETTY_FUNCTION__, - neigh_str, src_str, grp_str, + neigh_str, pim_str_sg_dump (&up->sg), up->join_state == PIM_UPSTREAM_JOINED, rpf_addr_str); } @@ -726,9 +688,9 @@ pim_upstream_keep_alive_timer (struct thread *t) up = THREAD_ARG(t); - if (I_am_RP (up->group_addr)) + if (I_am_RP (up->sg.u.sg.grp)) { - pim_br_clear_pmbr (up->source_addr, up->group_addr); + pim_br_clear_pmbr (up->sg.u.sg.src, up->sg.u.sg.grp); /* * We need to do more here :) * But this is the start. @@ -830,13 +792,8 @@ pim_upstream_register_stop_timer (struct thread *t) if (PIM_DEBUG_TRACE) { - char src_str[100]; - char grp_str[100]; - - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); - zlog_debug ("%s: (S,G)=(%s,%s) upstream register stop timer %d", - __PRETTY_FUNCTION__, src_str, grp_str, up->join_state); + zlog_debug ("%s: (S,G)=%s upstream register stop timer %d", + __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg), up->join_state); } switch (up->join_state) @@ -848,13 +805,13 @@ pim_upstream_register_stop_timer (struct thread *t) up->join_state = PIM_UPSTREAM_JOIN_PENDING; pim_upstream_start_register_stop_timer (up, 1); - rpg = RP (up->group_addr); + rpg = RP (up->sg.u.sg.grp); memset (&ip_hdr, 0, sizeof (struct ip)); ip_hdr.ip_p = PIM_IP_PROTO_PIM; ip_hdr.ip_hl = 5; ip_hdr.ip_v = 4; - ip_hdr.ip_src = up->source_addr; - ip_hdr.ip_dst = up->group_addr; + ip_hdr.ip_src = up->sg.u.sg.src; + ip_hdr.ip_dst = up->sg.u.sg.grp; ip_hdr.ip_len = 20; // checksum is broken pim_register_send ((uint8_t *)&ip_hdr, sizeof (struct ip), rpg, 1); @@ -889,13 +846,8 @@ pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_regist if (PIM_DEBUG_TRACE) { - char src_str[100]; - char grp_str[100]; - - pim_inet4_dump("", up->source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", up->group_addr, grp_str, sizeof(grp_str)); - zlog_debug ("%s: (S,G)=(%s,%s) Starting upstream register stop timer %d", - __PRETTY_FUNCTION__, src_str, grp_str, time); + zlog_debug ("%s: (S,G)=%s Starting upstream register stop timer %d", + __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg), time); } THREAD_TIMER_ON (master, up->t_rs_timer, pim_upstream_register_stop_timer, diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 78206e8db7..580bb945e9 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -24,6 +24,7 @@ #define PIM_UPSTREAM_H #include +#include #define PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED (1 << 0) #define PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED (2 << 0) @@ -89,8 +90,9 @@ enum pim_upstream_sptbit { struct pim_upstream { int fhr; struct in_addr upstream_addr;/* Who we are talking to */ - struct in_addr source_addr; /* (S,G) source key */ - struct in_addr group_addr; /* (S,G) group key */ + struct prefix sg; + //struct in_addr source_addr; /* (S,G) source key */ + //struct in_addr group_addr; /* (S,G) group key */ uint32_t flags; struct channel_oil *channel_oil; diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index bda5dd6845..e01b50fa87 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -360,15 +360,13 @@ static void scan_upstream_rpf_cache() /* send Prune(S,G) to the old upstream neighbor */ pim_joinprune_send(up->rpf.source_nexthop.interface, old_rpf_addr, - up->source_addr, - up->group_addr, + &up->sg, 0 /* prune */); /* send Join(S,G) to the current upstream neighbor */ pim_joinprune_send(up->rpf.source_nexthop.interface, up->rpf.rpf_addr, - up->source_addr, - up->group_addr, + &up->sg, 1 /* join */); pim_upstream_join_timer_restart(up); @@ -951,16 +949,16 @@ static int del_oif(struct channel_oil *channel_oil, void igmp_source_forward_start(struct igmp_source *source) { struct igmp_group *group; + struct prefix sg; int result; + sg.u.sg.src = source->source_addr; + sg.u.sg.grp = source->source_group->group_addr; + if (PIM_DEBUG_IGMP_TRACE) { - char source_str[100]; - char group_str[100]; - pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("", source->source_group->group_addr, group_str, sizeof(group_str)); - zlog_debug("%s: (S,G)=(%s,%s) igmp_sock=%d oif=%s fwd=%d", + zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", __PRETTY_FUNCTION__, - source_str, group_str, + pim_str_sg_dump (&sg), source->source_group->group_igmp_sock->fd, source->source_group->group_igmp_sock->interface->name, IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); @@ -1013,13 +1011,9 @@ void igmp_source_forward_start(struct igmp_source *source) if (input_iface_vif_index == pim_oif->mroute_vif_index) { /* ignore request for looped MFC entry */ if (PIM_DEBUG_IGMP_TRACE) { - char source_str[100]; - char group_str[100]; - pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("", source->source_group->group_addr, group_str, sizeof(group_str)); - zlog_debug("%s: ignoring request for looped MFC entry (S,G)=(%s,%s): igmp_sock=%d oif=%s vif_index=%d", + zlog_debug("%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d", __PRETTY_FUNCTION__, - source_str, group_str, + pim_str_sg_dump (&sg), source->source_group->group_igmp_sock->fd, source->source_group->group_igmp_sock->interface->name, input_iface_vif_index); @@ -1027,17 +1021,12 @@ void igmp_source_forward_start(struct igmp_source *source) return; } - source->source_channel_oil = pim_channel_oil_add(group->group_addr, - source->source_addr, + source->source_channel_oil = pim_channel_oil_add(&sg, input_iface_vif_index); if (!source->source_channel_oil) { - char group_str[100]; - char source_str[100]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); - zlog_warn("%s %s: could not create OIL for channel (S,G)=(%s,%s)", + zlog_warn("%s %s: could not create OIL for channel (S,G)=%s", __FILE__, __PRETTY_FUNCTION__, - source_str, group_str); + pim_str_sg_dump (&sg)); return; } } @@ -1142,23 +1131,19 @@ void pim_forward_start(struct pim_ifchannel *ch) int input_iface_vif_index = fib_lookup_if_vif_index(up->upstream_addr); if (input_iface_vif_index < 1) { char source_str[100]; - pim_inet4_dump("", up->source_addr, source_str, sizeof(source_str)); + pim_inet4_dump("", up->sg.u.sg.src, source_str, sizeof(source_str)); zlog_warn("%s %s: could not find input interface for source %s", __FILE__, __PRETTY_FUNCTION__, source_str); return; } - up->channel_oil = pim_channel_oil_add(up->group_addr, up->source_addr, + up->channel_oil = pim_channel_oil_add(&up->sg, input_iface_vif_index); if (!up->channel_oil) { - char group_str[100]; - char source_str[100]; - pim_inet4_dump("", up->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", up->source_addr, source_str, sizeof(source_str)); - zlog_warn("%s %s: could not create OIL for channel (S,G)=(%s,%s)", + zlog_warn("%s %s: could not create OIL for channel (S,G)=%s", __FILE__, __PRETTY_FUNCTION__, - source_str, group_str); + pim_str_sg_dump (&up->sg)); return; } } @@ -1173,23 +1158,15 @@ void pim_forward_stop(struct pim_ifchannel *ch) struct pim_upstream *up = ch->upstream; if (PIM_DEBUG_PIM_TRACE) { - char source_str[100]; - char group_str[100]; - pim_inet4_dump("", ch->sg.u.sg.src, source_str, sizeof(source_str)); - pim_inet4_dump("", ch->sg.u.sg.grp, group_str, sizeof(group_str)); - zlog_debug("%s: (S,G)=(%s,%s) oif=%s", + zlog_debug("%s: (S,G)=%s oif=%s", __PRETTY_FUNCTION__, - source_str, group_str, ch->interface->name); + pim_str_sg_dump (&ch->sg), ch->interface->name); } if (!up->channel_oil) { - char source_str[100]; - char group_str[100]; - pim_inet4_dump("", ch->sg.u.sg.src, source_str, sizeof(source_str)); - pim_inet4_dump("", ch->sg.u.sg.grp, group_str, sizeof(group_str)); - zlog_warn("%s: (S,G)=(%s,%s) oif=%s missing channel OIL", - __PRETTY_FUNCTION__, - source_str, group_str, ch->interface->name); + zlog_warn("%s: (S,G)=%s oif=%s missing channel OIL", + __PRETTY_FUNCTION__, + pim_str_sg_dump(&ch->sg), ch->interface->name); return; } From 5074a4230a11607b837fe07c7419ce5b3275f942 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 22 Jul 2016 23:12:06 -0400 Subject: [PATCH 027/386] pimd: more source,group conversion to prefix sg Convert more of the code to pass around a 'struct prefix sg' instead of individual struct addr's. Signed-off-by: Donald Sharp --- pimd/pim_assert.c | 22 +++++------- pimd/pim_ifchannel.c | 82 +++++++++++++++++++++++--------------------- pimd/pim_ifchannel.h | 6 ++-- pimd/pim_mroute.c | 31 ++++++++++------- pimd/pim_register.c | 16 ++++++--- pimd/pim_rpf.c | 2 +- pimd/pim_upstream.c | 22 +++++------- pimd/pim_upstream.h | 10 ++---- 8 files changed, 96 insertions(+), 95 deletions(-) diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index 63f4e33868..e8e3549d24 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -146,16 +146,16 @@ static int dispatch_assert(struct interface *ifp, struct pim_assert_metric recv_metric) { struct pim_ifchannel *ch; + struct prefix sg; - ch = pim_ifchannel_add(ifp, source_addr, group_addr); + memset (&sg, 0, sizeof (struct prefix)); + sg.u.sg.src = source_addr; + sg.u.sg.grp = group_addr; + ch = pim_ifchannel_add(ifp, &sg); if (!ch) { - char source_str[100]; - char group_str[100]; - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - zlog_warn("%s: (S,G)=(%s,%s) failure creating channel on interface %s", + zlog_warn("%s: (S,G)=%s failure creating channel on interface %s", __PRETTY_FUNCTION__, - source_str, group_str, ifp->name); + pim_str_sg_dump (&sg), ifp->name); return -1; } @@ -212,13 +212,9 @@ static int dispatch_assert(struct interface *ifp, break; default: { - char source_str[100]; - char group_str[100]; - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - zlog_warn("%s: (S,G)=(%s,%s) invalid assert state %d on interface %s", + zlog_warn("%s: (S,G)=%s invalid assert state %d on interface %s", __PRETTY_FUNCTION__, - source_str, group_str, ch->ifassert_state, ifp->name); + pim_str_sg_dump (&sg), ch->ifassert_state, ifp->name); } return -2; } diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index cf2cc99f58..27d51ea731 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -184,8 +184,7 @@ void reset_ifassert_state(struct pim_ifchannel *ch) } struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, - struct in_addr source_addr, - struct in_addr group_addr) + struct prefix *sg) { struct pim_interface *pim_ifp; struct listnode *ch_node; @@ -196,21 +195,17 @@ struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, pim_ifp = ifp->info; if (!pim_ifp) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", group_addr, grp_str, sizeof(grp_str)); - zlog_warn("%s: (S,G)=(%s,%s): multicast not enabled on interface %s", + zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, + pim_str_sg_dump (sg), ifp->name); return 0; } for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { if ( - (source_addr.s_addr == ch->sg.u.sg.src.s_addr) && - (group_addr.s_addr == ch->sg.u.sg.grp.s_addr) + (sg->u.sg.src.s_addr == ch->sg.u.sg.src.s_addr) && + (sg->u.sg.grp.s_addr == ch->sg.u.sg.grp.s_addr) ) { return ch; } @@ -275,41 +270,32 @@ void pim_ifchannel_delete_on_noinfo(struct interface *ifp) } struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, - struct in_addr source_addr, - struct in_addr group_addr) + struct prefix *sg) { struct pim_interface *pim_ifp; struct pim_ifchannel *ch; struct pim_upstream *up; - char src_str[100]; - char grp_str[100]; - ch = pim_ifchannel_find(ifp, source_addr, group_addr); + ch = pim_ifchannel_find(ifp, sg); if (ch) return ch; pim_ifp = ifp->info; zassert(pim_ifp); - up = pim_upstream_add(source_addr, group_addr, NULL); + up = pim_upstream_add(sg, NULL); if (!up) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", group_addr, grp_str, sizeof(grp_str)); - zlog_err("%s: could not attach upstream (S,G)=(%s,%s) on interface %s", + zlog_err("%s: could not attach upstream (S,G)=%s on interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); + pim_str_sg_dump (sg), ifp->name); return NULL; } ch = XMALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch)); if (!ch) { - pim_inet4_dump("", source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", group_addr, grp_str, sizeof(grp_str)); - zlog_warn("%s: pim_ifchannel_new() failure for (S,G)=(%s,%s) on interface %s", + zlog_warn("%s: pim_ifchannel_new() failure for (S,G)=%s on interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); + pim_str_sg_dump (sg), ifp->name); return NULL; } @@ -317,8 +303,7 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, ch->flags = 0; ch->upstream = up; ch->interface = ifp; - ch->sg.u.sg.src = source_addr; - ch->sg.u.sg.grp = group_addr; + ch->sg = *sg; ch->local_ifmembership = PIM_IFMEMBERSHIP_NOINFO; ch->ifjoin_state = PIM_IFJOIN_NOINFO; @@ -420,9 +405,13 @@ static void check_recv_upstream(int is_join, int holdtime) { struct pim_upstream *up; + struct prefix sg; + memset (&sg, 0, sizeof (struct prefix)); + sg.u.sg.src = source_addr; + sg.u.sg.grp = group_addr; /* Upstream (S,G) in Joined state ? */ - up = pim_upstream_find(source_addr, group_addr); + up = pim_upstream_find(&sg); if (!up) return; if (up->join_state != PIM_UPSTREAM_JOINED) @@ -541,13 +530,17 @@ void pim_ifchannel_join_add(struct interface *ifp, { struct pim_interface *pim_ifp; struct pim_ifchannel *ch; + struct prefix sg; + memset (&sg, 0, sizeof (struct prefix)); + sg.u.sg.src = source_addr; + sg.u.sg.grp = group_addr; if (nonlocal_upstream(1 /* join */, ifp, upstream, source_addr, group_addr, source_flags, holdtime)) { return; } - ch = pim_ifchannel_add(ifp, source_addr, group_addr); + ch = pim_ifchannel_add(ifp, &sg); if (!ch) return; @@ -568,15 +561,11 @@ void pim_ifchannel_join_add(struct interface *ifp, address of the join message is our primary address. */ if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { - char src_str[100]; - char grp_str[100]; char neigh_str[100]; - pim_inet4_dump("", source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", group_addr, grp_str, sizeof(grp_str)); pim_inet4_dump("", neigh_addr, neigh_str, sizeof(neigh_str)); - zlog_warn("%s: Assert Loser recv Join(%s,%s) from %s on %s", + zlog_warn("%s: Assert Loser recv Join%s from %s on %s", __PRETTY_FUNCTION__, - src_str, grp_str, neigh_str, ifp->name); + pim_str_sg_dump (&sg), neigh_str, ifp->name); assert_action_a5(ch); } @@ -648,13 +637,18 @@ void pim_ifchannel_prune(struct interface *ifp, { struct pim_ifchannel *ch; int jp_override_interval_msec; + struct prefix sg; + + memset (&sg, 0, sizeof (struct prefix)); + sg.u.sg.src = source_addr; + sg.u.sg.grp = group_addr; if (nonlocal_upstream(0 /* prune */, ifp, upstream, source_addr, group_addr, source_flags, holdtime)) { return; } - ch = pim_ifchannel_add(ifp, source_addr, group_addr); + ch = pim_ifchannel_add(ifp, &sg); if (!ch) return; @@ -705,6 +699,11 @@ void pim_ifchannel_local_membership_add(struct interface *ifp, { struct pim_ifchannel *ch; struct pim_interface *pim_ifp; + struct prefix sg; + + memset (&sg, 0, sizeof (struct prefix)); + sg.u.sg.src = source_addr; + sg.u.sg.grp = group_addr; /* PIM enabled on interface? */ pim_ifp = ifp->info; @@ -713,7 +712,7 @@ void pim_ifchannel_local_membership_add(struct interface *ifp, if (!PIM_IF_TEST_PIM(pim_ifp->options)) return; - ch = pim_ifchannel_add(ifp, source_addr, group_addr); + ch = pim_ifchannel_add(ifp, &sg); if (!ch) { return; } @@ -729,6 +728,11 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, { struct pim_ifchannel *ch; struct pim_interface *pim_ifp; + struct prefix sg; + + memset (&sg, 0, sizeof (struct prefix)); + sg.u.sg.src = source_addr; + sg.u.sg.grp = group_addr; /* PIM enabled on interface? */ pim_ifp = ifp->info; @@ -737,7 +741,7 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, if (!PIM_IF_TEST_PIM(pim_ifp->options)) return; - ch = pim_ifchannel_find(ifp, source_addr, group_addr); + ch = pim_ifchannel_find(ifp, &sg); if (!ch) return; diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 747ee39bf2..aa8585a2b7 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -104,11 +104,9 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch); void pim_ifchannel_membership_clear(struct interface *ifp); void pim_ifchannel_delete_on_noinfo(struct interface *ifp); struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, - struct in_addr source_addr, - struct in_addr group_addr); + struct prefix *sg); struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, - struct in_addr source_addr, - struct in_addr group_addr); + struct prefix *sg); void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr, struct in_addr upstream, diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index aeb49f770c..796b8cf2db 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -128,14 +128,15 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg __PRETTY_FUNCTION__, grp_str, src_str); } + memset (&sg, 0, sizeof (struct prefix)); sg.u.sg.src = msg->im_src; sg.u.sg.grp = msg->im_dst; - up = pim_upstream_add(msg->im_src, msg->im_dst, ifp); + up = pim_upstream_add (&sg, ifp); if (!up) { if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: Failure to add upstream information for (%s,%s)", + zlog_debug("%s: Failure to add upstream information for %s", __PRETTY_FUNCTION__, - src_str, grp_str); + pim_str_sg_dump (&sg)); } return 0; } @@ -154,7 +155,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg } up->channel_oil->cc.pktcnt++; up->fhr = 1; - ch = pim_ifchannel_add (pim_regiface, msg->im_src, msg->im_dst); + ch = pim_ifchannel_add (pim_regiface, &sg); pim_ifchannel_ifjoin_switch (__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN_PIMREG); up->join_state = PIM_UPSTREAM_JOINED; @@ -166,29 +167,29 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf, const char *src_str, const char *grp_str) { struct pim_interface *pim_ifp; - struct in_addr group; - struct in_addr src; + struct prefix sg; struct pim_rpf *rpg; const struct ip *ip_hdr; struct pim_upstream *up; ip_hdr = (const struct ip *)buf; - src = ip_hdr->ip_src; - group = ip_hdr->ip_dst; + memset (&sg, 0, sizeof (struct prefix)); + sg.u.sg.src = ip_hdr->ip_src; + sg.u.sg.grp = ip_hdr->ip_dst; - up = pim_upstream_find(src, group); + up = pim_upstream_find(&sg); if (!up) { if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: Unable to find upstream channel WHOLEPKT(%s,%s)", - __PRETTY_FUNCTION__, src_str, grp_str); + zlog_debug("%s: Unable to find upstream channel WHOLEPKT%s", + __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); } return 0; } pim_ifp = up->rpf.source_nexthop.interface->info; - rpg = RP(group); + rpg = RP(sg.u.sg.grp); if ((rpg->rpf_addr.s_addr == INADDR_NONE) || (!pim_ifp) || @@ -215,6 +216,7 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms { struct pim_ifchannel *ch; struct pim_interface *pim_ifp; + struct prefix sg; /* Send Assert(S,G) on iif as response to WRONGVIF kernel upcall. @@ -246,7 +248,10 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms return -2; } - ch = pim_ifchannel_find(ifp, msg->im_src, msg->im_dst); + memset (&sg, 0, sizeof (struct prefix)); + sg.u.sg.src = msg->im_src; + sg.u.sg.grp = msg->im_dst; + ch = pim_ifchannel_find(ifp, &sg); if (!ch) { if (PIM_DEBUG_PIM_TRACE) { zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) could not find channel on interface %s", diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 003b8a1bd0..608b1bf300 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -117,6 +117,7 @@ pim_register_stop_recv (uint8_t *buf, int buf_size) struct pim_upstream *upstream = NULL; struct prefix source; struct prefix group; + struct prefix sg; int l; if (PIM_DEBUG_PIM_PACKETDUMP_RECV) @@ -126,7 +127,10 @@ pim_register_stop_recv (uint8_t *buf, int buf_size) buf += l; buf_size -= l; l = pim_parse_addr_ucast (&source, buf, buf_size); - upstream = pim_upstream_find (source.u.prefix4, group.u.prefix4); + memset (&sg, 0, sizeof (struct prefix)); + sg.u.sg.src = source.u.prefix4; + sg.u.sg.grp = group.u.prefix4; + upstream = pim_upstream_find (&sg); if (!upstream) { return 0; @@ -239,10 +243,9 @@ pim_register_recv (struct interface *ifp, { int sentRegisterStop = 0; struct ip *ip_hdr; - //size_t hlen; struct in_addr group = { .s_addr = 0 }; struct in_addr source = { .s_addr = 0 }; - //uint8_t *msg; + struct prefix sg; uint32_t *bits; if (!pim_check_is_my_ip_address (dest_addr)) { @@ -308,13 +311,16 @@ pim_register_recv (struct interface *ifp, } } - struct pim_upstream *upstream = pim_upstream_find (source, group); + memset (&sg, 0, sizeof (struct prefix)); + sg.u.sg.src = source; + sg.u.sg.grp = group; + struct pim_upstream *upstream = pim_upstream_find (&sg); /* * If we don't have a place to send ignore the packet */ if (!upstream) { - upstream = pim_upstream_add (source, group, ifp); + upstream = pim_upstream_add (&sg, ifp); pim_upstream_switch (upstream, PIM_UPSTREAM_PRUNE); } diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 6802997076..6ba1b2e499 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -236,7 +236,7 @@ static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up) } rpf_ch = pim_ifchannel_find(up->rpf.source_nexthop.interface, - up->sg.u.sg.src, up->sg.u.sg.grp); + &up->sg); if (rpf_ch) { if (rpf_ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { return rpf_ch->ifassert_winner; diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 2f16226f01..85f45566a4 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -325,8 +325,7 @@ pim_upstream_switch(struct pim_upstream *up, } } -static struct pim_upstream *pim_upstream_new(struct in_addr source_addr, - struct in_addr group_addr, +static struct pim_upstream *pim_upstream_new(struct prefix *sg, struct interface *incoming) { struct pim_upstream *up; @@ -339,8 +338,8 @@ static struct pim_upstream *pim_upstream_new(struct in_addr source_addr, return NULL; } - up->sg.u.sg.src = source_addr; - if (!pim_rp_set_upstream_addr (&up->upstream_addr, source_addr)) + up->sg = *sg; + if (!pim_rp_set_upstream_addr (&up->upstream_addr, sg->u.sg.src)) { if (PIM_DEBUG_PIM_TRACE) zlog_debug("%s: Received a (*,G) with no RP configured", __PRETTY_FUNCTION__); @@ -349,7 +348,6 @@ static struct pim_upstream *pim_upstream_new(struct in_addr source_addr, return NULL; } - up->sg.u.sg.grp = group_addr; up->flags = 0; up->ref_count = 1; up->t_join_timer = NULL; @@ -377,16 +375,15 @@ static struct pim_upstream *pim_upstream_new(struct in_addr source_addr, return up; } -struct pim_upstream *pim_upstream_find(struct in_addr source_addr, - struct in_addr group_addr) +struct pim_upstream *pim_upstream_find(struct prefix *sg) { struct listnode *up_node; struct pim_upstream *up; for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, up_node, up)) { - if (group_addr.s_addr == up->sg.u.sg.grp.s_addr) { + if (sg->u.sg.grp.s_addr == up->sg.u.sg.grp.s_addr) { if ((up->sg.u.sg.src.s_addr == INADDR_ANY) || - (source_addr.s_addr == up->sg.u.sg.src.s_addr)) { + (sg->u.sg.src.s_addr == up->sg.u.sg.src.s_addr)) { return up; } } @@ -395,18 +392,17 @@ struct pim_upstream *pim_upstream_find(struct in_addr source_addr, return NULL; } -struct pim_upstream *pim_upstream_add(struct in_addr source_addr, - struct in_addr group_addr, +struct pim_upstream *pim_upstream_add(struct prefix *sg, struct interface *incoming) { struct pim_upstream *up; - up = pim_upstream_find(source_addr, group_addr); + up = pim_upstream_find(sg); if (up) { ++up->ref_count; } else { - up = pim_upstream_new(source_addr, group_addr, incoming); + up = pim_upstream_new(sg, incoming); } return up; diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 580bb945e9..7783cc4bc9 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -90,9 +90,7 @@ enum pim_upstream_sptbit { struct pim_upstream { int fhr; struct in_addr upstream_addr;/* Who we are talking to */ - struct prefix sg; - //struct in_addr source_addr; /* (S,G) source key */ - //struct in_addr group_addr; /* (S,G) group key */ + struct prefix sg; /* (S,G) group key */ uint32_t flags; struct channel_oil *channel_oil; @@ -124,10 +122,8 @@ struct pim_upstream { void pim_upstream_free(struct pim_upstream *up); void pim_upstream_delete(struct pim_upstream *up); -struct pim_upstream *pim_upstream_find(struct in_addr source_addr, - struct in_addr group_addr); -struct pim_upstream *pim_upstream_add(struct in_addr source_addr, - struct in_addr group_addr, +struct pim_upstream *pim_upstream_find (struct prefix *sg); +struct pim_upstream *pim_upstream_add (struct prefix *sg, struct interface *ifp); void pim_upstream_del(struct pim_upstream *up); From ee1a477a046442f251e18d16fcfc8039b94a09bf Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 22 Jul 2016 23:28:13 -0400 Subject: [PATCH 028/386] pimd: Convert pim_ifchannel_join_add to struct prefix *sg Convert the pim_ifchannel_join_add to use a struct prefix *sg instead of struct in_addr's. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 29 ++++++++--------------------- pimd/pim_ifchannel.h | 3 +-- pimd/pim_join.c | 16 +++++++++------- 3 files changed, 18 insertions(+), 30 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 27d51ea731..17e3de5710 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -124,13 +124,9 @@ void pim_ifchannel_ifjoin_switch(const char *caller, ) { if (PIM_DEBUG_PIM_EVENTS) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", ch->sg.u.sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->sg.u.sg.grp, grp_str, sizeof(grp_str)); - zlog_debug("PIM_IFCHANNEL_%s: (S,G)=(%s,%s) on interface %s", + zlog_debug("PIM_IFCHANNEL_%s: (S,G)=%s on interface %s", ((new_state == PIM_IFJOIN_NOINFO) ? "DOWN" : "UP"), - src_str, grp_str, ch->interface->name); + pim_str_sg_dump (&ch->sg), ch->interface->name); } /* @@ -221,13 +217,9 @@ static void ifmembership_set(struct pim_ifchannel *ch, return; if (PIM_DEBUG_PIM_EVENTS) { - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", ch->sg.u.sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->sg.u.sg.grp, grp_str, sizeof(grp_str)); - zlog_debug("%s: (S,G)=(%s,%s) membership now is %s on interface %s", + zlog_debug("%s: (S,G)=%s membership now is %s on interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, + pim_str_sg_dump (&ch->sg), membership == PIM_IFMEMBERSHIP_INCLUDE ? "INCLUDE" : "NOINFO", ch->interface->name); } @@ -523,24 +515,19 @@ static int nonlocal_upstream(int is_join, void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr, struct in_addr upstream, - struct in_addr source_addr, - struct in_addr group_addr, + struct prefix *sg, uint8_t source_flags, uint16_t holdtime) { struct pim_interface *pim_ifp; struct pim_ifchannel *ch; - struct prefix sg; - memset (&sg, 0, sizeof (struct prefix)); - sg.u.sg.src = source_addr; - sg.u.sg.grp = group_addr; if (nonlocal_upstream(1 /* join */, ifp, upstream, - source_addr, group_addr, source_flags, holdtime)) { + sg->u.sg.src, sg->u.sg.grp, source_flags, holdtime)) { return; } - ch = pim_ifchannel_add(ifp, &sg); + ch = pim_ifchannel_add(ifp, sg); if (!ch) return; @@ -565,7 +552,7 @@ void pim_ifchannel_join_add(struct interface *ifp, pim_inet4_dump("", neigh_addr, neigh_str, sizeof(neigh_str)); zlog_warn("%s: Assert Loser recv Join%s from %s on %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), neigh_str, ifp->name); + pim_str_sg_dump (sg), neigh_str, ifp->name); assert_action_a5(ch); } diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index aa8585a2b7..17678f7425 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -110,8 +110,7 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr, struct in_addr upstream, - struct in_addr source_addr, - struct in_addr group_addr, + struct prefix *sg, uint8_t source_flags, uint16_t holdtime); void pim_ifchannel_prune(struct interface *ifp, diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 75f484e577..afebc03109 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -55,18 +55,20 @@ static void recv_join(struct interface *ifp, struct in_addr source, uint8_t source_flags) { + struct prefix sg; + + memset (&sg, 0, sizeof (struct prefix)); + sg.u.sg.src = source; + sg.u.sg.grp = group; + if (PIM_DEBUG_PIM_TRACE) { char up_str[100]; - char src_str[100]; - char grp_str[100]; char neigh_str[100]; pim_inet4_dump("", upstream, up_str, sizeof(up_str)); - pim_inet4_dump("", source, src_str, sizeof(src_str)); - pim_inet4_dump("", group, grp_str, sizeof(grp_str)); pim_inet4_dump("", neigh->source_addr, neigh_str, sizeof(neigh_str)); - zlog_warn("%s: join (S,G)=(%s,%s) rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", + zlog_warn("%s: join (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", __PRETTY_FUNCTION__, - src_str, grp_str, + pim_str_sg_dump (&sg), source_flags & PIM_RPT_BIT_MASK, source_flags & PIM_WILDCARD_BIT_MASK, up_str, holdtime, neigh_str, ifp->name); @@ -74,7 +76,7 @@ static void recv_join(struct interface *ifp, /* Restart join expiry timer */ pim_ifchannel_join_add(ifp, neigh->source_addr, upstream, - source, group, source_flags, holdtime); + &sg, source_flags, holdtime); } static void recv_prune(struct interface *ifp, From 7bd2c6fa0a1fdff6cb0a52b7427534d4d912b32d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 22 Jul 2016 23:34:27 -0400 Subject: [PATCH 029/386] pimd: Convert pim_ifchannel_prune to use struct prefix *sg Convert the pim_ifchannel_prune function to use a struct prefix *sg for the source group. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 12 +++--------- pimd/pim_ifchannel.h | 3 +-- pimd/pim_join.c | 16 +++++++++------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 17e3de5710..06f5b756b4 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -617,25 +617,19 @@ void pim_ifchannel_join_add(struct interface *ifp, void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream, - struct in_addr source_addr, - struct in_addr group_addr, + struct prefix *sg, uint8_t source_flags, uint16_t holdtime) { struct pim_ifchannel *ch; int jp_override_interval_msec; - struct prefix sg; - - memset (&sg, 0, sizeof (struct prefix)); - sg.u.sg.src = source_addr; - sg.u.sg.grp = group_addr; if (nonlocal_upstream(0 /* prune */, ifp, upstream, - source_addr, group_addr, source_flags, holdtime)) { + sg->u.sg.src, sg->u.sg.grp, source_flags, holdtime)) { return; } - ch = pim_ifchannel_add(ifp, &sg); + ch = pim_ifchannel_add(ifp, sg); if (!ch) return; diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 17678f7425..1fb066445c 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -115,8 +115,7 @@ void pim_ifchannel_join_add(struct interface *ifp, uint16_t holdtime); void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream, - struct in_addr source_addr, - struct in_addr group_addr, + struct prefix *sg, uint8_t source_flags, uint16_t holdtime); void pim_ifchannel_local_membership_add(struct interface *ifp, diff --git a/pimd/pim_join.c b/pimd/pim_join.c index afebc03109..e0ad3e4399 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -87,24 +87,26 @@ static void recv_prune(struct interface *ifp, struct in_addr source, uint8_t source_flags) { + struct prefix sg; + + memset (&sg, 0, sizeof (struct prefix)); + sg.u.sg.src = source; + sg.u.sg.grp = group; + if (PIM_DEBUG_PIM_TRACE) { char up_str[100]; - char src_str[100]; - char grp_str[100]; char neigh_str[100]; pim_inet4_dump("", upstream, up_str, sizeof(up_str)); - pim_inet4_dump("", source, src_str, sizeof(src_str)); - pim_inet4_dump("", group, grp_str, sizeof(grp_str)); pim_inet4_dump("", neigh->source_addr, neigh_str, sizeof(neigh_str)); - zlog_warn("%s: prune (S,G)=(%s,%s) rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", + zlog_warn("%s: prune (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", __PRETTY_FUNCTION__, - src_str, grp_str, + pim_str_sg_dump (&sg), source_flags & PIM_RPT_BIT_MASK, source_flags & PIM_WILDCARD_BIT_MASK, up_str, holdtime, neigh_str, ifp->name); } - pim_ifchannel_prune(ifp, upstream, source, group, source_flags, holdtime); + pim_ifchannel_prune(ifp, upstream, &sg, source_flags, holdtime); } int pim_joinprune_recv(struct interface *ifp, From 69283639958151a3941369804fcfaa3b9f14a150 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 22 Jul 2016 23:42:11 -0400 Subject: [PATCH 030/386] pimd: convert pim_ifchannel_local_membership_add to use struct prefix sg Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 9 ++++++--- pimd/pim_ifchannel.c | 10 ++-------- pimd/pim_ifchannel.h | 3 +-- pimd/pim_zebra.c | 3 +-- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index e8323ff08a..18957234cf 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -129,9 +129,12 @@ static void pim_if_membership_refresh(struct interface *ifp) for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) { if (IGMP_SOURCE_TEST_FORWARDING(src->source_flags)) { - pim_ifchannel_local_membership_add(ifp, - src->source_addr, - grp->group_addr); + struct prefix sg; + + memset (&sg, 0, sizeof (struct prefix)); + sg.u.sg.src = src->source_addr; + sg.u.sg.grp = grp->group_addr; + pim_ifchannel_local_membership_add(ifp, &sg); } } /* scan group sources */ diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 06f5b756b4..edb1a104b1 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -675,16 +675,10 @@ void pim_ifchannel_prune(struct interface *ifp, } void pim_ifchannel_local_membership_add(struct interface *ifp, - struct in_addr source_addr, - struct in_addr group_addr) + struct prefix *sg) { struct pim_ifchannel *ch; struct pim_interface *pim_ifp; - struct prefix sg; - - memset (&sg, 0, sizeof (struct prefix)); - sg.u.sg.src = source_addr; - sg.u.sg.grp = group_addr; /* PIM enabled on interface? */ pim_ifp = ifp->info; @@ -693,7 +687,7 @@ void pim_ifchannel_local_membership_add(struct interface *ifp, if (!PIM_IF_TEST_PIM(pim_ifp->options)) return; - ch = pim_ifchannel_add(ifp, &sg); + ch = pim_ifchannel_add(ifp, sg); if (!ch) { return; } diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 1fb066445c..3b7e2806a4 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -119,8 +119,7 @@ void pim_ifchannel_prune(struct interface *ifp, uint8_t source_flags, uint16_t holdtime); void pim_ifchannel_local_membership_add(struct interface *ifp, - struct in_addr source_addr, - struct in_addr group_addr); + struct prefix *sg); void pim_ifchannel_local_membership_del(struct interface *ifp, struct in_addr source_addr, struct in_addr group_addr); diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index e01b50fa87..8dce69a0da 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -1044,8 +1044,7 @@ void igmp_source_forward_start(struct igmp_source *source) Feed IGMPv3-gathered local membership information into PIM per-interface (S,G) state. */ - pim_ifchannel_local_membership_add(group->group_igmp_sock->interface, - source->source_addr, group->group_addr); + pim_ifchannel_local_membership_add(group->group_igmp_sock->interface, &sg); IGMP_SOURCE_DO_FORWARDING(source->source_flags); } From 1103466bb34bbdcb5963eb009b06e77de9e4ea68 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 22 Jul 2016 23:50:29 -0400 Subject: [PATCH 031/386] pimd: Convert pim_ifchannel_local_membership_del to struct prefix *sg Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 10 ++-------- pimd/pim_ifchannel.h | 3 +-- pimd/pim_zebra.c | 16 +++++++++------- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index edb1a104b1..0d246a57f8 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -698,16 +698,10 @@ void pim_ifchannel_local_membership_add(struct interface *ifp, } void pim_ifchannel_local_membership_del(struct interface *ifp, - struct in_addr source_addr, - struct in_addr group_addr) + struct prefix *sg) { struct pim_ifchannel *ch; struct pim_interface *pim_ifp; - struct prefix sg; - - memset (&sg, 0, sizeof (struct prefix)); - sg.u.sg.src = source_addr; - sg.u.sg.grp = group_addr; /* PIM enabled on interface? */ pim_ifp = ifp->info; @@ -716,7 +710,7 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, if (!PIM_IF_TEST_PIM(pim_ifp->options)) return; - ch = pim_ifchannel_find(ifp, &sg); + ch = pim_ifchannel_find(ifp, sg); if (!ch) return; diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 3b7e2806a4..2fd429ca04 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -121,8 +121,7 @@ void pim_ifchannel_prune(struct interface *ifp, void pim_ifchannel_local_membership_add(struct interface *ifp, struct prefix *sg); void pim_ifchannel_local_membership_del(struct interface *ifp, - struct in_addr source_addr, - struct in_addr group_addr); + struct prefix *sg); void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch, diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 8dce69a0da..87e2258ad7 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -952,6 +952,7 @@ void igmp_source_forward_start(struct igmp_source *source) struct prefix sg; int result; + memset (&sg, 0, sizeof (struct prefix)); sg.u.sg.src = source->source_addr; sg.u.sg.grp = source->source_group->group_addr; @@ -1056,16 +1057,17 @@ void igmp_source_forward_start(struct igmp_source *source) void igmp_source_forward_stop(struct igmp_source *source) { struct igmp_group *group; + struct prefix sg; int result; + memset (&sg, 0, sizeof (struct prefix)); + sg.u.sg.src = source->source_addr; + sg.u.sg.grp = source->source_group->group_addr; + if (PIM_DEBUG_IGMP_TRACE) { - char source_str[100]; - char group_str[100]; - pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("", source->source_group->group_addr, group_str, sizeof(group_str)); - zlog_debug("%s: (S,G)=(%s,%s) igmp_sock=%d oif=%s fwd=%d", + zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", __PRETTY_FUNCTION__, - source_str, group_str, + pim_str_sg_dump (&sg), source->source_group->group_igmp_sock->fd, source->source_group->group_igmp_sock->interface->name, IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); @@ -1104,7 +1106,7 @@ void igmp_source_forward_stop(struct igmp_source *source) per-interface (S,G) state. */ pim_ifchannel_local_membership_del(group->group_igmp_sock->interface, - source->source_addr, group->group_addr); + &sg); IGMP_SOURCE_DONT_FORWARDING(source->source_flags); } From 01d45d04a381595f34af0f3676338f6ec00df1d7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 22 Jul 2016 23:58:55 -0400 Subject: [PATCH 032/386] pimd: More conversion of struct prefix *sg Some more conversion to use struct prefix *sg in pim_ifchannel.c Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 42 ++++++++++++------------------------------ 1 file changed, 12 insertions(+), 30 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 0d246a57f8..80a98ad4b9 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -391,19 +391,14 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) static void check_recv_upstream(int is_join, struct interface *recv_ifp, struct in_addr upstream, - struct in_addr source_addr, - struct in_addr group_addr, + struct prefix *sg, uint8_t source_flags, int holdtime) { struct pim_upstream *up; - struct prefix sg; - memset (&sg, 0, sizeof (struct prefix)); - sg.u.sg.src = source_addr; - sg.u.sg.grp = group_addr; /* Upstream (S,G) in Joined state ? */ - up = pim_upstream_find(&sg); + up = pim_upstream_find(sg); if (!up) return; if (up->join_state != PIM_UPSTREAM_JOINED) @@ -413,29 +408,21 @@ static void check_recv_upstream(int is_join, if (PIM_INADDR_IS_ANY(up->rpf.rpf_addr)) { /* RPF'(S,G) not found */ - char src_str[100]; - char grp_str[100]; - pim_inet4_dump("", source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", group_addr, grp_str, sizeof(grp_str)); - zlog_warn("%s %s: RPF'(%s,%s) not found", + zlog_warn("%s %s: RPF'%s not found", __FILE__, __PRETTY_FUNCTION__, - src_str, grp_str); + pim_str_sg_dump (sg)); return; } /* upstream directed to RPF'(S,G) ? */ if (upstream.s_addr != up->rpf.rpf_addr.s_addr) { - char src_str[100]; - char grp_str[100]; char up_str[100]; char rpf_str[100]; - pim_inet4_dump("", source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", group_addr, grp_str, sizeof(grp_str)); pim_inet4_dump("", upstream, up_str, sizeof(up_str)); pim_inet4_dump("", up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); - zlog_warn("%s %s: (S,G)=(%s,%s) upstream=%s not directed to RPF'(S,G)=%s on interface %s", + zlog_warn("%s %s: (S,G)=%s upstream=%s not directed to RPF'(S,G)=%s on interface %s", __FILE__, __PRETTY_FUNCTION__, - src_str, grp_str, + pim_str_sg_dump (sg), up_str, rpf_str, recv_ifp->name); return; } @@ -471,8 +458,7 @@ static void check_recv_upstream(int is_join, static int nonlocal_upstream(int is_join, struct interface *recv_ifp, struct in_addr upstream, - struct in_addr source_addr, - struct in_addr group_addr, + struct prefix *sg, uint8_t source_flags, uint16_t holdtime) { @@ -486,15 +472,11 @@ static int nonlocal_upstream(int is_join, if (PIM_DEBUG_PIM_TRACE) { char up_str[100]; - char src_str[100]; - char grp_str[100]; pim_inet4_dump("", upstream, up_str, sizeof(up_str)); - pim_inet4_dump("", source_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", group_addr, grp_str, sizeof(grp_str)); - zlog_warn("%s: recv %s (S,G)=(%s,%s) to %s upstream=%s on %s", + zlog_warn("%s: recv %s (S,G)=%s to %s upstream=%s on %s", __PRETTY_FUNCTION__, is_join ? "join" : "prune", - src_str, grp_str, + pim_str_sg_dump (sg), is_local ? "local" : "non-local", up_str, recv_ifp->name); } @@ -506,7 +488,7 @@ static int nonlocal_upstream(int is_join, Since recv upstream addr was not directed to our primary address, check if we should react to it in any way. */ - check_recv_upstream(is_join, recv_ifp, upstream, source_addr, group_addr, + check_recv_upstream(is_join, recv_ifp, upstream, sg, source_flags, holdtime); return 1; /* non-local */ @@ -523,7 +505,7 @@ void pim_ifchannel_join_add(struct interface *ifp, struct pim_ifchannel *ch; if (nonlocal_upstream(1 /* join */, ifp, upstream, - sg->u.sg.src, sg->u.sg.grp, source_flags, holdtime)) { + sg, source_flags, holdtime)) { return; } @@ -625,7 +607,7 @@ void pim_ifchannel_prune(struct interface *ifp, int jp_override_interval_msec; if (nonlocal_upstream(0 /* prune */, ifp, upstream, - sg->u.sg.src, sg->u.sg.grp, source_flags, holdtime)) { + sg, source_flags, holdtime)) { return; } From ad410c6c7ba5121c87c95da28f6c68e960b4374d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 23 Jul 2016 00:06:55 -0400 Subject: [PATCH 033/386] pimd: SwitchToSptDesired now uses struct prefix *sg. Signed-off-by: Donald Sharp --- pimd/pim_register.c | 4 ++-- pimd/pim_upstream.c | 2 +- pimd/pim_upstream.h | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 608b1bf300..c1a78b722f 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -331,14 +331,14 @@ pim_register_recv (struct interface *ifp, } if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || - ((SwitchToSptDesired(source, group)) && + ((SwitchToSptDesired(&sg)) && (inherited_olist(source, group) == NULL))) { pim_register_stop_send (ifp, source, group, src_addr); sentRegisterStop = 1; } if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || - (SwitchToSptDesired(source, group))) { + (SwitchToSptDesired(&sg))) { if (sentRegisterStop) { pim_upstream_keep_alive_timer_start (upstream, PIM_RP_KEEPALIVE_PERIOD); } else { diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 85f45566a4..4931c6c667 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -749,7 +749,7 @@ pim_upstream_keep_alive_timer_start (struct pim_upstream *up, * received for the source and group. */ int -pim_upstream_switch_to_spt_desired (struct in_addr source, struct in_addr group) +pim_upstream_switch_to_spt_desired (struct prefix *sg) { return 0; } diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 7783cc4bc9..3bfddd7d05 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -146,8 +146,8 @@ void pim_upstream_update_my_assert_metric(struct pim_upstream *up); void pim_upstream_keep_alive_timer_start (struct pim_upstream *up, uint32_t time); -int pim_upstream_switch_to_spt_desired (struct in_addr source, struct in_addr group); -#define SwitchToSptDesired(S,G) pim_upstream_switch_to_spt_desired ((S), (G)) +int pim_upstream_switch_to_spt_desired (struct prefix *sg); +#define SwitchToSptDesired(sg) pim_upstream_switch_to_spt_desired (sg) void pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_register); From 65e1fcd766040fea4453effbbf09b31059d29e98 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 23 Jul 2016 00:35:35 -0400 Subject: [PATCH 034/386] pimd: pim_br switch to struct prefix Signed-off-by: Donald Sharp --- pimd/pim_br.c | 24 +++++++++++------------- pimd/pim_br.h | 6 +++--- pimd/pim_register.c | 38 +++++++++++++++++--------------------- pimd/pim_upstream.c | 2 +- 4 files changed, 32 insertions(+), 38 deletions(-) diff --git a/pimd/pim_br.c b/pimd/pim_br.c index 121a45fd16..ceee40e716 100644 --- a/pimd/pim_br.c +++ b/pimd/pim_br.c @@ -30,8 +30,7 @@ #include "linklist.h" struct pim_br { - struct in_addr source; - struct in_addr group; + struct prefix sg; struct in_addr pmbr; }; @@ -40,14 +39,14 @@ struct in_addr pim_br_unknown = { .s_addr = 0 }; static struct list *pim_br_list = NULL; struct in_addr -pim_br_get_pmbr (struct in_addr source, struct in_addr group) +pim_br_get_pmbr (struct prefix *sg) { struct listnode *node; struct pim_br *pim_br; for (ALL_LIST_ELEMENTS_RO (pim_br_list, node, pim_br)) { - if (source.s_addr == pim_br->source.s_addr && - group.s_addr == pim_br->group.s_addr) + if (sg->u.sg.src.s_addr == pim_br->sg.u.sg.src.s_addr && + sg->u.sg.grp.s_addr == pim_br->sg.u.sg.grp.s_addr) return pim_br->pmbr; } @@ -55,14 +54,14 @@ pim_br_get_pmbr (struct in_addr source, struct in_addr group) } void -pim_br_set_pmbr (struct in_addr source, struct in_addr group, struct in_addr br) +pim_br_set_pmbr (struct prefix *sg, struct in_addr br) { struct listnode *node, *next; struct pim_br *pim_br; for (ALL_LIST_ELEMENTS (pim_br_list, node, next, pim_br)) { - if (source.s_addr == pim_br->source.s_addr && - group.s_addr == pim_br->group.s_addr) + if (sg->u.sg.src.s_addr == pim_br->sg.u.sg.src.s_addr && + sg->u.sg.grp.s_addr == pim_br->sg.u.sg.grp.s_addr) break; } @@ -73,8 +72,7 @@ pim_br_set_pmbr (struct in_addr source, struct in_addr group, struct in_addr br) return; } - pim_br->source = source; - pim_br->group = group; + pim_br->sg = *sg; listnode_add(pim_br_list, pim_br); } @@ -86,14 +84,14 @@ pim_br_set_pmbr (struct in_addr source, struct in_addr group, struct in_addr br) * Remove the (S,G) from the stored values */ void -pim_br_clear_pmbr (struct in_addr source, struct in_addr group) +pim_br_clear_pmbr (struct prefix *sg) { struct listnode *node, *next; struct pim_br *pim_br; for (ALL_LIST_ELEMENTS (pim_br_list, node, next, pim_br)) { - if (source.s_addr == pim_br->source.s_addr && - group.s_addr == pim_br->group.s_addr) + if (sg->u.sg.src.s_addr == pim_br->sg.u.sg.src.s_addr && + sg->u.sg.grp.s_addr == pim_br->sg.u.sg.grp.s_addr) break; } diff --git a/pimd/pim_br.h b/pimd/pim_br.h index 06b10ada30..bcb864dfc1 100644 --- a/pimd/pim_br.h +++ b/pimd/pim_br.h @@ -21,10 +21,10 @@ #ifndef PIM_BR_H #define PIM_BR_H -struct in_addr pim_br_get_pmbr (struct in_addr source, struct in_addr group); +struct in_addr pim_br_get_pmbr (struct prefix *sg); -void pim_br_set_pmbr (struct in_addr source, struct in_addr group, struct in_addr value); -void pim_br_clear_pmbr (struct in_addr source, struct in_addr group); +void pim_br_set_pmbr (struct prefix *sg, struct in_addr value); +void pim_br_clear_pmbr (struct prefix *sg); void pim_br_init (void); diff --git a/pimd/pim_register.c b/pimd/pim_register.c index c1a78b722f..480c5e36cf 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -67,8 +67,8 @@ pim_check_is_my_ip_address (struct in_addr dest_addr) } static void -pim_register_stop_send (struct interface *ifp, struct in_addr source, - struct in_addr group, struct in_addr originator) +pim_register_stop_send (struct interface *ifp, struct prefix *sg, + struct in_addr originator) { struct pim_interface *pinfo; unsigned char buffer[3000]; @@ -80,12 +80,12 @@ pim_register_stop_send (struct interface *ifp, struct in_addr source, memset (buffer, 0, 3000); b1 = (uint8_t *)buffer + PIM_MSG_REGISTER_STOP_LEN; - length = pim_encode_addr_group (b1, AFI_IP, 0, 0, group); + length = pim_encode_addr_group (b1, AFI_IP, 0, 0, sg->u.sg.grp); b1length += length; b1 += length; p.family = AF_INET; - p.u.prefix4 = source; + p.u.prefix4 = sg->u.sg.src; p.prefixlen = 32; length = pim_encode_addr_ucast (b1, &p); b1length += length; @@ -243,8 +243,6 @@ pim_register_recv (struct interface *ifp, { int sentRegisterStop = 0; struct ip *ip_hdr; - struct in_addr group = { .s_addr = 0 }; - struct in_addr source = { .s_addr = 0 }; struct prefix sg; uint32_t *bits; @@ -288,21 +286,22 @@ pim_register_recv (struct interface *ifp, */ #define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4 ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN); - source = ip_hdr->ip_src; - group = ip_hdr->ip_dst; + memset (&sg, 0, sizeof (struct prefix)); + sg.u.sg.src = ip_hdr->ip_src; + sg.u.sg.grp = ip_hdr->ip_dst; - if (I_am_RP (group) && (dest_addr.s_addr == ((RP (group))->rpf_addr.s_addr))) { + if (I_am_RP (sg.u.sg.grp) && (dest_addr.s_addr == ((RP (sg.u.sg.grp))->rpf_addr.s_addr))) { sentRegisterStop = 0; if (*bits & PIM_REGISTER_BORDER_BIT) { - struct in_addr pimbr = pim_br_get_pmbr (source, group); + struct in_addr pimbr = pim_br_get_pmbr (&sg); if (PIM_DEBUG_PIM_PACKETS) zlog_debug("%s: Received Register message with Border bit set", __func__); if (pimbr.s_addr == pim_br_unknown.s_addr) - pim_br_set_pmbr(source, group, src_addr); + pim_br_set_pmbr(&sg, src_addr); else if (src_addr.s_addr != pimbr.s_addr) { - pim_register_stop_send (ifp, source, group, src_addr); + pim_register_stop_send (ifp, &sg, src_addr); if (PIM_DEBUG_PIM_PACKETS) zlog_debug("%s: Sending register-Stop to %s and dropping mr. packet", __func__, "Sender"); @@ -311,9 +310,6 @@ pim_register_recv (struct interface *ifp, } } - memset (&sg, 0, sizeof (struct prefix)); - sg.u.sg.src = source; - sg.u.sg.grp = group; struct pim_upstream *upstream = pim_upstream_find (&sg); /* * If we don't have a place to send ignore the packet @@ -326,14 +322,14 @@ pim_register_recv (struct interface *ifp, if (upstream->join_state == PIM_UPSTREAM_PRUNE) { - pim_register_stop_send (ifp, source, group, src_addr); + pim_register_stop_send (ifp, &sg, src_addr); return 1; } if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || ((SwitchToSptDesired(&sg)) && (inherited_olist(source, group) == NULL))) { - pim_register_stop_send (ifp, source, group, src_addr); + pim_register_stop_send (ifp, &sg, src_addr); sentRegisterStop = 1; } @@ -349,13 +345,13 @@ pim_register_recv (struct interface *ifp, if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) && !(*bits & PIM_REGISTER_NR_BIT)) { - pim_rp_set_upstream_addr (&upstream->upstream_addr, source); + pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.u.sg.src); pim_nexthop_lookup (&upstream->rpf.source_nexthop, upstream->upstream_addr, NULL); upstream->rpf.source_nexthop.interface = ifp; - upstream->sg.u.sg.src.s_addr = source.s_addr; + upstream->sg.u.sg.src = sg.u.sg.src; upstream->rpf.rpf_addr = upstream->rpf.source_nexthop.mrib_nexthop_addr; - upstream->channel_oil->oil.mfcc_origin = source; + upstream->channel_oil->oil.mfcc_origin = sg.u.sg.src; pim_scan_individual_oil (upstream->channel_oil); pim_upstream_send_join (upstream); @@ -363,7 +359,7 @@ pim_register_recv (struct interface *ifp, //inherited_olist(S,G,rpt) } } else { - pim_register_stop_send (ifp, source, group, src_addr); + pim_register_stop_send (ifp, &sg, src_addr); } return 1; diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 4931c6c667..60433dfe3d 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -686,7 +686,7 @@ pim_upstream_keep_alive_timer (struct thread *t) if (I_am_RP (up->sg.u.sg.grp)) { - pim_br_clear_pmbr (up->sg.u.sg.src, up->sg.u.sg.grp); + pim_br_clear_pmbr (&up->sg); /* * We need to do more here :) * But this is the start. From a3b58b4a14b838eb67c00a973d921bc060d66dca Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 23 Jul 2016 03:33:53 -0400 Subject: [PATCH 035/386] pimd: Fix _find and switch_to_spt_desired. The pim_upstream_find function should not be finding a *,G Find what is asked of it. The switch_to_spt_desired should return true on the RP currently. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 60433dfe3d..a2bca9f650 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -381,12 +381,9 @@ struct pim_upstream *pim_upstream_find(struct prefix *sg) struct pim_upstream *up; for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, up_node, up)) { - if (sg->u.sg.grp.s_addr == up->sg.u.sg.grp.s_addr) { - if ((up->sg.u.sg.src.s_addr == INADDR_ANY) || - (sg->u.sg.src.s_addr == up->sg.u.sg.src.s_addr)) { - return up; - } - } + if ((sg->u.sg.grp.s_addr == up->sg.u.sg.grp.s_addr) && + (sg->u.sg.src.s_addr == up->sg.u.sg.src.s_addr)) + return up; } return NULL; @@ -751,6 +748,9 @@ pim_upstream_keep_alive_timer_start (struct pim_upstream *up, int pim_upstream_switch_to_spt_desired (struct prefix *sg) { + if (I_am_RP (sg->u.sg.grp)) + return 1; + return 0; } From 7a60249e36d29145154653b45dbf147b6f8ae68c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 23 Jul 2016 03:36:25 -0400 Subject: [PATCH 036/386] pimd: Stop leaving pim_register_recv early When we received a pim_register_recv we were shortcutting the algorithm to determine what to do when we receive a register pim message. Signed-off-by: Donald Sharp --- pimd/pim_register.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 480c5e36cf..312e917827 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -320,12 +320,6 @@ pim_register_recv (struct interface *ifp, pim_upstream_switch (upstream, PIM_UPSTREAM_PRUNE); } - if (upstream->join_state == PIM_UPSTREAM_PRUNE) - { - pim_register_stop_send (ifp, &sg, src_addr); - return 1; - } - if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || ((SwitchToSptDesired(&sg)) && (inherited_olist(source, group) == NULL))) { From 4fdc8f363086445dcda388155794a56a70a79f70 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 23 Jul 2016 03:47:15 -0400 Subject: [PATCH 037/386] pimd: start fix of inherited_olist We were not correctly determing the inherited olist and applying it to the s,g. Start the work to do this. Signed-off-by: Donald Sharp --- pimd/pim_register.c | 3 +-- pimd/pim_upstream.c | 12 ++++++++++++ pimd/pim_upstream.h | 2 ++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 312e917827..0b78d08ce9 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -257,7 +257,6 @@ pim_register_recv (struct interface *ifp, return 0; } -#define inherited_olist(S,G) NULL /* * Please note this is not drawn to get the correct bit/data size * @@ -322,7 +321,7 @@ pim_register_recv (struct interface *ifp, if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || ((SwitchToSptDesired(&sg)) && - (inherited_olist(source, group) == NULL))) { + pim_upstream_inherited_olist (upstream) == 0)) { pim_register_stop_send (ifp, &sg, src_addr); sentRegisterStop = 1; } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index a2bca9f650..3cbe371549 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -849,3 +849,15 @@ pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_regist pim_upstream_register_stop_timer, up, time); } + +/* + * For a given upstream, determine the inherited_olist + * and apply it. + * return 1 if there are any output interfaces + * return 0 if there are not any output interfaces + */ +int +pim_upstream_inherited_olist (struct pim_upstream *up) +{ + return 0; +} diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 3bfddd7d05..0049c64992 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -156,4 +156,6 @@ void pim_upstream_send_join (struct pim_upstream *up); void pim_upstream_switch (struct pim_upstream *up, enum pim_upstream_state new_state); const char *pim_upstream_state2str (struct pim_upstream *up); + +int pim_upstream_inherited_olist (struct pim_upstream *up); #endif /* PIM_UPSTREAM_H */ From 7e0cff2f98e468dfab8df21b8579f81c06878aa2 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 23 Jul 2016 04:12:05 -0400 Subject: [PATCH 038/386] pimd: Remove unnecessary QuaggaId Signed-off-by: Donald Sharp --- pimd/AUTHORS | 1 - pimd/CAVEATS | 2 -- pimd/COMMANDS | 2 -- pimd/DEBUG | 1 - pimd/LINUX_KERNEL_MROUTE_MFC | 2 -- pimd/README | 1 - pimd/TODO | 2 -- pimd/pim_assert.c | 1 - pimd/pim_assert.h | 1 - pimd/pim_cmd.c | 1 - pimd/pim_cmd.h | 1 - pimd/pim_hello.c | 1 - pimd/pim_hello.h | 1 - pimd/pim_iface.c | 1 - pimd/pim_iface.h | 1 - pimd/pim_ifchannel.c | 1 - pimd/pim_ifchannel.h | 1 - pimd/pim_igmp.c | 1 - pimd/pim_igmp.h | 1 - pimd/pim_igmp_join.h | 1 - pimd/pim_igmpv3.c | 1 - pimd/pim_igmpv3.h | 1 - pimd/pim_int.c | 1 - pimd/pim_int.h | 1 - pimd/pim_join.c | 1 - pimd/pim_join.h | 1 - pimd/pim_macro.c | 1 - pimd/pim_macro.h | 1 - pimd/pim_main.c | 3 +-- pimd/pim_mroute.c | 1 - pimd/pim_mroute.h | 1 - pimd/pim_msg.c | 1 - pimd/pim_msg.h | 1 - pimd/pim_neighbor.c | 1 - pimd/pim_neighbor.h | 1 - pimd/pim_oil.c | 1 - pimd/pim_oil.h | 1 - pimd/pim_pim.c | 1 - pimd/pim_pim.h | 1 - pimd/pim_register.c | 3 ++- pimd/pim_rpf.c | 1 - pimd/pim_rpf.h | 1 - pimd/pim_signals.c | 1 - pimd/pim_signals.h | 1 - pimd/pim_sock.c | 1 - pimd/pim_sock.h | 1 - pimd/pim_ssmpingd.c | 1 - pimd/pim_ssmpingd.h | 1 - pimd/pim_static.c | 1 - pimd/pim_static.h | 1 - pimd/pim_str.c | 1 - pimd/pim_str.h | 1 - pimd/pim_time.c | 1 - pimd/pim_time.h | 1 - pimd/pim_tlv.c | 1 - pimd/pim_tlv.h | 1 - pimd/pim_upstream.c | 1 - pimd/pim_upstream.h | 1 - pimd/pim_util.c | 1 - pimd/pim_util.h | 1 - pimd/pim_version.c | 1 - pimd/pim_version.h | 1 - pimd/pim_vty.c | 1 - pimd/pim_vty.h | 1 - pimd/pim_zebra.c | 1 - pimd/pim_zebra.h | 1 - pimd/pim_zlookup.c | 1 - pimd/pim_zlookup.h | 1 - pimd/pimd.c | 1 - pimd/pimd.conf.sample | 1 - pimd/pimd.h | 1 - pimd/test_igmpv3_join.c | 1 - 72 files changed, 3 insertions(+), 77 deletions(-) diff --git a/pimd/AUTHORS b/pimd/AUTHORS index f6135a410e..aa58d958e1 100644 --- a/pimd/AUTHORS +++ b/pimd/AUTHORS @@ -1,4 +1,3 @@ -# $QuaggaId: $Format:%an, %ai, %h$ $ # Everton da Silva Marques $ more ~/.gitconfig diff --git a/pimd/CAVEATS b/pimd/CAVEATS index 9f07bda666..43dd823ae5 100644 --- a/pimd/CAVEATS +++ b/pimd/CAVEATS @@ -1,5 +1,3 @@ -# $QuaggaId: $Format:%an, %ai, %h$ $ - C1 IGMPv3 backward compatibility with IGMPv1 and IGMPv2 is not implemented. See RFC 3376, 7.3. Multicast Router Behavior. That's because only Source-Specific Multicast is currently targeted. diff --git a/pimd/COMMANDS b/pimd/COMMANDS index 425ac82297..c545eca56e 100644 --- a/pimd/COMMANDS +++ b/pimd/COMMANDS @@ -1,5 +1,3 @@ -# $QuaggaId: $Format:%an, %ai, %h$ $ - global configuration commands: pimd: ip multicast-routing Enable IP multicast forwarding diff --git a/pimd/DEBUG b/pimd/DEBUG index 72fb8264b9..ea1b14158d 100644 --- a/pimd/DEBUG +++ b/pimd/DEBUG @@ -1,4 +1,3 @@ -# $QuaggaId: $Format:%an, %ai, %h$ $ DEBUG HINTS diff --git a/pimd/LINUX_KERNEL_MROUTE_MFC b/pimd/LINUX_KERNEL_MROUTE_MFC index e87e567f9d..3e482465f1 100644 --- a/pimd/LINUX_KERNEL_MROUTE_MFC +++ b/pimd/LINUX_KERNEL_MROUTE_MFC @@ -1,5 +1,3 @@ -# $QuaggaId: $Format:%an, %ai, %h$ $ - # # The Linux Kernel MFC (Multicast Forwarding Cache) # diff --git a/pimd/README b/pimd/README index 1e3f72c838..9f7776fb45 100644 --- a/pimd/README +++ b/pimd/README @@ -1,5 +1,4 @@ # -# $QuaggaId: $Format:%an, %ai, %h$ $ # INTRODUCTION diff --git a/pimd/TODO b/pimd/TODO index 2308573b87..4c0f183100 100644 --- a/pimd/TODO +++ b/pimd/TODO @@ -1,5 +1,3 @@ -# $QuaggaId: $Format:%an, %ai, %h$ $ - T1 DONE Implement debug command test pim receive join diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index e8e3549d24..07f49c6adf 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_assert.h b/pimd/pim_assert.h index bd3fb3e253..c1f314f85b 100644 --- a/pimd/pim_assert.h +++ b/pimd/pim_assert.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_ASSERT_H diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 18957234cf..68899d8c7c 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_cmd.h b/pimd/pim_cmd.h index 53df562ab9..6e6e80d4f2 100644 --- a/pimd/pim_cmd.h +++ b/pimd/pim_cmd.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_CMD_H diff --git a/pimd/pim_hello.c b/pimd/pim_hello.c index 21d0e5b85c..3502f4e962 100644 --- a/pimd/pim_hello.c +++ b/pimd/pim_hello.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_hello.h b/pimd/pim_hello.h index b5e272d5de..3ab83db5eb 100644 --- a/pimd/pim_hello.h +++ b/pimd/pim_hello.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_HELLO_H diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 584aebb1d4..fae11b674a 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -16,7 +16,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index 790afabea1..75b85c306a 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_IFACE_H diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 80a98ad4b9..f940c4d4ef 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 2fd429ca04..e262944f03 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_IFCHANNEL_H diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 0f141d4fc6..6624edca59 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h index c6685c2837..2067bb30aa 100644 --- a/pimd/pim_igmp.h +++ b/pimd/pim_igmp.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_IGMP_H diff --git a/pimd/pim_igmp_join.h b/pimd/pim_igmp_join.h index 1700276de8..2c72a4bea6 100644 --- a/pimd/pim_igmp_join.h +++ b/pimd/pim_igmp_join.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_IGMP_JOIN_H diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index 2738a9ca5c..bf81c8d2c5 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_igmpv3.h b/pimd/pim_igmpv3.h index bb7e92672a..37baca5c8d 100644 --- a/pimd/pim_igmpv3.h +++ b/pimd/pim_igmpv3.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_IGMPV3_H diff --git a/pimd/pim_int.c b/pimd/pim_int.c index 208075190f..e922620f0d 100644 --- a/pimd/pim_int.c +++ b/pimd/pim_int.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_int.h b/pimd/pim_int.h index d64b103277..a0f281ccd8 100644 --- a/pimd/pim_int.h +++ b/pimd/pim_int.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_INT_H diff --git a/pimd/pim_join.c b/pimd/pim_join.c index e0ad3e4399..b5ebfb5d9a 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_join.h b/pimd/pim_join.h index 994b0e47e3..6777587c39 100644 --- a/pimd/pim_join.h +++ b/pimd/pim_join.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_JOIN_H diff --git a/pimd/pim_macro.c b/pimd/pim_macro.c index ea9fc3b063..e6eb462b77 100644 --- a/pimd/pim_macro.c +++ b/pimd/pim_macro.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_macro.h b/pimd/pim_macro.h index 472fa9b4e7..6cb5d3822e 100644 --- a/pimd/pim_macro.h +++ b/pimd/pim_macro.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_MACRO_H diff --git a/pimd/pim_main.c b/pimd/pim_main.c index aa3db3d5b2..2fb4a22f07 100644 --- a/pimd/pim_main.c +++ b/pimd/pim_main.c @@ -16,8 +16,7 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - $QuaggaId: $Format:%an, %ai, %h$ $ + */ #include diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 796b8cf2db..361fee499c 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_mroute.h b/pimd/pim_mroute.h index 176fb81cbc..a09c604486 100644 --- a/pimd/pim_mroute.h +++ b/pimd/pim_mroute.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_MROUTE_H diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index aa0433a2e2..92382ccc4d 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_msg.h b/pimd/pim_msg.h index a884fc84d9..ece900db5f 100644 --- a/pimd/pim_msg.h +++ b/pimd/pim_msg.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_MSG_H diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index 749390595a..2703b8fcf5 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_neighbor.h b/pimd/pim_neighbor.h index 5b2172dfc1..10d0cf3a68 100644 --- a/pimd/pim_neighbor.h +++ b/pimd/pim_neighbor.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_NEIGHBOR_H diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 2b26b54e08..a06b7937b6 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index c16e42efdb..fc5188e327 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_OIL_H diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 6b8478424b..382c9bc46d 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_pim.h b/pimd/pim_pim.h index e3559a2d97..01c9044a26 100644 --- a/pimd/pim_pim.h +++ b/pimd/pim_pim.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_PIM_H diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 0b78d08ce9..93483b8973 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -338,6 +338,7 @@ pim_register_recv (struct interface *ifp, if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) && !(*bits & PIM_REGISTER_NR_BIT)) { +#if 0 pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.u.sg.src); pim_nexthop_lookup (&upstream->rpf.source_nexthop, upstream->upstream_addr, NULL); @@ -347,7 +348,7 @@ pim_register_recv (struct interface *ifp, upstream->channel_oil->oil.mfcc_origin = sg.u.sg.src; pim_scan_individual_oil (upstream->channel_oil); pim_upstream_send_join (upstream); - +#endif //decapsulate and forward the iner packet to //inherited_olist(S,G,rpt) } diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 6ba1b2e499..b610d91073 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_rpf.h b/pimd/pim_rpf.h index 72cc7ba215..86c33c2e45 100644 --- a/pimd/pim_rpf.h +++ b/pimd/pim_rpf.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_RPF_H diff --git a/pimd/pim_signals.c b/pimd/pim_signals.c index 0344aa81d4..8e14627e4d 100644 --- a/pimd/pim_signals.c +++ b/pimd/pim_signals.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_signals.h b/pimd/pim_signals.h index 62523c038b..b05dbb39cb 100644 --- a/pimd/pim_signals.h +++ b/pimd/pim_signals.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_SIGNALS_H diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index 3eeda040b1..b100c37b46 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_sock.h b/pimd/pim_sock.h index cd29543fa0..556049d9b0 100644 --- a/pimd/pim_sock.h +++ b/pimd/pim_sock.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_SOCK_H diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c index 0bab8b6586..40873ca69f 100644 --- a/pimd/pim_ssmpingd.c +++ b/pimd/pim_ssmpingd.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_ssmpingd.h b/pimd/pim_ssmpingd.h index 4bef20b209..ab3351cde1 100644 --- a/pimd/pim_ssmpingd.h +++ b/pimd/pim_ssmpingd.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_SSMPINGD_H diff --git a/pimd/pim_static.c b/pimd/pim_static.c index 98c74caab5..a24a3f92a8 100644 --- a/pimd/pim_static.c +++ b/pimd/pim_static.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_static.h b/pimd/pim_static.h index 07d31d59b7..33f700ea78 100644 --- a/pimd/pim_static.h +++ b/pimd/pim_static.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_STATIC_H_ diff --git a/pimd/pim_str.c b/pimd/pim_str.c index 2d647876f6..f02732426e 100644 --- a/pimd/pim_str.c +++ b/pimd/pim_str.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_str.h b/pimd/pim_str.h index ea84362699..ca20352504 100644 --- a/pimd/pim_str.h +++ b/pimd/pim_str.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_STR_H diff --git a/pimd/pim_time.c b/pimd/pim_time.c index 4e5832cc65..ab3ac7340a 100644 --- a/pimd/pim_time.c +++ b/pimd/pim_time.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_time.h b/pimd/pim_time.h index 2984d9a8df..0081b21bbb 100644 --- a/pimd/pim_time.h +++ b/pimd/pim_time.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_TIME_H diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index f441e043a7..5269bb5efe 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_tlv.h b/pimd/pim_tlv.h index 586d989684..3f1b7a34e7 100644 --- a/pimd/pim_tlv.h +++ b/pimd/pim_tlv.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_TLV_H diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 3cbe371549..8fb51e2e82 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 0049c64992..18f302183a 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_UPSTREAM_H diff --git a/pimd/pim_util.c b/pimd/pim_util.c index 57a8488eca..daee941f8b 100644 --- a/pimd/pim_util.c +++ b/pimd/pim_util.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_util.h b/pimd/pim_util.h index a8613e2b97..23a9688647 100644 --- a/pimd/pim_util.h +++ b/pimd/pim_util.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_UTIL_H diff --git a/pimd/pim_version.c b/pimd/pim_version.c index f3a5ee3359..32020f6a83 100644 --- a/pimd/pim_version.c +++ b/pimd/pim_version.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_version.h b/pimd/pim_version.h index ef9f370c73..a4b34d1063 100644 --- a/pimd/pim_version.h +++ b/pimd/pim_version.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_VERSION_H diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 95792d5aa1..16ccd6f2b2 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_vty.h b/pimd/pim_vty.h index 904ee55302..787af60c3b 100644 --- a/pimd/pim_vty.h +++ b/pimd/pim_vty.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_VTY_H diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 87e2258ad7..66550d9cb2 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_zebra.h b/pimd/pim_zebra.h index 8e8f09551a..ae79ed815a 100644 --- a/pimd/pim_zebra.h +++ b/pimd/pim_zebra.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_ZEBRA_H diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 86d7edbd01..f38475b12c 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pim_zlookup.h b/pimd/pim_zlookup.h index f2be6d4fa0..b32dfe2b7c 100644 --- a/pimd/pim_zlookup.h +++ b/pimd/pim_zlookup.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIM_ZLOOKUP_H diff --git a/pimd/pimd.c b/pimd/pimd.c index 4ec9023f0a..d4a0250a0e 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include diff --git a/pimd/pimd.conf.sample b/pimd/pimd.conf.sample index 67530856b6..de1da6b838 100644 --- a/pimd/pimd.conf.sample +++ b/pimd/pimd.conf.sample @@ -1,6 +1,5 @@ ! ! pimd sample configuration file -! $QuaggaId: $Format:%an, %ai, %h$ $ ! hostname quagga-pimd-router password zebra diff --git a/pimd/pimd.h b/pimd/pimd.h index 8855a2ab3f..6ff36a2a51 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #ifndef PIMD_H diff --git a/pimd/test_igmpv3_join.c b/pimd/test_igmpv3_join.c index 5c4574024b..a345945ea4 100644 --- a/pimd/test_igmpv3_join.c +++ b/pimd/test_igmpv3_join.c @@ -17,7 +17,6 @@ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - $QuaggaId: $Format:%an, %ai, %h$ $ */ #include From 219e00134ca35eb999b52b3bed9b2f6bbbfd4caf Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 23 Jul 2016 05:36:44 -0400 Subject: [PATCH 039/386] pimd: Add code to handle the inheritance for (s,g) Add code to handle the inheritance and to send the join upstream as appropriate. Signed-off-by: Donald Sharp --- pimd/pim_register.c | 20 ++++++++--------- pimd/pim_upstream.c | 52 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 93483b8973..87a8ca935f 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -317,11 +317,20 @@ pim_register_recv (struct interface *ifp, { upstream = pim_upstream_add (&sg, ifp); pim_upstream_switch (upstream, PIM_UPSTREAM_PRUNE); + } if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || ((SwitchToSptDesired(&sg)) && pim_upstream_inherited_olist (upstream) == 0)) { + pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.u.sg.src); + pim_nexthop_lookup (&upstream->rpf.source_nexthop, + upstream->upstream_addr, NULL); + upstream->rpf.source_nexthop.interface = ifp; + upstream->sg.u.sg.src = sg.u.sg.src; + upstream->rpf.rpf_addr = upstream->rpf.source_nexthop.mrib_nexthop_addr; + upstream->channel_oil->oil.mfcc_origin = sg.u.sg.src; + pim_scan_individual_oil (upstream->channel_oil); pim_register_stop_send (ifp, &sg, src_addr); sentRegisterStop = 1; } @@ -338,17 +347,6 @@ pim_register_recv (struct interface *ifp, if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) && !(*bits & PIM_REGISTER_NR_BIT)) { -#if 0 - pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.u.sg.src); - pim_nexthop_lookup (&upstream->rpf.source_nexthop, - upstream->upstream_addr, NULL); - upstream->rpf.source_nexthop.interface = ifp; - upstream->sg.u.sg.src = sg.u.sg.src; - upstream->rpf.rpf_addr = upstream->rpf.source_nexthop.mrib_nexthop_addr; - upstream->channel_oil->oil.mfcc_origin = sg.u.sg.src; - pim_scan_individual_oil (upstream->channel_oil); - pim_upstream_send_join (upstream); -#endif //decapsulate and forward the iner packet to //inherited_olist(S,G,rpt) } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 8fb51e2e82..fc83acf7ea 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -852,11 +852,61 @@ pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_regist /* * For a given upstream, determine the inherited_olist * and apply it. + * + * inherited_olist(S,G,rpt) = + * ( joins(*,*,RP(G)) (+) joins(*,G) (-) prunes(S,G,rpt) ) + * (+) ( pim_include(*,G) (-) pim_exclude(S,G)) + * (-) ( lost_assert(*,G) (+) lost_assert(S,G,rpt) ) + * + * inherited_olist(S,G) = + * inherited_olist(S,G,rpt) (+) + * joins(S,G) (+) pim_include(S,G) (-) lost_assert(S,G) + * * return 1 if there are any output interfaces * return 0 if there are not any output interfaces */ int pim_upstream_inherited_olist (struct pim_upstream *up) { - return 0; + struct pim_upstream *anysrc_up; + struct pim_interface *pim_ifp; + struct listnode *ifnextnode; + struct listnode *chnextnode; + struct pim_ifchannel *ch; + struct listnode *chnode; + struct listnode *ifnode; + struct interface *ifp; + struct prefix anysrc; + int output_intf = 0; + + anysrc = up->sg; + anysrc.u.sg.src.s_addr = INADDR_ANY; + + anysrc_up = pim_upstream_find (&anysrc); + if (anysrc_up) + { + for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) + { + pim_ifp = ifp->info; + if (!pim_ifp) + continue; + + for (ALL_LIST_ELEMENTS (pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) + { + if (ch->upstream != anysrc_up) + continue; + + if (ch->ifjoin_state == PIM_IFJOIN_JOIN) + { + pim_ifchannel_add (ifp, &up->sg); + output_intf++; + } + } + } + } + + if (output_intf) + pim_upstream_send_join (up); + + return output_intf; } From 6c62910301f0d03e88c4c30286f95383ef8eb195 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 23 Jul 2016 06:01:55 -0400 Subject: [PATCH 040/386] pimd: Allow (*,G) joins to join a (s,g) that pre-exists Signed-off-by: Donald Sharp --- pimd/pim_join.c | 37 +++++++++++++++++++++++++++++++++++++ pimd/pim_upstream.c | 21 +++++++++++++++++++++ pimd/pim_upstream.h | 1 + 3 files changed, 59 insertions(+) diff --git a/pimd/pim_join.c b/pimd/pim_join.c index b5ebfb5d9a..c496b988ee 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -34,6 +34,8 @@ #include "pim_iface.h" #include "pim_hello.h" #include "pim_ifchannel.h" +#include "pim_rpf.h" +#include "pim_rp.h" static void on_trace(const char *label, struct interface *ifp, struct in_addr src) @@ -76,6 +78,25 @@ static void recv_join(struct interface *ifp, /* Restart join expiry timer */ pim_ifchannel_join_add(ifp, neigh->source_addr, upstream, &sg, source_flags, holdtime); + + if (I_am_RP (group) && source.s_addr == INADDR_ANY) + { + struct pim_upstream *up; + + up = pim_upstream_find_non_any (&sg); + + if (up) + { + zlog_debug("%s %s: Join(S,G)=%s from %s", + __FILE__, __PRETTY_FUNCTION__, + pim_str_sg_dump (&up->sg), pim_str_sg_dump (&sg)); + + pim_rp_set_upstream_addr (&up->upstream_addr, up->sg.u.sg.src); + pim_nexthop_lookup (&up->rpf.source_nexthop, up->upstream_addr, NULL); + pim_ifchannel_join_add (ifp, neigh->source_addr, upstream, &up->sg, source_flags, holdtime); + } + } + } static void recv_prune(struct interface *ifp, @@ -106,6 +127,22 @@ static void recv_prune(struct interface *ifp, } pim_ifchannel_prune(ifp, upstream, &sg, source_flags, holdtime); + + if (I_am_RP (group) && source.s_addr == INADDR_ANY) + { + struct pim_upstream *up; + + up = pim_upstream_find_non_any (&sg); + + if (up) + { + zlog_debug("%s %s: Prune(S,G)=%s from %s", + __FILE__, __PRETTY_FUNCTION__, + pim_str_sg_dump (&up->sg), pim_str_sg_dump (&sg)); + pim_ifchannel_prune (ifp, upstream, &up->sg, source_flags, holdtime); + } + } + } int pim_joinprune_recv(struct interface *ifp, diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index fc83acf7ea..34e7d9a759 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -374,6 +374,27 @@ static struct pim_upstream *pim_upstream_new(struct prefix *sg, return up; } +/* + * For a given sg, find any non * source + */ +struct pim_upstream *pim_upstream_find_non_any (struct prefix *sg) +{ + struct listnode *up_node; + struct prefix any = *sg; + struct pim_upstream *up; + + any.u.sg.src.s_addr = INADDR_ANY; + + for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, up_node, up)) + { + if ((any.u.sg.grp.s_addr == up->sg.u.sg.grp.s_addr) && + (up->sg.u.sg.src.s_addr != any.u.sg.src.s_addr)) + return up; + } + + return NULL; +} + struct pim_upstream *pim_upstream_find(struct prefix *sg) { struct listnode *up_node; diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 18f302183a..2fb193d42d 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -122,6 +122,7 @@ struct pim_upstream { void pim_upstream_free(struct pim_upstream *up); void pim_upstream_delete(struct pim_upstream *up); struct pim_upstream *pim_upstream_find (struct prefix *sg); +struct pim_upstream *pim_upstream_find_non_any (struct prefix *sg); struct pim_upstream *pim_upstream_add (struct prefix *sg, struct interface *ifp); void pim_upstream_del(struct pim_upstream *up); From 216bb84fd5f287d5e52ea170efd37cc002db8493 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 23 Jul 2016 12:30:41 -0400 Subject: [PATCH 041/386] pimd: Some bug fixes for the register receive code path When we receive a register receive handle it a bit better. Signed-off-by: Donald Sharp --- pimd/pim_register.c | 17 +++++++++-------- pimd/pim_upstream.c | 12 +++++++++--- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 87a8ca935f..79bfa4afc9 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -316,6 +316,14 @@ pim_register_recv (struct interface *ifp, if (!upstream) { upstream = pim_upstream_add (&sg, ifp); + + pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.u.sg.src); + pim_nexthop_lookup (&upstream->rpf.source_nexthop, + upstream->upstream_addr, NULL); + upstream->rpf.source_nexthop.interface = ifp; + upstream->sg.u.sg.src = sg.u.sg.src; + upstream->rpf.rpf_addr = upstream->rpf.source_nexthop.mrib_nexthop_addr; + pim_upstream_switch (upstream, PIM_UPSTREAM_PRUNE); } @@ -323,14 +331,7 @@ pim_register_recv (struct interface *ifp, if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || ((SwitchToSptDesired(&sg)) && pim_upstream_inherited_olist (upstream) == 0)) { - pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.u.sg.src); - pim_nexthop_lookup (&upstream->rpf.source_nexthop, - upstream->upstream_addr, NULL); - upstream->rpf.source_nexthop.interface = ifp; - upstream->sg.u.sg.src = sg.u.sg.src; - upstream->rpf.rpf_addr = upstream->rpf.source_nexthop.mrib_nexthop_addr; - upstream->channel_oil->oil.mfcc_origin = sg.u.sg.src; - pim_scan_individual_oil (upstream->channel_oil); + //pim_scan_individual_oil (upstream->channel_oil); pim_register_stop_send (ifp, &sg, src_addr); sentRegisterStop = 1; } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 34e7d9a759..7d20de6bda 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -507,7 +507,8 @@ void pim_upstream_update_join_desired(struct pim_upstream *up) /* switched from false to true */ if (is_join_desired && !was_join_desired) { - zassert(up->join_state == PIM_UPSTREAM_NOTJOINED); + zassert(up->join_state == PIM_UPSTREAM_NOTJOINED || + up->join_state == PIM_UPSTREAM_PRUNE); pim_upstream_switch(up, PIM_UPSTREAM_JOINED); return; } @@ -914,12 +915,16 @@ pim_upstream_inherited_olist (struct pim_upstream *up) for (ALL_LIST_ELEMENTS (pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) { + struct pim_ifchannel *nch; + if (ch->upstream != anysrc_up) continue; if (ch->ifjoin_state == PIM_IFJOIN_JOIN) { - pim_ifchannel_add (ifp, &up->sg); + nch = pim_ifchannel_add (ifp, &up->sg); + pim_ifchannel_ifjoin_switch (__PRETTY_FUNCTION__, nch, PIM_IFJOIN_JOIN); + pim_forward_start (ch); output_intf++; } } @@ -927,7 +932,8 @@ pim_upstream_inherited_olist (struct pim_upstream *up) } if (output_intf) - pim_upstream_send_join (up); + if (up->join_state != PIM_UPSTREAM_JOINED) + pim_upstream_switch (up, PIM_UPSTREAM_JOINED); return output_intf; } From c823065de9272719824d40b3483e847bb2f0dc99 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 26 Jul 2016 21:00:09 -0400 Subject: [PATCH 042/386] pimd: Add some 'show debug pim' output Add some missing 'show debug pim' output so that I can see what I think I'm debugging. In general the pim debugs need another round of fixing. Signed-off-by: Donald Sharp --- pimd/pim_vty.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 16ccd6f2b2..c6fb3464b1 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -35,7 +35,8 @@ #include "pim_oil.h" #include "pim_static.h" -int pim_debug_config_write(struct vty *vty) +int +pim_debug_config_write (struct vty *vty) { int writes = 0; @@ -51,6 +52,10 @@ int pim_debug_config_write(struct vty *vty) vty_out(vty, "debug igmp trace%s", VTY_NEWLINE); ++writes; } + if (PIM_DEBUG_IGMP_TRACE_DETAIL) { + vty_out(vty, "debug igmp trace detail%s", VTY_NEWLINE); + ++writes; + } if (PIM_DEBUG_MROUTE) { vty_out(vty, "debug mroute%s", VTY_NEWLINE); @@ -73,10 +78,15 @@ int pim_debug_config_write(struct vty *vty) vty_out(vty, "debug pim packet-dump receive%s", VTY_NEWLINE); ++writes; } + if (PIM_DEBUG_PIM_TRACE) { vty_out(vty, "debug pim trace%s", VTY_NEWLINE); ++writes; } + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + vty_out(vty, "debug pim trace detail%s", VTY_NEWLINE); + ++writes; + } if (PIM_DEBUG_ZEBRA) { vty_out(vty, "debug pim zebra%s", VTY_NEWLINE); @@ -88,6 +98,21 @@ int pim_debug_config_write(struct vty *vty) ++writes; } + if (PIM_DEBUG_PIM_HELLO) { + vty_out (vty, "debug pim packets hello%s", VTY_NEWLINE); + ++writes; + } + + if (PIM_DEBUG_PIM_J_P) { + vty_out (vty, "debug pim packets join%s", VTY_NEWLINE); + ++writes; + } + + if (PIM_DEBUG_STATIC) { + vty_out (vty, "debug pim static%s", VTY_NEWLINE); + ++writes; + } + return writes; } From 4950938e0cc100bb74d3f261d9c57e2488ac1f31 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 23 Jul 2016 19:18:19 -0400 Subject: [PATCH 043/386] pimd: Fix Join/Prune logging For some reason Join/Prune debugs were being turned on by trace not by the 'debug pim packets join' command. Signed-off-by: Donald Sharp --- pimd/pim_join.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/pimd/pim_join.c b/pimd/pim_join.c index c496b988ee..5a2ff744e5 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -37,8 +37,9 @@ #include "pim_rpf.h" #include "pim_rp.h" -static void on_trace(const char *label, - struct interface *ifp, struct in_addr src) +static void +on_trace (const char *label, + struct interface *ifp, struct in_addr src) { if (PIM_DEBUG_PIM_TRACE) { char src_str[100]; @@ -183,7 +184,7 @@ int pim_joinprune_recv(struct interface *ifp, Check upstream address family */ if (msg_upstream_addr.family != AF_INET) { - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_PIM_J_P) { char src_str[100]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: ignoring join/prune directed to unexpected addr family=%d from %s on %s", @@ -210,16 +211,16 @@ int pim_joinprune_recv(struct interface *ifp, ++buf; ++buf; - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_PIM_J_P) { char src_str[100]; char upstream_str[100]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); pim_inet4_dump("", msg_upstream_addr.u.prefix4, upstream_str, sizeof(upstream_str)); - zlog_warn("%s: join/prune upstream=%s groups=%d holdtime=%d from %s on %s", - __PRETTY_FUNCTION__, - upstream_str, msg_num_groups, msg_holdtime, - src_str, ifp->name); + zlog_debug ("%s: join/prune upstream=%s groups=%d holdtime=%d from %s on %s", + __PRETTY_FUNCTION__, + upstream_str, msg_num_groups, msg_holdtime, + src_str, ifp->name); } /* Scan groups */ @@ -253,7 +254,7 @@ int pim_joinprune_recv(struct interface *ifp, msg_num_pruned_sources = ntohs(*(const uint16_t *) buf); buf += 2; - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_PIM_J_P) { char src_str[100]; char upstream_str[100]; char group_str[100]; @@ -322,6 +323,8 @@ int pim_joinprune_send(struct interface *ifp, int pim_msg_size; int remain; + on_trace (__PRETTY_FUNCTION__, ifp, upstream_addr); + zassert(ifp); pim_ifp = ifp->info; @@ -333,7 +336,7 @@ int pim_joinprune_send(struct interface *ifp, return -1; } - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_PIM_J_P) { char dst_str[100]; pim_inet4_dump("", upstream_addr, dst_str, sizeof(dst_str)); zlog_debug("%s: sending %s(S,G)=%s to upstream=%s on interface %s", @@ -343,7 +346,7 @@ int pim_joinprune_send(struct interface *ifp, } if (PIM_INADDR_IS_ANY(upstream_addr)) { - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_PIM_J_P) { char dst_str[100]; pim_inet4_dump("", upstream_addr, dst_str, sizeof(dst_str)); zlog_debug("%s: %s(S,G)=%s: upstream=%s is myself on interface %s", From 630f76b6f174aff0b9662e3fdd455529b1250266 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 23 Jul 2016 19:54:51 -0400 Subject: [PATCH 044/386] pimd: Make kernel upcalls PIM_DEBUG_MROUTE The kernel upcalls for control messages should be PIM_DEBUG_MROUTE instead of PIM_DEBUG_PIM_TRACE Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 361fee499c..7893bc926b 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -116,13 +116,13 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg */ if (!pim_mroute_connected_to_source (ifp, msg->im_src)) { - if (PIM_DEBUG_PIM_TRACE) + if (PIM_DEBUG_MROUTE) zlog_debug ("%s: Received incoming packet that does originate on our seg", __PRETTY_FUNCTION__); return 0; } - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_MROUTE) { zlog_debug("%s: Adding a Route for %s from %s for WHOLEPKT consumption", __PRETTY_FUNCTION__, grp_str, src_str); } @@ -132,7 +132,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg sg.u.sg.grp = msg->im_dst; up = pim_upstream_add (&sg, ifp); if (!up) { - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_MROUTE) { zlog_debug("%s: Failure to add upstream information for %s", __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); @@ -145,7 +145,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg up->channel_oil = pim_channel_oil_add(&sg, pim_ifp->mroute_vif_index); if (!up->channel_oil) { - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_MROUTE) { zlog_debug("%s: Failure to add channel oil for (%s,%s)", __PRETTY_FUNCTION__, src_str, grp_str); @@ -179,7 +179,7 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf, up = pim_upstream_find(&sg); if (!up) { - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_MROUTE) { zlog_debug("%s: Unable to find upstream channel WHOLEPKT%s", __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); } @@ -194,7 +194,7 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf, (!pim_ifp) || (!(PIM_I_am_DR(pim_ifp))) || (pim_ifp->itype == PIM_INTERFACE_SSM)) { - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_MROUTE) { zlog_debug("%s: Failed Check send packet", __PRETTY_FUNCTION__); } return 0; @@ -229,7 +229,7 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms */ if (!ifp) { - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_MROUTE) { zlog_debug("%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); @@ -239,7 +239,7 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms pim_ifp = ifp->info; if (!pim_ifp) { - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_MROUTE) { zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) multicast not enabled on interface %s", __PRETTY_FUNCTION__, src_str, grp_str, ifp->name); @@ -252,7 +252,7 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms sg.u.sg.grp = msg->im_dst; ch = pim_ifchannel_find(ifp, &sg); if (!ch) { - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_MROUTE) { zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) could not find channel on interface %s", __PRETTY_FUNCTION__, src_str, grp_str, ifp->name); @@ -275,7 +275,7 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms */ if (ch->ifassert_state != PIM_IFASSERT_NOINFO) { - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_MROUTE) { 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); @@ -284,7 +284,7 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms } if (!PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_MROUTE) { zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) interface %s is not downstream for channel", __PRETTY_FUNCTION__, src_str, grp_str, ifp->name); @@ -293,7 +293,7 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms } if (assert_action_a1(ch)) { - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_MROUTE) { zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) assert_action_a1 failure on interface %s", __PRETTY_FUNCTION__, src_str, grp_str, ifp->name); @@ -317,7 +317,7 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size) /* kernel upcall must have protocol=0 */ if (ip_hdr->ip_p) { /* this is not a kernel upcall */ - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_MROUTE) { pim_inet4_dump("", ip_hdr->ip_src, src_str, sizeof(src_str)); pim_inet4_dump("", ip_hdr->ip_dst, grp_str, sizeof(grp_str)); zlog_debug("%s: not a kernel upcall proto=%d src: %s dst: %s msg_size=%d", @@ -330,7 +330,7 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size) ifp = pim_if_find_by_vif_index(msg->im_vif); - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_MROUTE) { 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", From 4d99418beb40898c043efb77543ff19228cee211 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 24 Jul 2016 01:15:09 -0400 Subject: [PATCH 045/386] pimd: Find the parent on newly created upstream's When we create a new upstream data structure find the parent. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 31 +++++++++++++++++++++++++++++++ pimd/pim_upstream.h | 1 + 2 files changed, 32 insertions(+) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 7d20de6bda..b404e144e8 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -50,6 +50,36 @@ static void join_timer_start(struct pim_upstream *up); static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up); +/* + * If we have a (*,*) || (S,*) there is no parent + * If we have a (S,G), find the (*,G) + * If we have a (*,G), find the (*,*) + */ +static struct pim_upstream * +pim_upstream_find_parent (struct prefix *sg) +{ + struct prefix any = *sg; + + // (*,*) || (S,*) + if (((sg->u.sg.src.s_addr == INADDR_ANY) && + (sg->u.sg.grp.s_addr == INADDR_ANY)) || + ((sg->u.sg.src.s_addr != INADDR_ANY) && + (sg->u.sg.grp.s_addr == INADDR_ANY))) + return NULL; + + // (S,G) + if ((sg->u.sg.src.s_addr != INADDR_ANY) && + (sg->u.sg.grp.s_addr != INADDR_ANY)) + { + any.u.sg.src.s_addr = INADDR_ANY; + return pim_upstream_find (&any); + } + + // (*,G) + any.u.sg.grp.s_addr = INADDR_ANY; + return pim_upstream_find (&any); +} + void pim_upstream_free(struct pim_upstream *up) { XFREE(MTYPE_PIM_UPSTREAM, up); @@ -347,6 +377,7 @@ static struct pim_upstream *pim_upstream_new(struct prefix *sg, return NULL; } + up->parent = pim_upstream_find_parent (sg); up->flags = 0; up->ref_count = 1; up->t_join_timer = NULL; diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 2fb193d42d..92535c46b0 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -87,6 +87,7 @@ enum pim_upstream_sptbit { See RFC 4601: 4.5.7. Sending (S,G) Join/Prune Message */ struct pim_upstream { + struct pim_upstream *parent; int fhr; struct in_addr upstream_addr;/* Who we are talking to */ struct prefix sg; /* (S,G) group key */ From 7293a05356086cc75cc0690f4b03110229771743 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 27 Jul 2016 15:39:28 -0400 Subject: [PATCH 046/386] pimd: Fixup pim_oil interface to be a bit more consistent. Signed-off-by: Donald Sharp --- pimd/pim_oil.c | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index a06b7937b6..8c7beeb97b 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -37,7 +37,8 @@ void pim_channel_oil_free(struct channel_oil *c_oil) XFREE(MTYPE_PIM_CHANNEL_OIL, c_oil); } -static void pim_channel_oil_delete(struct channel_oil *c_oil) +static void +pim_del_channel_oil (struct channel_oil *c_oil) { /* notice that listnode_delete() can't be moved @@ -49,14 +50,15 @@ static void pim_channel_oil_delete(struct channel_oil *c_oil) pim_channel_oil_free(c_oil); } -static struct channel_oil *channel_oil_new(struct prefix *sg, - int input_vif_index) +static struct channel_oil * +pim_add_channel_oil (struct prefix *sg, + int input_vif_index) { struct channel_oil *c_oil; - struct interface *ifp_in; + struct interface *ifp; - ifp_in = pim_if_find_by_vif_index(input_vif_index); - if (!ifp_in) { + ifp = pim_if_find_by_vif_index(input_vif_index); + if (!ifp) { /* warning only */ zlog_warn("%s: (S,G)=%s could not find input interface for input_vif_index=%d", __PRETTY_FUNCTION__, @@ -66,7 +68,7 @@ static struct channel_oil *channel_oil_new(struct prefix *sg, c_oil = XCALLOC(MTYPE_PIM_CHANNEL_OIL, sizeof(*c_oil)); if (!c_oil) { zlog_err("PIM XCALLOC(%zu) failure", sizeof(*c_oil)); - return 0; + return NULL; } c_oil->oil.mfcc_mcastgrp = sg->u.sg.grp; @@ -75,22 +77,6 @@ static struct channel_oil *channel_oil_new(struct prefix *sg, c_oil->oil_ref_count = 1; c_oil->installed = 0; - zassert(c_oil->oil_size == 0); - - return c_oil; -} - -static struct channel_oil *pim_add_channel_oil(struct prefix *sg, - int input_vif_index) -{ - struct channel_oil *c_oil; - - c_oil = channel_oil_new(sg, input_vif_index); - if (!c_oil) { - zlog_warn("PIM XCALLOC(%zu) failure", sizeof(*c_oil)); - return 0; - } - listnode_add(qpim_channel_oil_list, c_oil); return c_oil; @@ -129,7 +115,7 @@ void pim_channel_oil_del(struct channel_oil *c_oil) --c_oil->oil_ref_count; if (c_oil->oil_ref_count < 1) { - pim_channel_oil_delete(c_oil); + pim_del_channel_oil(c_oil); } } From 984c84f48600a9c6b7b0513e3ad8f234465dec1e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 27 Jul 2016 15:27:52 -0400 Subject: [PATCH 047/386] pimd: Start abstraction for WC and RPT bits Start the abstraction of the WC and RPT bits so we can send the data as appropriate. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 3 ++- pimd/pim_join.c | 3 ++- pimd/pim_msg.c | 8 ++++---- pimd/pim_msg.h | 7 ++++++- pimd/pim_tlv.c | 27 +++++++++++++++++++++++++++ 5 files changed, 41 insertions(+), 7 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 68899d8c7c..c089a3fd3f 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4624,7 +4624,8 @@ static int recv_joinprune(struct vty *vty, remain = buf_pastend - pim_msg_curr; pim_msg_curr = pim_msg_addr_encode_ipv4_source(pim_msg_curr, remain, - source_addr); + source_addr, + PIM_ENCODE_SPARSE_BIT); if (!pim_msg_curr) { vty_out(vty, "Failure encoding source address %s: space left=%d%s", source_str, remain, VTY_NEWLINE); diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 5a2ff744e5..2806320c02 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -431,7 +431,8 @@ int pim_joinprune_send(struct interface *ifp, remain = pastend - pim_msg_curr; pim_msg_curr = pim_msg_addr_encode_ipv4_source(pim_msg_curr, remain, - sg->u.sg.src); + sg->u.sg.src, + PIM_ENCODE_SPARSE_BIT); if (!pim_msg_curr) { char source_str[100]; pim_inet4_dump("", sg->u.sg.src, source_str, sizeof(source_str)); diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index 92382ccc4d..2027d42119 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -87,9 +87,9 @@ uint8_t *pim_msg_addr_encode_ipv4_group(uint8_t *buf, return buf + ENCODED_IPV4_GROUP_SIZE; } -uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, - int buf_size, - struct in_addr addr) +uint8_t * +pim_msg_addr_encode_ipv4_source(uint8_t *buf, int buf_size, + struct in_addr addr, uint8_t bits) { const int ENCODED_IPV4_SOURCE_SIZE = 8; @@ -99,7 +99,7 @@ uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ buf[1] = '\0'; /* native encoding */ - buf[2] = 4; /* reserved = 0 | S bit = 1 | W bit = 0 | R bit = 0 */ + buf[2] = bits; buf[3] = 32; /* mask len */ memcpy(buf+4, &addr, sizeof(struct in_addr)); diff --git a/pimd/pim_msg.h b/pimd/pim_msg.h index ece900db5f..4a13040af6 100644 --- a/pimd/pim_msg.h +++ b/pimd/pim_msg.h @@ -44,8 +44,13 @@ uint8_t *pim_msg_addr_encode_ipv4_ucast(uint8_t *buf, uint8_t *pim_msg_addr_encode_ipv4_group(uint8_t *buf, int buf_size, struct in_addr addr); + +#define PIM_ENCODE_SPARSE_BIT 0x04 +#define PIM_ENCODE_WC_BIT 0x02 +#define PIM_ENCODE_RPT_BIT 0x01 uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, int buf_size, - struct in_addr addr); + struct in_addr addr, + uint8_t bits); #endif /* PIM_MSG_H */ diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index 5269bb5efe..93227d6339 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -96,6 +96,33 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf, #define ucast_ipv4_encoding_len (2 + sizeof(struct in_addr)) +/* + * An Encoded-Unicast address takes the following format: + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Addr Family | Encoding Type | Unicast Address + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+... + * + * Addr Family + * The PIM address family of the 'Unicast Address' field of this + * address. + * + * Values 0-127 are as assigned by the IANA for Internet Address * Families in [7]. Values 128-250 are reserved to be assigned by + * the IANA for PIM-specific Address Families. Values 251 though + * 255 are designated for private use. As there is no assignment + * authority for this space, collisions should be expected. + * + * Encoding Type + * The type of encoding used within a specific Address Family. The + * value '0' is reserved for this field and represents the native + * encoding of the Address Family. + * + * Unicast Address + * The unicast address as represented by the given Address Family + * and Encoding Type. + */ int pim_encode_addr_ucast (uint8_t *buf, struct prefix *p) { From 346cffe31ef871d7876aacafea9cf4086146f110 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 27 Jul 2016 16:33:41 -0400 Subject: [PATCH 048/386] pimd: Revamp send of join/prune to actually set bits right. When a *,G report is sent, the RPT and WC bits are set as well as the source is the RP address for the group. If this routers idea of the RP for this group is different than the idea of the RP from the sender than that particular *,G can be dropped. Ticket: CM-12031 Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 88 ++-------------------------------------- pimd/pim_join.c | 104 ++++++++++++------------------------------------ pimd/pim_msg.c | 94 +++++++++++++++++++++++++++++++++++++++++++ pimd/pim_msg.h | 4 ++ 4 files changed, 126 insertions(+), 164 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index c089a3fd3f..b94fb1c767 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4474,7 +4474,6 @@ static int recv_joinprune(struct vty *vty, uint8_t buf[1000]; const uint8_t *buf_pastend = buf + sizeof(buf); uint8_t *pim_msg; - uint8_t *pim_msg_curr; int pim_msg_size; struct ip *ip_hdr; size_t ip_hlen; /* ip header length in bytes */ @@ -4491,9 +4490,6 @@ static int recv_joinprune(struct vty *vty, const char *ifname; struct interface *ifp; int result; - int remain; - uint16_t num_joined; - uint16_t num_pruned; /* Find interface */ ifname = argv[0]->arg; @@ -4557,87 +4553,9 @@ static int recv_joinprune(struct vty *vty, */ pim_msg = buf + ip_hlen; - /* skip room for pim header */ - pim_msg_curr = pim_msg + PIM_MSG_HEADER_LEN; - - remain = buf_pastend - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_ucast(pim_msg_curr, - remain, - neigh_dst_addr); - if (!pim_msg_curr) { - vty_out(vty, "Failure encoding destination address %s: space left=%d%s", - neigh_dst_str, remain, VTY_NEWLINE); - return CMD_WARNING; - } - - remain = buf_pastend - pim_msg_curr; - if (remain < 4) { - vty_out(vty, "Group will not fit: space left=%d%s", - remain, VTY_NEWLINE); - return CMD_WARNING; - } - - *pim_msg_curr = 0; /* reserved */ - ++pim_msg_curr; - *pim_msg_curr = 1; /* number of groups */ - ++pim_msg_curr; - *((uint16_t *) pim_msg_curr) = htons(neigh_holdtime); - ++pim_msg_curr; - ++pim_msg_curr; - - remain = buf_pastend - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_group(pim_msg_curr, - remain, - group_addr); - if (!pim_msg_curr) { - vty_out(vty, "Failure encoding group address %s: space left=%d%s", - group_str, remain, VTY_NEWLINE); - return CMD_WARNING; - } - - remain = buf_pastend - pim_msg_curr; - if (remain < 4) { - vty_out(vty, "Sources will not fit: space left=%d%s", - remain, VTY_NEWLINE); - return CMD_WARNING; - } - - if (src_is_join) { - num_joined = 1; - num_pruned = 0; - } - else { - num_joined = 0; - num_pruned = 1; - } - - /* number of joined sources */ - *((uint16_t *) pim_msg_curr) = htons(num_joined); - ++pim_msg_curr; - ++pim_msg_curr; - - /* number of pruned sources */ - *((uint16_t *) pim_msg_curr) = htons(num_pruned); - ++pim_msg_curr; - ++pim_msg_curr; - - remain = buf_pastend - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_source(pim_msg_curr, - remain, - source_addr, - PIM_ENCODE_SPARSE_BIT); - if (!pim_msg_curr) { - vty_out(vty, "Failure encoding source address %s: space left=%d%s", - source_str, remain, VTY_NEWLINE); - return CMD_WARNING; - } - - /* Add PIM header */ - - pim_msg_size = pim_msg_curr - pim_msg; - - pim_msg_build_header(pim_msg, pim_msg_size, - PIM_MSG_TYPE_JOIN_PRUNE); + pim_msg_size = pim_msg_join_prune_encode (pim_msg, buf_pastend - pim_msg, src_is_join, + source_addr, group_addr, neigh_dst_addr, + neigh_holdtime); /* "Receive" message diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 2806320c02..732dd823ad 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -75,7 +75,26 @@ static void recv_join(struct interface *ifp, source_flags & PIM_WILDCARD_BIT_MASK, up_str, holdtime, neigh_str, ifp->name); } - + + /* + * If the RPT and WC are set it's a (*,G) + * and the source is the RP + */ + if ((source_flags & PIM_RPT_BIT_MASK) && + (source_flags & PIM_WILDCARD_BIT_MASK)) + { + struct pim_rpf *rp = RP (sg.u.sg.grp); + + /* + * If the RP sent in the message is not + * our RP for the group, drop the message + */ + if (sg.u.sg.src.s_addr != rp->rpf_addr.s_addr) + return; + + sg.u.sg.src.s_addr = INADDR_ANY; + } + /* Restart join expiry timer */ pim_ifchannel_join_add(ifp, neigh->source_addr, upstream, &sg, source_flags, holdtime); @@ -318,10 +337,7 @@ int pim_joinprune_send(struct interface *ifp, { struct pim_interface *pim_ifp; uint8_t pim_msg[1000]; - const uint8_t *pastend = pim_msg + sizeof(pim_msg); - uint8_t *pim_msg_curr = pim_msg + PIM_MSG_HEADER_LEN; /* room for pim header */ int pim_msg_size; - int remain; on_trace (__PRETTY_FUNCTION__, ifp, upstream_addr); @@ -371,82 +387,12 @@ int pim_joinprune_send(struct interface *ifp, /* Build PIM message */ + pim_msg_size = pim_msg_join_prune_encode (pim_msg, 1000, send_join, + sg->u.sg.src, sg->u.sg.grp, + upstream_addr, PIM_JP_HOLDTIME); - remain = pastend - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_ucast(pim_msg_curr, - remain, - upstream_addr); - if (!pim_msg_curr) { - char dst_str[100]; - pim_inet4_dump("", upstream_addr, dst_str, sizeof(dst_str)); - zlog_warn("%s: failure encoding destination address %s: space left=%d", - __PRETTY_FUNCTION__, dst_str, remain); - return -3; - } - - remain = pastend - pim_msg_curr; - if (remain < 4) { - zlog_warn("%s: group will not fit: space left=%d", - __PRETTY_FUNCTION__, remain); - return -4; - } - - *pim_msg_curr = 0; /* reserved */ - ++pim_msg_curr; - *pim_msg_curr = 1; /* number of groups */ - ++pim_msg_curr; - *((uint16_t *) pim_msg_curr) = htons(PIM_JP_HOLDTIME); - ++pim_msg_curr; - ++pim_msg_curr; - - remain = pastend - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_group(pim_msg_curr, - remain, - sg->u.sg.grp); - if (!pim_msg_curr) { - char group_str[100]; - pim_inet4_dump("", sg->u.sg.grp, group_str, sizeof(group_str)); - zlog_warn("%s: failure encoding group address %s: space left=%d", - __PRETTY_FUNCTION__, group_str, remain); - return -5; - } - - remain = pastend - pim_msg_curr; - if (remain < 4) { - zlog_warn("%s: sources will not fit: space left=%d", - __PRETTY_FUNCTION__, remain); - return -6; - } - - /* number of joined sources */ - *((uint16_t *) pim_msg_curr) = htons(send_join ? 1 : 0); - ++pim_msg_curr; - ++pim_msg_curr; - - /* number of pruned sources */ - *((uint16_t *) pim_msg_curr) = htons(send_join ? 0 : 1); - ++pim_msg_curr; - ++pim_msg_curr; - - remain = pastend - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_source(pim_msg_curr, - remain, - sg->u.sg.src, - PIM_ENCODE_SPARSE_BIT); - if (!pim_msg_curr) { - char source_str[100]; - pim_inet4_dump("", sg->u.sg.src, source_str, sizeof(source_str)); - zlog_warn("%s: failure encoding source address %s: space left=%d", - __PRETTY_FUNCTION__, source_str, remain); - return -7; - } - - /* Add PIM header */ - - pim_msg_size = pim_msg_curr - pim_msg; - - pim_msg_build_header(pim_msg, pim_msg_size, - PIM_MSG_TYPE_JOIN_PRUNE); + if (pim_msg_size < 0) + return pim_msg_size; if (pim_msg_send(pim_ifp->pim_sock_fd, qpim_all_pim_routers_addr, diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index 2027d42119..61fc480bf9 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -22,11 +22,13 @@ #include #include "if.h" +#include "log.h" #include "pimd.h" #include "pim_pim.h" #include "pim_msg.h" #include "pim_util.h" +#include "pim_str.h" void pim_msg_build_header(uint8_t *pim_msg, int pim_msg_size, uint8_t pim_msg_type) @@ -105,3 +107,95 @@ pim_msg_addr_encode_ipv4_source(uint8_t *buf, int buf_size, return buf + ENCODED_IPV4_SOURCE_SIZE; } + +int +pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, + struct in_addr source, struct in_addr group, + struct in_addr upstream, int holdtime) +{ + uint8_t *pim_msg = buf; + uint8_t *pim_msg_curr = buf + PIM_MSG_HEADER_LEN; + uint8_t *end = buf + buf_size; + struct in_addr stosend; + uint8_t bits; + int remain; + + remain = end - pim_msg_curr; + pim_msg_curr = pim_msg_addr_encode_ipv4_ucast (pim_msg_curr, buf_size - PIM_MSG_HEADER_LEN, upstream); + if (!pim_msg_curr) { + char dst_str[100]; + pim_inet4_dump("", upstream, dst_str, sizeof(dst_str)); + zlog_warn("%s: failure encoding destination address %s: space left=%d", + __PRETTY_FUNCTION__, dst_str, remain); + return -3; + } + + remain = end - pim_msg_curr; + if (remain < 4) { + zlog_warn("%s: group will not fit: space left=%d", + __PRETTY_FUNCTION__, remain); + return -4; + } + + *pim_msg_curr = 0; /* reserved */ + ++pim_msg_curr; + *pim_msg_curr = 1; /* number of groups */ + ++pim_msg_curr; + + *((uint16_t *) pim_msg_curr) = htons(holdtime); + ++pim_msg_curr; + ++pim_msg_curr; + + remain = end - pim_msg_curr; + pim_msg_curr = pim_msg_addr_encode_ipv4_group (pim_msg_curr, remain, + group); + if (!pim_msg_curr) { + char group_str[100]; + pim_inet4_dump("", group, group_str, sizeof(group_str)); + zlog_warn("%s: failure encoding group address %s: space left=%d", + __PRETTY_FUNCTION__, group_str, remain); + return -5; + } + + remain = end - pim_msg_curr; + if (remain < 4) { + zlog_warn("%s: sources will not fit: space left=%d", + __PRETTY_FUNCTION__, remain); + return -6; + } + + /* number of joined sources */ + *((uint16_t *) pim_msg_curr) = htons(is_join ? 1 : 0); + ++pim_msg_curr; + ++pim_msg_curr; + + /* number of pruned sources */ + *((uint16_t *) pim_msg_curr) = htons(is_join ? 0 : 1); + ++pim_msg_curr; + ++pim_msg_curr; + + remain = end - pim_msg_curr; + if (source.s_addr == INADDR_ANY) + { + bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT | PIM_ENCODE_RPT_BIT; + stosend = qpim_rp.rpf_addr; + } + else + { + bits = PIM_ENCODE_SPARSE_BIT; + stosend = source; + } + pim_msg_curr = pim_msg_addr_encode_ipv4_source (pim_msg_curr, remain, stosend, bits); + if (!pim_msg_curr) { + char source_str[100]; + pim_inet4_dump("", source, source_str, sizeof(source_str)); + zlog_warn("%s: failure encoding source address %s: space left=%d", + __PRETTY_FUNCTION__, source_str, remain); + return -7; + } + + remain = pim_msg_curr - pim_msg; + pim_msg_build_header (pim_msg, remain, PIM_MSG_TYPE_JOIN_PRUNE); + + return remain; +} diff --git a/pimd/pim_msg.h b/pimd/pim_msg.h index 4a13040af6..1bd8207cc1 100644 --- a/pimd/pim_msg.h +++ b/pimd/pim_msg.h @@ -53,4 +53,8 @@ uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, struct in_addr addr, uint8_t bits); + +int pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, + struct in_addr source, struct in_addr group, + struct in_addr upstream, int holdtime); #endif /* PIM_MSG_H */ From 728cd663005142392693bdefdef489e4991949de Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 27 Jul 2016 20:13:16 -0400 Subject: [PATCH 049/386] pimd: Create pim_socket_bind Allow a socket to be bound to a specified interface. Signed-off-by: Donald Sharp --- pimd/pim_sock.c | 34 +++++++++++++++++++++++----------- pimd/pim_sock.h | 1 + 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index b100c37b46..70b18b14a4 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -68,6 +68,28 @@ int pim_socket_raw(int protocol) return fd; } +/* + * Given a socket and a interface, + * Bind that socket to that interface + */ +int pim_socket_bind (int fd, struct interface *ifp) +{ + int ret; + + if (pimd_privs.change (ZPRIVS_RAISE)) + zlog_err ("%s: could not raise privs, %s", + __PRETTY_FUNCTION__, safe_strerror (errno)); + + ret = setsockopt (fd, SOL_SOCKET, + SO_BINDTODEVICE, ifp->name, strlen (ifp->name)); + + if (pimd_privs.change (ZPRIVS_LOWER)) + zlog_err ("%s: could not lower privs, %s", + __PRETTY_FUNCTION__, safe_strerror (errno)); + + return ret; +} + int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, u_char loop) { int fd; @@ -87,17 +109,7 @@ int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, u_char lo ifp = if_lookup_by_index_vrf (ifindex, VRF_DEFAULT); - if (pimd_privs.change (ZPRIVS_RAISE)) - zlog_err ("%s: could not raise privs, %s", - __PRETTY_FUNCTION__, safe_strerror (errno)); - - ret = setsockopt (fd, SOL_SOCKET, - SO_BINDTODEVICE, ifp->name, strlen (ifp->name)); - - if (pimd_privs.change (ZPRIVS_LOWER)) - zlog_err ("%s: could not lower privs, %s", - __PRETTY_FUNCTION__, safe_strerror (errno)); - + ret = pim_socket_bind (fd, ifp); if (ret) { zlog_warn("Could not set fd: %d for interface: %s to device", diff --git a/pimd/pim_sock.h b/pimd/pim_sock.h index 556049d9b0..51ad88e24e 100644 --- a/pimd/pim_sock.h +++ b/pimd/pim_sock.h @@ -37,6 +37,7 @@ #define PIM_SOCK_ERR_NAME (-10) /* Socket name (getsockname) */ #define PIM_SOCK_ERR_BIND (-11) /* Can't bind to interface */ +int pim_socket_bind (int fd, struct interface *ifp); int pim_socket_raw(int protocol); int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, u_char loop); int pim_socket_join(int fd, struct in_addr group, From 13afbd05fd6d97c36e0cf10213e376d716a06842 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 27 Jul 2016 21:17:54 -0400 Subject: [PATCH 050/386] pimd: Create raw socket for register packets to be forwarded. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 9 +++++---- pimd/pim_rp.c | 30 ++++++++++++++++++++++++++++++ pimd/pim_rp.h | 1 + 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index b94fb1c767..e9ef72c637 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2438,10 +2438,11 @@ DEFUN (ip_pim_rp, return CMD_WARNING; } - if (pim_nexthop_lookup(&qpim_rp.source_nexthop, qpim_rp.rpf_addr, NULL) != 0) { - vty_out(vty, "%% No Path to RP address specified: %s", argv[idx_ipv4]->arg); - return CMD_WARNING; - } + if (!pim_rp_setup ()) + { + vty_out(vty, "%% No Path to RP address specified: %s", argv[idx_ipv4]->arg); + return CMD_WARNING; + } return CMD_SUCCESS; } diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 26d108bcaa..e7c03792cd 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -29,9 +29,38 @@ #include "pim_rp.h" #include "pim_str.h" #include "pim_rpf.h" +#include "pim_sock.h" static int i_am_rp = 0; +/* + * The Raw socket to pump packets down + * if we are the RP + */ +static int fd_rp = -1; + +static void +pim_rp_create_socket (void) +{ + fd_rp = pim_socket_raw (IPPROTO_RAW); + if (pim_socket_bind (fd_rp, qpim_rp.source_nexthop.interface) != 0) + zlog_debug ("Unable to Bind to a particular socket"); +} + +int +pim_rp_setup (void) +{ + if (pim_nexthop_lookup (&qpim_rp.source_nexthop, qpim_rp.rpf_addr, NULL) != 0) + { + zlog_err ("Unable to lookup nexthop for rp specified"); + return 0; + } + + pim_rp_create_socket (); + + return 1; +} + /* * Checks to see if we should elect ourself the actual RP */ @@ -54,6 +83,7 @@ pim_rp_check_rp (struct in_addr old, struct in_addr new) if (new.s_addr == qpim_rp.rpf_addr.s_addr) { i_am_rp = 1; + pim_rp_create_socket(); return; } diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index bb785e7efc..35a7e9dfc7 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -21,6 +21,7 @@ #ifndef PIM_RP_H #define PIM_RP_H +int pim_rp_setup (void); void pim_rp_check_rp (struct in_addr old, struct in_addr new); int pim_rp_i_am_rp (struct in_addr group); int pim_rp_set_upstream_addr (struct in_addr *up, struct in_addr source); From 31c680fc88838cd7e0be8bf12165084d4cb03b52 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 27 Jul 2016 22:19:08 -0400 Subject: [PATCH 051/386] pimd: Infrastructure to forward packet down (*,G) tree When a register is received, forward the packet as appropriate. This is the infrastructure to make this happen. Signed-off-by: Donald Sharp --- pimd/pim_register.c | 1 + pimd/pim_rp.c | 19 +++++++++++++++++++ pimd/pim_rp.h | 1 + pimd/pim_sock.c | 25 +++++++++++++++++++++++-- pimd/pim_sock.h | 1 + 5 files changed, 45 insertions(+), 2 deletions(-) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 79bfa4afc9..da84e245d4 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -348,6 +348,7 @@ pim_register_recv (struct interface *ifp, if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) && !(*bits & PIM_REGISTER_NR_BIT)) { + pim_rp_forward_packet (ip_hdr); //decapsulate and forward the iner packet to //inherited_olist(S,G,rpt) } diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index e7c03792cd..929211cdd8 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -39,10 +39,29 @@ static int i_am_rp = 0; */ static int fd_rp = -1; +void +pim_rp_forward_packet (struct ip *ip_hdr) +{ + struct sockaddr_in sin; + + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = ip_hdr->ip_dst.s_addr; + + zlog_debug ("Sending Packet"); + if (sendto (fd_rp, ip_hdr, ntohs (ip_hdr->ip_len), 0, (struct sockaddr *)&sin, sizeof (struct sockaddr)) < 0) + { + zlog_debug ("Failure to send packet: %s", safe_strerror (errno)); + } +} + static void pim_rp_create_socket (void) { fd_rp = pim_socket_raw (IPPROTO_RAW); + + if (pim_socket_ip_hdr (fd_rp) != 0) + zlog_debug ("Unable to setup socket for ip hdr inclusion"); + if (pim_socket_bind (fd_rp, qpim_rp.source_nexthop.interface) != 0) zlog_debug ("Unable to Bind to a particular socket"); } diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index 35a7e9dfc7..ccbc5b6ad4 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -26,6 +26,7 @@ void pim_rp_check_rp (struct in_addr old, struct in_addr new); int pim_rp_i_am_rp (struct in_addr group); int pim_rp_set_upstream_addr (struct in_addr *up, struct in_addr source); struct pim_rpf *pim_rp_g (struct in_addr group); +void pim_rp_forward_packet (struct ip *ip_hdr); #define I_am_RP(G) pim_rp_i_am_rp ((G)) #define RP(G) pim_rp_g ((G)) diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index 70b18b14a4..a4155549c9 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -45,7 +45,8 @@ /* GLOBAL VARS */ extern struct zebra_privs_t pimd_privs; -int pim_socket_raw(int protocol) +int +pim_socket_raw (int protocol) { int fd; @@ -68,11 +69,31 @@ int pim_socket_raw(int protocol) return fd; } +int +pim_socket_ip_hdr (int fd) +{ + const int on = 1; + int ret; + + if (pimd_privs.change (ZPRIVS_RAISE)) + zlog_err ("%s: could not raise privs, %s", + __PRETTY_FUNCTION__, safe_strerror (errno)); + + ret = setsockopt (fd, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)); + + if (pimd_privs.change (ZPRIVS_LOWER)) + zlog_err ("%s: could not lower privs, %s", + __PRETTY_FUNCTION__, safe_strerror (errno)); + + return ret; +} + /* * Given a socket and a interface, * Bind that socket to that interface */ -int pim_socket_bind (int fd, struct interface *ifp) +int +pim_socket_bind (int fd, struct interface *ifp) { int ret; diff --git a/pimd/pim_sock.h b/pimd/pim_sock.h index 51ad88e24e..c47d08f440 100644 --- a/pimd/pim_sock.h +++ b/pimd/pim_sock.h @@ -38,6 +38,7 @@ #define PIM_SOCK_ERR_BIND (-11) /* Can't bind to interface */ int pim_socket_bind (int fd, struct interface *ifp); +int pim_socket_ip_hdr (int fd); int pim_socket_raw(int protocol); int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, u_char loop); int pim_socket_join(int fd, struct in_addr group, From 035f28f683f1c0fd581dc37011f059cf68c76324 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 28 Jul 2016 02:46:36 -0400 Subject: [PATCH 052/386] pimd: Fix *,g pruning We were not properly handling the receipt of prune *,g messages. Signed-off-by: Donald Sharp --- pimd/pim_join.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 732dd823ad..09af3f1ab3 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -99,7 +99,7 @@ static void recv_join(struct interface *ifp, pim_ifchannel_join_add(ifp, neigh->source_addr, upstream, &sg, source_flags, holdtime); - if (I_am_RP (group) && source.s_addr == INADDR_ANY) + if (I_am_RP (group) && sg.u.sg.src.s_addr == INADDR_ANY) { struct pim_upstream *up; @@ -145,10 +145,22 @@ static void recv_prune(struct interface *ifp, source_flags & PIM_WILDCARD_BIT_MASK, up_str, holdtime, neigh_str, ifp->name); } + + if ((source_flags & PIM_RPT_BIT_MASK) && + (source_flags & PIM_WILDCARD_BIT_MASK)) + { + struct pim_rpf *rp = RP (sg.u.sg.grp); + + // Ignoring Prune *,G's at the moment. + if (sg.u.sg.src.s_addr != rp->rpf_addr.s_addr) + return; + + sg.u.sg.src.s_addr = INADDR_ANY; + } pim_ifchannel_prune(ifp, upstream, &sg, source_flags, holdtime); - if (I_am_RP (group) && source.s_addr == INADDR_ANY) + if (I_am_RP (group) && sg.u.sg.src.s_addr == INADDR_ANY) { struct pim_upstream *up; From 6997705858f3bce0024d7cec56edc33040ace245 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 28 Jul 2016 03:08:03 -0400 Subject: [PATCH 053/386] pimd: pim_str_sg_dump can't be called 2 times in the same debug When we call pim_str_sg_dump we cannot call the variable twice for the same debug. This fixes this issue in the 2 places it was borked. Ticket: CM-12045 Signed-off-by: Donald Sharp --- pimd/pim_join.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 09af3f1ab3..265165d83b 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -107,9 +107,11 @@ static void recv_join(struct interface *ifp, if (up) { + char buff[100]; + strcpy (buff, pim_str_sg_dump (&up->sg)); zlog_debug("%s %s: Join(S,G)=%s from %s", __FILE__, __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg), pim_str_sg_dump (&sg)); + buff, pim_str_sg_dump (&sg)); pim_rp_set_upstream_addr (&up->upstream_addr, up->sg.u.sg.src); pim_nexthop_lookup (&up->rpf.source_nexthop, up->upstream_addr, NULL); @@ -168,9 +170,11 @@ static void recv_prune(struct interface *ifp, if (up) { + char buff[100]; + strcpy (buff, pim_str_sg_dump (&up->sg)); zlog_debug("%s %s: Prune(S,G)=%s from %s", __FILE__, __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg), pim_str_sg_dump (&sg)); + buff, pim_str_sg_dump (&sg)); pim_ifchannel_prune (ifp, upstream, &up->sg, source_flags, holdtime); } } From 1a10fc742fcdb05024be3721b7641e19107edad7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 28 Jul 2016 12:21:31 -0400 Subject: [PATCH 054/386] pimd: Allow ifchannel S,G's to know their *,G parent Given a S,G ifchannel, create a parent pointer for any *,G state for that interface. When removing a *,G remove S,G pointers. We need to think about the case where their is a *,G but no S,G for a interface when we are determing. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 105 ++++++++++++++++++++++++++++++++++++++++++- pimd/pim_ifchannel.h | 1 + 2 files changed, 104 insertions(+), 2 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index f940c4d4ef..bbab8197dd 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -38,6 +38,65 @@ #include "pim_rpf.h" #include "pim_macro.h" +/* + * A (*,G) or a (*,*) is going away + * remove the parent pointer from + * those pointing at us + */ +static void +pim_ifchannel_remove_children (struct pim_ifchannel *ch) +{ + struct pim_interface *pim_ifp = ch->interface->info; + struct listnode *ch_node; + struct pim_ifchannel *child; + + // Basic sanity, (*,*) not currently supported + if ((ch->sg.u.sg.src.s_addr == INADDR_ANY) && + (ch->sg.u.sg.grp.s_addr == INADDR_ANY)) + return; + + // Basic sanity (S,G) have no children + if ((ch->sg.u.sg.src.s_addr != INADDR_ANY) && + (ch->sg.u.sg.grp.s_addr != INADDR_ANY)) + return; + + for (ALL_LIST_ELEMENTS_RO (pim_ifp->pim_ifchannel_list, ch_node, child)) + { + if (child->parent == ch) + child->parent = NULL; + } +} + +/* + * A (*,G) or a (*,*) is being created + * find all the children that would point + * at us. + */ +static void +pim_ifchannel_find_new_children (struct pim_ifchannel *ch) +{ + struct pim_interface *pim_ifp = ch->interface->info; + struct pim_ifchannel *child; + struct listnode *ch_node; + + // Basic Sanity that we are not being silly + if ((ch->sg.u.sg.src.s_addr != INADDR_ANY) && + (ch->sg.u.sg.grp.s_addr != INADDR_ANY)) + return; + + if ((ch->sg.u.sg.src.s_addr == INADDR_ANY) && + (ch->sg.u.sg.grp.s_addr == INADDR_ANY)) + return; + + for (ALL_LIST_ELEMENTS_RO (pim_ifp->pim_ifchannel_list, ch_node, child)) + { + if ((ch->sg.u.sg.grp.s_addr != INADDR_ANY) && + (child->sg.u.sg.grp.s_addr == ch->sg.u.sg.grp.s_addr) && + (child != ch)) + child->parent = ch; + } +} + void pim_ifchannel_free(struct pim_ifchannel *ch) { zassert(!ch->t_ifjoin_expiry_timer); @@ -54,6 +113,13 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) pim_ifp = ch->interface->info; zassert(pim_ifp); + /* + * When this channel is removed + * we need to find all our children + * and make sure our pointers are fixed + */ + pim_ifchannel_remove_children (ch); + if (ch->ifjoin_state != PIM_IFJOIN_NOINFO) { pim_upstream_update_join_desired(ch->upstream); } @@ -260,8 +326,41 @@ void pim_ifchannel_delete_on_noinfo(struct interface *ifp) } } -struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, - struct prefix *sg) +/* + * For a given Interface, if we are given a S,G + * Find the *,G (If we have it). + * If we are passed a *,G, find the *,* ifchannel + * if we have it. + */ +static struct pim_ifchannel * +pim_ifchannel_find_parent (struct interface *ifp, + struct prefix *sg) +{ + struct prefix parent_sg = *sg; + + // (*,*) || (S,*) + if (((sg->u.sg.src.s_addr == INADDR_ANY) && + (sg->u.sg.grp.s_addr == INADDR_ANY)) || + ((sg->u.sg.src.s_addr != INADDR_ANY) && + (sg->u.sg.grp.s_addr == INADDR_ANY))) + return NULL; + + // (S,G) + if ((sg->u.sg.src.s_addr != INADDR_ANY) && + (sg->u.sg.grp.s_addr != INADDR_ANY)) + { + parent_sg.u.sg.src.s_addr = INADDR_ANY; + return pim_ifchannel_find (ifp, &parent_sg); + } + + // (*,G) -- Not going to find anything currently + parent_sg.u.sg.grp.s_addr = INADDR_ANY; + return pim_ifchannel_find (ifp, &parent_sg); +} + +struct pim_ifchannel * +pim_ifchannel_add(struct interface *ifp, + struct prefix *sg) { struct pim_interface *pim_ifp; struct pim_ifchannel *ch; @@ -295,6 +394,8 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, ch->upstream = up; ch->interface = ifp; ch->sg = *sg; + ch->parent = pim_ifchannel_find_parent (ifp, sg); + pim_ifchannel_find_new_children (ch); ch->local_ifmembership = PIM_IFMEMBERSHIP_NOINFO; ch->ifjoin_state = PIM_IFJOIN_NOINFO; diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index e262944f03..2767e4862b 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -73,6 +73,7 @@ struct pim_assert_metric { Per-interface (S,G) state */ struct pim_ifchannel { + struct pim_ifchannel *parent; struct prefix sg; struct interface *interface; /* backpointer to interface */ uint32_t flags; From 978d48a9fe6c8ad23fa8500631c4ffac0b0c7c9c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 29 Jul 2016 21:02:17 -0400 Subject: [PATCH 055/386] pimd: Fix DownstreamJPState(S,G,I) check. Fix the DownStreamJPState(S,G,I) and DownStreamJPState(*,G,I) macros. Signed-off-by: Donald Sharp --- pimd/pim_macro.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pimd/pim_macro.c b/pimd/pim_macro.c index e6eb462b77..22da24da4a 100644 --- a/pimd/pim_macro.c +++ b/pimd/pim_macro.c @@ -28,16 +28,19 @@ #include "pim_str.h" #include "pim_iface.h" #include "pim_ifchannel.h" +#include "pim_rp.h" /* DownstreamJPState(S,G,I) is the per-interface state machine for receiving (S,G) Join/Prune messages. - DownstreamJPState(S,G,I) is either Join or Prune-Pending ? + DownstreamJPState(S,G,I) is either Join or Prune-Pending + DownstreamJPState(*,G,I) is either Join or Prune-Pending */ static int downstream_jpstate_isjoined(const struct pim_ifchannel *ch) { - return ch->ifjoin_state != PIM_IFJOIN_NOINFO; + return (ch->ifjoin_state == PIM_IFJOIN_NOINFO || + ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING); } /* From c8fa5a1e4f2e34319a9bf8e9d1e98476f143742a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 29 Jul 2016 21:20:19 -0400 Subject: [PATCH 056/386] pimd: Create storage for a raw socket. Each interface needs the ability to send raw packets at the RP. Create the data structure to do so. Further commits will create the socket as necessary and send the packet. Signed-off-by: Donald Sharp --- pimd/pim_iface.c | 7 +++++++ pimd/pim_iface.h | 1 + 2 files changed, 8 insertions(+) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index fae11b674a..1ffea6ab46 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -87,6 +87,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim) pim_ifp->options = 0; pim_ifp->mroute_vif_index = -1; + pim_ifp->pim_raw_fd = -1; pim_ifp->igmp_default_robustness_variable = IGMP_DEFAULT_ROBUSTNESS_VARIABLE; pim_ifp->igmp_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL; @@ -162,6 +163,12 @@ void pim_if_delete(struct interface *ifp) pim_ifp = ifp->info; zassert(pim_ifp); + if (pim_ifp->pim_raw_fd == -1) + { + close (pim_ifp->pim_raw_fd); + pim_ifp->pim_raw_fd = -1; + } + if (pim_ifp->igmp_join_list) { pim_if_igmp_join_del_all(ifp); } diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index 75b85c306a..7f3d6961fa 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -73,6 +73,7 @@ struct pim_interface { struct list *igmp_join_list; /* list of struct igmp_join */ int pim_sock_fd; /* PIM socket file descriptor */ + int pim_raw_fd; /* RP forwarding */ struct thread *t_pim_sock_read; /* thread for reading PIM socket */ int64_t pim_sock_creation; /* timestamp of PIM socket creation */ From ae4cf53f4986c596e7b943b9b3304e30281828e7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 1 Aug 2016 08:29:00 -0400 Subject: [PATCH 057/386] pimd: Fix pim_macro downstream_jpstate Signed-off-by: Donald Sharp --- pimd/pim_macro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_macro.c b/pimd/pim_macro.c index 22da24da4a..8dbf851aa9 100644 --- a/pimd/pim_macro.c +++ b/pimd/pim_macro.c @@ -39,7 +39,7 @@ */ static int downstream_jpstate_isjoined(const struct pim_ifchannel *ch) { - return (ch->ifjoin_state == PIM_IFJOIN_NOINFO || + return (ch->ifjoin_state == PIM_IFJOIN_JOIN || ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING); } From 13376be4f28cbc99394452f50ce214f7127f2965 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 1 Aug 2016 09:09:47 -0400 Subject: [PATCH 058/386] pimd: More macro fallout fix. Signed-off-by: Donald Sharp --- pimd/pim_macro.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pimd/pim_macro.c b/pimd/pim_macro.c index 8dbf851aa9..62decfd5f9 100644 --- a/pimd/pim_macro.c +++ b/pimd/pim_macro.c @@ -39,8 +39,7 @@ */ static int downstream_jpstate_isjoined(const struct pim_ifchannel *ch) { - return (ch->ifjoin_state == PIM_IFJOIN_JOIN || - ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING); + return (ch->ifjoin_state != PIM_IFJOIN_NOINFO); } /* From 3667b0bcf62d73248587ece9d4efd91f78c83a63 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 1 Aug 2016 12:29:58 -0400 Subject: [PATCH 059/386] pimd: change from ifchannels to oil's Signed-off-by: Donald Sharp --- pimd/pim_join.c | 53 +++++++++++++++++++++++++-------------------- pimd/pim_upstream.c | 13 +++++++---- 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 265165d83b..0a40ab6210 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -31,6 +31,7 @@ #include "pim_msg.h" #include "pim_pim.h" #include "pim_join.h" +#include "pim_oil.h" #include "pim_iface.h" #include "pim_hello.h" #include "pim_ifchannel.h" @@ -99,23 +100,24 @@ static void recv_join(struct interface *ifp, pim_ifchannel_join_add(ifp, neigh->source_addr, upstream, &sg, source_flags, holdtime); - if (I_am_RP (group) && sg.u.sg.src.s_addr == INADDR_ANY) + if (sg.u.sg.src.s_addr == INADDR_ANY) { - struct pim_upstream *up; + struct pim_upstream *up = pim_upstream_find (&sg); + struct pim_upstream *child; + struct listnode *up_node; - up = pim_upstream_find_non_any (&sg); - - if (up) + for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, up_node, child)) { - char buff[100]; - strcpy (buff, pim_str_sg_dump (&up->sg)); - zlog_debug("%s %s: Join(S,G)=%s from %s", - __FILE__, __PRETTY_FUNCTION__, - buff, pim_str_sg_dump (&sg)); + if (child->parent == up) + { + char buff[100]; + strcpy (buff, pim_str_sg_dump (&up->sg)); + zlog_debug("%s %s: Join(S,G)=%s from %s", + __FILE__, __PRETTY_FUNCTION__, + buff, pim_str_sg_dump (&sg)); - pim_rp_set_upstream_addr (&up->upstream_addr, up->sg.u.sg.src); - pim_nexthop_lookup (&up->rpf.source_nexthop, up->upstream_addr, NULL); - pim_ifchannel_join_add (ifp, neigh->source_addr, upstream, &up->sg, source_flags, holdtime); + pim_channel_add_oif (up->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + } } } @@ -162,20 +164,23 @@ static void recv_prune(struct interface *ifp, pim_ifchannel_prune(ifp, upstream, &sg, source_flags, holdtime); - if (I_am_RP (group) && sg.u.sg.src.s_addr == INADDR_ANY) + if (sg.u.sg.src.s_addr == INADDR_ANY) { - struct pim_upstream *up; + struct pim_upstream *up = pim_upstream_find (&sg); + struct pim_upstream *child; + struct listnode *up_node; - up = pim_upstream_find_non_any (&sg); - - if (up) + for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, up_node, child)) { - char buff[100]; - strcpy (buff, pim_str_sg_dump (&up->sg)); - zlog_debug("%s %s: Prune(S,G)=%s from %s", - __FILE__, __PRETTY_FUNCTION__, - buff, pim_str_sg_dump (&sg)); - pim_ifchannel_prune (ifp, upstream, &up->sg, source_flags, holdtime); + if (child->parent == up) + { + char buff[100]; + strcpy (buff, pim_str_sg_dump (&up->sg)); + zlog_debug("%s %s: Prune(S,G)=%s from %s", + __FILE__, __PRETTY_FUNCTION__, + buff, pim_str_sg_dump (&sg)); + pim_channel_del_oif (up->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + } } } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index b404e144e8..7b87bdac73 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -932,6 +932,10 @@ pim_upstream_inherited_olist (struct pim_upstream *up) struct prefix anysrc; int output_intf = 0; + pim_ifp = up->rpf.source_nexthop.interface->info; + zlog_debug ("Channel Oil%s: %p", pim_str_sg_dump (&up->sg), up->channel_oil); + if (!up->channel_oil) + up->channel_oil = pim_channel_oil_add (&up->sg, pim_ifp->mroute_vif_index); anysrc = up->sg; anysrc.u.sg.src.s_addr = INADDR_ANY; @@ -946,16 +950,17 @@ pim_upstream_inherited_olist (struct pim_upstream *up) for (ALL_LIST_ELEMENTS (pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) { - struct pim_ifchannel *nch; + //struct pim_ifchannel *nch; if (ch->upstream != anysrc_up) continue; if (ch->ifjoin_state == PIM_IFJOIN_JOIN) { - nch = pim_ifchannel_add (ifp, &up->sg); - pim_ifchannel_ifjoin_switch (__PRETTY_FUNCTION__, nch, PIM_IFJOIN_JOIN); - pim_forward_start (ch); + pim_channel_add_oif (up->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + //nch = pim_ifchannel_add (ifp, &up->sg); + //pim_ifchannel_ifjoin_switch (__PRETTY_FUNCTION__, nch, PIM_IFJOIN_JOIN); + //pim_forward_start (ch); output_intf++; } } From a459fe85c85e51bf36c10fc5700b6345c904d01d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 1 Aug 2016 13:06:35 -0400 Subject: [PATCH 060/386] pimd: igmpv3.c was causing prune/join messages to be sent We were erroneously sending a prune *,G immediately followed by a join *,G under certain situations Signed-off-by: Donald Sharp --- pimd/pim_igmpv3.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index bf81c8d2c5..79932edb35 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -933,6 +933,16 @@ static void toex_excl(struct igmp_group *group, /* clear off SEND flag from all known sources (X,Y) */ source_clear_send_flag(group->group_source_list); + if (num_sources == 0) + { + struct igmp_source *source; + struct in_addr any = { .s_addr = INADDR_ANY }; + + source = igmp_find_source_by_addr (group, any); + if (source) + IGMP_SOURCE_DONT_DELETE(source->source_flags); + } + /* scan received sources (A) */ for (i = 0; i < num_sources; ++i) { struct igmp_source *source; From 0365f56bd00b2d136df71a063b87d8d4bb479991 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 2 Aug 2016 09:21:51 -0400 Subject: [PATCH 061/386] pimd: Allow the kernel to forward encap'ed packets for us When we get a pim register allow the kernel to forward the saved packets. Signed-off-by: Donald Sharp --- pimd/pim_iface.c | 7 ------- pimd/pim_iface.h | 1 - pimd/pim_mroute.c | 22 ++++++++++++++++++++++ pimd/pim_register.c | 2 +- pimd/pim_rp.c | 35 ----------------------------------- 5 files changed, 23 insertions(+), 44 deletions(-) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 1ffea6ab46..fae11b674a 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -87,7 +87,6 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim) pim_ifp->options = 0; pim_ifp->mroute_vif_index = -1; - pim_ifp->pim_raw_fd = -1; pim_ifp->igmp_default_robustness_variable = IGMP_DEFAULT_ROBUSTNESS_VARIABLE; pim_ifp->igmp_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL; @@ -163,12 +162,6 @@ void pim_if_delete(struct interface *ifp) pim_ifp = ifp->info; zassert(pim_ifp); - if (pim_ifp->pim_raw_fd == -1) - { - close (pim_ifp->pim_raw_fd); - pim_ifp->pim_raw_fd = -1; - } - if (pim_ifp->igmp_join_list) { pim_if_igmp_join_del_all(ifp); } diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index 7f3d6961fa..75b85c306a 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -73,7 +73,6 @@ struct pim_interface { struct list *igmp_join_list; /* list of struct igmp_join */ int pim_sock_fd; /* PIM socket file descriptor */ - int pim_raw_fd; /* RP forwarding */ struct thread *t_pim_sock_read; /* thread for reading PIM socket */ int64_t pim_sock_creation; /* timestamp of PIM socket creation */ diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 7893bc926b..8efe7635cd 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -570,6 +570,7 @@ int pim_mroute_add(struct channel_oil *c_oil) { int err; int orig = 0; + int orig_iif_vif = 0; qpim_mroute_add_last = pim_time_monotonic_sec(); ++qpim_mroute_add_events; @@ -590,9 +591,30 @@ int pim_mroute_add(struct channel_oil *c_oil) c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = 1; } + /* + * If we have an unresolved cache entry for the S,G + * it is owned by the pimreg for the incoming IIF + * So set pimreg as the IIF temporarily to cause + * the packets to be forwarded. Then set it + * to the correct IIF afterwords. + */ + if (!c_oil->installed && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY && + c_oil->oil.mfcc_parent != 0) + { + orig_iif_vif = c_oil->oil.mfcc_parent; + c_oil->oil.mfcc_parent = 0; + } err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, &c_oil->oil, sizeof(c_oil->oil)); + if (!err && !c_oil->installed && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY && + orig_iif_vif != 0) + { + c_oil->oil.mfcc_parent = orig_iif_vif; + err = setsockopt (qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, + &c_oil->oil, sizeof (c_oil->oil)); + } + if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = orig; diff --git a/pimd/pim_register.c b/pimd/pim_register.c index da84e245d4..aaf05bbb19 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -348,9 +348,9 @@ pim_register_recv (struct interface *ifp, if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) && !(*bits & PIM_REGISTER_NR_BIT)) { - pim_rp_forward_packet (ip_hdr); //decapsulate and forward the iner packet to //inherited_olist(S,G,rpt) + // This is taken care of by the kernel for us } } else { pim_register_stop_send (ifp, &sg, src_addr); diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 929211cdd8..b98ff2859a 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -33,38 +33,6 @@ static int i_am_rp = 0; -/* - * The Raw socket to pump packets down - * if we are the RP - */ -static int fd_rp = -1; - -void -pim_rp_forward_packet (struct ip *ip_hdr) -{ - struct sockaddr_in sin; - - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = ip_hdr->ip_dst.s_addr; - - zlog_debug ("Sending Packet"); - if (sendto (fd_rp, ip_hdr, ntohs (ip_hdr->ip_len), 0, (struct sockaddr *)&sin, sizeof (struct sockaddr)) < 0) - { - zlog_debug ("Failure to send packet: %s", safe_strerror (errno)); - } -} - -static void -pim_rp_create_socket (void) -{ - fd_rp = pim_socket_raw (IPPROTO_RAW); - - if (pim_socket_ip_hdr (fd_rp) != 0) - zlog_debug ("Unable to setup socket for ip hdr inclusion"); - - if (pim_socket_bind (fd_rp, qpim_rp.source_nexthop.interface) != 0) - zlog_debug ("Unable to Bind to a particular socket"); -} int pim_rp_setup (void) @@ -75,8 +43,6 @@ pim_rp_setup (void) return 0; } - pim_rp_create_socket (); - return 1; } @@ -102,7 +68,6 @@ pim_rp_check_rp (struct in_addr old, struct in_addr new) if (new.s_addr == qpim_rp.rpf_addr.s_addr) { i_am_rp = 1; - pim_rp_create_socket(); return; } From 2a05c94c91dd05a3d3604fcd8bd7fd7edbf78c82 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 2 Aug 2016 09:58:14 -0400 Subject: [PATCH 062/386] pimd: Add Local Genid to 'show ip pim hello' Display the local idea of what the Genid is Ticket: CM-11980 Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index e9ef72c637..9d1602ac40 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -614,7 +614,7 @@ static void pim_show_hello(struct vty *vty) now = pim_time_monotonic_sec(); - vty_out(vty, "Interface Address Period Timer StatStart Recv Rfail Send Sfail%s", VTY_NEWLINE); + vty_out(vty, "Interface Address Period Timer StatStart Recv Rfail Send Sfail LGenid%s", VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { struct pim_interface *pim_ifp; @@ -637,7 +637,7 @@ static void pim_show_hello(struct vty *vty) pim_time_mmss(hello_period, sizeof(hello_period), pim_ifp->pim_hello_period); pim_time_uptime(stat_uptime, sizeof(stat_uptime), now - pim_ifp->pim_ifstat_start); - vty_out(vty, "%-9s %-15s %6s %5s %9s %4u %5u %4u %5u%s", + vty_out(vty, "%-9s %-15s %6s %5s %9s %4u %5u %4u %5u %08x%s", ifp->name, inet_ntoa(ifaddr), hello_period, @@ -647,6 +647,7 @@ static void pim_show_hello(struct vty *vty) pim_ifp->pim_ifstat_hello_recvfail, pim_ifp->pim_ifstat_hello_sent, pim_ifp->pim_ifstat_hello_sendfail, + pim_ifp->pim_generation_id, VTY_NEWLINE); } } From cfa91a87332343da59e272a275a5be1bebf2c60d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 2 Aug 2016 11:21:49 -0400 Subject: [PATCH 063/386] pimd: Add upstream children finding When we receive a *,g find all S,G that are related and set pointer appropriately Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 58 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 7b87bdac73..e71f856aa3 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -50,6 +50,62 @@ static void join_timer_start(struct pim_upstream *up); static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up); +/* + * A (*,G) or a (*,*) is going away + * remove the parent pointer from + * those pointing at us + */ +static void +pim_upstream_remove_children (struct pim_upstream *up) +{ + struct listnode *ch_node; + struct pim_upstream *child; + + // Basic sanity, (*,*) not currently supported + if ((up->sg.u.sg.src.s_addr == INADDR_ANY) && + (up->sg.u.sg.grp.s_addr == INADDR_ANY)) + return; + + // Basic sanity (S,G) have no children + if ((up->sg.u.sg.src.s_addr != INADDR_ANY) && + (up->sg.u.sg.grp.s_addr != INADDR_ANY)) + return; + + for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, ch_node, child)) + { + if (child->parent == up) + child->parent = NULL; + } +} + +/* + * A (*,G) or a (*,*) is being created + * Find the children that would point + * at us. + */ +static void +pim_upstream_find_new_children (struct pim_upstream *up) +{ + struct pim_upstream *child; + struct listnode *ch_node; + + if ((up->sg.u.sg.src.s_addr != INADDR_ANY) && + (up->sg.u.sg.grp.s_addr != INADDR_ANY)) + return; + + if ((up->sg.u.sg.src.s_addr == INADDR_ANY) && + (up->sg.u.sg.grp.s_addr == INADDR_ANY)) + return; + + for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, ch_node, child)) + { + if ((up->sg.u.sg.grp.s_addr != INADDR_ANY) && + (child->sg.u.sg.grp.s_addr == up->sg.u.sg.grp.s_addr) && + (child != up)) + child->parent = up; + } +} + /* * If we have a (*,*) || (S,*) there is no parent * If we have a (S,G), find the (*,G) @@ -99,6 +155,7 @@ void pim_upstream_delete(struct pim_upstream *up) THREAD_OFF(up->t_ka_timer); THREAD_OFF(up->t_rs_timer); + pim_upstream_remove_children (up); upstream_channel_oil_detach(up); /* @@ -378,6 +435,7 @@ static struct pim_upstream *pim_upstream_new(struct prefix *sg, } up->parent = pim_upstream_find_parent (sg); + pim_upstream_find_new_children (up); up->flags = 0; up->ref_count = 1; up->t_join_timer = NULL; From fa1a4e366ba4120d4009b5a7aedea10c062639e0 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 2 Aug 2016 11:39:16 -0400 Subject: [PATCH 064/386] pimd: Send join when a S,G is pruned When a *,G is received, and we have S,G that is in a non-joined state, Send the join to the S,G. Signed-off-by: Donald Sharp --- pimd/pim_join.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 0a40ab6210..3d98f9f95f 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -116,7 +116,9 @@ static void recv_join(struct interface *ifp, __FILE__, __PRETTY_FUNCTION__, buff, pim_str_sg_dump (&sg)); - pim_channel_add_oif (up->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + if (child->join_state != PIM_UPSTREAM_JOINED) + pim_upstream_switch (child, PIM_UPSTREAM_JOINED); } } } From 8a294fa2e4214dd56d0f2cd6c4ed5d284da05d1c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 2 Aug 2016 13:12:31 -0400 Subject: [PATCH 065/386] pimd: Make the NOCACHE just set the regiface to the coil When we receive a NOCACHE upcall, add the pimreg interface to the oil so that we can receive the data. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 8efe7635cd..f26fb7ae24 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -93,7 +93,6 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg const char *src_str, const char *grp_str) { struct pim_interface *pim_ifp = ifp->info; - struct pim_ifchannel *ch; struct pim_upstream *up; struct pim_rpf *rpg; struct prefix sg; @@ -154,8 +153,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg } up->channel_oil->cc.pktcnt++; up->fhr = 1; - ch = pim_ifchannel_add (pim_regiface, &sg); - pim_ifchannel_ifjoin_switch (__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN_PIMREG); + pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); up->join_state = PIM_UPSTREAM_JOINED; return 0; From facebf05097cd02b20bc89bde7e2fa9a8c434bdf Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 2 Aug 2016 14:14:54 -0400 Subject: [PATCH 066/386] pimd: Remove Wrong PIMREG ifchannel state The PIMREG ifchannel state is an evolutionary dead-end. I should not have introduced this code. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 4 ---- pimd/pim_ifchannel.h | 1 - 2 files changed, 5 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index bbab8197dd..f1da740e78 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -209,7 +209,6 @@ const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state) { switch (ifjoin_state) { case PIM_IFJOIN_NOINFO: return "NOINFO"; - case PIM_IFJOIN_JOIN_PIMREG: return "REGT"; case PIM_IFJOIN_JOIN: return "JOIN"; case PIM_IFJOIN_PRUNE_PENDING: return "PRUNEP"; } @@ -684,8 +683,6 @@ void pim_ifchannel_join_add(struct interface *ifp, THREAD_OFF(ch->t_ifjoin_prune_pending_timer); pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN); break; - case PIM_IFJOIN_JOIN_PIMREG: - zlog_warn("Received Incorrect new state"); } zassert(!IFCHANNEL_NOINFO(ch)); @@ -718,7 +715,6 @@ void pim_ifchannel_prune(struct interface *ifp, switch (ch->ifjoin_state) { case PIM_IFJOIN_NOINFO: case PIM_IFJOIN_PRUNE_PENDING: - case PIM_IFJOIN_JOIN_PIMREG: /* nothing to do */ break; case PIM_IFJOIN_JOIN: diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 2767e4862b..eb6b0925a8 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -38,7 +38,6 @@ enum pim_ifjoin_state { PIM_IFJOIN_NOINFO, PIM_IFJOIN_JOIN, PIM_IFJOIN_PRUNE_PENDING, - PIM_IFJOIN_JOIN_PIMREG, }; enum pim_ifassert_state { From 9add3b8812e75c2dc5cc858c2a6a0bc26b4316d2 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 2 Aug 2016 21:44:29 -0400 Subject: [PATCH 067/386] pimd: Add ability to debug pim Register packets Allow the user to specify the ability to debug pim register packets. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 31 +++++++++++++++++++++---------- pimd/pim_cmd.h | 1 + pimd/pim_register.c | 31 ++++++++++++++++++++++++++++--- pimd/pim_vty.c | 5 +++++ pimd/pimd.h | 4 ++++ 5 files changed, 59 insertions(+), 13 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 9d1602ac40..f3d1244e9a 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3752,23 +3752,29 @@ DEFUN (debug_pim_packets, DEFUN (debug_pim_packets_filter, debug_pim_packets_filter_cmd, - "debug pim packets ", + "debug pim packets ", DEBUG_STR DEBUG_PIM_STR DEBUG_PIM_PACKETS_STR DEBUG_PIM_HELLO_PACKETS_STR - DEBUG_PIM_J_P_PACKETS_STR) + DEBUG_PIM_J_P_PACKETS_STR + DEBUG_PIM_PIM_REG_PACKETS_STR) { int idx_hello_join = 3; - if (strncmp(argv[idx_hello_join]->arg,"h",1) == 0) + if (strncmp(argv[idx_hello_join]->arg,"h",1) == 0) { PIM_DO_DEBUG_PIM_HELLO; - vty_out (vty, "PIM Hello debugging is on %s", VTY_NEWLINE); + vty_out (vty, "PIM Hello debugging is on%s", VTY_NEWLINE); } - else if (strncmp(argv[idx_hello_join]->arg,"j",1) == 0) + else if (strncmp(argv[idx_hello_join]->arg,"j",1) == 0) { PIM_DO_DEBUG_PIM_J_P; - vty_out (vty, "PIM Join/Prune debugging is on %s", VTY_NEWLINE); + vty_out (vty, "PIM Join/Prune debugging is on%s", VTY_NEWLINE); + } + else if (strncmp(argv[idx_hello_join]->arg,"r",1) == 0) + { + PIM_DO_DEBUG_PIM_REG; + vty_out (vty, "PIM Register debugging is on%s", VTY_NEWLINE); } return CMD_SUCCESS; } @@ -3790,7 +3796,7 @@ DEFUN (no_debug_pim_packets, DEFUN (no_debug_pim_packets_filter, no_debug_pim_packets_filter_cmd, - "no debug pim packets ", + "no debug pim packets ", NO_STR DEBUG_STR DEBUG_PIM_STR @@ -3799,17 +3805,22 @@ DEFUN (no_debug_pim_packets_filter, DEBUG_PIM_J_P_PACKETS_STR) { int idx_hello_join = 4; - if (strncmp(argv[idx_hello_join]->arg,"h",1) == 0) + if (strncmp(argv[idx_hello_join]->arg,"h",1) == 0) { PIM_DONT_DEBUG_PIM_HELLO; vty_out (vty, "PIM Hello debugging is off %s", VTY_NEWLINE); } - else if (strncmp(argv[idx_hello_join]->arg,"j",1) == 0) + else if (strncmp(argv[idx_hello_join]->arg,"j",1) == 0) { PIM_DONT_DEBUG_PIM_J_P; vty_out (vty, "PIM Join/Prune debugging is off %s", VTY_NEWLINE); } - return CMD_SUCCESS; + else if (strncmp (argv[idx_hello_join]->arg, "r", 1) == 0) + { + PIM_DONT_DEBUG_PIM_REG; + vty_out (vty, "PIM Register debugging is off%s", VTY_NEWLINE); + } + return CMD_SUCCESS; } diff --git a/pimd/pim_cmd.h b/pimd/pim_cmd.h index 6e6e80d4f2..d5e5c6a304 100644 --- a/pimd/pim_cmd.h +++ b/pimd/pim_cmd.h @@ -48,6 +48,7 @@ #define DEBUG_PIM_PACKETS_STR "PIM protocol packets\n" #define DEBUG_PIM_HELLO_PACKETS_STR "PIM Hello protocol packets\n" #define DEBUG_PIM_J_P_PACKETS_STR "PIM Join/Prune protocol packets\n" +#define DEBUG_PIM_PIM_REG_PACKETS_STR "PIM Register/Reg-Stop protocol packets\n" #define DEBUG_PIM_PACKETDUMP_STR "PIM packet dump\n" #define DEBUG_PIM_PACKETDUMP_SEND_STR "Dump sent packets\n" #define DEBUG_PIM_PACKETDUMP_RECV_STR "Dump received packets\n" diff --git a/pimd/pim_register.c b/pimd/pim_register.c index aaf05bbb19..5da8a677ef 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -77,6 +77,12 @@ pim_register_stop_send (struct interface *ifp, struct prefix *sg, uint8_t *b1; struct prefix p; + if (PIM_DEBUG_PIM_REG) + { + zlog_debug ("Sending Register stop for %s to %s on %s", + pim_str_sg_dump (sg), inet_ntoa(originator), ifp->name); + } + memset (buffer, 0, 3000); b1 = (uint8_t *)buffer + PIM_MSG_REGISTER_STOP_LEN; @@ -120,9 +126,6 @@ pim_register_stop_recv (uint8_t *buf, int buf_size) struct prefix sg; int l; - if (PIM_DEBUG_PIM_PACKETDUMP_RECV) - pim_pkt_dump ("Received Register Stop", buf, buf_size); - l = pim_parse_addr_group (&group, buf, buf_size); buf += l; buf_size -= l; @@ -130,6 +133,13 @@ pim_register_stop_recv (uint8_t *buf, int buf_size) memset (&sg, 0, sizeof (struct prefix)); sg.u.sg.src = source.u.prefix4; sg.u.sg.grp = group.u.prefix4; + + if (PIM_DEBUG_PIM_REG) + { + zlog_debug ("Received Register stop for %s", + pim_str_sg_dump (&sg)); + } + upstream = pim_upstream_find (&sg); if (!upstream) { @@ -162,6 +172,13 @@ pim_register_send (const uint8_t *buf, int buf_size, struct pim_rpf *rpg, int nu struct pim_interface *pinfo; struct interface *ifp; + if (PIM_DEBUG_PIM_REG) + { + char rp_str[100]; + strcpy (rp_str, inet_ntoa (rpg->rpf_addr)); + zlog_debug ("Sending %sRegister Packet to %s", null_register ? "NULL " : "", rp_str); + } + ifp = rpg->source_nexthop.interface; pinfo = (struct pim_interface *)ifp->info; if (!pinfo) { @@ -257,6 +274,14 @@ pim_register_recv (struct interface *ifp, return 0; } + if (PIM_DEBUG_PIM_REG) + { + char src_str[100]; + + pim_inet4_dump ("", src_addr, src_str, sizeof (src_str)); + zlog_debug ("Received Register message from %s on %s", src_str, ifp->name); + } + /* * Please note this is not drawn to get the correct bit/data size * diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index c6fb3464b1..9c3df6bbdc 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -108,6 +108,11 @@ pim_debug_config_write (struct vty *vty) ++writes; } + if (PIM_DEBUG_PIM_REG) { + vty_out (vty, "debug pim packets register%s", VTY_NEWLINE); + ++writes; + } + if (PIM_DEBUG_STATIC) { vty_out (vty, "debug pim static%s", VTY_NEWLINE); ++writes; diff --git a/pimd/pimd.h b/pimd/pimd.h index 6ff36a2a51..e91959948a 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -69,6 +69,7 @@ #define PIM_MASK_PIM_HELLO (1 << 14) #define PIM_MASK_PIM_J_P (1 << 15) #define PIM_MASK_STATIC (1 << 16) +#define PIM_MASK_PIM_REG (1 << 17) const char *const PIM_ALL_SYSTEMS; const char *const PIM_ALL_ROUTERS; @@ -135,6 +136,7 @@ extern int32_t qpim_register_probe_time; #define PIM_DEBUG_MROUTE (qpim_debugs & PIM_MASK_MROUTE) #define PIM_DEBUG_PIM_HELLO (qpim_debugs & PIM_MASK_PIM_HELLO) #define PIM_DEBUG_PIM_J_P (qpim_debugs & PIM_MASK_PIM_J_P) +#define PIM_DEBUG_PIM_REG (qpim_debugs & PIM_MASK_PIM_REG) #define PIM_DEBUG_STATIC (qpim_debugs & PIM_MASK_STATIC) #define PIM_DEBUG_EVENTS (qpim_debugs & (PIM_MASK_PIM_EVENTS | PIM_MASK_IGMP_EVENTS)) @@ -155,6 +157,7 @@ extern int32_t qpim_register_probe_time; #define PIM_DO_DEBUG_MROUTE (qpim_debugs |= PIM_MASK_MROUTE) #define PIM_DO_DEBUG_PIM_HELLO (qpim_debugs |= PIM_MASK_PIM_HELLO) #define PIM_DO_DEBUG_PIM_J_P (qpim_debugs |= PIM_MASK_PIM_J_P) +#define PIM_DO_DEBUG_PIM_REG (qpim_debugs |= PIM_MASK_PIM_REG) #define PIM_DO_DEBUG_STATIC (qpim_debugs |= PIM_MASK_STATIC) #define PIM_DONT_DEBUG_PIM_EVENTS (qpim_debugs &= ~PIM_MASK_PIM_EVENTS) @@ -171,6 +174,7 @@ extern int32_t qpim_register_probe_time; #define PIM_DONT_DEBUG_MROUTE (qpim_debugs &= ~PIM_MASK_MROUTE) #define PIM_DONT_DEBUG_PIM_HELLO (qpim_debugs &= ~PIM_MASK_PIM_HELLO) #define PIM_DONT_DEBUG_PIM_J_P (qpim_debugs &= ~PIM_MASK_PIM_J_P) +#define PIM_DONT_DEBUG_PIM_REG (qpim_debugs &= ~PIM_MASK_PIM_REG) #define PIM_DONT_DEBUG_STATIC (qpim_debugs &= ~PIM_MASK_STATIC) void pim_init(void); From d41b415c8bef5faa342ec6cb13f487ea01c2c5ac Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 3 Aug 2016 11:32:15 -0400 Subject: [PATCH 068/386] pimd: Change packet debug to pim register specific debug Signed-off-by: Donald Sharp --- pimd/pim_register.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 5da8a677ef..456581127e 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -264,7 +264,7 @@ pim_register_recv (struct interface *ifp, uint32_t *bits; if (!pim_check_is_my_ip_address (dest_addr)) { - if (PIM_DEBUG_PIM_PACKETS) { + if (PIM_DEBUG_PIM_REG) { char dest[100]; pim_inet4_dump ("", dest_addr, dest, sizeof(dest)); From 81900c5a083428f81ac5a92d2846790aa6f4da4f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 3 Aug 2016 11:34:38 -0400 Subject: [PATCH 069/386] pimd: Fix upstream state machine. RFC 4601 4.5.7: Joined The downstream state machines and local membership information indicate that the router should join the shortest-path tree for this (S,G). The code has a upstream state that is in 'J' state already due to a S,G multicast packet received on an incoming interface. This packet has been forwarded to the RP. The RP sees this and immediately sends a join towards the S,G. The code as originally written assumed that you could not transition from a J state to a J state. This is not true. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index e71f856aa3..a304f359eb 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -381,8 +381,6 @@ pim_upstream_switch(struct pim_upstream *up, { enum pim_upstream_state old_state = up->join_state; - zassert(old_state != new_state); - up->join_state = new_state; up->state_transition = pim_time_monotonic_sec(); @@ -396,9 +394,16 @@ pim_upstream_switch(struct pim_upstream *up, pim_upstream_update_assert_tracking_desired(up); if (new_state == PIM_UPSTREAM_JOINED) { - forward_on(up); - pim_upstream_send_join (up); - join_timer_start(up); + if (old_state != PIM_UPSTREAM_JOINED) + { + forward_on(up); + pim_upstream_send_join (up); + join_timer_start(up); + } + else + { + forward_on (up); + } } else { forward_off(up); @@ -596,8 +601,6 @@ void pim_upstream_update_join_desired(struct pim_upstream *up) /* switched from false to true */ if (is_join_desired && !was_join_desired) { - zassert(up->join_state == PIM_UPSTREAM_NOTJOINED || - up->join_state == PIM_UPSTREAM_PRUNE); pim_upstream_switch(up, PIM_UPSTREAM_JOINED); return; } From ad6ec47b81a362ff1a2ef0a0c16d69401c2cc376 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 3 Aug 2016 14:40:10 -0400 Subject: [PATCH 070/386] pimd: Add rs_timer display For the 'show ip pim upstream' command addd the RSTimer to the display Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index f3d1244e9a..4319b06815 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -982,26 +982,29 @@ static void pim_show_upstream(struct vty *vty) now = pim_time_monotonic_sec(); - vty_out(vty, "Iif Source Group State Uptime JoinTimer RefCnt%s", VTY_NEWLINE); + vty_out(vty, "Iif Source Group State Uptime JoinTimer RSTimer RefCnt%s", VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) { char src_str[100]; char grp_str[100]; char uptime[10]; char join_timer[10]; + char rs_timer[10]; pim_inet4_dump("", up->sg.u.sg.src, src_str, sizeof(src_str)); pim_inet4_dump("", up->sg.u.sg.grp, grp_str, sizeof(grp_str)); pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer), up->t_join_timer); + pim_time_timer_to_hhmmss (rs_timer, sizeof (rs_timer), up->t_rs_timer); - vty_out(vty, "%-10s%-15s %-15s %-5s %-8s %-9s %6d%s", + vty_out(vty, "%-10s%-15s %-15s %-5s %-8s %-9s %-9s %6d%s", up->rpf.source_nexthop.interface->name, src_str, grp_str, pim_upstream_state2str (up), uptime, join_timer, + rs_timer, up->ref_count, VTY_NEWLINE); } From 4ed0af7013a8885e7c18d7ed532b16c5be5f2df9 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 2 Aug 2016 04:38:11 -0400 Subject: [PATCH 071/386] lib, pimd: Fix borked up prefix code Fix the struct prefix to be an actual struct prefix_sg. This cleans up a bunch of code to make it look nicer. Signed-off-by: Donald Sharp --- lib/prefix.h | 20 +++++------- pimd/pim_assert.c | 12 +++---- pimd/pim_br.c | 20 ++++++------ pimd/pim_br.h | 6 ++-- pimd/pim_cmd.c | 48 +++++++++++++-------------- pimd/pim_ifchannel.c | 74 ++++++++++++++++++++--------------------- pimd/pim_ifchannel.h | 14 ++++---- pimd/pim_join.c | 36 ++++++++++---------- pimd/pim_join.h | 2 +- pimd/pim_mroute.c | 26 +++++++-------- pimd/pim_oil.c | 14 ++++---- pimd/pim_oil.h | 2 +- pimd/pim_register.c | 28 ++++++++-------- pimd/pim_str.c | 6 ++-- pimd/pim_str.h | 2 +- pimd/pim_upstream.c | 78 ++++++++++++++++++++++---------------------- pimd/pim_upstream.h | 10 +++--- pimd/pim_zebra.c | 18 +++++----- 18 files changed, 206 insertions(+), 210 deletions(-) diff --git a/lib/prefix.h b/lib/prefix.h index 4878fcfdd2..a2cdfe96fb 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -74,20 +74,13 @@ struct prefix { u_char prefix; struct in_addr prefix4; -#ifdef HAVE_IPV6 struct in6_addr prefix6; -#endif /* HAVE_IPV6 */ struct { struct in_addr id; struct in_addr adv_router; } lp; struct ethaddr prefix_eth; /* AF_ETHERNET */ - struct - { - struct in_addr src; - struct in_addr grp; - } sg; u_char val[8]; uintptr_t ptr; } u __attribute__ ((aligned (8))); @@ -102,14 +95,12 @@ struct prefix_ipv4 }; /* IPv6 prefix structure. */ -#ifdef HAVE_IPV6 struct prefix_ipv6 { u_char family; u_char prefixlen; struct in6_addr prefix __attribute__ ((aligned (8))); }; -#endif /* HAVE_IPV6 */ struct prefix_ls { @@ -143,6 +134,14 @@ struct prefix_ptr uintptr_t prefix __attribute__ ((aligned (8))); }; +struct prefix_sg +{ + u_char family; + u_char prefixlen; + struct in_addr src __attribute ((aligned (8))); + struct in_addr grp; +}; + /* helper to get type safety/avoid casts on calls * (w/o this, functions accepting all prefix types need casts on the caller * side, which strips type safety since the cast will accept any pointer @@ -276,7 +275,6 @@ extern in_addr_t ipv4_broadcast_addr (in_addr_t hostaddr, int masklen); extern int netmask_str2prefix_str (const char *, const char *, char *); -#ifdef HAVE_IPV6 extern struct prefix_ipv6 *prefix_ipv6_new (void); extern void prefix_ipv6_free (struct prefix_ipv6 *); extern int str2prefix_ipv6 (const char *, struct prefix_ipv6 *); @@ -303,8 +301,6 @@ static inline int ipv6_martian (struct in6_addr *addr) return 0; } -#endif /* HAVE_IPV6 */ - extern int all_digit (const char *); /* NOTE: This routine expects the address argument in network byte order. */ diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index 07f49c6adf..4443e4459a 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -145,11 +145,11 @@ static int dispatch_assert(struct interface *ifp, struct pim_assert_metric recv_metric) { struct pim_ifchannel *ch; - struct prefix sg; + struct prefix_sg sg; - memset (&sg, 0, sizeof (struct prefix)); - sg.u.sg.src = source_addr; - sg.u.sg.grp = group_addr; + memset (&sg, 0, sizeof (struct prefix_sg)); + sg.src = source_addr; + sg.grp = group_addr; ch = pim_ifchannel_add(ifp, &sg); if (!ch) { zlog_warn("%s: (S,G)=%s failure creating channel on interface %s", @@ -443,7 +443,7 @@ static int pim_assert_do(struct pim_ifchannel *ch, } pim_msg_size = pim_assert_build_msg(pim_msg, sizeof(pim_msg), ifp, - ch->sg.u.sg.grp, ch->sg.u.sg.src, + ch->sg.grp, ch->sg.src, metric.metric_preference, metric.route_metric, metric.rpt_bit_flag); @@ -504,7 +504,7 @@ static int pim_assert_cancel(struct pim_ifchannel *ch) metric.rpt_bit_flag = 0; metric.metric_preference = PIM_ASSERT_METRIC_PREFERENCE_MAX; metric.route_metric = PIM_ASSERT_ROUTE_METRIC_MAX; - metric.ip_address = ch->sg.u.sg.src; + metric.ip_address = ch->sg.src; return pim_assert_do(ch, metric); } diff --git a/pimd/pim_br.c b/pimd/pim_br.c index ceee40e716..3f84de79c8 100644 --- a/pimd/pim_br.c +++ b/pimd/pim_br.c @@ -30,7 +30,7 @@ #include "linklist.h" struct pim_br { - struct prefix sg; + struct prefix_sg sg; struct in_addr pmbr; }; @@ -39,14 +39,14 @@ struct in_addr pim_br_unknown = { .s_addr = 0 }; static struct list *pim_br_list = NULL; struct in_addr -pim_br_get_pmbr (struct prefix *sg) +pim_br_get_pmbr (struct prefix_sg *sg) { struct listnode *node; struct pim_br *pim_br; for (ALL_LIST_ELEMENTS_RO (pim_br_list, node, pim_br)) { - if (sg->u.sg.src.s_addr == pim_br->sg.u.sg.src.s_addr && - sg->u.sg.grp.s_addr == pim_br->sg.u.sg.grp.s_addr) + if (sg->src.s_addr == pim_br->sg.src.s_addr && + sg->grp.s_addr == pim_br->sg.grp.s_addr) return pim_br->pmbr; } @@ -54,14 +54,14 @@ pim_br_get_pmbr (struct prefix *sg) } void -pim_br_set_pmbr (struct prefix *sg, struct in_addr br) +pim_br_set_pmbr (struct prefix_sg *sg, struct in_addr br) { struct listnode *node, *next; struct pim_br *pim_br; for (ALL_LIST_ELEMENTS (pim_br_list, node, next, pim_br)) { - if (sg->u.sg.src.s_addr == pim_br->sg.u.sg.src.s_addr && - sg->u.sg.grp.s_addr == pim_br->sg.u.sg.grp.s_addr) + if (sg->src.s_addr == pim_br->sg.src.s_addr && + sg->grp.s_addr == pim_br->sg.grp.s_addr) break; } @@ -84,14 +84,14 @@ pim_br_set_pmbr (struct prefix *sg, struct in_addr br) * Remove the (S,G) from the stored values */ void -pim_br_clear_pmbr (struct prefix *sg) +pim_br_clear_pmbr (struct prefix_sg *sg) { struct listnode *node, *next; struct pim_br *pim_br; for (ALL_LIST_ELEMENTS (pim_br_list, node, next, pim_br)) { - if (sg->u.sg.src.s_addr == pim_br->sg.u.sg.src.s_addr && - sg->u.sg.grp.s_addr == pim_br->sg.u.sg.grp.s_addr) + if (sg->src.s_addr == pim_br->sg.src.s_addr && + sg->grp.s_addr == pim_br->sg.grp.s_addr) break; } diff --git a/pimd/pim_br.h b/pimd/pim_br.h index bcb864dfc1..8e4f719ed0 100644 --- a/pimd/pim_br.h +++ b/pimd/pim_br.h @@ -21,10 +21,10 @@ #ifndef PIM_BR_H #define PIM_BR_H -struct in_addr pim_br_get_pmbr (struct prefix *sg); +struct in_addr pim_br_get_pmbr (struct prefix_sg *sg); -void pim_br_set_pmbr (struct prefix *sg, struct in_addr value); -void pim_br_clear_pmbr (struct prefix *sg); +void pim_br_set_pmbr (struct prefix_sg *sg, struct in_addr value); +void pim_br_clear_pmbr (struct prefix_sg *sg); void pim_br_init (void); diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 4319b06815..ed7e57a95e 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -128,11 +128,11 @@ static void pim_if_membership_refresh(struct interface *ifp) for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) { if (IGMP_SOURCE_TEST_FORWARDING(src->source_flags)) { - struct prefix sg; + struct prefix_sg sg; - memset (&sg, 0, sizeof (struct prefix)); - sg.u.sg.src = src->source_addr; - sg.u.sg.grp = grp->group_addr; + memset (&sg, 0, sizeof (struct prefix_sg)); + sg.src = src->source_addr; + sg.grp = grp->group_addr; pim_ifchannel_local_membership_add(ifp, &sg); } @@ -180,9 +180,9 @@ static void pim_show_assert(struct vty *vty) char uptime[10]; char timer[10]; - pim_inet4_dump("", ch->sg.u.sg.src, + pim_inet4_dump("", ch->sg.src, ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->sg.u.sg.grp, + pim_inet4_dump("", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str)); pim_inet4_dump("", ch->ifassert_winner, winner_str, sizeof(winner_str)); @@ -238,9 +238,9 @@ static void pim_show_assert_internal(struct vty *vty) char ch_src_str[100]; char ch_grp_str[100]; - pim_inet4_dump("", ch->sg.u.sg.src, + pim_inet4_dump("", ch->sg.src, ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->sg.u.sg.grp, + pim_inet4_dump("", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str)); vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s%s", ifp->name, @@ -286,9 +286,9 @@ static void pim_show_assert_metric(struct vty *vty) am = pim_macro_spt_assert_metric(&ch->upstream->rpf, pim_ifp->primary_address); - pim_inet4_dump("", ch->sg.u.sg.src, + pim_inet4_dump("", ch->sg.src, ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->sg.u.sg.grp, + pim_inet4_dump("", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str)); pim_inet4_dump("", am.ip_address, addr_str, sizeof(addr_str)); @@ -339,9 +339,9 @@ static void pim_show_assert_winner_metric(struct vty *vty) am = &ch->ifassert_winner_metric; - pim_inet4_dump("", ch->sg.u.sg.src, + pim_inet4_dump("", ch->sg.src, ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->sg.u.sg.grp, + pim_inet4_dump("", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str)); pim_inet4_dump("", am->ip_address, addr_str, sizeof(addr_str)); @@ -396,9 +396,9 @@ static void pim_show_membership(struct vty *vty) char ch_src_str[100]; char ch_grp_str[100]; - pim_inet4_dump("", ch->sg.u.sg.src, + pim_inet4_dump("", ch->sg.src, ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->sg.u.sg.grp, + pim_inet4_dump("", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str)); vty_out(vty, "%-9s %-15s %-15s %-15s %-10s%s", @@ -730,9 +730,9 @@ static void pim_show_join(struct vty *vty) char expire[10]; char prune[10]; - pim_inet4_dump("", ch->sg.u.sg.src, + pim_inet4_dump("", ch->sg.src, ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->sg.u.sg.grp, + pim_inet4_dump("", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str)); pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation); @@ -991,8 +991,8 @@ static void pim_show_upstream(struct vty *vty) char join_timer[10]; char rs_timer[10]; - pim_inet4_dump("", up->sg.u.sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", up->sg.u.sg.grp, grp_str, sizeof(grp_str)); + pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer), up->t_join_timer); pim_time_timer_to_hhmmss (rs_timer, sizeof (rs_timer), up->t_rs_timer); @@ -1034,8 +1034,8 @@ static void pim_show_join_desired(struct vty *vty) for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, chnode, ch)) { struct pim_upstream *up = ch->upstream; - pim_inet4_dump("", up->sg.u.sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", up->sg.u.sg.grp, grp_str, sizeof(grp_str)); + pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); vty_out(vty, "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s%s", ifp->name, @@ -1070,8 +1070,8 @@ static void pim_show_upstream_rpf(struct vty *vty) rpf = &up->rpf; - pim_inet4_dump("", up->sg.u.sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", up->sg.u.sg.grp, grp_str, sizeof(grp_str)); + pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); pim_inet4_dump("", rpf->source_nexthop.mrib_nexthop_addr, rpf_nexthop_str, sizeof(rpf_nexthop_str)); pim_inet4_dump("", rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); @@ -1147,8 +1147,8 @@ static void pim_show_rpf(struct vty *vty) const char *rpf_ifname; struct pim_rpf *rpf = &up->rpf; - pim_inet4_dump("", up->sg.u.sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", up->sg.u.sg.grp, grp_str, sizeof(grp_str)); + pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); pim_inet4_dump("", rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); pim_inet4_dump("", rpf->source_nexthop.mrib_nexthop_addr, rib_nexthop_str, sizeof(rib_nexthop_str)); diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index f1da740e78..dcd9da64b6 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -51,13 +51,13 @@ pim_ifchannel_remove_children (struct pim_ifchannel *ch) struct pim_ifchannel *child; // Basic sanity, (*,*) not currently supported - if ((ch->sg.u.sg.src.s_addr == INADDR_ANY) && - (ch->sg.u.sg.grp.s_addr == INADDR_ANY)) + if ((ch->sg.src.s_addr == INADDR_ANY) && + (ch->sg.grp.s_addr == INADDR_ANY)) return; // Basic sanity (S,G) have no children - if ((ch->sg.u.sg.src.s_addr != INADDR_ANY) && - (ch->sg.u.sg.grp.s_addr != INADDR_ANY)) + if ((ch->sg.src.s_addr != INADDR_ANY) && + (ch->sg.grp.s_addr != INADDR_ANY)) return; for (ALL_LIST_ELEMENTS_RO (pim_ifp->pim_ifchannel_list, ch_node, child)) @@ -80,18 +80,18 @@ pim_ifchannel_find_new_children (struct pim_ifchannel *ch) struct listnode *ch_node; // Basic Sanity that we are not being silly - if ((ch->sg.u.sg.src.s_addr != INADDR_ANY) && - (ch->sg.u.sg.grp.s_addr != INADDR_ANY)) + if ((ch->sg.src.s_addr != INADDR_ANY) && + (ch->sg.grp.s_addr != INADDR_ANY)) return; - if ((ch->sg.u.sg.src.s_addr == INADDR_ANY) && - (ch->sg.u.sg.grp.s_addr == INADDR_ANY)) + if ((ch->sg.src.s_addr == INADDR_ANY) && + (ch->sg.grp.s_addr == INADDR_ANY)) return; for (ALL_LIST_ELEMENTS_RO (pim_ifp->pim_ifchannel_list, ch_node, child)) { - if ((ch->sg.u.sg.grp.s_addr != INADDR_ANY) && - (child->sg.u.sg.grp.s_addr == ch->sg.u.sg.grp.s_addr) && + if ((ch->sg.grp.s_addr != INADDR_ANY) && + (child->sg.grp.s_addr == ch->sg.grp.s_addr) && (child != ch)) child->parent = ch; } @@ -244,7 +244,7 @@ void reset_ifassert_state(struct pim_ifchannel *ch) } struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, - struct prefix *sg) + struct prefix_sg *sg) { struct pim_interface *pim_ifp; struct listnode *ch_node; @@ -264,8 +264,8 @@ struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { if ( - (sg->u.sg.src.s_addr == ch->sg.u.sg.src.s_addr) && - (sg->u.sg.grp.s_addr == ch->sg.u.sg.grp.s_addr) + (sg->src.s_addr == ch->sg.src.s_addr) && + (sg->grp.s_addr == ch->sg.grp.s_addr) ) { return ch; } @@ -333,33 +333,33 @@ void pim_ifchannel_delete_on_noinfo(struct interface *ifp) */ static struct pim_ifchannel * pim_ifchannel_find_parent (struct interface *ifp, - struct prefix *sg) + struct prefix_sg *sg) { - struct prefix parent_sg = *sg; + struct prefix_sg parent_sg = *sg; // (*,*) || (S,*) - if (((sg->u.sg.src.s_addr == INADDR_ANY) && - (sg->u.sg.grp.s_addr == INADDR_ANY)) || - ((sg->u.sg.src.s_addr != INADDR_ANY) && - (sg->u.sg.grp.s_addr == INADDR_ANY))) + if (((sg->src.s_addr == INADDR_ANY) && + (sg->grp.s_addr == INADDR_ANY)) || + ((sg->src.s_addr != INADDR_ANY) && + (sg->grp.s_addr == INADDR_ANY))) return NULL; // (S,G) - if ((sg->u.sg.src.s_addr != INADDR_ANY) && - (sg->u.sg.grp.s_addr != INADDR_ANY)) + if ((sg->src.s_addr != INADDR_ANY) && + (sg->grp.s_addr != INADDR_ANY)) { - parent_sg.u.sg.src.s_addr = INADDR_ANY; + parent_sg.src.s_addr = INADDR_ANY; return pim_ifchannel_find (ifp, &parent_sg); } // (*,G) -- Not going to find anything currently - parent_sg.u.sg.grp.s_addr = INADDR_ANY; + parent_sg.grp.s_addr = INADDR_ANY; return pim_ifchannel_find (ifp, &parent_sg); } struct pim_ifchannel * pim_ifchannel_add(struct interface *ifp, - struct prefix *sg) + struct prefix_sg *sg) { struct pim_interface *pim_ifp; struct pim_ifchannel *ch; @@ -459,7 +459,7 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) int send_prune_echo; /* boolean */ struct interface *ifp; struct pim_interface *pim_ifp; - struct prefix sg; + struct prefix_sg sg; zassert(t); ch = THREAD_ARG(t); @@ -490,7 +490,7 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) static void check_recv_upstream(int is_join, struct interface *recv_ifp, struct in_addr upstream, - struct prefix *sg, + struct prefix_sg *sg, uint8_t source_flags, int holdtime) { @@ -557,7 +557,7 @@ static void check_recv_upstream(int is_join, static int nonlocal_upstream(int is_join, struct interface *recv_ifp, struct in_addr upstream, - struct prefix *sg, + struct prefix_sg *sg, uint8_t source_flags, uint16_t holdtime) { @@ -596,7 +596,7 @@ static int nonlocal_upstream(int is_join, void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr, struct in_addr upstream, - struct prefix *sg, + struct prefix_sg *sg, uint8_t source_flags, uint16_t holdtime) { @@ -696,7 +696,7 @@ void pim_ifchannel_join_add(struct interface *ifp, void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream, - struct prefix *sg, + struct prefix_sg *sg, uint8_t source_flags, uint16_t holdtime) { @@ -753,7 +753,7 @@ void pim_ifchannel_prune(struct interface *ifp, } void pim_ifchannel_local_membership_add(struct interface *ifp, - struct prefix *sg) + struct prefix_sg *sg) { struct pim_ifchannel *ch; struct pim_interface *pim_ifp; @@ -776,7 +776,7 @@ void pim_ifchannel_local_membership_add(struct interface *ifp, } void pim_ifchannel_local_membership_del(struct interface *ifp, - struct prefix *sg) + struct prefix_sg *sg) { struct pim_ifchannel *ch; struct pim_interface *pim_ifp; @@ -808,8 +808,8 @@ void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch) if (PIM_DEBUG_PIM_EVENTS) { char src_str[100]; char grp_str[100]; - pim_inet4_dump("", ch->sg.u.sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->sg.u.sg.grp, grp_str, sizeof(grp_str)); + pim_inet4_dump("", ch->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", ch->sg.grp, grp_str, sizeof(grp_str)); zlog_debug("%s: CouldAssert(%s,%s,%s) changed from %d to %d", __PRETTY_FUNCTION__, src_str, grp_str, ch->interface->name, @@ -852,8 +852,8 @@ void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch) char grp_str[100]; char old_addr_str[100]; char new_addr_str[100]; - pim_inet4_dump("", ch->sg.u.sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->sg.u.sg.grp, grp_str, sizeof(grp_str)); + pim_inet4_dump("", ch->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", ch->sg.grp, grp_str, sizeof(grp_str)); pim_inet4_dump("", ch->ifassert_my_metric.ip_address, old_addr_str, sizeof(old_addr_str)); pim_inet4_dump("", my_metric_new.ip_address, new_addr_str, sizeof(new_addr_str)); zlog_debug("%s: my_assert_metric(%s,%s,%s) changed from %u,%u,%u,%s to %u,%u,%u,%s", @@ -888,8 +888,8 @@ void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch) if (PIM_DEBUG_PIM_EVENTS) { char src_str[100]; char grp_str[100]; - pim_inet4_dump("", ch->sg.u.sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->sg.u.sg.grp, grp_str, sizeof(grp_str)); + pim_inet4_dump("", ch->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", ch->sg.grp, grp_str, sizeof(grp_str)); zlog_debug("%s: AssertTrackingDesired(%s,%s,%s) changed from %d to %d", __PRETTY_FUNCTION__, src_str, grp_str, ch->interface->name, diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index eb6b0925a8..7036131e56 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -73,7 +73,7 @@ struct pim_assert_metric { */ struct pim_ifchannel { struct pim_ifchannel *parent; - struct prefix sg; + struct prefix_sg sg; struct interface *interface; /* backpointer to interface */ uint32_t flags; @@ -103,24 +103,24 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch); void pim_ifchannel_membership_clear(struct interface *ifp); void pim_ifchannel_delete_on_noinfo(struct interface *ifp); struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, - struct prefix *sg); + struct prefix_sg *sg); struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, - struct prefix *sg); + struct prefix_sg *sg); void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr, struct in_addr upstream, - struct prefix *sg, + struct prefix_sg *sg, uint8_t source_flags, uint16_t holdtime); void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream, - struct prefix *sg, + struct prefix_sg *sg, uint8_t source_flags, uint16_t holdtime); void pim_ifchannel_local_membership_add(struct interface *ifp, - struct prefix *sg); + struct prefix_sg *sg); void pim_ifchannel_local_membership_del(struct interface *ifp, - struct prefix *sg); + struct prefix_sg *sg); void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch, diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 3d98f9f95f..7e0f268f9b 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -58,11 +58,11 @@ static void recv_join(struct interface *ifp, struct in_addr source, uint8_t source_flags) { - struct prefix sg; + struct prefix_sg sg; - memset (&sg, 0, sizeof (struct prefix)); - sg.u.sg.src = source; - sg.u.sg.grp = group; + memset (&sg, 0, sizeof (struct prefix_sg)); + sg.src = source; + sg.grp = group; if (PIM_DEBUG_PIM_TRACE) { char up_str[100]; @@ -84,23 +84,23 @@ static void recv_join(struct interface *ifp, if ((source_flags & PIM_RPT_BIT_MASK) && (source_flags & PIM_WILDCARD_BIT_MASK)) { - struct pim_rpf *rp = RP (sg.u.sg.grp); + struct pim_rpf *rp = RP (sg.grp); /* * If the RP sent in the message is not * our RP for the group, drop the message */ - if (sg.u.sg.src.s_addr != rp->rpf_addr.s_addr) + if (sg.src.s_addr != rp->rpf_addr.s_addr) return; - sg.u.sg.src.s_addr = INADDR_ANY; + sg.src.s_addr = INADDR_ANY; } /* Restart join expiry timer */ pim_ifchannel_join_add(ifp, neigh->source_addr, upstream, &sg, source_flags, holdtime); - if (sg.u.sg.src.s_addr == INADDR_ANY) + if (sg.src.s_addr == INADDR_ANY) { struct pim_upstream *up = pim_upstream_find (&sg); struct pim_upstream *child; @@ -133,11 +133,11 @@ static void recv_prune(struct interface *ifp, struct in_addr source, uint8_t source_flags) { - struct prefix sg; + struct prefix_sg sg; - memset (&sg, 0, sizeof (struct prefix)); - sg.u.sg.src = source; - sg.u.sg.grp = group; + memset (&sg, 0, sizeof (struct prefix_sg)); + sg.src = source; + sg.grp = group; if (PIM_DEBUG_PIM_TRACE) { char up_str[100]; @@ -155,18 +155,18 @@ static void recv_prune(struct interface *ifp, if ((source_flags & PIM_RPT_BIT_MASK) && (source_flags & PIM_WILDCARD_BIT_MASK)) { - struct pim_rpf *rp = RP (sg.u.sg.grp); + struct pim_rpf *rp = RP (sg.grp); // Ignoring Prune *,G's at the moment. - if (sg.u.sg.src.s_addr != rp->rpf_addr.s_addr) + if (sg.src.s_addr != rp->rpf_addr.s_addr) return; - sg.u.sg.src.s_addr = INADDR_ANY; + sg.src.s_addr = INADDR_ANY; } pim_ifchannel_prune(ifp, upstream, &sg, source_flags, holdtime); - if (sg.u.sg.src.s_addr == INADDR_ANY) + if (sg.src.s_addr == INADDR_ANY) { struct pim_upstream *up = pim_upstream_find (&sg); struct pim_upstream *child; @@ -355,7 +355,7 @@ int pim_joinprune_recv(struct interface *ifp, int pim_joinprune_send(struct interface *ifp, struct in_addr upstream_addr, - struct prefix *sg, + struct prefix_sg *sg, int send_join) { struct pim_interface *pim_ifp; @@ -411,7 +411,7 @@ int pim_joinprune_send(struct interface *ifp, Build PIM message */ pim_msg_size = pim_msg_join_prune_encode (pim_msg, 1000, send_join, - sg->u.sg.src, sg->u.sg.grp, + sg->src, sg->grp, upstream_addr, PIM_JP_HOLDTIME); if (pim_msg_size < 0) diff --git a/pimd/pim_join.h b/pimd/pim_join.h index 6777587c39..e6bddf31be 100644 --- a/pimd/pim_join.h +++ b/pimd/pim_join.h @@ -35,7 +35,7 @@ int pim_joinprune_recv(struct interface *ifp, int pim_joinprune_send(struct interface *ifp, struct in_addr upstream_addr, - struct prefix *sg, + struct prefix_sg *sg, int send_join); #endif /* PIM_JOIN_H */ diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index f26fb7ae24..aa2d021eed 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -95,7 +95,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg struct pim_interface *pim_ifp = ifp->info; struct pim_upstream *up; struct pim_rpf *rpg; - struct prefix sg; + struct prefix_sg sg; rpg = RP(msg->im_dst); /* @@ -126,9 +126,9 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg __PRETTY_FUNCTION__, grp_str, src_str); } - memset (&sg, 0, sizeof (struct prefix)); - sg.u.sg.src = msg->im_src; - sg.u.sg.grp = msg->im_dst; + memset (&sg, 0, sizeof (struct prefix_sg)); + sg.src = msg->im_src; + sg.grp = msg->im_dst; up = pim_upstream_add (&sg, ifp); if (!up) { if (PIM_DEBUG_MROUTE) { @@ -164,16 +164,16 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf, const char *src_str, const char *grp_str) { struct pim_interface *pim_ifp; - struct prefix sg; + struct prefix_sg sg; struct pim_rpf *rpg; const struct ip *ip_hdr; struct pim_upstream *up; ip_hdr = (const struct ip *)buf; - memset (&sg, 0, sizeof (struct prefix)); - sg.u.sg.src = ip_hdr->ip_src; - sg.u.sg.grp = ip_hdr->ip_dst; + memset (&sg, 0, sizeof (struct prefix_sg)); + sg.src = ip_hdr->ip_src; + sg.grp = ip_hdr->ip_dst; up = pim_upstream_find(&sg); if (!up) { @@ -186,7 +186,7 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf, pim_ifp = up->rpf.source_nexthop.interface->info; - rpg = RP(sg.u.sg.grp); + rpg = RP(sg.grp); if ((rpg->rpf_addr.s_addr == INADDR_NONE) || (!pim_ifp) || @@ -213,7 +213,7 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms { struct pim_ifchannel *ch; struct pim_interface *pim_ifp; - struct prefix sg; + struct prefix_sg sg; /* Send Assert(S,G) on iif as response to WRONGVIF kernel upcall. @@ -245,9 +245,9 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms return -2; } - memset (&sg, 0, sizeof (struct prefix)); - sg.u.sg.src = msg->im_src; - sg.u.sg.grp = msg->im_dst; + memset (&sg, 0, sizeof (struct prefix_sg)); + sg.src = msg->im_src; + sg.grp = msg->im_dst; ch = pim_ifchannel_find(ifp, &sg); if (!ch) { if (PIM_DEBUG_MROUTE) { diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 8c7beeb97b..d3895ea286 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -51,7 +51,7 @@ pim_del_channel_oil (struct channel_oil *c_oil) } static struct channel_oil * -pim_add_channel_oil (struct prefix *sg, +pim_add_channel_oil (struct prefix_sg *sg, int input_vif_index) { struct channel_oil *c_oil; @@ -71,8 +71,8 @@ pim_add_channel_oil (struct prefix *sg, return NULL; } - c_oil->oil.mfcc_mcastgrp = sg->u.sg.grp; - c_oil->oil.mfcc_origin = sg->u.sg.src; + c_oil->oil.mfcc_mcastgrp = sg->grp; + c_oil->oil.mfcc_origin = sg->src; c_oil->oil.mfcc_parent = input_vif_index; c_oil->oil_ref_count = 1; c_oil->installed = 0; @@ -82,21 +82,21 @@ pim_add_channel_oil (struct prefix *sg, return c_oil; } -static struct channel_oil *pim_find_channel_oil(struct prefix *sg) +static struct channel_oil *pim_find_channel_oil(struct prefix_sg *sg) { struct listnode *node; struct channel_oil *c_oil; for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) { - if ((sg->u.sg.grp.s_addr == c_oil->oil.mfcc_mcastgrp.s_addr) && - (sg->u.sg.src.s_addr == c_oil->oil.mfcc_origin.s_addr)) + if ((sg->grp.s_addr == c_oil->oil.mfcc_mcastgrp.s_addr) && + (sg->src.s_addr == c_oil->oil.mfcc_origin.s_addr)) return c_oil; } return 0; } -struct channel_oil *pim_channel_oil_add(struct prefix *sg, +struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg, int input_vif_index) { struct channel_oil *c_oil; diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index fc5188e327..6b55bdc4d5 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -78,7 +78,7 @@ struct channel_oil { }; void pim_channel_oil_free(struct channel_oil *c_oil); -struct channel_oil *pim_channel_oil_add(struct prefix *sg, +struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg, int input_vif_index); void pim_channel_oil_del(struct channel_oil *c_oil); diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 456581127e..c43818dfff 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -67,7 +67,7 @@ pim_check_is_my_ip_address (struct in_addr dest_addr) } static void -pim_register_stop_send (struct interface *ifp, struct prefix *sg, +pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, struct in_addr originator) { struct pim_interface *pinfo; @@ -86,12 +86,12 @@ pim_register_stop_send (struct interface *ifp, struct prefix *sg, memset (buffer, 0, 3000); b1 = (uint8_t *)buffer + PIM_MSG_REGISTER_STOP_LEN; - length = pim_encode_addr_group (b1, AFI_IP, 0, 0, sg->u.sg.grp); + length = pim_encode_addr_group (b1, AFI_IP, 0, 0, sg->grp); b1length += length; b1 += length; p.family = AF_INET; - p.u.prefix4 = sg->u.sg.src; + p.u.prefix4 = sg->src; p.prefixlen = 32; length = pim_encode_addr_ucast (b1, &p); b1length += length; @@ -123,16 +123,16 @@ pim_register_stop_recv (uint8_t *buf, int buf_size) struct pim_upstream *upstream = NULL; struct prefix source; struct prefix group; - struct prefix sg; + struct prefix_sg sg; int l; l = pim_parse_addr_group (&group, buf, buf_size); buf += l; buf_size -= l; l = pim_parse_addr_ucast (&source, buf, buf_size); - memset (&sg, 0, sizeof (struct prefix)); - sg.u.sg.src = source.u.prefix4; - sg.u.sg.grp = group.u.prefix4; + memset (&sg, 0, sizeof (struct prefix_sg)); + sg.src = source.u.prefix4; + sg.grp = group.u.prefix4; if (PIM_DEBUG_PIM_REG) { @@ -260,7 +260,7 @@ pim_register_recv (struct interface *ifp, { int sentRegisterStop = 0; struct ip *ip_hdr; - struct prefix sg; + struct prefix_sg sg; uint32_t *bits; if (!pim_check_is_my_ip_address (dest_addr)) { @@ -310,11 +310,11 @@ pim_register_recv (struct interface *ifp, */ #define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4 ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN); - memset (&sg, 0, sizeof (struct prefix)); - sg.u.sg.src = ip_hdr->ip_src; - sg.u.sg.grp = ip_hdr->ip_dst; + memset (&sg, 0, sizeof (struct prefix_sg)); + sg.src = ip_hdr->ip_src; + sg.grp = ip_hdr->ip_dst; - if (I_am_RP (sg.u.sg.grp) && (dest_addr.s_addr == ((RP (sg.u.sg.grp))->rpf_addr.s_addr))) { + if (I_am_RP (sg.grp) && (dest_addr.s_addr == ((RP (sg.grp))->rpf_addr.s_addr))) { sentRegisterStop = 0; if (*bits & PIM_REGISTER_BORDER_BIT) { @@ -342,11 +342,11 @@ pim_register_recv (struct interface *ifp, { upstream = pim_upstream_add (&sg, ifp); - pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.u.sg.src); + pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.src); pim_nexthop_lookup (&upstream->rpf.source_nexthop, upstream->upstream_addr, NULL); upstream->rpf.source_nexthop.interface = ifp; - upstream->sg.u.sg.src = sg.u.sg.src; + upstream->sg.src = sg.src; upstream->rpf.rpf_addr = upstream->rpf.source_nexthop.mrib_nexthop_addr; pim_upstream_switch (upstream, PIM_UPSTREAM_PRUNE); diff --git a/pimd/pim_str.c b/pimd/pim_str.c index f02732426e..8e1d7cec29 100644 --- a/pimd/pim_str.c +++ b/pimd/pim_str.c @@ -44,14 +44,14 @@ void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, int buf_ } char * -pim_str_sg_dump (const struct prefix *sg) +pim_str_sg_dump (const struct prefix_sg *sg) { char src_str[100]; char grp_str[100]; static char sg_str[200]; - pim_inet4_dump ("", sg->u.sg.src, src_str, sizeof(src_str)); - pim_inet4_dump ("", sg->u.sg.grp, grp_str, sizeof(grp_str)); + pim_inet4_dump ("", sg->src, src_str, sizeof(src_str)); + pim_inet4_dump ("", sg->grp, grp_str, sizeof(grp_str)); snprintf (sg_str, 200, "(%s,%s)", src_str, grp_str); return sg_str; } diff --git a/pimd/pim_str.h b/pimd/pim_str.h index ca20352504..3dff9fa1e9 100644 --- a/pimd/pim_str.h +++ b/pimd/pim_str.h @@ -29,6 +29,6 @@ #include void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, int buf_size); -char *pim_str_sg_dump (const struct prefix *sg); +char *pim_str_sg_dump (const struct prefix_sg *sg); #endif diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index a304f359eb..3321161c51 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -62,13 +62,13 @@ pim_upstream_remove_children (struct pim_upstream *up) struct pim_upstream *child; // Basic sanity, (*,*) not currently supported - if ((up->sg.u.sg.src.s_addr == INADDR_ANY) && - (up->sg.u.sg.grp.s_addr == INADDR_ANY)) + if ((up->sg.src.s_addr == INADDR_ANY) && + (up->sg.grp.s_addr == INADDR_ANY)) return; // Basic sanity (S,G) have no children - if ((up->sg.u.sg.src.s_addr != INADDR_ANY) && - (up->sg.u.sg.grp.s_addr != INADDR_ANY)) + if ((up->sg.src.s_addr != INADDR_ANY) && + (up->sg.grp.s_addr != INADDR_ANY)) return; for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, ch_node, child)) @@ -89,18 +89,18 @@ pim_upstream_find_new_children (struct pim_upstream *up) struct pim_upstream *child; struct listnode *ch_node; - if ((up->sg.u.sg.src.s_addr != INADDR_ANY) && - (up->sg.u.sg.grp.s_addr != INADDR_ANY)) + if ((up->sg.src.s_addr != INADDR_ANY) && + (up->sg.grp.s_addr != INADDR_ANY)) return; - if ((up->sg.u.sg.src.s_addr == INADDR_ANY) && - (up->sg.u.sg.grp.s_addr == INADDR_ANY)) + if ((up->sg.src.s_addr == INADDR_ANY) && + (up->sg.grp.s_addr == INADDR_ANY)) return; for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, ch_node, child)) { - if ((up->sg.u.sg.grp.s_addr != INADDR_ANY) && - (child->sg.u.sg.grp.s_addr == up->sg.u.sg.grp.s_addr) && + if ((up->sg.grp.s_addr != INADDR_ANY) && + (child->sg.grp.s_addr == up->sg.grp.s_addr) && (child != up)) child->parent = up; } @@ -112,27 +112,27 @@ pim_upstream_find_new_children (struct pim_upstream *up) * If we have a (*,G), find the (*,*) */ static struct pim_upstream * -pim_upstream_find_parent (struct prefix *sg) +pim_upstream_find_parent (struct prefix_sg *sg) { - struct prefix any = *sg; + struct prefix_sg any = *sg; // (*,*) || (S,*) - if (((sg->u.sg.src.s_addr == INADDR_ANY) && - (sg->u.sg.grp.s_addr == INADDR_ANY)) || - ((sg->u.sg.src.s_addr != INADDR_ANY) && - (sg->u.sg.grp.s_addr == INADDR_ANY))) + if (((sg->src.s_addr == INADDR_ANY) && + (sg->grp.s_addr == INADDR_ANY)) || + ((sg->src.s_addr != INADDR_ANY) && + (sg->grp.s_addr == INADDR_ANY))) return NULL; // (S,G) - if ((sg->u.sg.src.s_addr != INADDR_ANY) && - (sg->u.sg.grp.s_addr != INADDR_ANY)) + if ((sg->src.s_addr != INADDR_ANY) && + (sg->grp.s_addr != INADDR_ANY)) { - any.u.sg.src.s_addr = INADDR_ANY; + any.src.s_addr = INADDR_ANY; return pim_upstream_find (&any); } // (*,G) - any.u.sg.grp.s_addr = INADDR_ANY; + any.grp.s_addr = INADDR_ANY; return pim_upstream_find (&any); } @@ -416,7 +416,7 @@ pim_upstream_switch(struct pim_upstream *up, } } -static struct pim_upstream *pim_upstream_new(struct prefix *sg, +static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, struct interface *incoming) { struct pim_upstream *up; @@ -430,7 +430,7 @@ static struct pim_upstream *pim_upstream_new(struct prefix *sg, } up->sg = *sg; - if (!pim_rp_set_upstream_addr (&up->upstream_addr, sg->u.sg.src)) + if (!pim_rp_set_upstream_addr (&up->upstream_addr, sg->src)) { if (PIM_DEBUG_PIM_TRACE) zlog_debug("%s: Received a (*,G) with no RP configured", __PRETTY_FUNCTION__); @@ -471,39 +471,39 @@ static struct pim_upstream *pim_upstream_new(struct prefix *sg, /* * For a given sg, find any non * source */ -struct pim_upstream *pim_upstream_find_non_any (struct prefix *sg) +struct pim_upstream *pim_upstream_find_non_any (struct prefix_sg *sg) { struct listnode *up_node; - struct prefix any = *sg; + struct prefix_sg any = *sg; struct pim_upstream *up; - any.u.sg.src.s_addr = INADDR_ANY; + any.src.s_addr = INADDR_ANY; for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, up_node, up)) { - if ((any.u.sg.grp.s_addr == up->sg.u.sg.grp.s_addr) && - (up->sg.u.sg.src.s_addr != any.u.sg.src.s_addr)) + if ((any.grp.s_addr == up->sg.grp.s_addr) && + (up->sg.src.s_addr != any.src.s_addr)) return up; } return NULL; } -struct pim_upstream *pim_upstream_find(struct prefix *sg) +struct pim_upstream *pim_upstream_find(struct prefix_sg *sg) { struct listnode *up_node; struct pim_upstream *up; for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, up_node, up)) { - if ((sg->u.sg.grp.s_addr == up->sg.u.sg.grp.s_addr) && - (sg->u.sg.src.s_addr == up->sg.u.sg.src.s_addr)) + if ((sg->grp.s_addr == up->sg.grp.s_addr) && + (sg->src.s_addr == up->sg.src.s_addr)) return up; } return NULL; } -struct pim_upstream *pim_upstream_add(struct prefix *sg, +struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, struct interface *incoming) { struct pim_upstream *up; @@ -794,7 +794,7 @@ pim_upstream_keep_alive_timer (struct thread *t) up = THREAD_ARG(t); - if (I_am_RP (up->sg.u.sg.grp)) + if (I_am_RP (up->sg.grp)) { pim_br_clear_pmbr (&up->sg); /* @@ -859,9 +859,9 @@ pim_upstream_keep_alive_timer_start (struct pim_upstream *up, * received for the source and group. */ int -pim_upstream_switch_to_spt_desired (struct prefix *sg) +pim_upstream_switch_to_spt_desired (struct prefix_sg *sg) { - if (I_am_RP (sg->u.sg.grp)) + if (I_am_RP (sg->grp)) return 1; return 0; @@ -914,13 +914,13 @@ pim_upstream_register_stop_timer (struct thread *t) up->join_state = PIM_UPSTREAM_JOIN_PENDING; pim_upstream_start_register_stop_timer (up, 1); - rpg = RP (up->sg.u.sg.grp); + rpg = RP (up->sg.grp); memset (&ip_hdr, 0, sizeof (struct ip)); ip_hdr.ip_p = PIM_IP_PROTO_PIM; ip_hdr.ip_hl = 5; ip_hdr.ip_v = 4; - ip_hdr.ip_src = up->sg.u.sg.src; - ip_hdr.ip_dst = up->sg.u.sg.grp; + ip_hdr.ip_src = up->sg.src; + ip_hdr.ip_dst = up->sg.grp; ip_hdr.ip_len = 20; // checksum is broken pim_register_send ((uint8_t *)&ip_hdr, sizeof (struct ip), rpg, 1); @@ -990,7 +990,7 @@ pim_upstream_inherited_olist (struct pim_upstream *up) struct listnode *chnode; struct listnode *ifnode; struct interface *ifp; - struct prefix anysrc; + struct prefix_sg anysrc; int output_intf = 0; pim_ifp = up->rpf.source_nexthop.interface->info; @@ -998,7 +998,7 @@ pim_upstream_inherited_olist (struct pim_upstream *up) if (!up->channel_oil) up->channel_oil = pim_channel_oil_add (&up->sg, pim_ifp->mroute_vif_index); anysrc = up->sg; - anysrc.u.sg.src.s_addr = INADDR_ANY; + anysrc.src.s_addr = INADDR_ANY; anysrc_up = pim_upstream_find (&anysrc); if (anysrc_up) diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 92535c46b0..eea9456013 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -90,7 +90,7 @@ struct pim_upstream { struct pim_upstream *parent; int fhr; struct in_addr upstream_addr;/* Who we are talking to */ - struct prefix sg; /* (S,G) group key */ + struct prefix_sg sg; /* (S,G) group key */ uint32_t flags; struct channel_oil *channel_oil; @@ -122,9 +122,9 @@ struct pim_upstream { void pim_upstream_free(struct pim_upstream *up); void pim_upstream_delete(struct pim_upstream *up); -struct pim_upstream *pim_upstream_find (struct prefix *sg); -struct pim_upstream *pim_upstream_find_non_any (struct prefix *sg); -struct pim_upstream *pim_upstream_add (struct prefix *sg, +struct pim_upstream *pim_upstream_find (struct prefix_sg *sg); +struct pim_upstream *pim_upstream_find_non_any (struct prefix_sg *sg); +struct pim_upstream *pim_upstream_add (struct prefix_sg *sg, struct interface *ifp); void pim_upstream_del(struct pim_upstream *up); @@ -147,7 +147,7 @@ void pim_upstream_update_my_assert_metric(struct pim_upstream *up); void pim_upstream_keep_alive_timer_start (struct pim_upstream *up, uint32_t time); -int pim_upstream_switch_to_spt_desired (struct prefix *sg); +int pim_upstream_switch_to_spt_desired (struct prefix_sg *sg); #define SwitchToSptDesired(sg) pim_upstream_switch_to_spt_desired (sg) void pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_register); diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 66550d9cb2..b4fb070443 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -948,12 +948,12 @@ static int del_oif(struct channel_oil *channel_oil, void igmp_source_forward_start(struct igmp_source *source) { struct igmp_group *group; - struct prefix sg; + struct prefix_sg sg; int result; memset (&sg, 0, sizeof (struct prefix)); - sg.u.sg.src = source->source_addr; - sg.u.sg.grp = source->source_group->group_addr; + sg.src = source->source_addr; + sg.grp = source->source_group->group_addr; if (PIM_DEBUG_IGMP_TRACE) { zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", @@ -1056,12 +1056,12 @@ void igmp_source_forward_start(struct igmp_source *source) void igmp_source_forward_stop(struct igmp_source *source) { struct igmp_group *group; - struct prefix sg; + struct prefix_sg sg; int result; memset (&sg, 0, sizeof (struct prefix)); - sg.u.sg.src = source->source_addr; - sg.u.sg.grp = source->source_group->group_addr; + sg.src = source->source_addr; + sg.grp = source->source_group->group_addr; if (PIM_DEBUG_IGMP_TRACE) { zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", @@ -1119,8 +1119,8 @@ void pim_forward_start(struct pim_ifchannel *ch) char group_str[100]; char upstream_str[100]; - pim_inet4_dump("", ch->sg.u.sg.src, source_str, sizeof(source_str)); - pim_inet4_dump("", ch->sg.u.sg.grp, group_str, sizeof(group_str)); + pim_inet4_dump("", ch->sg.src, source_str, sizeof(source_str)); + pim_inet4_dump("", ch->sg.grp, group_str, sizeof(group_str)); pim_inet4_dump("", up->upstream_addr, upstream_str, sizeof(upstream_str)); zlog_debug("%s: (S,G)=(%s,%s) oif=%s(%s)", __PRETTY_FUNCTION__, @@ -1131,7 +1131,7 @@ void pim_forward_start(struct pim_ifchannel *ch) int input_iface_vif_index = fib_lookup_if_vif_index(up->upstream_addr); if (input_iface_vif_index < 1) { char source_str[100]; - pim_inet4_dump("", up->sg.u.sg.src, source_str, sizeof(source_str)); + pim_inet4_dump("", up->sg.src, source_str, sizeof(source_str)); zlog_warn("%s %s: could not find input interface for source %s", __FILE__, __PRETTY_FUNCTION__, source_str); From 565fdc75259e6a273b9a46d14934a82e3bb041d7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 3 Aug 2016 19:53:42 -0400 Subject: [PATCH 072/386] zebra: Remove unused variable. Remove the rtnh variable since it is unused. Signed-off-by: Donald Sharp --- zebra/kernel_netlink.c | 4 +- zebra/rt_netlink.c | 110 ++++++++++++++++++++++++++++++----------- 2 files changed, 83 insertions(+), 31 deletions(-) diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 9f9a62f384..70b56b31b6 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -91,6 +91,7 @@ static const struct message rtproto_str[] = { #ifdef RTPROT_BIRD {RTPROT_BIRD, "BIRD"}, #endif /* RTPROT_BIRD */ + {RTPROT_MROUTED, "mroute"}, {0, NULL} }; @@ -718,7 +719,8 @@ kernel_init (struct zebra_ns *zns) /* Initialize netlink sockets */ groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR | - RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR; + RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR | + RTMGRP_IPV4_MROUTE; snprintf (zns->netlink.name, sizeof (zns->netlink.name), "netlink-listen (NS %u)", zns->ns_id); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index f168ef3957..bf2fc6d189 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -303,9 +303,17 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, return 0; } +static const struct message family_str[] = { + {AF_INET, "ipv4"}, + {AF_INET6, "ipv6"}, + {RTNL_FAMILY_IPMR, "ipv4MR"}, + {RTNL_FAMILY_IP6MR, "ipv6MR"}, + {0, NULL}, +}; + /* Routing information change from the kernel. */ -int -netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, +static int +netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, ns_id_t ns_id) { int len; @@ -327,35 +335,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, rtm = NLMSG_DATA (h); - if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) - { - /* If this is not route add/delete message print warning. */ - zlog_warn ("Kernel message: %d", h->nlmsg_type); - return 0; - } - - /* Connected route. */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s %s %s proto %s", - h->nlmsg_type == - RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", - rtm->rtm_family == AF_INET ? "ipv4" : "ipv6", - rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast", - nl_rtproto_to_str (rtm->rtm_protocol)); - - if (rtm->rtm_type != RTN_UNICAST) - { - return 0; - } - - /* We don't care about change notifications for the MPLS table. */ - /* TODO: Revisit this. */ - if (rtm->rtm_family == AF_MPLS) - return 0; - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); - if (len < 0) - return -1; memset (tb, 0, sizeof tb); netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len); @@ -544,6 +524,76 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, return 0; } +static int +netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id) +{ + int len; + struct rtmsg *rtm; + struct rtattr *tb[RTA_MAX + 1]; + + rtm = NLMSG_DATA (h); + + len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); + + memset (tb, 0, sizeof tb); + netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len); + + return 0; +} + +int +netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id) +{ + int len; + vrf_id_t vrf_id = ns_id; + struct rtmsg *rtm; + + rtm = NLMSG_DATA (h); + + if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) + { + /* If this is not route add/delete message print warning. */ + zlog_warn ("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id); + return 0; + } + + /* Connected route. */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("%s %s %s proto %s vrf %u", + h->nlmsg_type == + RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", + lookup (family_str, rtm->rtm_family), + rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast", + nl_rtproto_to_str (rtm->rtm_protocol), + vrf_id); + + /* We don't care about change notifications for the MPLS table. */ + /* TODO: Revisit this. */ + if (rtm->rtm_family == AF_MPLS) + return 0; + + len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); + if (len < 0) + return -1; + + switch (rtm->rtm_type) + { + case RTN_UNICAST: + netlink_route_change_read_unicast (snl, h, ns_id); + break; + case RTN_MULTICAST: + netlink_route_change_read_multicast (snl, h, ns_id); + break; + default: + return 0; + break; + } + + return 0; +} + /* Routing table read function using netlink interface. Only called bootstrap time. */ int From 02e6923ef3a291b32c3d473faabdd1941d9aa148 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 3 Aug 2016 20:57:47 -0400 Subject: [PATCH 073/386] pimd: Fix broken build I missed 2 instances of the conversion from struct prefix to struct prefix_sg Signed-off-by: Donald Sharp --- pimd/pim_zebra.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index b4fb070443..046628de26 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -951,7 +951,7 @@ void igmp_source_forward_start(struct igmp_source *source) struct prefix_sg sg; int result; - memset (&sg, 0, sizeof (struct prefix)); + memset (&sg, 0, sizeof (struct prefix_sg)); sg.src = source->source_addr; sg.grp = source->source_group->group_addr; @@ -1059,7 +1059,7 @@ void igmp_source_forward_stop(struct igmp_source *source) struct prefix_sg sg; int result; - memset (&sg, 0, sizeof (struct prefix)); + memset (&sg, 0, sizeof (struct prefix_sg)); sg.src = source->source_addr; sg.grp = source->source_group->group_addr; From 872439346dcd717f38f259b830d6ff425e701e83 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 4 Aug 2016 11:09:30 -0400 Subject: [PATCH 074/386] pimd: Enable WrongVif and WRWHOLEVIF callbacks. Turn on Wrong Vif and Whole packet wrong vif callbacks. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 14 ++++++++++++++ pimd/pim_mroute.h | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index aa2d021eed..31ca10b6b6 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -56,6 +56,20 @@ static int pim_mroute_set(int fd, int enable) return -1; } + if (enable) + { + int upcalls = IGMPMSG_WRVIFWHOLE; + opt = MRT_PIM; + + err = setsockopt (fd, IPPROTO_IP, opt, &upcalls, sizeof (upcalls)); + if (err) + { + zlog_warn ("Failure to register for VIFWHOLE and WRONGVIF upcalls %d %s", + errno, safe_strerror (errno)); + return -1; + } + } + return 0; } diff --git a/pimd/pim_mroute.h b/pimd/pim_mroute.h index a09c604486..4ae089f16b 100644 --- a/pimd/pim_mroute.h +++ b/pimd/pim_mroute.h @@ -158,6 +158,10 @@ struct igmpmsg #endif #endif +#ifndef IGMPMSG_WRVIFWHOLE +#define IGMPMSG_WRVIFWHOLE 4 +#endif + /* Above: from */ From 6029d31f7c01651da8aa3ce49f34dc73e2b6c015 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 4 Aug 2016 11:44:11 -0400 Subject: [PATCH 075/386] pimd: Was removing the wrong channel. When receiving a prune (*,G), we were removing from the wrong channel. Signed-off-by: Donald Sharp --- pimd/pim_join.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 7e0f268f9b..6385bb7124 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -181,7 +181,7 @@ static void recv_prune(struct interface *ifp, zlog_debug("%s %s: Prune(S,G)=%s from %s", __FILE__, __PRETTY_FUNCTION__, buff, pim_str_sg_dump (&sg)); - pim_channel_del_oif (up->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + pim_channel_del_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); } } } From 7a3ddda53f9ad14a9f2c786dbc06fe3f47ef6a2e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 4 Aug 2016 12:06:58 -0400 Subject: [PATCH 076/386] pimd: Fix join_desired for (*,G) states When we are evaluating if we have a inherited_olist, include the *,G state in determing what to do. Additionally when we receive a join or prune of *,G do the right thing. Signed-off-by: Donald Sharp --- pimd/pim_join.c | 13 +++++--- pimd/pim_upstream.c | 77 +++++++++++++++++++++++---------------------- 2 files changed, 48 insertions(+), 42 deletions(-) diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 6385bb7124..abab730439 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -111,14 +111,17 @@ static void recv_join(struct interface *ifp, if (child->parent == up) { char buff[100]; + strcpy (buff, pim_str_sg_dump (&up->sg)); zlog_debug("%s %s: Join(S,G)=%s from %s", __FILE__, __PRETTY_FUNCTION__, buff, pim_str_sg_dump (&sg)); - pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); - if (child->join_state != PIM_UPSTREAM_JOINED) - pim_upstream_switch (child, PIM_UPSTREAM_JOINED); + if (pim_upstream_evaluate_join_desired (child)) + { + pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + pim_upstream_switch (child, PIM_UPSTREAM_JOINED); + } } } } @@ -181,7 +184,9 @@ static void recv_prune(struct interface *ifp, zlog_debug("%s %s: Prune(S,G)=%s from %s", __FILE__, __PRETTY_FUNCTION__, buff, pim_str_sg_dump (&sg)); - pim_channel_del_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + + if (!pim_upstream_evaluate_join_desired (child)) + pim_channel_del_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); } } } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 3321161c51..9889264aa6 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -528,6 +528,29 @@ void pim_upstream_del(struct pim_upstream *up) } } +static int +pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up, + struct pim_ifchannel *ch) +{ + struct pim_upstream *parent = up->parent; + + if (ch->upstream == up) + { + if (!pim_macro_ch_lost_assert(ch) && pim_macro_chisin_joins_or_include(ch)) + return 1; + } + /* + * joins (*,G) + */ + if (parent && ch->upstream == parent) + { + if (!pim_macro_ch_lost_assert (ch) && pim_macro_chisin_joins_or_include (ch)) + return 1; + } + + return 0; +} + /* Evaluate JoinDesired(S,G): @@ -560,6 +583,7 @@ int pim_upstream_evaluate_join_desired(struct pim_upstream *up) struct interface *ifp; struct pim_interface *pim_ifp; struct pim_ifchannel *ch; + int ret = 0; /* scan all interfaces */ for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { @@ -568,19 +592,13 @@ int pim_upstream_evaluate_join_desired(struct pim_upstream *up) continue; /* scan per-interface (S,G) state */ - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) { - if (ch->upstream != up) - continue; - - if (pim_macro_ch_lost_assert(ch)) - continue; /* keep searching */ - - if (pim_macro_chisin_joins_or_include(ch)) - return 1; /* true */ - } /* scan iface channel list */ + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) + { + ret += pim_upstream_evaluate_join_desired_interface (up, ch); + } /* scan iface channel list */ } /* scan iflist */ - return 0; /* false */ + return ret; /* false */ } /* @@ -982,7 +1000,6 @@ pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_regist int pim_upstream_inherited_olist (struct pim_upstream *up) { - struct pim_upstream *anysrc_up; struct pim_interface *pim_ifp; struct listnode *ifnextnode; struct listnode *chnextnode; @@ -990,47 +1007,31 @@ pim_upstream_inherited_olist (struct pim_upstream *up) struct listnode *chnode; struct listnode *ifnode; struct interface *ifp; - struct prefix_sg anysrc; int output_intf = 0; pim_ifp = up->rpf.source_nexthop.interface->info; zlog_debug ("Channel Oil%s: %p", pim_str_sg_dump (&up->sg), up->channel_oil); if (!up->channel_oil) up->channel_oil = pim_channel_oil_add (&up->sg, pim_ifp->mroute_vif_index); - anysrc = up->sg; - anysrc.src.s_addr = INADDR_ANY; - anysrc_up = pim_upstream_find (&anysrc); - if (anysrc_up) + for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) + pim_ifp = ifp->info; + if (!pim_ifp) + continue; + + for (ALL_LIST_ELEMENTS (pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) { - pim_ifp = ifp->info; - if (!pim_ifp) - continue; - - for (ALL_LIST_ELEMENTS (pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) + if (pim_upstream_evaluate_join_desired_interface (up, ch)) { - //struct pim_ifchannel *nch; - - if (ch->upstream != anysrc_up) - continue; - - if (ch->ifjoin_state == PIM_IFJOIN_JOIN) - { - pim_channel_add_oif (up->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); - //nch = pim_ifchannel_add (ifp, &up->sg); - //pim_ifchannel_ifjoin_switch (__PRETTY_FUNCTION__, nch, PIM_IFJOIN_JOIN); - //pim_forward_start (ch); - output_intf++; - } + pim_channel_add_oif (up->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + output_intf++; } } } if (output_intf) - if (up->join_state != PIM_UPSTREAM_JOINED) - pim_upstream_switch (up, PIM_UPSTREAM_JOINED); + pim_upstream_switch (up, PIM_UPSTREAM_JOINED); return output_intf; } From dc686f820be848d9b80e3f3918228d6eb321c826 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 4 Aug 2016 12:58:47 -0400 Subject: [PATCH 077/386] pimd: Fix some null register issues The Null register bit was not properly being set and the total length was wrong as well. Signed-off-by: Donald Sharp --- pimd/pim_join.c | 19 +++++++++++++++---- pimd/pim_register.c | 2 +- pimd/pim_upstream.c | 2 +- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/pimd/pim_join.c b/pimd/pim_join.c index abab730439..80e77ecb32 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -166,7 +166,7 @@ static void recv_prune(struct interface *ifp, sg.src.s_addr = INADDR_ANY; } - + pim_ifchannel_prune(ifp, upstream, &sg, source_flags, holdtime); if (sg.src.s_addr == INADDR_ANY) @@ -179,18 +179,29 @@ static void recv_prune(struct interface *ifp, { if (child->parent == up) { + struct channel_oil *c_oil = child->channel_oil; + struct pim_ifchannel *ch = pim_ifchannel_find (ifp, &child->sg); + struct pim_interface *pim_ifp = ifp->info; + char buff[100]; strcpy (buff, pim_str_sg_dump (&up->sg)); zlog_debug("%s %s: Prune(S,G)=%s from %s", __FILE__, __PRETTY_FUNCTION__, - buff, pim_str_sg_dump (&sg)); + buff, pim_str_sg_dump (&child->sg)); if (!pim_upstream_evaluate_join_desired (child)) - pim_channel_del_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + + /* + * If the S,G has no if channel and the c_oil still + * has output here then the *,G was supplying the implied + * if channel. So remove it. + */ + if (!ch && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) + pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); } } } - } int pim_joinprune_recv(struct interface *ifp, diff --git a/pimd/pim_register.c b/pimd/pim_register.c index c43818dfff..15a0e65574 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -188,7 +188,7 @@ pim_register_send (const uint8_t *buf, int buf_size, struct pim_rpf *rpg, int nu memset(buffer, 0, 3000); b1 = buffer + PIM_MSG_HEADER_LEN; - *b1 |= null_register << 31; + *b1 |= null_register << 6; b1 = buffer + PIM_MSG_REGISTER_LEN; memcpy(b1, (const unsigned char *)buf, buf_size); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 9889264aa6..0d77783738 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -939,7 +939,7 @@ pim_upstream_register_stop_timer (struct thread *t) ip_hdr.ip_v = 4; ip_hdr.ip_src = up->sg.src; ip_hdr.ip_dst = up->sg.grp; - ip_hdr.ip_len = 20; + ip_hdr.ip_len = htons (20); // checksum is broken pim_register_send ((uint8_t *)&ip_hdr, sizeof (struct ip), rpg, 1); pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); From 75a26779e8f25e9868f1f33e0fd35677f17c978b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 5 Aug 2016 09:07:46 -0400 Subject: [PATCH 078/386] pimd: Refactor RP code and start the ability to handle ranges Refactor the qpim_rp into pim_rp.c so that the global data is protected. This will allow us to easily add the group ranges. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 21 +++++++++------- pimd/pim_mroute.h | 2 +- pimd/pim_msg.c | 5 +++- pimd/pim_register.c | 29 +++------------------- pimd/pim_rp.c | 60 +++++++++++++++++++++++++++++++++++++++++++++ pimd/pim_rp.h | 11 ++++++++- pimd/pim_vty.c | 8 +++--- pimd/pimd.c | 1 - pimd/pimd.h | 1 - 9 files changed, 94 insertions(+), 44 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index ed7e57a95e..9c32ab1c32 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2427,7 +2427,7 @@ DEFUN (show_ip_ssmpingd, DEFUN (ip_pim_rp, ip_pim_rp_cmd, - "ip pim rp A.B.C.D", + "ip pim rp A.B.C.D [A.B.C.D/M]", IP_STR "pim multicast routing\n" "Rendevous Point\n" @@ -2436,13 +2436,15 @@ DEFUN (ip_pim_rp, int idx_ipv4 = 3; int result; - result = inet_pton(AF_INET, argv[idx_ipv4]->arg, &qpim_rp.rpf_addr.s_addr); - if (result <= 0) { - vty_out(vty, "%% Bad RP address specified: %s", argv[idx_ipv4]->arg); - return CMD_WARNING; - } + result = pim_rp_new (argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg); - if (!pim_rp_setup ()) + if (result == -1) + { + vty_out(vty, "%% Bad RP address specified: %s", argv[idx_ipv4]->arg); + return CMD_ERR_NO_MATCH; + } + + if (result == -2) { vty_out(vty, "%% No Path to RP address specified: %s", argv[idx_ipv4]->arg); return CMD_WARNING; @@ -2453,14 +2455,15 @@ DEFUN (ip_pim_rp, DEFUN (no_ip_pim_rp, no_ip_pim_rp_cmd, - "no ip pim rp [A.B.C.D]", + "no ip pim rp A.B.C.D [A.B.C.D/M]", NO_STR IP_STR "pim multicast routing\n" "Rendevous Point\n" "ip address of RP\n") { - qpim_rp.rpf_addr.s_addr = INADDR_NONE; + int idx_ipv4 = 4; + pim_rp_del (argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg); return CMD_SUCCESS; } diff --git a/pimd/pim_mroute.h b/pimd/pim_mroute.h index 4ae089f16b..ce300f0ab0 100644 --- a/pimd/pim_mroute.h +++ b/pimd/pim_mroute.h @@ -159,7 +159,7 @@ struct igmpmsg #endif #ifndef IGMPMSG_WRVIFWHOLE -#define IGMPMSG_WRVIFWHOLE 4 +#define IGMPMSG_WRVIFWHOLE 4 /* For PIM processing */ #endif /* diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index 61fc480bf9..df7f7051d3 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -25,10 +25,12 @@ #include "log.h" #include "pimd.h" +#include "pim_vty.h" #include "pim_pim.h" #include "pim_msg.h" #include "pim_util.h" #include "pim_str.h" +#include "pim_rp.h" void pim_msg_build_header(uint8_t *pim_msg, int pim_msg_size, uint8_t pim_msg_type) @@ -177,8 +179,9 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, remain = end - pim_msg_curr; if (source.s_addr == INADDR_ANY) { + struct pim_rpf *rpf = pim_rp_g (group); bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT | PIM_ENCODE_RPT_BIT; - stosend = qpim_rp.rpf_addr; + stosend = rpf->rpf_addr; } else { diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 15a0e65574..f484b5cc82 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -44,28 +44,6 @@ struct thread *send_test_packet_timer = NULL; -/* - * This seems stupidly expensive. A list lookup. Why is this - * not a hash? - */ -static int -pim_check_is_my_ip_address (struct in_addr dest_addr) -{ - /* - * See if we can short-cut some? - * This might not make sense if we ever leave a static RP - * type of configuration. - * Note - Premature optimization might bite our patooeys' here. - */ - if (I_am_RP(dest_addr) && (dest_addr.s_addr == qpim_rp.rpf_addr.s_addr)) - return 1; - - if (if_lookup_exact_address (&dest_addr, AF_INET)) - return 1; - - return 0; -} - static void pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, struct in_addr originator) @@ -263,7 +241,10 @@ pim_register_recv (struct interface *ifp, struct prefix_sg sg; uint32_t *bits; - if (!pim_check_is_my_ip_address (dest_addr)) { +#define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4 + ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN); + + if (!pim_rp_check_is_my_ip_address (ip_hdr->ip_dst, dest_addr)) { if (PIM_DEBUG_PIM_REG) { char dest[100]; @@ -308,8 +289,6 @@ pim_register_recv (struct interface *ifp, * Line above. So we need to add 4 bytes to get to the * start of the actual Encapsulated data. */ -#define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4 - ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN); memset (&sg, 0, sizeof (struct prefix_sg)); sg.src = ip_hdr->ip_src; sg.grp = ip_hdr->ip_dst; diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index b98ff2859a..5e2ee2e716 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -25,6 +25,7 @@ #include "if.h" #include "pimd.h" +#include "pim_vty.h" #include "pim_str.h" #include "pim_rp.h" #include "pim_str.h" @@ -33,6 +34,30 @@ static int i_am_rp = 0; +static struct pim_rpf qpim_rp = { .rpf_addr.s_addr = INADDR_NONE }; + +int +pim_rp_new (const char *rp, const char *group_range) +{ + int result; + + result = inet_pton (AF_INET, rp, &qpim_rp.rpf_addr.s_addr); + if (result <= 0) + return -1; + + if (!pim_rp_setup ()) + return -2; + + return 0; +} + +int +pim_rp_del (const char *rp, const char *group_range) +{ + qpim_rp.rpf_addr.s_addr = INADDR_NONE; + + return 0; +} int pim_rp_setup (void) @@ -127,3 +152,38 @@ pim_rp_set_upstream_addr (struct in_addr *up, struct in_addr source) return 1; } + +int +pim_rp_config_write (struct vty *vty) +{ + char buffer[32]; + + if (qpim_rp.rpf_addr.s_addr != INADDR_NONE) + { + vty_out(vty, "ip pim rp %s%s", inet_ntop(AF_INET, &qpim_rp.rpf_addr, buffer, 32), VTY_NEWLINE); + return 1; + } + + return 0; +} + +int +pim_rp_check_is_my_ip_address (struct in_addr group, struct in_addr dest_addr) +{ + /* + * See if we can short-cut some? + * This might not make sense if we ever leave a static RP + * type of configuration. + * Note - Premature optimization might bite our patooeys' here. + */ + if (I_am_RP(group)) + { + if (dest_addr.s_addr == qpim_rp.rpf_addr.s_addr) + return 1; + } + + if (if_lookup_exact_address (&dest_addr, AF_INET)) + return 1; + + return 0; +} diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index ccbc5b6ad4..6299971567 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -21,12 +21,21 @@ #ifndef PIM_RP_H #define PIM_RP_H +int pim_rp_new (const char *rp, const char *group); +int pim_rp_del (const char *rp, const char *group); + +int pim_rp_config_write (struct vty *vty); + int pim_rp_setup (void); + void pim_rp_check_rp (struct in_addr old, struct in_addr new); int pim_rp_i_am_rp (struct in_addr group); + +int pim_rp_check_is_my_ip_address (struct in_addr group, struct in_addr dest_addr); + int pim_rp_set_upstream_addr (struct in_addr *up, struct in_addr source); + struct pim_rpf *pim_rp_g (struct in_addr group); -void pim_rp_forward_packet (struct ip *ip_hdr); #define I_am_RP(G) pim_rp_i_am_rp ((G)) #define RP(G) pim_rp_g ((G)) diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 9c3df6bbdc..e27c69411c 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -34,6 +34,7 @@ #include "pim_pim.h" #include "pim_oil.h" #include "pim_static.h" +#include "pim_rp.h" int pim_debug_config_write (struct vty *vty) @@ -124,16 +125,13 @@ pim_debug_config_write (struct vty *vty) int pim_global_config_write(struct vty *vty) { int writes = 0; - char buffer[32]; if (PIM_MROUTE_IS_ENABLED) { vty_out(vty, "ip multicast-routing%s", VTY_NEWLINE); ++writes; } - if (qpim_rp.rpf_addr.s_addr != INADDR_NONE) { - vty_out(vty, "ip pim rp %s%s", inet_ntop(AF_INET, &qpim_rp.rpf_addr, buffer, 32), VTY_NEWLINE); - ++writes; - } + + writes += pim_rp_config_write (vty); if (qpim_ssmpingd_list) { struct listnode *node; diff --git a/pimd/pimd.c b/pimd/pimd.c index d4a0250a0e..709c367135 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -69,7 +69,6 @@ int64_t qpim_mroute_add_last = 0; int64_t qpim_mroute_del_events = 0; int64_t qpim_mroute_del_last = 0; struct list *qpim_static_route_list = NULL; -struct pim_rpf qpim_rp = { .rpf_addr.s_addr = INADDR_NONE }; int32_t qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; int32_t qpim_register_probe_time = PIM_REGISTER_PROBE_TIME_DEFAULT; diff --git a/pimd/pimd.h b/pimd/pimd.h index e91959948a..b4b8d4886d 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -104,7 +104,6 @@ int64_t qpim_mroute_add_last; int64_t qpim_mroute_del_events; int64_t qpim_mroute_del_last; struct list *qpim_static_route_list; /* list of routes added statically */ -struct pim_rpf qpim_rp; #define PIM_JP_HOLDTIME (qpim_t_periodic * 7 / 2) From 36d6bd7d34090d3af3dd1953b7ccc1b02f042849 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 5 Aug 2016 17:08:06 +0000 Subject: [PATCH 079/386] pimd: multiple rp commands Allow the user to specify multiple rp commands. 'ip pim rp A.B.C.D' -> translates to 'ip pim rp A.G.C.D 224.0.0.0/24' ip pim rp A.B.C.D A.B.C.D/M First is the rp, second is the group with mask. Groups and masks cannot be over each other except 224.0.0.0/24 which is the fallback if used. Ticket: CM-7860 Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 45 ++++-- pimd/pim_memory.c | 1 + pimd/pim_memory.h | 1 + pimd/pim_register.c | 2 +- pimd/pim_rp.c | 344 +++++++++++++++++++++++++++++++++++++++----- pimd/pim_rp.h | 5 +- pimd/pim_upstream.c | 2 +- pimd/pim_zebra.c | 4 +- pimd/pimd.c | 5 + 9 files changed, 357 insertions(+), 52 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 9c32ab1c32..e804b47ebd 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2425,6 +2425,33 @@ DEFUN (show_ip_ssmpingd, return CMD_SUCCESS; } +static int +pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group) +{ + int result; + result = pim_rp_new (rp, group); + + if (result == -1) + { + vty_out (vty, "%% Bad RP/group address specified: %s", rp); + return CMD_WARNING; + } + + if (result == -2) + { + vty_out (vty, "%% No Path to RP address specified: %s", rp); + return CMD_WARNING; + } + + if (result == -3) + { + vty_out (vty, "%% Group range specified cannot overlap"); + return CMD_ERR_NO_MATCH; + } + + return CMD_SUCCESS; +} + DEFUN (ip_pim_rp, ip_pim_rp_cmd, "ip pim rp A.B.C.D [A.B.C.D/M]", @@ -2434,19 +2461,23 @@ DEFUN (ip_pim_rp, "ip address of RP\n") { int idx_ipv4 = 3; - int result; + return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg); +} - result = pim_rp_new (argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg); +static int +pim_no_rp_cmd_worker (struct vty *vty, const char *rp, const char *group) +{ + int result = pim_rp_del (rp, group); if (result == -1) { - vty_out(vty, "%% Bad RP address specified: %s", argv[idx_ipv4]->arg); - return CMD_ERR_NO_MATCH; + vty_out (vty, "%% Unable to Decode specified RP"); + return CMD_WARNING; } if (result == -2) { - vty_out(vty, "%% No Path to RP address specified: %s", argv[idx_ipv4]->arg); + vty_out (vty, "%% Unable to find specified RP"); return CMD_WARNING; } @@ -2463,9 +2494,7 @@ DEFUN (no_ip_pim_rp, "ip address of RP\n") { int idx_ipv4 = 4; - pim_rp_del (argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg); - - return CMD_SUCCESS; + return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg); } DEFUN (ip_multicast_routing, diff --git a/pimd/pim_memory.c b/pimd/pim_memory.c index 6014725020..9994ea5d6b 100644 --- a/pimd/pim_memory.c +++ b/pimd/pim_memory.c @@ -39,3 +39,4 @@ DEFINE_MTYPE(PIMD, PIM_UPSTREAM, "PIM upstream (S,G) state") DEFINE_MTYPE(PIMD, PIM_SSMPINGD, "PIM sspimgd socket") DEFINE_MTYPE(PIMD, PIM_STATIC_ROUTE, "PIM Static Route") DEFINE_MTYPE(PIMD, PIM_BR, "PIM Bridge Router info") +DEFINE_MTYPE(PIMD, PIM_RP, "PIM RP info") diff --git a/pimd/pim_memory.h b/pimd/pim_memory.h index 81841e58b6..3d3f14467b 100644 --- a/pimd/pim_memory.h +++ b/pimd/pim_memory.h @@ -38,5 +38,6 @@ DECLARE_MTYPE(PIM_UPSTREAM) DECLARE_MTYPE(PIM_SSMPINGD) DECLARE_MTYPE(PIM_STATIC_ROUTE) DECLARE_MTYPE(PIM_BR) +DECLARE_MTYPE(PIM_RP) #endif /* _QUAGGA_PIM_MEMORY_H */ diff --git a/pimd/pim_register.c b/pimd/pim_register.c index f484b5cc82..2854b3d59d 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -321,7 +321,7 @@ pim_register_recv (struct interface *ifp, { upstream = pim_upstream_add (&sg, ifp); - pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.src); + pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.src, sg.grp); pim_nexthop_lookup (&upstream->rpf.source_nexthop, upstream->upstream_addr, NULL); upstream->rpf.source_nexthop.interface = ifp; diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 5e2ee2e716..0af7a991ee 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -23,6 +23,9 @@ #include "log.h" #include "network.h" #include "if.h" +#include "linklist.h" +#include "prefix.h" +#include "memory.h" #include "pimd.h" #include "pim_vty.h" @@ -31,20 +34,179 @@ #include "pim_str.h" #include "pim_rpf.h" #include "pim_sock.h" +#include "pim_memory.h" -static int i_am_rp = 0; +struct rp_info +{ + struct prefix group; + struct pim_rpf rp; + int i_am_rp; +}; -static struct pim_rpf qpim_rp = { .rpf_addr.s_addr = INADDR_NONE }; +static struct list *qpim_rp_list = NULL; +static struct rp_info *tail = NULL; + +static void +pim_rp_info_free (struct rp_info *rp_info) +{ + XFREE (MTYPE_PIM_RP, rp_info); +} + +static int +pim_rp_list_cmp (void *v1, void *v2) +{ + struct rp_info *rp1 = (struct rp_info *)v1; + struct rp_info *rp2 = (struct rp_info *)v2; + + if (rp1 == rp2) + return 0; + + if (!rp1 && rp2) + return -1; + + if (rp1 && !rp2) + return 1; + + if (rp1 == tail) + return 1; + + return -1; +} + +void +pim_rp_init (void) +{ + struct rp_info *rp_info; + + qpim_rp_list = list_new (); + qpim_rp_list->del = (void (*)(void *))pim_rp_info_free; + qpim_rp_list->cmp = pim_rp_list_cmp; + + rp_info = XCALLOC (MTYPE_PIM_RP, sizeof (*rp_info)); + + if (!rp_info) + return; + + str2prefix ("224.0.0.0/4", &rp_info->group); + rp_info->rp.rpf_addr.s_addr = INADDR_NONE; + tail = rp_info; + + listnode_add (qpim_rp_list, rp_info); +} + +void +pim_rp_free (void) +{ + if (qpim_rp_list) + list_free (qpim_rp_list); +} + +static struct rp_info * +pim_rp_find_exact (struct in_addr rp, struct prefix *group) +{ + struct listnode *node; + struct rp_info *rp_info; + + for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) + { + if (rp.s_addr == rp_info->rp.rpf_addr.s_addr && + prefix_same (&rp_info->group, group)) + return rp_info; + } + + return NULL; +} + +static struct rp_info * +pim_rp_find_match (struct in_addr rp, struct prefix *group) +{ + struct listnode *node; + struct rp_info *rp_info; + + for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) + { + if (rp.s_addr == rp_info->rp.rpf_addr.s_addr && + prefix_match (&rp_info->group, group)) + return rp_info; + } + + return NULL; +} + +static struct rp_info * +pim_rp_find_match_group (struct prefix *group) +{ + struct listnode *node; + struct rp_info *rp_info; + + for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) + { + if (prefix_match (&rp_info->group, group)) + return rp_info; + } + + return NULL; +} int pim_rp_new (const char *rp, const char *group_range) { int result; + struct rp_info *rp_info; + struct rp_info *rp_all; + struct prefix group_all; - result = inet_pton (AF_INET, rp, &qpim_rp.rpf_addr.s_addr); + str2prefix ("224.0.0.0/4", &group_all); + rp_all = pim_rp_find_match_group(&group_all); + + rp_info = XCALLOC (MTYPE_PIM_RP, sizeof (*rp_info)); + if (!rp) + return -1; + + if (group_range == NULL) + result = str2prefix ("224.0.0.0/4", &rp_info->group); + else + result = str2prefix (group_range, &rp_info->group); + + if (!result) + return -1; + + result = inet_pton (AF_INET, rp, &rp_info->rp.rpf_addr.s_addr); if (result <= 0) return -1; + /* + * Take over the 224.0.0.0/4 group if the rp is INADDR_NONE + */ + if (prefix_same (&rp_all->group, &rp_info->group) && + rp_all->rp.rpf_addr.s_addr == INADDR_NONE) + { + rp_all->rp.rpf_addr = rp_info->rp.rpf_addr; + XFREE (MTYPE_PIM_RP, rp_info); + if (!pim_rp_setup ()) + return -2; + return 0; + } + + if (pim_rp_find_exact (rp_info->rp.rpf_addr, &rp_info->group)) + { + XFREE (MTYPE_PIM_RP, rp_info); + return 0; + } + + if (pim_rp_find_match (rp_info->rp.rpf_addr, &rp_info->group)) + { + if (prefix_same (&group_all, &rp_info->group)) + { + return 0; + } + + XFREE (MTYPE_PIM_RP, rp_info); + return -3; + } + + listnode_add_sort (qpim_rp_list, rp_info); + if (!pim_rp_setup ()) return -2; @@ -54,20 +216,62 @@ pim_rp_new (const char *rp, const char *group_range) int pim_rp_del (const char *rp, const char *group_range) { - qpim_rp.rpf_addr.s_addr = INADDR_NONE; + struct prefix group; + struct in_addr rp_addr; + struct prefix g_all; + struct rp_info *rp_info; + struct rp_info *rp_all; + int result; + str2prefix ("224.0.0.0/4", &g_all); + if (group_range == NULL) + result = str2prefix ("224.0.0.0/4", &group); + else + result = str2prefix (group_range, &group); + + if (!result) + return -1; + + rp_all = pim_rp_find_match_group (&g_all); + + result = inet_pton (AF_INET, rp, &rp_addr); + if (result <= 0) + return -1; + + rp_info = pim_rp_find_exact (rp_addr, &group); + if (!rp_info) + return -2; + + if (rp_all == rp_info) + { + rp_all->rp.rpf_addr.s_addr = INADDR_NONE; + rp_all->i_am_rp = 0; + return 0; + } + + listnode_delete (qpim_rp_list, rp_info); return 0; } int pim_rp_setup (void) { - if (pim_nexthop_lookup (&qpim_rp.source_nexthop, qpim_rp.rpf_addr, NULL) != 0) + struct listnode *node; + struct rp_info *rp_info; + int ret = 0; + + for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { - zlog_err ("Unable to lookup nexthop for rp specified"); - return 0; + if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr, NULL) != 0) + { + zlog_err ("Unable to lookup nexthop for rp specified"); + ret++; + } } + if (ret) + return 0; + return 1; } @@ -77,29 +281,35 @@ pim_rp_setup (void) void pim_rp_check_rp (struct in_addr old, struct in_addr new) { - if (PIM_DEBUG_ZEBRA) { - char sold[100]; - char snew[100]; - char rp[100]; - pim_inet4_dump("", qpim_rp.rpf_addr, rp, sizeof(rp)); - pim_inet4_dump("", old, sold, sizeof(sold)); - pim_inet4_dump("", new, snew, sizeof(snew)); - zlog_debug("%s: %s for old %s new %s", __func__, rp, sold, snew ); - } + struct listnode *node; + struct rp_info *rp_info; - if (qpim_rp.rpf_addr.s_addr == INADDR_NONE) + if (qpim_rp_list == NULL) return; - if (new.s_addr == qpim_rp.rpf_addr.s_addr) + for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { - i_am_rp = 1; - return; - } + if (PIM_DEBUG_ZEBRA) { + char sold[100]; + char snew[100]; + char rp[100]; + pim_inet4_dump("", rp_info->rp.rpf_addr, rp, sizeof(rp)); + pim_inet4_dump("", old, sold, sizeof(sold)); + pim_inet4_dump("", new, snew, sizeof(snew)); + zlog_debug("%s: %s for old %s new %s", __func__, rp, sold, snew ); + } + if (rp_info->rp.rpf_addr.s_addr == INADDR_NONE) + continue; - if (old.s_addr == qpim_rp.rpf_addr.s_addr) - { - i_am_rp = 0; - return; + if (new.s_addr == rp_info->rp.rpf_addr.s_addr) + { + rp_info->i_am_rp = 1; + } + + if (old.s_addr == rp_info->rp.rpf_addr.s_addr) + { + rp_info->i_am_rp = 0; + } } } @@ -112,7 +322,20 @@ pim_rp_check_rp (struct in_addr old, struct in_addr new) int pim_rp_i_am_rp (struct in_addr group) { - return i_am_rp; + struct prefix g; + struct rp_info *rp_info; + + memset (&g, 0, sizeof (g)); + g.family = AF_INET; + g.prefixlen = 32; + g.u.prefix4 = group; + + rp_info = pim_rp_find_match_group (&g); + + if (rp_info) + return rp_info->i_am_rp; + + return 0; } /* @@ -123,11 +346,24 @@ pim_rp_i_am_rp (struct in_addr group) struct pim_rpf * pim_rp_g (struct in_addr group) { - /* - * For staticly configured RP, it is always the qpim_rp - */ - pim_nexthop_lookup(&qpim_rp.source_nexthop, qpim_rp.rpf_addr, NULL); - return(&qpim_rp); + struct prefix g; + struct rp_info *rp_info; + + memset (&g, 0, sizeof (g)); + g.family = AF_INET; + g.prefixlen = 32; + g.u.prefix4 = group; + + rp_info = pim_rp_find_match_group (&g); + + if (rp_info) + { + pim_nexthop_lookup(&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr, NULL); + return (&rp_info->rp); + } + + // About to Go Down + return NULL; } /* @@ -139,16 +375,26 @@ pim_rp_g (struct in_addr group) * */ int -pim_rp_set_upstream_addr (struct in_addr *up, struct in_addr source) +pim_rp_set_upstream_addr (struct in_addr *up, struct in_addr source, struct in_addr group) { - if ((qpim_rp.rpf_addr.s_addr == INADDR_NONE) && (source.s_addr == INADDR_ANY)) + struct rp_info *rp_info; + struct prefix g; + + memset (&g, 0, sizeof (g)); + g.family = AF_INET; + g.prefixlen = 32; + g.u.prefix4 = group; + + rp_info = pim_rp_find_match_group (&g); + + if ((rp_info->rp.rpf_addr.s_addr == INADDR_NONE) && (source.s_addr == INADDR_ANY)) { if (PIM_DEBUG_PIM_TRACE) zlog_debug("%s: Received a (*,G) with no RP configured", __PRETTY_FUNCTION__); return 0; } - *up = (source.s_addr == INADDR_ANY) ? qpim_rp.rpf_addr : source; + *up = (source.s_addr == INADDR_ANY) ? rp_info->rp.rpf_addr : source; return 1; } @@ -156,20 +402,40 @@ pim_rp_set_upstream_addr (struct in_addr *up, struct in_addr source) int pim_rp_config_write (struct vty *vty) { + struct listnode *node; + struct rp_info *rp_info; char buffer[32]; + int count = 0; - if (qpim_rp.rpf_addr.s_addr != INADDR_NONE) + for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { - vty_out(vty, "ip pim rp %s%s", inet_ntop(AF_INET, &qpim_rp.rpf_addr, buffer, 32), VTY_NEWLINE); - return 1; + if (rp_info->rp.rpf_addr.s_addr == INADDR_NONE) + continue; + + if (rp_info->rp.rpf_addr.s_addr != INADDR_NONE) + { + char buf[32]; + vty_out(vty, "ip pim rp %s %s%s", inet_ntop(AF_INET, &rp_info->rp.rpf_addr, buffer, 32), + prefix2str(&rp_info->group, buf, 32), VTY_NEWLINE); + count++; + } } - return 0; + return count; } int pim_rp_check_is_my_ip_address (struct in_addr group, struct in_addr dest_addr) { + struct rp_info *rp_info; + struct prefix g; + + memset (&g, 0, sizeof (g)); + g.family = AF_INET; + g.prefixlen = 32; + g.u.prefix4 = group; + + rp_info = pim_rp_find_match_group (&g); /* * See if we can short-cut some? * This might not make sense if we ever leave a static RP @@ -178,7 +444,7 @@ pim_rp_check_is_my_ip_address (struct in_addr group, struct in_addr dest_addr) */ if (I_am_RP(group)) { - if (dest_addr.s_addr == qpim_rp.rpf_addr.s_addr) + if (dest_addr.s_addr == rp_info->rp.rpf_addr.s_addr) return 1; } diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index 6299971567..be50bbb18b 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -21,6 +21,9 @@ #ifndef PIM_RP_H #define PIM_RP_H +void pim_rp_init (void); +void pim_rp_free (void); + int pim_rp_new (const char *rp, const char *group); int pim_rp_del (const char *rp, const char *group); @@ -33,7 +36,7 @@ int pim_rp_i_am_rp (struct in_addr group); int pim_rp_check_is_my_ip_address (struct in_addr group, struct in_addr dest_addr); -int pim_rp_set_upstream_addr (struct in_addr *up, struct in_addr source); +int pim_rp_set_upstream_addr (struct in_addr *up, struct in_addr source, struct in_addr group); struct pim_rpf *pim_rp_g (struct in_addr group); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 0d77783738..5b7f67c703 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -430,7 +430,7 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, } up->sg = *sg; - if (!pim_rp_set_upstream_addr (&up->upstream_addr, sg->src)) + if (!pim_rp_set_upstream_addr (&up->upstream_addr, sg->src, sg->grp)) { if (PIM_DEBUG_PIM_TRACE) zlog_debug("%s: Received a (*,G) with no RP configured", __PRETTY_FUNCTION__); diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 046628de26..c6ca5189c1 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -388,7 +388,7 @@ pim_scan_individual_oil (struct channel_oil *c_oil) int input_iface_vif_index; int old_vif_index; - if (!pim_rp_set_upstream_addr (&vif_source, c_oil->oil.mfcc_origin)) + if (!pim_rp_set_upstream_addr (&vif_source, c_oil->oil.mfcc_origin, c_oil->oil.mfcc_mcastgrp)) return; input_iface_vif_index = fib_lookup_if_vif_index (vif_source); @@ -976,7 +976,7 @@ void igmp_source_forward_start(struct igmp_source *source) struct in_addr vif_source; struct pim_interface *pim_oif; - if (!pim_rp_set_upstream_addr (&vif_source, source->source_addr)) + if (!pim_rp_set_upstream_addr (&vif_source, source->source_addr, sg.grp)) return; int input_iface_vif_index = fib_lookup_if_vif_index(vif_source); diff --git a/pimd/pimd.c b/pimd/pimd.c index 709c367135..fa80aec5a2 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -36,6 +36,7 @@ #include "pim_rpf.h" #include "pim_ssmpingd.h" #include "pim_static.h" +#include "pim_rp.h" const char *const PIM_ALL_SYSTEMS = MCAST_ALL_SYSTEMS; const char *const PIM_ALL_ROUTERS = MCAST_ALL_ROUTERS; @@ -87,12 +88,16 @@ static void pim_free() list_free(qpim_static_route_list); pim_route_map_terminate(); + + pim_rp_free (); } void pim_init() { srandom(time(NULL)); + pim_rp_init (); + if (!inet_aton(PIM_ALL_PIM_ROUTERS, &qpim_all_pim_routers_addr)) { zlog_err("%s %s: could not solve %s to group address: errno=%d: %s", __FILE__, __PRETTY_FUNCTION__, From 1148de0adbb606c64ffabdb7cb70030365d51c65 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 6 Aug 2016 06:26:05 -0400 Subject: [PATCH 080/386] pimd: Send hello immediately with receive of new genid When we receive a new genid from a neighbor, we need to form the neigbhor relationship before the join/prune messages are sent to the neighbor. Additionally we were calling the pim_upstream_rpf_genid_changed function 2 times in a row. This function just spun throught the upstream list and marked all relevant upstreams to be sent immediately Ticket:CM-11979 Signed-off-by: Donald Sharp --- pimd/pim_hello.c | 11 ++++------- pimd/pim_neighbor.c | 13 +++++++++++-- pimd/pim_neighbor.h | 7 ++++++- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/pimd/pim_hello.c b/pimd/pim_hello.c index 3502f4e962..434a0e66c4 100644 --- a/pimd/pim_hello.c +++ b/pimd/pim_hello.c @@ -350,7 +350,8 @@ int pim_hello_recv(struct interface *ifp, hello_option_override_interval, hello_option_dr_priority, hello_option_generation_id, - hello_option_addr_list); + hello_option_addr_list, + PIM_NEIGHBOR_SEND_DELAY); if (!neigh) { if (PIM_DEBUG_PIM_HELLO) { char src_str[100]; @@ -374,11 +375,6 @@ int pim_hello_recv(struct interface *ifp, /* GenID mismatch ? */ if (!PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_GENERATION_ID) || (hello_option_generation_id != neigh->generation_id)) { - - /* GenID changed */ - - pim_upstream_rpf_genid_changed(neigh->source_addr); - /* GenID mismatch, then replace neighbor */ if (PIM_DEBUG_PIM_HELLO) { @@ -401,7 +397,8 @@ int pim_hello_recv(struct interface *ifp, hello_option_override_interval, hello_option_dr_priority, hello_option_generation_id, - hello_option_addr_list); + hello_option_addr_list, + PIM_NEIGHBOR_SEND_NOW); if (!neigh) { if (PIM_DEBUG_PIM_HELLO) { char src_str[100]; diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index 2703b8fcf5..4d79388092 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -411,7 +411,8 @@ struct pim_neighbor *pim_neighbor_add(struct interface *ifp, uint16_t override_interval, uint32_t dr_priority, uint32_t generation_id, - struct list *addr_list) + struct list *addr_list, + int send_hello_now) { struct pim_interface *pim_ifp; struct pim_neighbor *neigh; @@ -450,8 +451,16 @@ struct pim_neighbor *pim_neighbor_add(struct interface *ifp, message with a new GenID is received from an existing neighbor, a new Hello message should be sent on this interface after a randomized delay between 0 and Triggered_Hello_Delay. + + This is a bit silly to do it that way. If I get a new + genid we need to send the hello *now* because we've + lined up a bunch of join/prune messages to go out the + interface. */ - pim_hello_restart_triggered(neigh->interface); + if (send_hello_now) + pim_hello_restart_now (ifp); + else + pim_hello_restart_triggered(neigh->interface); return neigh; } diff --git a/pimd/pim_neighbor.h b/pimd/pim_neighbor.h index 10d0cf3a68..4bf78d063e 100644 --- a/pimd/pim_neighbor.h +++ b/pimd/pim_neighbor.h @@ -47,6 +47,10 @@ void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime); void pim_neighbor_free(struct pim_neighbor *neigh); struct pim_neighbor *pim_neighbor_find(struct interface *ifp, struct in_addr source_addr); + + +#define PIM_NEIGHBOR_SEND_DELAY 0 +#define PIM_NEIGHBOR_SEND_NOW 1 struct pim_neighbor *pim_neighbor_add(struct interface *ifp, struct in_addr source_addr, pim_hello_options hello_options, @@ -55,7 +59,8 @@ struct pim_neighbor *pim_neighbor_add(struct interface *ifp, uint16_t override_interval, uint32_t dr_priority, uint32_t generation_id, - struct list *addr_list); + struct list *addr_list, + int send_hello_now); void pim_neighbor_delete(struct interface *ifp, struct pim_neighbor *neigh, const char *delete_message); From a878ba45729e28709f5916b0ff04bd1620751d60 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 5 Aug 2016 03:23:33 -0400 Subject: [PATCH 081/386] pimd: Some SA analysis fixes. This commit addresses some SA issues found: 1) double set variables 2) value set but never used. 3) wrong return path used. Signed-off-by: Donald Sharp --- pimd/pim_igmpv3.c | 3 --- pimd/pim_register.c | 2 +- pimd/pim_sock.c | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index 79932edb35..149d18df54 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -1134,9 +1134,6 @@ static int group_retransmit_sources(struct igmp_group *group, struct igmp_source *src; int num_retransmit_sources_left = 0; - query_buf1_max_sources = (sizeof(query_buf1) - IGMP_V3_SOURCES_OFFSET) >> 2; - query_buf2_max_sources = (sizeof(query_buf2) - IGMP_V3_SOURCES_OFFSET) >> 2; - source_addr1 = (struct in_addr *)(query_buf1 + IGMP_V3_SOURCES_OFFSET); source_addr2 = (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET); diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 2854b3d59d..d0fe89b01b 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -107,7 +107,7 @@ pim_register_stop_recv (uint8_t *buf, int buf_size) l = pim_parse_addr_group (&group, buf, buf_size); buf += l; buf_size -= l; - l = pim_parse_addr_ucast (&source, buf, buf_size); + pim_parse_addr_ucast (&source, buf, buf_size); memset (&sg, 0, sizeof (struct prefix_sg)); sg.src = source.u.prefix4; sg.grp = group.u.prefix4; diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index a4155549c9..8f8f4f191f 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -334,7 +334,7 @@ int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len, ((struct sockaddr_in *) to)->sin_family = AF_INET; - if (pim_socket_getsockname(fd, (struct sockaddr *) &si, &si_len)) { + if (pim_socket_getsockname(fd, (struct sockaddr *) &si, &si_len) != PIM_SOCK_ERR_NONE) { ((struct sockaddr_in *) to)->sin_port = ntohs(0); ((struct sockaddr_in *) to)->sin_addr.s_addr = ntohl(0); } From 0bc327f7b45dbb5bbc21ebdf4e546de2761821cb Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 8 Aug 2016 09:37:51 -0400 Subject: [PATCH 082/386] pimd: Fix some SA issues SA found these two issues: 1) Check of ifp non-null caused other non-checks down code to assume ifp could be null. This is not the case. If we get a callback at this point we must have a valid ifp pointer. 2) We were inadvertently calling igmp_source_reset_gmi with a possible NULL source pointer. Signed-off-by: Donald Sharp --- pimd/pim_igmpv3.c | 6 ++++-- pimd/pim_mroute.c | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index 149d18df54..ba75fc221f 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -647,8 +647,10 @@ static void isex_excl(struct igmp_group *group, struct in_addr star = { .s_addr = INADDR_ANY }; source = igmp_find_source_by_addr (group, star); if (source) - IGMP_SOURCE_DONT_DELETE(source->source_flags); - igmp_source_reset_gmi (group->group_igmp_sock, group, source); + { + IGMP_SOURCE_DONT_DELETE(source->source_flags); + igmp_source_reset_gmi (group->group_igmp_sock, group, source); + } } /* E.5: delete all sources marked with deletion flag: (X-A) and (Y-A) */ diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 31ca10b6b6..d875926871 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -353,7 +353,7 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size) fd, src_str, grp_str, - ifp ? ifp->name : "", + ifp->name, msg->im_vif); } From 469c6aa2654bc6944930e2e72bfa2eb4edf13406 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 8 Aug 2016 10:24:02 -0400 Subject: [PATCH 083/386] pimd: Fix another SA issue pim_zebra.c was checking to see if a ifp pointer was null in some debug statements. This caused the SA code to assume that if we were at this point then the ifp could be null and subsuquent code that doesn't check for it to be wrong. Signed-off-by: Donald Sharp --- pimd/pim_zebra.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index c6ca5189c1..5472fe3d3a 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -425,8 +425,8 @@ pim_scan_individual_oil (struct channel_oil *c_oil) zlog_debug("%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d", __FILE__, __PRETTY_FUNCTION__, source_str, group_str, - old_iif ? old_iif->name : "", c_oil->oil.mfcc_parent, - new_iif ? new_iif->name : "", input_iface_vif_index); + old_iif->name, c_oil->oil.mfcc_parent, + new_iif->name, input_iface_vif_index); } /* new iif loops to existing oif ? */ @@ -442,7 +442,7 @@ pim_scan_individual_oil (struct channel_oil *c_oil) zlog_debug("%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d", __FILE__, __PRETTY_FUNCTION__, source_str, group_str, - new_iif ? new_iif->name : "", input_iface_vif_index); + new_iif->name, input_iface_vif_index); } del_oif(c_oil, new_iif, PIM_OIF_FLAG_PROTO_ANY); From 2ecb76d375dd66dc6eb71643b357febcc32345dd Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 8 Aug 2016 15:55:52 -0400 Subject: [PATCH 084/386] pimd: Add the display of the Keep Alive Timer for upstream Add the ability to see the Keep Alive timer for upstream information. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index e804b47ebd..008e708349 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -982,7 +982,7 @@ static void pim_show_upstream(struct vty *vty) now = pim_time_monotonic_sec(); - vty_out(vty, "Iif Source Group State Uptime JoinTimer RSTimer RefCnt%s", VTY_NEWLINE); + vty_out(vty, "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt%s", VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) { char src_str[100]; @@ -990,14 +990,16 @@ static void pim_show_upstream(struct vty *vty) char uptime[10]; char join_timer[10]; char rs_timer[10]; + char ka_timer[10]; pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); - pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer), up->t_join_timer); + pim_time_timer_to_hhmmss (join_timer, sizeof(join_timer), up->t_join_timer); pim_time_timer_to_hhmmss (rs_timer, sizeof (rs_timer), up->t_rs_timer); + pim_time_timer_to_hhmmss (ka_timer, sizeof (ka_timer), up->t_ka_timer); - vty_out(vty, "%-10s%-15s %-15s %-5s %-8s %-9s %-9s %6d%s", + vty_out(vty, "%-10s%-15s %-15s %-5s %-8s %-9s %-9s %-9s %6d%s", up->rpf.source_nexthop.interface->name, src_str, grp_str, @@ -1005,6 +1007,7 @@ static void pim_show_upstream(struct vty *vty) uptime, join_timer, rs_timer, + ka_timer, up->ref_count, VTY_NEWLINE); } From 14315ea89902f72c7f82e3bec65235a70b2063b2 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 8 Aug 2016 18:56:05 -0400 Subject: [PATCH 085/386] pimd: Allow RP to clear based upon KAT(S,G) When the KAT(S,G) pops, allow the RP to clear the mroute. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 5b7f67c703..932e06b76d 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -820,21 +820,20 @@ pim_upstream_keep_alive_timer (struct thread *t) * But this is the start. */ } + + pim_mroute_update_counters (up->channel_oil); + + if (up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt) + { + pim_mroute_del (up->channel_oil); + pim_upstream_delete (up); + } else { - pim_mroute_update_counters (up->channel_oil); - - if (up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt) - { - pim_mroute_del (up->channel_oil); - pim_upstream_delete (up); - } - else - { - up->t_ka_timer = NULL; - pim_upstream_keep_alive_timer_start (up, PIM_KEEPALIVE_PERIOD); - } + up->t_ka_timer = NULL; + pim_upstream_keep_alive_timer_start (up, PIM_KEEPALIVE_PERIOD); } + return 1; } From c29a58063b9d0f9968428e16ac40c0c14f5f4f49 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 9 Aug 2016 08:05:48 -0400 Subject: [PATCH 086/386] pimd: Don't pass in src_str and grp_str Allow sub functions to call pim_str_sg_dump as appropriate Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 61 +++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index d875926871..3f8e29c075 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -103,8 +103,7 @@ static const char *igmpmsgtype2str[IGMPMSG_WHOLEPKT + 1] = { "WHOLEPKT", }; static int -pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg, - const char *src_str, const char *grp_str) +pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg) { struct pim_interface *pim_ifp = ifp->info; struct pim_upstream *up; @@ -135,14 +134,15 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg return 0; } - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: Adding a Route for %s from %s for WHOLEPKT consumption", - __PRETTY_FUNCTION__, grp_str, src_str); - } - memset (&sg, 0, sizeof (struct prefix_sg)); sg.src = msg->im_src; sg.grp = msg->im_dst; + + if (PIM_DEBUG_MROUTE) { + zlog_debug("%s: Adding a Route %s for WHOLEPKT consumption", + __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); + } + up = pim_upstream_add (&sg, ifp); if (!up) { if (PIM_DEBUG_MROUTE) { @@ -159,9 +159,9 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg pim_ifp->mroute_vif_index); if (!up->channel_oil) { if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: Failure to add channel oil for (%s,%s)", + zlog_debug("%s: Failure to add channel oil for %s", __PRETTY_FUNCTION__, - src_str, grp_str); + pim_str_sg_dump (&sg)); } return 0; } @@ -174,8 +174,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg } static int -pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf, - const char *src_str, const char *grp_str) +pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf) { struct pim_interface *pim_ifp; struct prefix_sg sg; @@ -222,13 +221,16 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf, } static int -pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *msg, - const char *src_str, const char *grp_str) +pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *msg) { struct pim_ifchannel *ch; struct pim_interface *pim_ifp; struct prefix_sg sg; + memset (&sg, 0, sizeof (struct prefix_sg)); + sg.src = msg->im_src; + sg.grp = msg->im_dst; + /* Send Assert(S,G) on iif as response to WRONGVIF kernel upcall. @@ -242,9 +244,9 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms if (!ifp) { if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) could not find input interface for input_vif_index=%d", + zlog_debug("%s: WRONGVIF (S,G)=%s could not find input interface for input_vif_index=%d", __PRETTY_FUNCTION__, - src_str, grp_str, msg->im_vif); + pim_str_sg_dump (&sg), msg->im_vif); } return -1; } @@ -252,22 +254,19 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms pim_ifp = ifp->info; if (!pim_ifp) { if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) multicast not enabled on interface %s", + zlog_debug("%s: WRONGVIF (S,G)=%s multicast not enabled on interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); + pim_str_sg_dump (&sg), ifp->name); } return -2; } - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = msg->im_src; - sg.grp = msg->im_dst; ch = pim_ifchannel_find(ifp, &sg); if (!ch) { if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) could not find channel on interface %s", + zlog_debug("%s: WRONGVIF (S,G)=%s could not find channel on interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); + pim_str_sg_dump (&sg), ifp->name); } return -3; } @@ -288,27 +287,27 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms if (ch->ifassert_state != PIM_IFASSERT_NOINFO) { if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) channel is not on Assert NoInfo state for interface %s", + zlog_debug("%s: WRONGVIF (S,G)=%s channel is not on Assert NoInfo state for interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); + pim_str_sg_dump (&sg), ifp->name); } return -4; } if (!PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) interface %s is not downstream for channel", + zlog_debug("%s: WRONGVIF (S,G)=%s interface %s is not downstream for channel", __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); + pim_str_sg_dump (&sg), ifp->name); } return -5; } if (assert_action_a1(ch)) { if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) assert_action_a1 failure on interface %s", + zlog_debug("%s: WRONGVIF (S,G)=%s assert_action_a1 failure on interface %s", __PRETTY_FUNCTION__, - src_str, grp_str, ifp->name); + pim_str_sg_dump (&sg), ifp->name); } return -6; } @@ -359,13 +358,13 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size) switch (msg->im_msgtype) { case IGMPMSG_WRONGVIF: - return pim_mroute_msg_wrongvif(fd, ifp, msg, src_str, grp_str); + return pim_mroute_msg_wrongvif(fd, ifp, msg); break; case IGMPMSG_NOCACHE: - return pim_mroute_msg_nocache(fd, ifp, msg, src_str, grp_str); + return pim_mroute_msg_nocache(fd, ifp, msg); break; case IGMPMSG_WHOLEPKT: - return pim_mroute_msg_wholepkt(fd, ifp, (const char *)msg, src_str, grp_str); + return pim_mroute_msg_wholepkt(fd, ifp, (const char *)msg); break; default: break; From 08e1fe769b0606e41a92dbe9b3a41180b43c3725 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 9 Aug 2016 12:30:26 -0400 Subject: [PATCH 087/386] pimd: Add WRVIFWHOLE callback. Naive implementation of the WRVIFWHOLE callback from the kernel. signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 64 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 3f8e29c075..ab07cb6792 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -96,11 +96,12 @@ pim_mroute_connected_to_source (struct interface *ifp, struct in_addr src) return 0; } -static const char *igmpmsgtype2str[IGMPMSG_WHOLEPKT + 1] = { +static const char *igmpmsgtype2str[IGMPMSG_WRVIFWHOLE + 1] = { "", "NOCACHE", "WRONGVIF", - "WHOLEPKT", }; + "WHOLEPKT", + "WRVIFWHOLE" }; static int pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg) @@ -315,6 +316,62 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms return 0; } +static int +pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) +{ + const struct ip *ip_hdr = (const struct ip *)buf; + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + struct pim_upstream *up; + struct prefix_sg sg; + + memset (&sg, 0, sizeof (struct prefix_sg)); + sg.src = ip_hdr->ip_src; + sg.grp = ip_hdr->ip_dst; + + if (PIM_DEBUG_MROUTE) + zlog_debug ("Received WHOLEPKT Wrong Vif for %s on %s", + pim_str_sg_dump (&sg), ifp->name); + + ch = pim_ifchannel_find(ifp, &sg); + if (ch) + { + if (PIM_DEBUG_MROUTE) + zlog_debug ("WRVIFWHOLE (S,G)=%s found ifchannel on interface %s", + pim_str_sg_dump (&sg), ifp->name); + return -1; + } + + if (PIM_DEBUG_MROUTE) + zlog_debug ("If channel: %p", ch); + + up = pim_upstream_add (&sg, ifp); + + if (!up) + { + if (PIM_DEBUG_MROUTE) + zlog_debug ("%s: WRONGVIF%s unable to create upstream on interface", + pim_str_sg_dump (&sg), ifp->name); + return -2; + } + + if (pim_mroute_connected_to_source (ifp, sg.src)) + up->fhr = 1; + + pim_ifp = ifp->info; + pim_upstream_keep_alive_timer_start (up, PIM_KEEPALIVE_PERIOD); + up->channel_oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); + up->channel_oil->cc.pktcnt++; + pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); + up->join_state = PIM_UPSTREAM_JOINED; + pim_upstream_inherited_olist (up); + + // Send the packet to the RP + pim_mroute_msg_wholepkt (fd, ifp, buf); + + return 0; +} + int pim_mroute_msg(int fd, const char *buf, int buf_size) { struct interface *ifp; @@ -366,6 +423,9 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size) case IGMPMSG_WHOLEPKT: return pim_mroute_msg_wholepkt(fd, ifp, (const char *)msg); break; + case IGMPMSG_WRVIFWHOLE: + return pim_mroute_msg_wrvifwhole (fd, ifp, (const char *)msg); + break; default: break; } From 856eb2535b6c78793031364c3e30af286d1a5b75 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 9 Aug 2016 13:02:27 -0400 Subject: [PATCH 088/386] zebra: Allow netlink_talk to choose the filter function to call The netlink_talk call sends a message to the kernel, which with netlink_talk_filter only waits for the ACK. It would be nice to have the ability to specify what the handler function would be for when we send queries about mcast S,G routes so that we can gather the data returned from the kernel. Signed-off-by: Donald Sharp --- zebra/kernel_netlink.c | 8 +++++--- zebra/kernel_netlink.h | 6 +++++- zebra/rt_netlink.c | 6 +++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 70b56b31b6..9142d4d151 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -100,7 +100,7 @@ extern u_int32_t nl_rcvbufsize; extern struct zebra_privs_t zserv_privs; -static int +int netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h, ns_id_t ns_id) { @@ -593,7 +593,9 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, /* sendmsg() to netlink socket then recvmsg(). */ int -netlink_talk (struct nlmsghdr *n, struct nlsock *nl, struct zebra_ns *zns) +netlink_talk (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, + ns_id_t), + struct nlmsghdr *n, struct nlsock *nl, struct zebra_ns *zns) { int status; struct sockaddr_nl snl; @@ -649,7 +651,7 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl, struct zebra_ns *zns) * Get reply from netlink socket. * The reply should either be an acknowlegement or an error. */ - return netlink_parse_info (netlink_talk_filter, nl, zns, 0); + return netlink_parse_info (filter, nl, zns, 0); } /* Get type specified information from netlink. */ diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h index 890236c047..f97e6e8ccc 100644 --- a/zebra/kernel_netlink.h +++ b/zebra/kernel_netlink.h @@ -44,7 +44,11 @@ extern const char * nl_rtproto_to_str (u_char rtproto); extern int netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, ns_id_t), struct nlsock *nl, struct zebra_ns *zns, int count); -extern int netlink_talk (struct nlmsghdr *n, struct nlsock *nl, +extern int netlink_talk_filter (struct sockaddr_nl *, struct nlmsghdr *, + ns_id_t); +extern int netlink_talk (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, + ns_id_t), + struct nlmsghdr *n, struct nlsock *nl, struct zebra_ns *zns); extern int netlink_request (int family, int type, struct nlsock *nl); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index bf2fc6d189..b032c2a31c 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1160,7 +1160,7 @@ netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4); addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); - return netlink_talk (&req.n, &zns->netlink_cmd, zns); + return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns); } /* Routing table change via netlink interface. */ @@ -1455,7 +1455,7 @@ skip: snl.nl_family = AF_NETLINK; /* Talk to netlink socket. */ - return netlink_talk (&req.n, &zns->netlink_cmd, zns); + return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns); } int @@ -1645,7 +1645,7 @@ netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp) } /* Talk to netlink socket. */ - return netlink_talk (&req.n, &zns->netlink_cmd, zns); + return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns); } /* From f0ce50d470379a2fafaaa20243345bc084c1ad2d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 9 Aug 2016 14:25:12 -0400 Subject: [PATCH 089/386] pimd: Remove some impossible error conditions. It is impossible that we can hit these error conditions. Remove them from the code. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index ab07cb6792..f6808feb49 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -435,27 +435,14 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size) static int mroute_read_msg(int fd) { - const int msg_min_size = MAX(sizeof(struct ip), sizeof(struct igmpmsg)); - char buf[1000]; + char buf[2000]; int rd; - if (((int) sizeof(buf)) < msg_min_size) { - zlog_err("%s: fd=%d: buf size=%zu lower than msg_min=%d", - __PRETTY_FUNCTION__, fd, sizeof(buf), msg_min_size); - return -1; - } - rd = read(fd, buf, sizeof(buf)); if (rd < 0) { zlog_warn("%s: failure reading fd=%d: errno=%d: %s", __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); - return -2; - } - - if (rd < msg_min_size) { - zlog_warn("%s: short message reading fd=%d: read=%d msg_min=%d", - __PRETTY_FUNCTION__, fd, rd, msg_min_size); - return -3; + return -1; } return pim_mroute_msg(fd, buf, rd); From 05b0d0d0ecadcf030ae8fdffc2e78ab6392fc500 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 9 Aug 2016 19:04:23 +0000 Subject: [PATCH 090/386] pimd: Properly isolate zlookup The qpim_zclient_lookup was a global variable. This is not needed. Isolate appropriately Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 11 +++-------- pimd/pim_rpf.c | 2 +- pimd/pim_zebra.c | 6 ++---- pimd/pim_zlookup.c | 44 +++++++++++++++++++++++++++++--------------- pimd/pim_zlookup.h | 7 ++++--- pimd/pimd.c | 1 - pimd/pimd.h | 1 - 7 files changed, 39 insertions(+), 33 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 008e708349..b51fe39a7b 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -51,6 +51,7 @@ #include "pim_zebra.h" #include "pim_static.h" #include "pim_rp.h" +#include "pim_zlookup.h" static struct cmd_node pim_global_node = { PIM_NODE, @@ -2099,14 +2100,8 @@ DEFUN (show_ip_multicast, else { vty_out(vty, "%s", VTY_NEWLINE); } - vty_out(vty, "Zclient lookup socket: "); - if (qpim_zclient_lookup) { - vty_out(vty, "%d failures=%d%s", qpim_zclient_lookup->sock, - qpim_zclient_lookup->fail, VTY_NEWLINE); - } - else { - vty_out(vty, "%s", VTY_NEWLINE); - } + + pim_zlookup_show_ip_multicast (vty); vty_out(vty, "%s", VTY_NEWLINE); vty_out(vty, "Current highest VifIndex: %d%s", diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index b610d91073..15b00d8d06 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -49,7 +49,7 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, if (!incoming) { - num_ifindex = zclient_lookup_nexthop(qpim_zclient_lookup, nexthop_tab, + num_ifindex = zclient_lookup_nexthop(nexthop_tab, PIM_NEXTHOP_IFINDEX_TAB_SIZE, addr, PIM_NEXTHOP_LOOKUP_MAX); if (num_ifindex < 1) { diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 5472fe3d3a..8a32b24e8c 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -718,9 +718,7 @@ void pim_zebra_init(char *zebra_sock_path) __PRETTY_FUNCTION__); } - zassert(!qpim_zclient_lookup); - qpim_zclient_lookup = zclient_lookup_new(); - zassert(qpim_zclient_lookup); + zclient_lookup_new(); } void igmp_anysource_forward_start(struct igmp_group *group) @@ -758,7 +756,7 @@ static int fib_lookup_if_vif_index(struct in_addr addr) int vif_index; ifindex_t first_ifindex; - num_ifindex = zclient_lookup_nexthop(qpim_zclient_lookup, nexthop_tab, + num_ifindex = zclient_lookup_nexthop(nexthop_tab, PIM_NEXTHOP_IFINDEX_TAB_SIZE, addr, PIM_NEXTHOP_LOOKUP_MAX); if (num_ifindex < 1) { diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index f38475b12c..ceac1eff7a 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -28,6 +28,7 @@ #include "stream.h" #include "network.h" #include "thread.h" +#include "vty.h" #include "pimd.h" #include "pim_pim.h" @@ -36,6 +37,8 @@ extern int zclient_debug; +static struct zclient *zlookup = NULL; + static void zclient_lookup_sched(struct zclient *zlookup, int delay); /* Connect to zebra for nexthop lookup. */ @@ -117,15 +120,14 @@ static void zclient_lookup_failed(struct zclient *zlookup) zclient_lookup_reconnect(zlookup); } -struct zclient *zclient_lookup_new() +void +zclient_lookup_new (void) { - struct zclient *zlookup; - zlookup = zclient_new (master); if (!zlookup) { zlog_err("%s: zclient_new() failure", __PRETTY_FUNCTION__); - return 0; + return; } zlookup->sock = -1; @@ -138,7 +140,6 @@ struct zclient *zclient_lookup_new() zlog_notice("%s: zclient lookup socket initialized", __PRETTY_FUNCTION__); - return zlookup; } static int zclient_read_nexthop(struct zclient *zlookup, @@ -296,10 +297,10 @@ static int zclient_read_nexthop(struct zclient *zlookup, return num_ifindex; } -static int zclient_lookup_nexthop_once(struct zclient *zlookup, - struct pim_zlookup_nexthop nexthop_tab[], - const int tab_size, - struct in_addr addr) +static int +zclient_lookup_nexthop_once (struct pim_zlookup_nexthop nexthop_tab[], + const int tab_size, + struct in_addr addr) { struct stream *s; int ret; @@ -344,11 +345,11 @@ static int zclient_lookup_nexthop_once(struct zclient *zlookup, tab_size, addr); } -int zclient_lookup_nexthop(struct zclient *zlookup, - struct pim_zlookup_nexthop nexthop_tab[], - const int tab_size, - struct in_addr addr, - int max_lookup) +int +zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], + const int tab_size, + struct in_addr addr, + int max_lookup) { int lookup; uint32_t route_metric = 0xFFFFFFFF; @@ -359,7 +360,7 @@ int zclient_lookup_nexthop(struct zclient *zlookup, int first_ifindex; struct in_addr nexthop_addr; - num_ifindex = zclient_lookup_nexthop_once(qpim_zclient_lookup, nexthop_tab, + num_ifindex = zclient_lookup_nexthop_once(nexthop_tab, PIM_NEXTHOP_IFINDEX_TAB_SIZE, addr); if (num_ifindex < 1) { if (PIM_DEBUG_ZEBRA) { @@ -437,3 +438,16 @@ int zclient_lookup_nexthop(struct zclient *zlookup, return -2; } + +void +pim_zlookup_show_ip_multicast (struct vty *vty) +{ + vty_out(vty, "Zclient lookup socket: "); + if (zlookup) { + vty_out(vty, "%d failures=%d%s", zlookup->sock, + zlookup->fail, VTY_NEWLINE); + } + else { + vty_out(vty, "%s", VTY_NEWLINE); + } +} diff --git a/pimd/pim_zlookup.h b/pimd/pim_zlookup.h index b32dfe2b7c..d92eb089b1 100644 --- a/pimd/pim_zlookup.h +++ b/pimd/pim_zlookup.h @@ -35,12 +35,13 @@ struct pim_zlookup_nexthop { uint8_t protocol_distance; }; -struct zclient *zclient_lookup_new(void); +void zclient_lookup_new (void); -int zclient_lookup_nexthop(struct zclient *zlookup, - struct pim_zlookup_nexthop nexthop_tab[], +int zclient_lookup_nexthop(struct pim_zlookup_nexthop nexthop_tab[], const int tab_size, struct in_addr addr, int max_lookup); +void pim_zlookup_show_ip_multicast (struct vty *vty); + #endif /* PIM_ZLOOKUP_H */ diff --git a/pimd/pimd.c b/pimd/pimd.c index fa80aec5a2..2e21349a48 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -53,7 +53,6 @@ struct list *qpim_channel_oil_list = NULL; int qpim_t_periodic = PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */ struct list *qpim_upstream_list = NULL; struct zclient *qpim_zclient_update = NULL; -struct zclient *qpim_zclient_lookup = NULL; struct pim_assert_metric qpim_infinite_assert_metric; long qpim_rpf_cache_refresh_delay_msec = 10000; struct thread *qpim_rpf_cache_refresher = NULL; diff --git a/pimd/pimd.h b/pimd/pimd.h index b4b8d4886d..a1bd225343 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -87,7 +87,6 @@ struct in_addr qpim_all_pim_routers_addr; int qpim_t_periodic; /* Period between Join/Prune Messages */ struct list *qpim_upstream_list; /* list of struct pim_upstream */ struct zclient *qpim_zclient_update; -struct zclient *qpim_zclient_lookup; struct pim_assert_metric qpim_infinite_assert_metric; long qpim_rpf_cache_refresh_delay_msec; struct thread *qpim_rpf_cache_refresher; From 163a4c3b32128eebeaca411e1d10ce5341a07ac2 Mon Sep 17 00:00:00 2001 From: vivek Date: Tue, 9 Aug 2016 15:54:14 -0700 Subject: [PATCH 091/386] lib: Use single correct definition for prefix string buffer Signed-off-by: Vivek Venkatraman Reivewed-by: Donald Sharp Ticket: CM-12262 Reviewed By: CCR-5065 Testing Done: Manual --- lib/prefix.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/prefix.h b/lib/prefix.h index a2cdfe96fb..45e6368463 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -230,13 +230,8 @@ extern const char *prefix_family_str (const struct prefix *); extern int prefix_blen (const struct prefix *); extern int str2prefix (const char *, struct prefix *); -/* - * 8 groups of 4 bytes of hexadecimal + 7 seperators is 39 - * /128 = 4 bytes - * Null = 1 byte - * 39 + 4 + 1 = 44 bytes - */ -#define PREFIX2STR_BUFFER 44 +#define PREFIX2STR_BUFFER PREFIX_STRLEN + extern const char *prefix2str (union prefix46constptr, char *, int); extern int prefix_match (const struct prefix *, const struct prefix *); extern int prefix_same (const struct prefix *, const struct prefix *); From 90d82769a88020c485118bc76faff15a2c8648cf Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 10 Aug 2016 08:54:58 -0400 Subject: [PATCH 092/386] zebra: Fully decode mcast messages Fully decode mcast messages from the kernel. We are not doing anything with this at the moment, but that will change. Additionally convert over to using lookup for displaying the route type. Signed-off-by: Donald Sharp --- lib/zebra.h | 18 ++++++++++ zebra/if_netlink.c | 2 +- zebra/kernel_netlink.c | 28 +++++++++++++++ zebra/kernel_netlink.h | 2 ++ zebra/rt_netlink.c | 79 ++++++++++++++++++++++++++++++++++-------- 5 files changed, 113 insertions(+), 16 deletions(-) diff --git a/lib/zebra.h b/lib/zebra.h index 5bb3590abd..1fc643d597 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -476,6 +476,24 @@ typedef enum { #define SAFI_ENCAP 7 /* per IANA */ #define SAFI_MAX 8 +/* + * The above AFI and SAFI definitions are for internal use. The protocol + * definitions (IANA values) as for example used in BGP protocol packets + * are defined below and these will get mapped to/from the internal values + * in the appropriate places. + * The rationale is that the protocol (IANA) values may be sparse and are + * not optimal for use in data-structure sizing. + * Note: Only useful (i.e., supported) values are defined below. + */ +typedef enum { + IANA_AFI_RESERVED = 0, + IANA_AFI_IPV4 = 1, + IANA_AFI_IPV6 = 2, + IANA_AFI_L2VPN = 25, + IANA_AFI_IPMR = 128, + IANA_AFI_IP6MR = 129 +} iana_afi_t; + /* Default Administrative Distance of each protocol. */ #define ZEBRA_KERNEL_DISTANCE_DEFAULT 0 #define ZEBRA_CONNECT_DISTANCE_DEFAULT 0 diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index c5fd16b9cd..180e8c5de6 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -435,7 +435,7 @@ netlink_address (int cmd, int family, struct interface *ifp, addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label, strlen (ifc->label) + 1); - return netlink_talk (&req.n, &zns->netlink_cmd, zns); + return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns); } int diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 9142d4d151..20c4b5afe2 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -95,6 +95,21 @@ static const struct message rtproto_str[] = { {0, NULL} }; +static const struct message family_str[] = { + {AF_INET, "ipv4"}, + {AF_INET6, "ipv6"}, + {AF_BRIDGE, "bridge"}, + {RTNL_FAMILY_IPMR, "ipv4MR"}, + {RTNL_FAMILY_IP6MR, "ipv6MR"}, + {0, NULL}, +}; + +static const struct message rttype_str[] = { + {RTN_UNICAST, "unicast"}, + {RTN_MULTICAST, "multicast"}, + {0, NULL}, +}; + extern struct thread_master *master; extern u_int32_t nl_rcvbufsize; @@ -398,6 +413,19 @@ nl_rtproto_to_str (u_char rtproto) { return lookup (rtproto_str, rtproto); } + +const char * +nl_family_to_str (u_char family) +{ + return lookup (family_str, family); +} + +const char * +nl_rttype_to_str (u_char rttype) +{ + return lookup (rttype_str, rttype); +} + /* Receive message from netlink interface and pass those information to the given function. */ int diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h index f97e6e8ccc..f17f1380c2 100644 --- a/zebra/kernel_netlink.h +++ b/zebra/kernel_netlink.h @@ -40,6 +40,8 @@ extern struct rtattr * rta_nest(struct rtattr *rta, int maxlen, int type); extern int rta_nest_end(struct rtattr *rta, struct rtattr *nest); extern const char * nl_msg_type_to_str (uint16_t msg_type); extern const char * nl_rtproto_to_str (u_char rtproto); +extern const char * nl_family_to_str (u_char family); +extern const char * nl_rttype_to_str (u_char rttype); extern int netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, ns_id_t), struct nlsock *nl, diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index b032c2a31c..ff907bb878 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -303,14 +303,6 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, return 0; } -static const struct message family_str[] = { - {AF_INET, "ipv4"}, - {AF_INET6, "ipv6"}, - {RTNL_FAMILY_IPMR, "ipv4MR"}, - {RTNL_FAMILY_IP6MR, "ipv6MR"}, - {0, NULL}, -}; - /* Routing information change from the kernel. */ static int netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, @@ -421,7 +413,7 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, { char buf[PREFIX_STRLEN]; zlog_debug ("%s %s vrf %u", - h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", + nl_msg_type_to_str (h->nlmsg_type), prefix2str (&p, buf, sizeof(buf)), vrf_id); } @@ -508,7 +500,7 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, { char buf[PREFIX_STRLEN]; zlog_debug ("%s %s vrf %u", - h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", + nl_msg_type_to_str (h->nlmsg_type), prefix2str (&p, buf, sizeof(buf)), vrf_id); } @@ -529,8 +521,20 @@ netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h ns_id_t ns_id) { int len; + unsigned long long lastused = 0; struct rtmsg *rtm; struct rtattr *tb[RTA_MAX + 1]; + struct prefix_sg sg; + int iif = 0; + int count; + int oif[256]; + int oif_count = 0; + char sbuf[40]; + char gbuf[40]; + char oif_list[256] = "\0"; + memset (&sg, 0, sizeof (sg)); + sg.family = IANA_AFI_IPMR; + vrf_id_t vrf = ns_id; rtm = NLMSG_DATA (h); @@ -539,6 +543,52 @@ netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h memset (tb, 0, sizeof tb); netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len); + if (tb[RTA_IIF]) + iif = *(int *)RTA_DATA (tb[RTA_IIF]); + + if (tb[RTA_SRC]) + sg.src = *(struct in_addr *)RTA_DATA (tb[RTA_SRC]); + + if (tb[RTA_DST]) + sg.grp = *(struct in_addr *)RTA_DATA (tb[RTA_DST]); + + if (tb[RTA_EXPIRES]) + lastused = *(unsigned long long *)RTA_DATA (tb[RTA_EXPIRES]); + + if (tb[RTA_MULTIPATH]) + { + struct rtnexthop *rtnh = + (struct rtnexthop *)RTA_DATA (tb[RTA_MULTIPATH]); + + len = RTA_PAYLOAD (tb[RTA_MULTIPATH]); + for (;;) + { + if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len) + break; + + oif[oif_count] = rtnh->rtnh_ifindex; + oif_count++; + + len -= NLMSG_ALIGN (rtnh->rtnh_len); + rtnh = RTNH_NEXT (rtnh); + } + } + + if (IS_ZEBRA_DEBUG_KERNEL) + { + strcpy (sbuf, inet_ntoa (sg.src)); + strcpy (gbuf, inet_ntoa (sg.grp)); + for (count = 0; count < oif_count; count++) + { + struct interface *ifp = if_lookup_by_index_vrf (oif[count], vrf); + char temp[256]; + + sprintf (temp, "%s ", ifp->name); + strcat (oif_list, temp); + } + zlog_debug ("MCAST %s (%s,%s) IIF: %d OIF: %s jiffies: %lld", + nl_msg_type_to_str (h->nlmsg_type), sbuf, gbuf, iif, oif_list, lastused); + } return 0; } @@ -562,12 +612,11 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, /* Connected route. */ if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug ("%s %s %s proto %s vrf %u", - h->nlmsg_type == - RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", - lookup (family_str, rtm->rtm_family), - rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast", + nl_msg_type_to_str (h->nlmsg_type), + nl_family_to_str (rtm->rtm_family), + nl_rttype_to_str (rtm->rtm_type), nl_rtproto_to_str (rtm->rtm_protocol), - vrf_id); + vrf_id); /* We don't care about change notifications for the MPLS table. */ /* TODO: Revisit this. */ From 8e38a2cfccfdf7b47fb69d6fae26f83c5825d1a6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 10 Aug 2016 16:16:22 -0400 Subject: [PATCH 093/386] pimd: Fix RP shenanigans The RP was not properly handling the series of events: 1) When a WRVIFWHOLE is received if we are the RP, send a pim register stop to the FHR. 2) When a register was received we were sending a join (S,G) towards the S, then a immediate prune (S,G) followed by another join (S,G). Just send the first join 3) Save whom we received the S,G register from so we can use it later 4) Allow a join timer to restart itself instead of causing a crash. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 12 ++++++++++++ pimd/pim_register.c | 6 ++++-- pimd/pim_register.h | 1 + pimd/pim_upstream.c | 3 +-- pimd/pim_upstream.h | 1 + 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index f6808feb49..9460219f13 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -26,6 +26,7 @@ #include "prefix.h" #include "pimd.h" +#include "pim_rpf.h" #include "pim_mroute.h" #include "pim_oil.h" #include "pim_str.h" @@ -345,6 +346,17 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) if (PIM_DEBUG_MROUTE) zlog_debug ("If channel: %p", ch); + up = pim_upstream_find (&sg); + if (up) + { + struct pim_nexthop source; + //No if channel, but upstream we are at the RP. + pim_nexthop_lookup (&source, up->upstream_register, NULL); + pim_register_stop_send(source.interface, &sg, up->upstream_register); + //Send S bit down the join. + return 0; + } + up = pim_upstream_add (&sg, ifp); if (!up) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index d0fe89b01b..79f9283138 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -44,7 +44,7 @@ struct thread *send_test_packet_timer = NULL; -static void +void pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, struct in_addr originator) { @@ -321,6 +321,7 @@ pim_register_recv (struct interface *ifp, { upstream = pim_upstream_add (&sg, ifp); + upstream->upstream_register = src_addr; pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.src, sg.grp); pim_nexthop_lookup (&upstream->rpf.source_nexthop, upstream->upstream_addr, NULL); @@ -328,7 +329,8 @@ pim_register_recv (struct interface *ifp, upstream->sg.src = sg.src; upstream->rpf.rpf_addr = upstream->rpf.source_nexthop.mrib_nexthop_addr; - pim_upstream_switch (upstream, PIM_UPSTREAM_PRUNE); + //pim_upstream_switch (upstream, PIM_UPSTREAM_PRUNE); + upstream->join_state = PIM_UPSTREAM_PRUNE; } diff --git a/pimd/pim_register.h b/pimd/pim_register.h index 8ab24b7137..ce2e052104 100644 --- a/pimd/pim_register.h +++ b/pimd/pim_register.h @@ -43,5 +43,6 @@ int pim_register_recv (struct interface *ifp, uint8_t *tlv_buf, int tlv_buf_size); void pim_register_send (const uint8_t *buf, int buf_size, struct pim_rpf *rpg, int null_register); +void pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, struct in_addr originator); #endif diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 932e06b76d..9ee0e87004 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -225,8 +225,7 @@ static void join_timer_start(struct pim_upstream *up) pim_str_sg_dump (&up->sg)); } - zassert(!up->t_join_timer); - + THREAD_OFF (up->t_join_timer); THREAD_TIMER_ON(master, up->t_join_timer, on_join_timer, up, qpim_t_periodic); diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index eea9456013..fccb1c4186 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -90,6 +90,7 @@ struct pim_upstream { struct pim_upstream *parent; int fhr; struct in_addr upstream_addr;/* Who we are talking to */ + struct in_addr upstream_register; /*Who we received a register from*/ struct prefix_sg sg; /* (S,G) group key */ uint32_t flags; struct channel_oil *channel_oil; From 79ce47c00d216b1403a80f86ba7e10190532bbac Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 11 Aug 2016 07:07:15 -0400 Subject: [PATCH 094/386] pimd: Fix register stop timer 1) Ensure Timer is actually off 2) I missread the rfc, when we are in prune state, just send the register stop. Do not add the tunnel device yet. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 9ee0e87004..39f609da28 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -913,6 +913,7 @@ pim_upstream_register_stop_timer (struct thread *t) up = THREAD_ARG (t); + THREAD_TIMER_OFF (up->t_rs_timer); up->t_rs_timer = NULL; if (PIM_DEBUG_TRACE) @@ -940,7 +941,6 @@ pim_upstream_register_stop_timer (struct thread *t) ip_hdr.ip_len = htons (20); // checksum is broken pim_register_send ((uint8_t *)&ip_hdr, sizeof (struct ip), rpg, 1); - pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); break; default: break; From 4712642e11f540e5c6e611afee9a699579c960fe Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 11 Aug 2016 08:08:28 -0400 Subject: [PATCH 095/386] pimd: Set spt bit when we receive first packet on RP When on the RP, if we receive the first correctly routed mroute from upstream, Set the SPT bit so that the state machine will work properly. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 1 + 1 file changed, 1 insertion(+) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 9460219f13..8426a4add5 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -354,6 +354,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) pim_nexthop_lookup (&source, up->upstream_register, NULL); pim_register_stop_send(source.interface, &sg, up->upstream_register); //Send S bit down the join. + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; return 0; } From dfbbce1dcec213368beb4a0e3d24dcf8f1e06acd Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 15 Aug 2016 07:28:36 -0400 Subject: [PATCH 096/386] pimd: Fix igmp(*,G) not influencing S,G mroutes When we receive a (*,G) route decide if we need to cause any output interfaces to be added to any S,G route associated. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 66 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index dcd9da64b6..b83f0072b4 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -37,6 +37,7 @@ #include "pim_join.h" #include "pim_rpf.h" #include "pim_macro.h" +#include "pim_oil.h" /* * A (*,G) or a (*,*) is going away @@ -773,6 +774,35 @@ void pim_ifchannel_local_membership_add(struct interface *ifp, ifmembership_set(ch, PIM_IFMEMBERSHIP_INCLUDE); zassert(!IFCHANNEL_NOINFO(ch)); + + if (sg->src.s_addr == INADDR_ANY) + { + struct pim_upstream *up = pim_upstream_find (sg); + struct pim_upstream *child; + struct listnode *up_node; + + for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, up_node, child)) + { + if (child->parent == up) + { + if (PIM_DEBUG_EVENTS) + { + char buff[100]; + + strcpy (buff, pim_str_sg_dump (&up->sg)); + zlog_debug("%s %s: IGMP (S,G)=%s from %s", + __FILE__, __PRETTY_FUNCTION__, + buff, pim_str_sg_dump (sg)); + } + + if (pim_upstream_evaluate_join_desired (child)) + { + pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + pim_upstream_switch (child, PIM_UPSTREAM_JOINED); + } + } + } + } } void pim_ifchannel_local_membership_del(struct interface *ifp, @@ -794,6 +824,42 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); + if (sg->src.s_addr == INADDR_ANY) + { + struct pim_upstream *up = pim_upstream_find (sg); + struct pim_upstream *child; + struct listnode *up_node; + + for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, up_node, child)) + { + if (child->parent == up) + { + struct channel_oil *c_oil = child->channel_oil; + struct pim_ifchannel *ch = pim_ifchannel_find (ifp, &child->sg); + struct pim_interface *pim_ifp = ifp->info; + + if (PIM_DEBUG_EVENTS) + { + char buff[100]; + strcpy (buff, pim_str_sg_dump (&up->sg)); + zlog_debug("%s %s: Prune(S,G)=%s from %s", + __FILE__, __PRETTY_FUNCTION__, + buff, pim_str_sg_dump (&child->sg)); + } + + if (!pim_upstream_evaluate_join_desired (child)) + pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + + /* + * If the S,G has no if channel and the c_oil still + * has output here then the *,G was supplying the implied + * if channel. So remove it. + */ + if (!ch && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) + pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + } + } + } delete_on_noinfo(ch); } From e3be04328f601963c825c722355f62c4b4e7cb31 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 11 Aug 2016 00:04:20 +0000 Subject: [PATCH 097/386] lib, pimd, zebra: Allow pimd to ask the kernel about mroute info When we need to lookup the mroute info for a route. Allow pimd to ask the kernel. Signed-off-by: Donald Sharp --- lib/log.c | 1 + lib/zebra.h | 1 + pimd/pim_mroute.c | 3 ++ pimd/pim_oil.h | 2 ++ pimd/pim_upstream.c | 3 +- pimd/pim_zlookup.c | 76 +++++++++++++++++++++++++++++++++++++++ pimd/pim_zlookup.h | 1 + zebra/Makefile.am | 4 +-- zebra/rt_netlink.c | 57 ++++++++++++++++++++++++----- zebra/rt_netlink.h | 1 + zebra/zebra_fpm_netlink.c | 1 + zebra/zebra_mroute.c | 66 ++++++++++++++++++++++++++++++++++ zebra/zebra_mroute.h | 35 ++++++++++++++++++ zebra/zserv.c | 4 +++ 14 files changed, 244 insertions(+), 11 deletions(-) create mode 100644 zebra/zebra_mroute.c create mode 100644 zebra/zebra_mroute.h diff --git a/lib/log.c b/lib/log.c index f9877300b4..67f335c6ae 100644 --- a/lib/log.c +++ b/lib/log.c @@ -989,6 +989,7 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY (ZEBRA_IPV4_NEXTHOP_DELETE), DESC_ENTRY (ZEBRA_IPV6_NEXTHOP_ADD), DESC_ENTRY (ZEBRA_IPV6_NEXTHOP_DELETE), + DESC_ENTRY (ZEBRA_IPMR_ROUTE_STATS), }; #undef DESC_ENTRY diff --git a/lib/zebra.h b/lib/zebra.h index 1fc643d597..f344867697 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -405,6 +405,7 @@ typedef enum { ZEBRA_IPV4_NEXTHOP_DELETE, ZEBRA_IPV6_NEXTHOP_ADD, ZEBRA_IPV6_NEXTHOP_DELETE, + ZEBRA_IPMR_ROUTE_STATS, } zebra_message_types_t; /* Marker value used in new Zserv, in the byte location corresponding diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 8426a4add5..2fc733e97f 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -37,6 +37,7 @@ #include "pim_oil.h" #include "pim_register.h" #include "pim_ifchannel.h" +#include "pim_zlookup.h" /* GLOBAL VARS */ extern struct zebra_privs_t pimd_privs; @@ -740,6 +741,7 @@ pim_mroute_update_counters (struct channel_oil *c_oil) c_oil->cc.oldpktcnt = c_oil->cc.pktcnt; c_oil->cc.oldbytecnt = c_oil->cc.bytecnt; c_oil->cc.oldwrong_if = c_oil->cc.wrong_if; + c_oil->cc.oldlastused = c_oil->cc.lastused; if (ioctl (qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) { @@ -758,6 +760,7 @@ pim_mroute_update_counters (struct channel_oil *c_oil) return; } + pim_zlookup_sg_statistics (c_oil); c_oil->cc.pktcnt = sgreq.pktcnt; c_oil->cc.bytecnt = sgreq.bytecnt; c_oil->cc.wrong_if = sgreq.wrong_if; diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index 6b55bdc4d5..1bbd232e4d 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -52,6 +52,8 @@ struct channel_counts { + unsigned long long lastused; + unsigned long long oldlastused; unsigned long pktcnt; unsigned long oldpktcnt; unsigned long bytecnt; diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 39f609da28..bb322a7cdd 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -822,7 +822,8 @@ pim_upstream_keep_alive_timer (struct thread *t) pim_mroute_update_counters (up->channel_oil); - if (up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt) + if ((up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt) && + (up->channel_oil->cc.oldlastused >= up->channel_oil->cc.lastused)) { pim_mroute_del (up->channel_oil); pim_upstream_delete (up); diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index ceac1eff7a..6cf6a6b2f7 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -28,11 +28,14 @@ #include "stream.h" #include "network.h" #include "thread.h" +#include "prefix.h" #include "vty.h" #include "pimd.h" +#include "pim_iface.h" #include "pim_pim.h" #include "pim_str.h" +#include "pim_oil.h" #include "pim_zlookup.h" extern int zclient_debug; @@ -451,3 +454,76 @@ pim_zlookup_show_ip_multicast (struct vty *vty) vty_out(vty, "%s", VTY_NEWLINE); } } + +int +pim_zlookup_sg_statistics (struct channel_oil *c_oil) +{ + struct stream *s = zlookup->obuf; + uint16_t command = 0; + unsigned long long lastused; + struct prefix_sg sg; + int count = 0; + int ret; + struct interface *ifp = pim_if_find_by_vif_index (c_oil->oil.mfcc_parent); + + if (PIM_DEBUG_ZEBRA) + zlog_debug ("Sending Request for New Channel Oil Information"); + + stream_reset (s); + zclient_create_header (s, ZEBRA_IPMR_ROUTE_STATS, VRF_DEFAULT); + stream_put_in_addr (s, &c_oil->oil.mfcc_origin); + stream_put_in_addr (s, &c_oil->oil.mfcc_mcastgrp); + stream_putl (s, ifp->ifindex); + stream_putw_at(s, 0, stream_get_endp(s)); + + count = stream_get_endp (s); + ret = writen (zlookup->sock, s->data, count); + if (ret <= 0) + { + zlog_err("%s %s: writen() failure writing to zclient lookup socket", + __FILE__, __PRETTY_FUNCTION__); + return -1; + } + + s = zlookup->ibuf; + + while (command != ZEBRA_IPMR_ROUTE_STATS) + { + int err; + uint16_t length = 0; + vrf_id_t vrf_id; + u_char marker; + u_char version; + + stream_reset (s); + err = zclient_read_header (s, zlookup->sock, &length, &marker, &version, + &vrf_id, &command); + if (err < 0) + { + zlog_err ("%s %s: zclient_read_header() failed", + __FILE__, __PRETTY_FUNCTION__); + zclient_lookup_failed(zlookup); + return -1; + } + } + + sg.src.s_addr = stream_get_ipv4 (s); + sg.grp.s_addr = stream_get_ipv4 (s); + if (sg.src.s_addr != c_oil->oil.mfcc_origin.s_addr || + sg.grp.s_addr != c_oil->oil.mfcc_mcastgrp.s_addr) + { + zlog_err ("%s: Received wrong %s information", + __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); + zclient_lookup_failed (zlookup); + return -3; + } + + stream_get (&lastused, s, sizeof (lastused)); + + zlog_debug ("Received %lld for %s", lastused, pim_str_sg_dump (&sg)); + + c_oil->cc.lastused = lastused; + + return 0; + +} diff --git a/pimd/pim_zlookup.h b/pimd/pim_zlookup.h index d92eb089b1..4dea5750c5 100644 --- a/pimd/pim_zlookup.h +++ b/pimd/pim_zlookup.h @@ -44,4 +44,5 @@ int zclient_lookup_nexthop(struct pim_zlookup_nexthop nexthop_tab[], void pim_zlookup_show_ip_multicast (struct vty *vty); +int pim_zlookup_sg_statistics (struct channel_oil *c_oil); #endif /* PIM_ZLOOKUP_H */ diff --git a/zebra/Makefile.am b/zebra/Makefile.am index 65927262f2..428090d488 100644 --- a/zebra/Makefile.am +++ b/zebra/Makefile.am @@ -44,7 +44,7 @@ zebra_SOURCES = \ irdp_main.c irdp_interface.c irdp_packet.c router-id.c zebra_fpm.c \ $(othersrc) zebra_ptm.c zebra_rnh.c zebra_ptm_redistribute.c \ zebra_ns.c zebra_vrf.c zebra_static.c zebra_mpls.c zebra_mpls_vty.c \ - $(protobuf_srcs) \ + $(protobuf_srcs) zebra_mroute.c \ $(dev_srcs) testzebra_SOURCES = test_main.c zebra_rib.c interface.c connected.c debug.c \ @@ -60,7 +60,7 @@ noinst_HEADERS = \ rt_netlink.h zebra_fpm.h zebra_fpm_private.h zebra_rnh.h \ zebra_ptm_redistribute.h zebra_ptm.h zebra_routemap.h \ zebra_ns.h zebra_vrf.h ioctl_solaris.h zebra_static.h zebra_mpls.h \ - kernel_netlink.h if_netlink.h + kernel_netlink.h if_netlink.h zebra_mroute.h zebra_LDADD = $(otherobj) ../lib/libzebra.la $(LIBCAP) $(Q_FPM_PB_CLIENT_LDOPTS) diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index ff907bb878..5dc9a10e29 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -55,6 +55,8 @@ #include "zebra/zebra_mpls.h" #include "zebra/kernel_netlink.h" #include "zebra/rt_netlink.h" +#include "zebra/zebra_mroute.h" + /* TODO - Temporary definitions, need to refine. */ #ifndef AF_MPLS @@ -516,6 +518,8 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, return 0; } +static struct mcast_route_data *mroute = NULL; + static int netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h, ns_id_t ns_id) @@ -524,7 +528,8 @@ netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h unsigned long long lastused = 0; struct rtmsg *rtm; struct rtattr *tb[RTA_MAX + 1]; - struct prefix_sg sg; + struct mcast_route_data *m; + struct mcast_route_data mr; int iif = 0; int count; int oif[256]; @@ -532,10 +537,13 @@ netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h char sbuf[40]; char gbuf[40]; char oif_list[256] = "\0"; - memset (&sg, 0, sizeof (sg)); - sg.family = IANA_AFI_IPMR; vrf_id_t vrf = ns_id; + if (mroute) + m = mroute; + else + m = &mr; + rtm = NLMSG_DATA (h); len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); @@ -547,13 +555,13 @@ netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h iif = *(int *)RTA_DATA (tb[RTA_IIF]); if (tb[RTA_SRC]) - sg.src = *(struct in_addr *)RTA_DATA (tb[RTA_SRC]); + m->sg.src = *(struct in_addr *)RTA_DATA (tb[RTA_SRC]); if (tb[RTA_DST]) - sg.grp = *(struct in_addr *)RTA_DATA (tb[RTA_DST]); + m->sg.grp = *(struct in_addr *)RTA_DATA (tb[RTA_DST]); if (tb[RTA_EXPIRES]) - lastused = *(unsigned long long *)RTA_DATA (tb[RTA_EXPIRES]); + m->lastused = *(unsigned long long *)RTA_DATA (tb[RTA_EXPIRES]); if (tb[RTA_MULTIPATH]) { @@ -576,8 +584,8 @@ netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h if (IS_ZEBRA_DEBUG_KERNEL) { - strcpy (sbuf, inet_ntoa (sg.src)); - strcpy (gbuf, inet_ntoa (sg.grp)); + strcpy (sbuf, inet_ntoa (m->sg.src)); + strcpy (gbuf, inet_ntoa (m->sg.grp)); for (count = 0; count < oif_count; count++) { struct interface *ifp = if_lookup_by_index_vrf (oif[count], vrf); @@ -1507,6 +1515,39 @@ skip: return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns); } +int +netlink_get_ipmr_sg_stats (void *in) +{ + int suc = 0; + struct mcast_route_data *mr = (struct mcast_route_data *)in; + struct { + struct nlmsghdr n; + struct ndmsg ndm; + char buf[256]; + } req; + + mroute = mr; + struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); + + memset(&req.n, 0, sizeof(req.n)); + memset(&req.ndm, 0, sizeof(req.ndm)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.ndm.ndm_family = AF_INET; + req.n.nlmsg_type = RTM_GETROUTE; + + addattr_l (&req.n, sizeof (req), RTA_IIF, &mroute->ifindex, 4); + addattr_l (&req.n, sizeof (req), RTA_OIF, &mroute->ifindex, 4); + addattr_l (&req.n, sizeof (req), RTA_SRC, &mroute->sg.src.s_addr, 4); + addattr_l (&req.n, sizeof (req), RTA_DST, &mroute->sg.grp.s_addr, 4); + + suc = netlink_talk (netlink_route_change_read_multicast, &req.n, &zns->netlink_cmd, zns); + + mroute = NULL; + return suc; +} + int kernel_route_rib (struct prefix *p, struct rib *old, struct rib *new) { diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index 7183525fba..6774b7dd3d 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -37,6 +37,7 @@ extern int netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, ns_id_t ns_id); extern int netlink_route_read (struct zebra_ns *zns); +extern int netlink_get_ipmr_sg_stats (void *mroute); #endif /* HAVE_NETLINK */ #endif /* _ZEBRA_RT_NETLINK_H */ diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c index a09008b396..5dd08ca782 100644 --- a/zebra/zebra_fpm_netlink.c +++ b/zebra/zebra_fpm_netlink.c @@ -28,6 +28,7 @@ #include "log.h" #include "rib.h" #include "vty.h" +#include "prefix.h" #include "zebra/zserv.h" #include "zebra/zebra_ns.h" diff --git a/zebra/zebra_mroute.c b/zebra/zebra_mroute.c new file mode 100644 index 0000000000..8dddb4e507 --- /dev/null +++ b/zebra/zebra_mroute.c @@ -0,0 +1,66 @@ +/* zebra_mroute code + * Copyright (C) 2016 Cumulus Networks, Inc. + * Donald Sharp + * + * This file is part of Quagga + * + * Quagga is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include + +#include "stream.h" +#include "prefix.h" +#include "vrf.h" +#include "rib.h" + +#include "zebra/zserv.h" +#include "zebra/zebra_vrf.h" +#include "zebra/zebra_mroute.h" +#include "zebra/rt_netlink.h" + +int +zebra_ipmr_route_stats (struct zserv *client, int fd, u_short length, struct zebra_vrf *zvrf) +{ + struct mcast_route_data mroute; + struct stream *s; + + char sbuf[40]; + char gbuf[40]; + + memset (&mroute, 0, sizeof (mroute)); + stream_get (&mroute.sg.src, client->ibuf, 4); + stream_get (&mroute.sg.grp, client->ibuf, 4); + mroute.ifindex = stream_getl (client->ibuf); + + strcpy (sbuf, inet_ntoa (mroute.sg.src)); + strcpy (gbuf, inet_ntoa (mroute.sg.grp)); + + netlink_get_ipmr_sg_stats (&mroute); + + s = client->obuf; + + stream_reset (s); + + zserv_create_header (s, ZEBRA_IPMR_ROUTE_STATS, zvrf_id (zvrf)); + stream_put_in_addr (s, &mroute.sg.src); + stream_put_in_addr (s, &mroute.sg.grp); + stream_put (s, &mroute.lastused, sizeof (mroute.lastused)); + + stream_putw_at (s, 0, stream_get_endp (s)); + zebra_server_send_message (client); + return 0; +} diff --git a/zebra/zebra_mroute.h b/zebra/zebra_mroute.h new file mode 100644 index 0000000000..c0bac43a81 --- /dev/null +++ b/zebra/zebra_mroute.h @@ -0,0 +1,35 @@ +/* zebra_mroute.h + * Copyright (C) 2016 Cumulus Networks, Inc. + * Donald Sharp + * + * This file is part of Quagga. + * + * Quagga is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef __ZEBRA_MROUTE_H__ +#define __ZEBRA_MROUTE_H__ + +struct mcast_route_data { + struct prefix_sg sg; + unsigned int ifindex; + unsigned long long lastused; +}; + +int zebra_ipmr_route_stats (struct zserv *client, int sock, u_short length, struct zebra_vrf *zvf); + +#endif + diff --git a/zebra/zserv.c b/zebra/zserv.c index a92efa027f..44e29a8bb0 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -54,6 +54,7 @@ #include "zebra/rtadv.h" #include "zebra/zebra_mpls.h" #include "zebra/zebra_fpm.h" +#include "zebra/zebra_mroute.h" /* Event list of zebra. */ enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE }; @@ -2051,6 +2052,9 @@ zebra_client_read (struct thread *thread) case ZEBRA_MPLS_LABELS_DELETE: zread_mpls_labels (command, client, length, vrf_id); break; + case ZEBRA_IPMR_ROUTE_STATS: + zebra_ipmr_route_stats (client, sock, length, zvrf); + break; default: zlog_info ("Zebra received unknown command %d", command); break; From 30df5c100e436a85429c11e57cf2f5fbba983bf1 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 16 Aug 2016 16:19:14 -0400 Subject: [PATCH 098/386] pimd: Use correct function to delete upstream information When the keep alive timer finds that we are no longer sending packets for that particular S,G, remove the upstream information but use the function that makes sure we check the ref count. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index bb322a7cdd..3685c6899f 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -826,7 +826,7 @@ pim_upstream_keep_alive_timer (struct thread *t) (up->channel_oil->cc.oldlastused >= up->channel_oil->cc.lastused)) { pim_mroute_del (up->channel_oil); - pim_upstream_delete (up); + pim_upstream_del (up); } else { From 8f547471df424da482dc745e9091e5daa4a10a67 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 16 Aug 2016 19:22:32 -0400 Subject: [PATCH 099/386] pimd: Fix typo in debug message The debug message was wrong. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 2fc733e97f..28c7f7dc88 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -132,7 +132,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg if (!pim_mroute_connected_to_source (ifp, msg->im_src)) { if (PIM_DEBUG_MROUTE) - zlog_debug ("%s: Received incoming packet that does originate on our seg", + zlog_debug ("%s: Received incoming packet that doesn't originate on our seg", __PRETTY_FUNCTION__); return 0; } From 34fe48e7de3b93848184e9546744fb1d3e481d28 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 16 Aug 2016 20:08:03 -0400 Subject: [PATCH 100/386] pimd: Restarting Quagga sometimes lost mroutes When on a intermediate switch between the FHR and RP when Quagga is restarted. Pimd is coming up so fast and getting the S,G join before networking is properly working on the switch. We would never install the mroute in this case. What was happening is that the scan of the S,G was occurring and we were figuring out who we should talk to but we were never installing the route for it. Notice that we've never installed the route and install it if the mroute has changed. Ticket: CM-12460 Signed-off-by: Donald Sharp --- pimd/pim_zebra.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 8a32b24e8c..f710fc20c9 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -340,7 +340,14 @@ static void scan_upstream_rpf_cache() if (rpf_result == PIM_RPF_CHANGED) { if (up->join_state == PIM_UPSTREAM_JOINED) { - + /* + * If we come up real fast we can be here + * where the mroute has not been installed + * so install it. + */ + if (!up->channel_oil->installed) + pim_mroute_add (up->channel_oil); + /* RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages @@ -452,7 +459,6 @@ pim_scan_individual_oil (struct channel_oil *c_oil) old_vif_index = c_oil->oil.mfcc_parent; c_oil->oil.mfcc_parent = input_iface_vif_index; - zlog_debug ("FF"); /* update kernel multicast forwarding cache (MFC) */ if (pim_mroute_add(c_oil)) { From 6c7197b142c76186fc3cb0aa318c97f1523913f5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 16 Aug 2016 21:13:22 -0400 Subject: [PATCH 101/386] pimd: Add 'debug mroute detail' When there is allot of IGMP activity for the kernel upcall that we are ignoring, just ignore it for the moment as well. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 26 ++++++++++++++++++++++++++ pimd/pim_mroute.c | 6 +++--- pimd/pim_vty.c | 5 +++++ pimd/pimd.h | 12 ++++++++---- 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index b51fe39a7b..d5f1255e17 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3683,6 +3683,17 @@ DEFUN (debug_mroute, return CMD_SUCCESS; } +DEFUN (debug_mroute_detail, + debug_mroute_detail_cmd, + "debug mroute detail", + DEBUG_STR + DEBUG_MROUTE_STR + "detailed\n") +{ + PIM_DO_DEBUG_MROUTE_DETAIL; + return CMD_SUCCESS; +} + DEFUN (no_debug_mroute, no_debug_mroute_cmd, "no debug mroute", @@ -3694,6 +3705,17 @@ DEFUN (no_debug_mroute, return CMD_SUCCESS; } +DEFUN (no_debug_mroute_detail, + no_debug_mroute_detail_cmd, + "no debug mroute detail", + NO_STR + DEBUG_STR + DEBUG_MROUTE_STR + "detailed\n") +{ + PIM_DONT_DEBUG_MROUTE_DETAIL; + return CMD_SUCCESS; +} DEFUN (debug_static, debug_static_cmd, @@ -4817,7 +4839,9 @@ void pim_cmd_init() install_element (ENABLE_NODE, &debug_igmp_trace_cmd); install_element (ENABLE_NODE, &no_debug_igmp_trace_cmd); install_element (ENABLE_NODE, &debug_mroute_cmd); + install_element (ENABLE_NODE, &debug_mroute_detail_cmd); install_element (ENABLE_NODE, &no_debug_mroute_cmd); + install_element (ENABLE_NODE, &no_debug_mroute_detail_cmd); install_element (ENABLE_NODE, &debug_static_cmd); install_element (ENABLE_NODE, &no_debug_static_cmd); install_element (ENABLE_NODE, &debug_pim_cmd); @@ -4848,7 +4872,9 @@ void pim_cmd_init() install_element (CONFIG_NODE, &debug_igmp_trace_cmd); install_element (CONFIG_NODE, &no_debug_igmp_trace_cmd); install_element (CONFIG_NODE, &debug_mroute_cmd); + install_element (CONFIG_NODE, &debug_mroute_detail_cmd); install_element (CONFIG_NODE, &no_debug_mroute_cmd); + install_element (CONFIG_NODE, &no_debug_mroute_detail_cmd); install_element (CONFIG_NODE, &debug_static_cmd); install_element (CONFIG_NODE, &no_debug_static_cmd); install_element (CONFIG_NODE, &debug_pim_cmd); diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 28c7f7dc88..f222e5f575 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -131,7 +131,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg */ if (!pim_mroute_connected_to_source (ifp, msg->im_src)) { - if (PIM_DEBUG_MROUTE) + if (PIM_DEBUG_MROUTE_DETAIL) zlog_debug ("%s: Received incoming packet that doesn't originate on our seg", __PRETTY_FUNCTION__); return 0; @@ -193,7 +193,7 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf) up = pim_upstream_find(&sg); if (!up) { - if (PIM_DEBUG_MROUTE) { + if (PIM_DEBUG_MROUTE_DETAIL) { zlog_debug("%s: Unable to find upstream channel WHOLEPKT%s", __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); } @@ -399,7 +399,7 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size) /* kernel upcall must have protocol=0 */ if (ip_hdr->ip_p) { /* this is not a kernel upcall */ - if (PIM_DEBUG_MROUTE) { + if (PIM_DEBUG_MROUTE_DETAIL) { pim_inet4_dump("", ip_hdr->ip_src, src_str, sizeof(src_str)); pim_inet4_dump("", ip_hdr->ip_dst, grp_str, sizeof(grp_str)); zlog_debug("%s: not a kernel upcall proto=%d src: %s dst: %s msg_size=%d", diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index e27c69411c..f279136651 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -63,6 +63,11 @@ pim_debug_config_write (struct vty *vty) ++writes; } + if (PIM_DEBUG_MROUTE_DETAIL) { + vty_out (vty, "debug mroute detail%s", VTY_NEWLINE); + ++writes; + } + if (PIM_DEBUG_PIM_EVENTS) { vty_out(vty, "debug pim events%s", VTY_NEWLINE); ++writes; diff --git a/pimd/pimd.h b/pimd/pimd.h index a1bd225343..e9b67aaa99 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -66,10 +66,11 @@ #define PIM_MASK_ZEBRA (1 << 11) #define PIM_MASK_SSMPINGD (1 << 12) #define PIM_MASK_MROUTE (1 << 13) -#define PIM_MASK_PIM_HELLO (1 << 14) -#define PIM_MASK_PIM_J_P (1 << 15) -#define PIM_MASK_STATIC (1 << 16) -#define PIM_MASK_PIM_REG (1 << 17) +#define PIM_MASK_MROUTE_DETAIL (1 << 14) +#define PIM_MASK_PIM_HELLO (1 << 15) +#define PIM_MASK_PIM_J_P (1 << 16) +#define PIM_MASK_STATIC (1 << 17) +#define PIM_MASK_PIM_REG (1 << 18) const char *const PIM_ALL_SYSTEMS; const char *const PIM_ALL_ROUTERS; @@ -132,6 +133,7 @@ extern int32_t qpim_register_probe_time; #define PIM_DEBUG_ZEBRA (qpim_debugs & PIM_MASK_ZEBRA) #define PIM_DEBUG_SSMPINGD (qpim_debugs & PIM_MASK_SSMPINGD) #define PIM_DEBUG_MROUTE (qpim_debugs & PIM_MASK_MROUTE) +#define PIM_DEBUG_MROUTE_DETAIL (qpim_debugs & PIM_MASK_MROUTE_DETAIL) #define PIM_DEBUG_PIM_HELLO (qpim_debugs & PIM_MASK_PIM_HELLO) #define PIM_DEBUG_PIM_J_P (qpim_debugs & PIM_MASK_PIM_J_P) #define PIM_DEBUG_PIM_REG (qpim_debugs & PIM_MASK_PIM_REG) @@ -153,6 +155,7 @@ extern int32_t qpim_register_probe_time; #define PIM_DO_DEBUG_ZEBRA (qpim_debugs |= PIM_MASK_ZEBRA) #define PIM_DO_DEBUG_SSMPINGD (qpim_debugs |= PIM_MASK_SSMPINGD) #define PIM_DO_DEBUG_MROUTE (qpim_debugs |= PIM_MASK_MROUTE) +#define PIM_DO_DEBUG_MROUTE_DETAIL (qpim_debugs |= PIM_MASK_MROUTE_DETAIL) #define PIM_DO_DEBUG_PIM_HELLO (qpim_debugs |= PIM_MASK_PIM_HELLO) #define PIM_DO_DEBUG_PIM_J_P (qpim_debugs |= PIM_MASK_PIM_J_P) #define PIM_DO_DEBUG_PIM_REG (qpim_debugs |= PIM_MASK_PIM_REG) @@ -170,6 +173,7 @@ extern int32_t qpim_register_probe_time; #define PIM_DONT_DEBUG_ZEBRA (qpim_debugs &= ~PIM_MASK_ZEBRA) #define PIM_DONT_DEBUG_SSMPINGD (qpim_debugs &= ~PIM_MASK_SSMPINGD) #define PIM_DONT_DEBUG_MROUTE (qpim_debugs &= ~PIM_MASK_MROUTE) +#define PIM_DONT_DEBUG_MROUTE_DETAIL (qpim_debugs &= ~PIM_MASK_MROUTE_DETAIL) #define PIM_DONT_DEBUG_PIM_HELLO (qpim_debugs &= ~PIM_MASK_PIM_HELLO) #define PIM_DONT_DEBUG_PIM_J_P (qpim_debugs &= ~PIM_MASK_PIM_J_P) #define PIM_DONT_DEBUG_PIM_REG (qpim_debugs &= ~PIM_MASK_PIM_REG) From bb027ee881eec8e98e30be04432438f644bb3979 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 17 Aug 2016 19:27:03 +0000 Subject: [PATCH 102/386] pimd: Fix register stop behavior Register stop was not being sent on a consistent basis. Signed-off-by: Donald Sharp --- pimd/pim_register.c | 4 +++- pimd/pim_upstream.c | 23 +++++++++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 79f9283138..471279f077 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -131,10 +131,12 @@ pim_register_stop_recv (uint8_t *buf, int buf_size) return 0; break; case PIM_UPSTREAM_JOINED: + upstream->join_state = PIM_UPSTREAM_PRUNE; + pim_channel_del_oif (upstream->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); + pim_upstream_start_register_stop_timer (upstream, 0); case PIM_UPSTREAM_JOIN_PENDING: upstream->join_state = PIM_UPSTREAM_PRUNE; pim_upstream_start_register_stop_timer (upstream, 0); - pim_channel_del_oif (upstream->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); return 0; break; } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 3685c6899f..da1a1c7666 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -380,9 +380,6 @@ pim_upstream_switch(struct pim_upstream *up, { enum pim_upstream_state old_state = up->join_state; - up->join_state = new_state; - up->state_transition = pim_time_monotonic_sec(); - if (PIM_DEBUG_PIM_EVENTS) { zlog_debug("%s: PIM_UPSTREAM_%s: (S,G)=%s", __PRETTY_FUNCTION__, @@ -390,6 +387,22 @@ pim_upstream_switch(struct pim_upstream *up, pim_str_sg_dump (&up->sg)); } + /* + * This code still needs work. + */ + switch (up->join_state) + { + case PIM_UPSTREAM_PRUNE: + case PIM_UPSTREAM_JOIN_PENDING: + break; + case PIM_UPSTREAM_NOTJOINED: + case PIM_UPSTREAM_JOINED: + up->join_state = new_state; + up->state_transition = pim_time_monotonic_sec(); + + break; + } + pim_upstream_update_assert_tracking_desired(up); if (new_state == PIM_UPSTREAM_JOINED) { @@ -911,7 +924,6 @@ pim_upstream_register_stop_timer (struct thread *t) struct pim_upstream *up; struct pim_rpf *rpg; struct ip ip_hdr; - up = THREAD_ARG (t); THREAD_TIMER_OFF (up->t_rs_timer); @@ -927,6 +939,9 @@ pim_upstream_register_stop_timer (struct thread *t) { case PIM_UPSTREAM_JOIN_PENDING: up->join_state = PIM_UPSTREAM_JOINED; + pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); + break; + case PIM_UPSTREAM_JOINED: break; case PIM_UPSTREAM_PRUNE: up->join_state = PIM_UPSTREAM_JOIN_PENDING; From 00d2f9e45b953f0f710cc0a14cc9dac5205acedc Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 17 Aug 2016 20:44:51 -0400 Subject: [PATCH 103/386] pimd: Fix RP handling of Register message The RP needs to send the join when we want to send it Also make sure the ka_timer is reset properly. Ticket: CM-12473 Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index da1a1c7666..8d908b719e 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -191,8 +191,6 @@ pim_upstream_send_join (struct pim_upstream *up) if (up->fhr) return; - zassert(up->join_state == PIM_UPSTREAM_JOINED); - /* send Join(S,G) to the current upstream neighbor */ pim_joinprune_send(up->rpf.source_nexthop.interface, up->rpf.rpf_addr, @@ -854,6 +852,7 @@ void pim_upstream_keep_alive_timer_start (struct pim_upstream *up, uint32_t time) { + THREAD_OFF (up->t_ka_timer); THREAD_TIMER_ON (master, up->t_ka_timer, pim_upstream_keep_alive_timer, From 4304f95c86af2ea658678fb969b984108a4c597f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 18 Aug 2016 09:07:14 -0400 Subject: [PATCH 104/386] pimd: Allow keep alive timer configuration Allow the user to specify the time to wait for a keep alive to happen. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 27 +++++++++++++++++++++++++++ pimd/pim_mroute.c | 4 ++-- pimd/pim_register.c | 2 +- pimd/pim_upstream.c | 2 +- pimd/pim_vty.c | 6 ++++++ pimd/pimd.c | 1 + pimd/pimd.h | 1 + 7 files changed, 39 insertions(+), 4 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index d5f1255e17..78e0d46715 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2450,6 +2450,31 @@ pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group) return CMD_SUCCESS; } +DEFUN (ip_pim_keep_alive, + ip_pim_keep_alive_cmd, + "ip pim keep-alive-timer <31-600>", + IP_STR + "pim multicast routing\n" + "Keep alive Timer" + "Seconds") +{ + qpim_keep_alive_time = atoi (argv[3]->arg); + return CMD_SUCCESS; +} + +DEFUN (no_ip_pim_keep_alive, + no_ip_pim_keep_alive_cmd, + "no ip pim keep-alive-timer <31-600>", + NO_STR + IP_STR + "pim multicast routing\n" + "Keep alive Timer" + "Seconds") +{ + qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; + return CMD_SUCCESS; +} + DEFUN (ip_pim_rp, ip_pim_rp_cmd, "ip pim rp A.B.C.D [A.B.C.D/M]", @@ -4754,6 +4779,8 @@ void pim_cmd_init() install_element (CONFIG_NODE, &no_ip_multicast_routing_cmd); install_element (CONFIG_NODE, &ip_pim_rp_cmd); install_element (CONFIG_NODE, &no_ip_pim_rp_cmd); + install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd); + install_element (CONFIG_NODE, &no_ip_pim_keep_alive_cmd); install_element (CONFIG_NODE, &ip_ssmpingd_cmd); install_element (CONFIG_NODE, &no_ip_ssmpingd_cmd); diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index f222e5f575..02d6e8a099 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -156,7 +156,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg return 0; } - pim_upstream_keep_alive_timer_start (up, PIM_KEEPALIVE_PERIOD); + pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); up->channel_oil = pim_channel_oil_add(&sg, pim_ifp->mroute_vif_index); @@ -373,7 +373,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) up->fhr = 1; pim_ifp = ifp->info; - pim_upstream_keep_alive_timer_start (up, PIM_KEEPALIVE_PERIOD); + pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); up->channel_oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); up->channel_oil->cc.pktcnt++; pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 471279f077..129f38cbdc 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -349,7 +349,7 @@ pim_register_recv (struct interface *ifp, if (sentRegisterStop) { pim_upstream_keep_alive_timer_start (upstream, PIM_RP_KEEPALIVE_PERIOD); } else { - pim_upstream_keep_alive_timer_start (upstream, PIM_KEEPALIVE_PERIOD); + pim_upstream_keep_alive_timer_start (upstream, qpim_keep_alive_time); } } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 8d908b719e..10f8b21ed0 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -842,7 +842,7 @@ pim_upstream_keep_alive_timer (struct thread *t) else { up->t_ka_timer = NULL; - pim_upstream_keep_alive_timer_start (up, PIM_KEEPALIVE_PERIOD); + pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); } return 1; diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index f279136651..bc4acfdb06 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -138,6 +138,12 @@ int pim_global_config_write(struct vty *vty) writes += pim_rp_config_write (vty); + if (qpim_keep_alive_time != PIM_KEEPALIVE_PERIOD) + { + vty_out (vty, "ip pim keep-alive-timer %d%s", + qpim_keep_alive_time, VTY_NEWLINE); + ++writes; + } if (qpim_ssmpingd_list) { struct listnode *node; struct ssmpingd_sock *ss; diff --git a/pimd/pimd.c b/pimd/pimd.c index 2e21349a48..4323fad0ec 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -69,6 +69,7 @@ int64_t qpim_mroute_add_last = 0; int64_t qpim_mroute_del_events = 0; int64_t qpim_mroute_del_last = 0; struct list *qpim_static_route_list = NULL; +unsigned int qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; int32_t qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; int32_t qpim_register_probe_time = PIM_REGISTER_PROBE_TIME_DEFAULT; diff --git a/pimd/pimd.h b/pimd/pimd.h index e9b67aaa99..1118fd2a62 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -104,6 +104,7 @@ int64_t qpim_mroute_add_last; int64_t qpim_mroute_del_events; int64_t qpim_mroute_del_last; struct list *qpim_static_route_list; /* list of routes added statically */ +extern unsigned int qpim_keep_alive_time; #define PIM_JP_HOLDTIME (qpim_t_periodic * 7 / 2) From d854589aba9d047f7601a2748d9ab9381f528cce Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 18 Aug 2016 09:44:52 -0400 Subject: [PATCH 105/386] pimd: When the Keep Alive timer Pops Stop timers When the Keep alive timer Pops stop the timer and send a prune upstream if we need to remove the state. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 10f8b21ed0..d1e90caf95 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -635,7 +635,6 @@ void pim_upstream_update_join_desired(struct pim_upstream *up) /* switched from true to false */ if (!is_join_desired && was_join_desired) { - zassert(up->join_state == PIM_UPSTREAM_JOINED); pim_upstream_switch(up, PIM_UPSTREAM_NOTJOINED); return; } @@ -837,6 +836,11 @@ pim_upstream_keep_alive_timer (struct thread *t) (up->channel_oil->cc.oldlastused >= up->channel_oil->cc.lastused)) { 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, + &up->sg, 0); pim_upstream_del (up); } else From 01408ede34dc6970d24483ae7447206b6e5d201e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 18 Aug 2016 10:00:02 -0400 Subject: [PATCH 106/386] pimd: Allow rp to configure it's keep alive timer Allow the end user to supply a RP based keep alive timer. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 33 +++++++++++++++++++++++++++++++-- pimd/pim_register.c | 2 +- pimd/pim_vty.c | 7 +++++++ pimd/pimd.c | 3 +++ pimd/pimd.h | 1 + 5 files changed, 43 insertions(+), 3 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 78e0d46715..8067219e45 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2468,13 +2468,40 @@ DEFUN (no_ip_pim_keep_alive, NO_STR IP_STR "pim multicast routing\n" - "Keep alive Timer" - "Seconds") + "Keep alive Timer\n" + "Seconds\n") { qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; return CMD_SUCCESS; } +DEFUN (ip_pim_rp_keep_alive, + ip_pim_rp_keep_alive_cmd, + "ip pim rp keep-alive-timer <31-600>", + IP_STR + "pim multicast routing\n" + "Rendevous Point\n" + "Keep alive Timer\n" + "Seconds\n") +{ + qpim_rp_keep_alive_time = atoi (argv[4]->arg); + return CMD_SUCCESS; +} + +DEFUN (no_ip_pim_rp_keep_alive, + no_ip_pim_rp_keep_alive_cmd, + "no ip pim rp keep-alive-timer <31-600>", + NO_STR + IP_STR + "pim multicast routing\n" + "Rendevous Point\n" + "Keep alive Timer\n" + "Seconds\n") +{ + qpim_rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD; + return CMD_SUCCESS; +} + DEFUN (ip_pim_rp, ip_pim_rp_cmd, "ip pim rp A.B.C.D [A.B.C.D/M]", @@ -4781,6 +4808,8 @@ void pim_cmd_init() install_element (CONFIG_NODE, &no_ip_pim_rp_cmd); install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd); install_element (CONFIG_NODE, &no_ip_pim_keep_alive_cmd); + install_element (CONFIG_NODE, &ip_pim_rp_keep_alive_cmd); + install_element (CONFIG_NODE, &no_ip_pim_rp_keep_alive_cmd); install_element (CONFIG_NODE, &ip_ssmpingd_cmd); install_element (CONFIG_NODE, &no_ip_ssmpingd_cmd); diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 129f38cbdc..439bb577c9 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -347,7 +347,7 @@ pim_register_recv (struct interface *ifp, if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || (SwitchToSptDesired(&sg))) { if (sentRegisterStop) { - pim_upstream_keep_alive_timer_start (upstream, PIM_RP_KEEPALIVE_PERIOD); + pim_upstream_keep_alive_timer_start (upstream, qpim_rp_keep_alive_time); } else { pim_upstream_keep_alive_timer_start (upstream, qpim_keep_alive_time); } diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index bc4acfdb06..85df83287b 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -144,6 +144,13 @@ int pim_global_config_write(struct vty *vty) qpim_keep_alive_time, VTY_NEWLINE); ++writes; } + if (qpim_rp_keep_alive_time != PIM_RP_KEEPALIVE_PERIOD) + { + vty_out (vty, "ip pim rp keep-alive-timer %d%s", + qpim_keep_alive_time, VTY_NEWLINE); + ++writes; + } + if (qpim_ssmpingd_list) { struct listnode *node; struct ssmpingd_sock *ss; diff --git a/pimd/pimd.c b/pimd/pimd.c index 4323fad0ec..7600637d91 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -70,6 +70,7 @@ int64_t qpim_mroute_del_events = 0; int64_t qpim_mroute_del_last = 0; struct list *qpim_static_route_list = NULL; unsigned int qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; +signed int qpim_rp_keep_alive_time = 0; int32_t qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; int32_t qpim_register_probe_time = PIM_REGISTER_PROBE_TIME_DEFAULT; @@ -96,6 +97,8 @@ void pim_init() { srandom(time(NULL)); + qpim_rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD; + pim_rp_init (); if (!inet_aton(PIM_ALL_PIM_ROUTERS, &qpim_all_pim_routers_addr)) { diff --git a/pimd/pimd.h b/pimd/pimd.h index 1118fd2a62..268b5ca60f 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -105,6 +105,7 @@ int64_t qpim_mroute_del_events; int64_t qpim_mroute_del_last; struct list *qpim_static_route_list; /* list of routes added statically */ extern unsigned int qpim_keep_alive_time; +extern signed int qpim_rp_keep_alive_time; #define PIM_JP_HOLDTIME (qpim_t_periodic * 7 / 2) From fa6a18f1c8111236bfc47bdd3d705cb3a530fe08 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 18 Aug 2016 13:47:08 -0400 Subject: [PATCH 107/386] pimd: Change RPF cache refresh time to 2 seconds 10 second delay is a bit too long. Let's crank it down a bit and see what happens. Signed-off-by: Donald Sharp --- pimd/pimd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pimd.c b/pimd/pimd.c index 7600637d91..c00baa3596 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -54,7 +54,7 @@ int qpim_t_periodic = PIM_DEFAULT_T_PERIODIC; /* Period be struct list *qpim_upstream_list = NULL; struct zclient *qpim_zclient_update = NULL; struct pim_assert_metric qpim_infinite_assert_metric; -long qpim_rpf_cache_refresh_delay_msec = 10000; +long qpim_rpf_cache_refresh_delay_msec = 2000; struct thread *qpim_rpf_cache_refresher = NULL; int64_t qpim_rpf_cache_refresh_requests = 0; int64_t qpim_rpf_cache_refresh_events = 0; From d5ed8a9cd1ea4f935877a4d2a7c8937b46c69fc1 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 18 Aug 2016 14:15:33 -0400 Subject: [PATCH 108/386] pimd: Fix debug to properly display state We should display the state the upstream is instead of the number of the state. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index d1e90caf95..957cf456c1 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -934,8 +934,9 @@ pim_upstream_register_stop_timer (struct thread *t) if (PIM_DEBUG_TRACE) { - zlog_debug ("%s: (S,G)=%s upstream register stop timer %d", - __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg), up->join_state); + zlog_debug ("%s: (S,G)=%s upstream register stop timer %s", + __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg), + pim_upstream_state2str(up)); } switch (up->join_state) From c98029541203906cfec89974658301367d55fe79 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 19 Aug 2016 07:56:59 -0400 Subject: [PATCH 109/386] pimd: Modify pim_upstream_state2str for more usage Just pass in the actual state to allow us to translate the state to a string even if we don't have a upstream. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 2 +- pimd/pim_upstream.c | 15 ++++++++------- pimd/pim_upstream.h | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 8067219e45..ba2d4a063b 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1004,7 +1004,7 @@ static void pim_show_upstream(struct vty *vty) up->rpf.source_nexthop.interface->name, src_str, grp_str, - pim_upstream_state2str (up), + pim_upstream_state2str (up->join_state), uptime, join_timer, rs_timer, diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 957cf456c1..abc3f53c56 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -175,7 +175,7 @@ pim_upstream_send_join (struct pim_upstream *up) char rpf_str[100]; pim_inet4_dump("", up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); zlog_debug ("%s: RPF'%s=%s(%s) for Interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg), rpf_str, pim_upstream_state2str (up), + pim_str_sg_dump (&up->sg), rpf_str, pim_upstream_state2str (up->join_state), up->rpf.source_nexthop.interface->name); if (PIM_INADDR_IS_ANY(up->rpf.rpf_addr)) { zlog_debug("%s: can't send join upstream: RPF'%s=%s", @@ -379,10 +379,11 @@ pim_upstream_switch(struct pim_upstream *up, enum pim_upstream_state old_state = up->join_state; if (PIM_DEBUG_PIM_EVENTS) { - zlog_debug("%s: PIM_UPSTREAM_%s: (S,G)=%s", + zlog_debug("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s", __PRETTY_FUNCTION__, - ((new_state == PIM_UPSTREAM_JOINED) ? "JOINED" : "NOTJOINED"), - pim_str_sg_dump (&up->sg)); + pim_str_sg_dump (&up->sg), + pim_upstream_state2str (up->join_state), + pim_upstream_state2str (new_state)); } /* @@ -901,9 +902,9 @@ pim_upstream_switch_to_spt_desired (struct prefix_sg *sg) } const char * -pim_upstream_state2str (struct pim_upstream *up) +pim_upstream_state2str (enum pim_upstream_state join_state) { - switch (up->join_state) + switch (join_state) { case PIM_UPSTREAM_NOTJOINED: return "NtJnd"; @@ -936,7 +937,7 @@ pim_upstream_register_stop_timer (struct thread *t) { zlog_debug ("%s: (S,G)=%s upstream register stop timer %s", __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg), - pim_upstream_state2str(up)); + pim_upstream_state2str(up->join_state)); } switch (up->join_state) diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index fccb1c4186..03dcd6bfd2 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -157,7 +157,7 @@ void pim_upstream_send_join (struct pim_upstream *up); void pim_upstream_switch (struct pim_upstream *up, enum pim_upstream_state new_state); -const char *pim_upstream_state2str (struct pim_upstream *up); +const char *pim_upstream_state2str (enum pim_upstream_state join_state); int pim_upstream_inherited_olist (struct pim_upstream *up); #endif /* PIM_UPSTREAM_H */ From 04329d4e498fff314d4b1df571bb509050a23e61 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 19 Aug 2016 09:07:19 -0400 Subject: [PATCH 110/386] pimd: Fix join received when in Prune or Prune Pending When we are a FHR, and the upstream state is in Prune or Prune Pending allow the join because we know we want to forward traffic to the RP. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 9 +++++++-- pimd/pim_macro.c | 2 +- pimd/pim_upstream.c | 1 - 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index b83f0072b4..85bd178d9b 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -169,6 +169,13 @@ void pim_ifchannel_ifjoin_switch(const char *caller, { enum pim_ifjoin_state old_state = ch->ifjoin_state; + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug ("PIM_IFCHANNEL: %s is switching from %s to %s", + pim_str_sg_dump (&ch->sg), + pim_ifchannel_ifjoin_name (ch->ifjoin_state), + pim_ifchannel_ifjoin_name (new_state)); + + if (old_state == new_state) { if (PIM_DEBUG_PIM_EVENTS) { zlog_debug("%s calledby %s: non-transition on state %d (%s)", @@ -178,8 +185,6 @@ void pim_ifchannel_ifjoin_switch(const char *caller, return; } - zassert(old_state != new_state); - ch->ifjoin_state = new_state; /* Transition to/from NOINFO ? */ diff --git a/pimd/pim_macro.c b/pimd/pim_macro.c index 62decfd5f9..4bcb62a90e 100644 --- a/pimd/pim_macro.c +++ b/pimd/pim_macro.c @@ -337,7 +337,7 @@ static int pim_macro_chisin_inherited_olist(const struct pim_ifchannel *ch) */ int pim_macro_chisin_oiflist(const struct pim_ifchannel *ch) { - if (ch->upstream->join_state != PIM_UPSTREAM_JOINED) { + if (ch->upstream->join_state == PIM_UPSTREAM_NOTJOINED) { /* oiflist is NULL */ return 0; /* false */ } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index abc3f53c56..4563b6ecb4 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1029,7 +1029,6 @@ pim_upstream_inherited_olist (struct pim_upstream *up) int output_intf = 0; pim_ifp = up->rpf.source_nexthop.interface->info; - zlog_debug ("Channel Oil%s: %p", pim_str_sg_dump (&up->sg), up->channel_oil); if (!up->channel_oil) up->channel_oil = pim_channel_oil_add (&up->sg, pim_ifp->mroute_vif_index); From 7fe1f66279eca025c39e401d1c9e8549c49fa284 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 19 Aug 2016 10:05:01 -0400 Subject: [PATCH 111/386] pimd: When deleting upstream double ensure route is removed Ensure that when an upstream is removed that we actually remove the route Also when we get a callback for whole packet before we send a register stop make sure we are actually on the RP. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 21 ++++++++++++++------- pimd/pim_upstream.c | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 02d6e8a099..e678b87cc7 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -350,13 +350,20 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) up = pim_upstream_find (&sg); if (up) { - struct pim_nexthop source; - //No if channel, but upstream we are at the RP. - pim_nexthop_lookup (&source, up->upstream_register, NULL); - pim_register_stop_send(source.interface, &sg, up->upstream_register); - //Send S bit down the join. - up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - return 0; + /* + * If we are the fhr that means we are getting a callback during + * the pimreg period, so I believe we can ignore this packet + */ + if (!up->fhr) + { + struct pim_nexthop source; + //No if channel, but upstream we are at the RP. + pim_nexthop_lookup (&source, up->upstream_register, NULL); + pim_register_stop_send(source.interface, &sg, up->upstream_register); + //Send S bit down the join. + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + } + return 0; } up = pim_upstream_add (&sg, ifp); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 4563b6ecb4..bd6677d47d 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -156,6 +156,7 @@ void pim_upstream_delete(struct pim_upstream *up) THREAD_OFF(up->t_rs_timer); pim_upstream_remove_children (up); + pim_mroute_del (up->channel_oil); upstream_channel_oil_detach(up); /* From f24405b1e81bf5a269936fc03187c20853e6056d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 19 Aug 2016 13:25:20 -0400 Subject: [PATCH 112/386] pimd - Fix rpf lookup to what it was originally I tried to be smart and skirt around rpf lookup if I knew the incoming interface. This turns out to be not necessarily a good thing because we can easily have asymetrical routing. This fix removes the attempt to cache the ifp we received the incoming packet on and just lets the lookup work like it should. Additionally it removes the weird hardcoding of the rpf interface from the register stuff. Ticket: CM-12530 Signed-off-by: Donald Sharp reb --- pimd/pim_cmd.c | 2 +- pimd/pim_mroute.c | 2 +- pimd/pim_register.c | 4 +-- pimd/pim_rp.c | 4 +-- pimd/pim_rpf.c | 76 +++++++++++++++++++-------------------------- pimd/pim_rpf.h | 7 ++--- pimd/pim_upstream.c | 4 +-- pimd/pim_zebra.c | 2 +- 8 files changed, 42 insertions(+), 59 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index ba2d4a063b..bd3a85abb0 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2347,7 +2347,7 @@ DEFUN (show_ip_rib, return CMD_WARNING; } - if (pim_nexthop_lookup(&nexthop, addr, NULL)) { + if (pim_nexthop_lookup(&nexthop, addr)) { vty_out(vty, "Failure querying RIB nexthop for unicast address %s%s", addr_str, VTY_NEWLINE); return CMD_WARNING; diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index e678b87cc7..a17a8b1006 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -358,7 +358,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) { struct pim_nexthop source; //No if channel, but upstream we are at the RP. - pim_nexthop_lookup (&source, up->upstream_register, NULL); + pim_nexthop_lookup (&source, up->upstream_register); pim_register_stop_send(source.interface, &sg, up->upstream_register); //Send S bit down the join. up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 439bb577c9..4cc4a2703c 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -326,12 +326,10 @@ pim_register_recv (struct interface *ifp, upstream->upstream_register = src_addr; pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.src, sg.grp); pim_nexthop_lookup (&upstream->rpf.source_nexthop, - upstream->upstream_addr, NULL); - upstream->rpf.source_nexthop.interface = ifp; + upstream->upstream_addr); upstream->sg.src = sg.src; upstream->rpf.rpf_addr = upstream->rpf.source_nexthop.mrib_nexthop_addr; - //pim_upstream_switch (upstream, PIM_UPSTREAM_PRUNE); upstream->join_state = PIM_UPSTREAM_PRUNE; } diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 0af7a991ee..84de870764 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -262,7 +262,7 @@ pim_rp_setup (void) for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { - if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr, NULL) != 0) + if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr) != 0) { zlog_err ("Unable to lookup nexthop for rp specified"); ret++; @@ -358,7 +358,7 @@ pim_rp_g (struct in_addr group) if (rp_info) { - pim_nexthop_lookup(&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr, NULL); + pim_nexthop_lookup(&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr); return (&rp_info->rp); } diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 15b00d8d06..e81e262cd6 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -37,8 +37,7 @@ static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up); -int pim_nexthop_lookup(struct pim_nexthop *nexthop, - struct in_addr addr, struct interface *incoming) +int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr) { struct pim_zlookup_nexthop nexthop_tab[PIM_NEXTHOP_IFINDEX_TAB_SIZE]; int num_ifindex; @@ -47,46 +46,38 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * PIM_NEXTHOP_IFINDEX_TAB_SIZE); - if (!incoming) - { - num_ifindex = zclient_lookup_nexthop(nexthop_tab, - PIM_NEXTHOP_IFINDEX_TAB_SIZE, - addr, PIM_NEXTHOP_LOOKUP_MAX); - if (num_ifindex < 1) { - char addr_str[100]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s %s: could not find nexthop ifindex for address %s", - __FILE__, __PRETTY_FUNCTION__, - addr_str); - return -1; - } + num_ifindex = zclient_lookup_nexthop(nexthop_tab, + PIM_NEXTHOP_IFINDEX_TAB_SIZE, + addr, PIM_NEXTHOP_LOOKUP_MAX); + if (num_ifindex < 1) { + char addr_str[100]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_warn("%s %s: could not find nexthop ifindex for address %s", + __FILE__, __PRETTY_FUNCTION__, + addr_str); + return -1; + } - first_ifindex = nexthop_tab[0].ifindex; + first_ifindex = nexthop_tab[0].ifindex; - if (num_ifindex > 1) { - char addr_str[100]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_info("%s %s: FIXME ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)", - __FILE__, __PRETTY_FUNCTION__, - num_ifindex, addr_str, first_ifindex); - /* debug warning only, do not return */ - } + if (num_ifindex > 1) { + char addr_str[100]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_info("%s %s: FIXME ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)", + __FILE__, __PRETTY_FUNCTION__, + num_ifindex, addr_str, first_ifindex); + /* debug warning only, do not return */ + } - ifp = if_lookup_by_index(first_ifindex); - if (!ifp) { - char addr_str[100]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s %s: could not find interface for ifindex %d (address %s)", - __FILE__, __PRETTY_FUNCTION__, - first_ifindex, addr_str); - return -2; - } - } - else - { - ifp = incoming; - first_ifindex = ifp->ifindex; - } + ifp = if_lookup_by_index(first_ifindex); + if (!ifp) { + char addr_str[100]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_warn("%s %s: could not find interface for ifindex %d (address %s)", + __FILE__, __PRETTY_FUNCTION__, + first_ifindex, addr_str); + return -2; + } if (!ifp->info) { char addr_str[100]; @@ -131,9 +122,7 @@ static int nexthop_mismatch(const struct pim_nexthop *nh1, (nh1->mrib_route_metric != nh2->mrib_route_metric); } -enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, - struct in_addr *old_rpf_addr, - struct interface *incoming) +enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_rpf_addr) { struct in_addr save_rpf_addr; struct pim_nexthop save_nexthop; @@ -142,8 +131,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, save_nexthop = rpf->source_nexthop; /* detect change in pim_nexthop */ save_rpf_addr = rpf->rpf_addr; /* detect change in RPF'(S,G) */ - if (pim_nexthop_lookup(&rpf->source_nexthop, - up->upstream_addr, incoming)) { + if (pim_nexthop_lookup(&rpf->source_nexthop, up->upstream_addr)) { return PIM_RPF_FAILURE; } diff --git a/pimd/pim_rpf.h b/pimd/pim_rpf.h index 86c33c2e45..ab16039a29 100644 --- a/pimd/pim_rpf.h +++ b/pimd/pim_rpf.h @@ -27,10 +27,7 @@ #include "pim_upstream.h" #include "pim_neighbor.h" -int pim_nexthop_lookup(struct pim_nexthop *nexthop, - struct in_addr addr, struct interface *incoming); -enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, - struct in_addr *old_rpf_addr, - struct interface *incoming); +int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr); +enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_rpf_addr); #endif /* PIM_RPF_H */ diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index bd6677d47d..37b900688e 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -463,13 +463,13 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, up->channel_oil = NULL; up->sptbit = PIM_UPSTREAM_SPTBIT_FALSE; - up->rpf.source_nexthop.interface = 0; + up->rpf.source_nexthop.interface = NULL; up->rpf.source_nexthop.mrib_nexthop_addr.s_addr = PIM_NET_INADDR_ANY; up->rpf.source_nexthop.mrib_metric_preference = qpim_infinite_assert_metric.metric_preference; up->rpf.source_nexthop.mrib_route_metric = qpim_infinite_assert_metric.route_metric; up->rpf.rpf_addr.s_addr = PIM_NET_INADDR_ANY; - rpf_result = pim_rpf_update(up, 0, incoming); + rpf_result = pim_rpf_update(up, 0); if (rpf_result == PIM_RPF_FAILURE) { XFREE(MTYPE_PIM_UPSTREAM, up); return NULL; diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index f710fc20c9..94cd658932 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -333,7 +333,7 @@ static void scan_upstream_rpf_cache() struct in_addr old_rpf_addr; enum pim_rpf_result rpf_result; - rpf_result = pim_rpf_update(up, &old_rpf_addr, NULL); + rpf_result = pim_rpf_update(up, &old_rpf_addr); if (rpf_result == PIM_RPF_FAILURE) continue; From 7747bad6ac449903b4ff95bb495c08010084f862 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 19 Aug 2016 15:21:45 -0400 Subject: [PATCH 113/386] pimd: Fix RP upstream Prune -> join state This fix allows the RP to transition from a Prune'd to Join state on reception of proper control messages. Additionally it was noticed on if down -> if up transitions the prune then join message was going out the wrong interface. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 6 ++++++ pimd/pim_zebra.c | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 37b900688e..68c773d0c8 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -393,6 +393,12 @@ pim_upstream_switch(struct pim_upstream *up, switch (up->join_state) { case PIM_UPSTREAM_PRUNE: + if (!up->fhr) + { + up->join_state = new_state; + up->state_transition = pim_time_monotonic_sec (); + } + break; case PIM_UPSTREAM_JOIN_PENDING: break; case PIM_UPSTREAM_NOTJOINED: diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 94cd658932..b171fbb702 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -331,8 +331,10 @@ static void scan_upstream_rpf_cache() for (ALL_LIST_ELEMENTS(qpim_upstream_list, up_node, up_nextnode, up)) { struct in_addr old_rpf_addr; + struct interface *old_interface; enum pim_rpf_result rpf_result; + old_interface = up->rpf.source_nexthop.interface; rpf_result = pim_rpf_update(up, &old_rpf_addr); if (rpf_result == PIM_RPF_FAILURE) continue; @@ -364,10 +366,8 @@ static void scan_upstream_rpf_cache() /* send Prune(S,G) to the old upstream neighbor */ - pim_joinprune_send(up->rpf.source_nexthop.interface, - old_rpf_addr, - &up->sg, - 0 /* prune */); + pim_joinprune_send(old_interface, old_rpf_addr, + &up->sg, 0 /* prune */); /* send Join(S,G) to the current upstream neighbor */ pim_joinprune_send(up->rpf.source_nexthop.interface, From 4df01a4e66fec6472d9d0b89d199654eb5c6e8bd Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 22 Aug 2016 09:10:05 -0400 Subject: [PATCH 114/386] pimd: Fix pim to use correct src address for packets When sending register packets to the RP from the FHR we should be using the ip address of the incoming interface that received the mcast packet. Ticket: CM-12445 Signed-off-by: Donald Sharp --- pimd/pim_assert.c | 1 + pimd/pim_join.c | 1 + pimd/pim_mroute.c | 8 ++++++-- pimd/pim_pim.c | 29 +++++++++++++++++++++++++++-- pimd/pim_pim.h | 1 + pimd/pim_register.c | 13 +++++++------ pimd/pim_register.h | 4 ++-- pimd/pim_upstream.c | 5 ++++- 8 files changed, 49 insertions(+), 13 deletions(-) diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index 4443e4459a..1add2ebb00 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -474,6 +474,7 @@ static int pim_assert_do(struct pim_ifchannel *ch, } if (pim_msg_send(pim_ifp->pim_sock_fd, + pim_ifp->primary_address, qpim_all_pim_routers_addr, pim_msg, pim_msg_size, diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 80e77ecb32..c7d54d3c04 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -434,6 +434,7 @@ int pim_joinprune_send(struct interface *ifp, return pim_msg_size; if (pim_msg_send(pim_ifp->pim_sock_fd, + pim_ifp->primary_address, qpim_all_pim_routers_addr, pim_msg, pim_msg_size, diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index a17a8b1006..65696f6d33 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -218,7 +218,8 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf) * If we've received a register suppress */ if (!up->t_rs_timer) - pim_register_send((uint8_t *)buf + sizeof(struct ip), ntohs (ip_hdr->ip_len), rpg, 0); + pim_register_send((uint8_t *)buf + sizeof(struct ip), ntohs (ip_hdr->ip_len), + pim_ifp->primary_address, rpg, 0); return 0; } @@ -357,9 +358,12 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) if (!up->fhr) { struct pim_nexthop source; + struct pim_rpf *rpf = RP (sg.grp); + pim_ifp = rpf->source_nexthop.interface->info; + //No if channel, but upstream we are at the RP. pim_nexthop_lookup (&source, up->upstream_register); - pim_register_stop_send(source.interface, &sg, up->upstream_register); + pim_register_stop_send(source.interface, &sg, pim_ifp->primary_address, up->upstream_register); //Send S bit down the join. up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; } diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 382c9bc46d..f58e326d16 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -480,7 +480,10 @@ void pim_sock_reset(struct interface *ifp) pim_ifstat_reset(ifp); } +static uint16_t ip_id = 0; + int pim_msg_send(int fd, + struct in_addr src, struct in_addr dst, uint8_t *pim_msg, int pim_msg_size, @@ -489,6 +492,25 @@ int pim_msg_send(int fd, ssize_t sent; struct sockaddr_in to; socklen_t tolen; + unsigned char buffer[3000]; + unsigned char *msg_start; + struct ip *ip; + + memset (buffer, 0, 3000); + int sendlen = sizeof (struct ip) + pim_msg_size; + + msg_start = buffer + sizeof (struct ip); + memcpy (msg_start, pim_msg, pim_msg_size); + + ip = (struct ip *)buffer; + ip->ip_id = htons (++ip_id); + ip->ip_hl = 5; + ip->ip_v = 4; + ip->ip_p = PIM_IP_PROTO_PIM; + ip->ip_src = src; + ip->ip_dst = dst; + ip->ip_ttl = MAXTTL; + ip->ip_len = htons (sendlen); if (PIM_DEBUG_PIM_PACKETS) { char dst_str[100]; @@ -508,9 +530,9 @@ int pim_msg_send(int fd, pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_size); } - sent = sendto(fd, pim_msg, pim_msg_size, MSG_DONTWAIT, + sent = sendto(fd, buffer, sendlen, MSG_DONTWAIT, (struct sockaddr *)&to, tolen); - if (sent != (ssize_t) pim_msg_size) { + if (sent != (ssize_t) sendlen) { char dst_str[100]; pim_inet4_dump("", dst, dst_str, sizeof(dst_str)); if (sent < 0) { @@ -577,6 +599,7 @@ static int hello_send(struct interface *ifp, PIM_MSG_TYPE_HELLO); if (pim_msg_send(pim_ifp->pim_sock_fd, + pim_ifp->primary_address, qpim_all_pim_routers_addr, pim_msg, pim_msg_size, @@ -759,6 +782,8 @@ int pim_sock_add(struct interface *ifp) return -2; } + pim_socket_ip_hdr (pim_ifp->pim_sock_fd); + pim_ifp->t_pim_sock_read = NULL; pim_ifp->pim_sock_creation = pim_time_monotonic_sec(); diff --git a/pimd/pim_pim.h b/pimd/pim_pim.h index 01c9044a26..fad572a125 100644 --- a/pimd/pim_pim.h +++ b/pimd/pim_pim.h @@ -70,6 +70,7 @@ void pim_hello_restart_triggered(struct interface *ifp); int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len); int pim_msg_send(int fd, + struct in_addr src, struct in_addr dst, uint8_t *pim_msg, int pim_msg_size, diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 4cc4a2703c..bd41f1f4f0 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -46,7 +46,7 @@ struct thread *send_test_packet_timer = NULL; void pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, - struct in_addr originator) + struct in_addr src, struct in_addr originator) { struct pim_interface *pinfo; unsigned char buffer[3000]; @@ -83,7 +83,7 @@ pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, zlog_debug ("%s: No pinfo!\n", __PRETTY_FUNCTION__); return; } - if (pim_msg_send (pinfo->pim_sock_fd, originator, + if (pim_msg_send (pinfo->pim_sock_fd, src, originator, buffer, b1length + PIM_MSG_REGISTER_STOP_LEN, ifp->name)) { @@ -145,7 +145,7 @@ pim_register_stop_recv (uint8_t *buf, int buf_size) } void -pim_register_send (const uint8_t *buf, int buf_size, struct pim_rpf *rpg, int null_register) +pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct pim_rpf *rpg, int null_register) { unsigned char buffer[3000]; unsigned char *b1; @@ -176,6 +176,7 @@ pim_register_send (const uint8_t *buf, int buf_size, struct pim_rpf *rpg, int nu pim_msg_build_header(buffer, buf_size + PIM_MSG_REGISTER_LEN, PIM_MSG_TYPE_REGISTER); if (pim_msg_send(pinfo->pim_sock_fd, + src, rpg->rpf_addr, buffer, buf_size + PIM_MSG_REGISTER_LEN, @@ -306,7 +307,7 @@ pim_register_recv (struct interface *ifp, if (pimbr.s_addr == pim_br_unknown.s_addr) pim_br_set_pmbr(&sg, src_addr); else if (src_addr.s_addr != pimbr.s_addr) { - pim_register_stop_send (ifp, &sg, src_addr); + pim_register_stop_send (ifp, &sg, dest_addr, src_addr); if (PIM_DEBUG_PIM_PACKETS) zlog_debug("%s: Sending register-Stop to %s and dropping mr. packet", __func__, "Sender"); @@ -338,7 +339,7 @@ pim_register_recv (struct interface *ifp, ((SwitchToSptDesired(&sg)) && pim_upstream_inherited_olist (upstream) == 0)) { //pim_scan_individual_oil (upstream->channel_oil); - pim_register_stop_send (ifp, &sg, src_addr); + pim_register_stop_send (ifp, &sg, dest_addr, src_addr); sentRegisterStop = 1; } @@ -359,7 +360,7 @@ pim_register_recv (struct interface *ifp, // This is taken care of by the kernel for us } } else { - pim_register_stop_send (ifp, &sg, src_addr); + pim_register_stop_send (ifp, &sg, dest_addr, src_addr); } return 1; diff --git a/pimd/pim_register.h b/pimd/pim_register.h index ce2e052104..4200c5e269 100644 --- a/pimd/pim_register.h +++ b/pimd/pim_register.h @@ -42,7 +42,7 @@ int pim_register_recv (struct interface *ifp, struct in_addr src_addr, uint8_t *tlv_buf, int tlv_buf_size); -void pim_register_send (const uint8_t *buf, int buf_size, struct pim_rpf *rpg, int null_register); -void pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, struct in_addr originator); +void pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct pim_rpf *rpg, int null_register); +void pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, struct in_addr src, struct in_addr originator); #endif diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 68c773d0c8..034878d20d 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -932,6 +932,7 @@ pim_upstream_state2str (enum pim_upstream_state join_state) static int pim_upstream_register_stop_timer (struct thread *t) { + struct pim_interface *pim_ifp; struct pim_upstream *up; struct pim_rpf *rpg; struct ip ip_hdr; @@ -956,6 +957,7 @@ pim_upstream_register_stop_timer (struct thread *t) case PIM_UPSTREAM_JOINED: break; case PIM_UPSTREAM_PRUNE: + pim_ifp = up->rpf.source_nexthop.interface->info; up->join_state = PIM_UPSTREAM_JOIN_PENDING; pim_upstream_start_register_stop_timer (up, 1); @@ -968,7 +970,8 @@ pim_upstream_register_stop_timer (struct thread *t) ip_hdr.ip_dst = up->sg.grp; ip_hdr.ip_len = htons (20); // checksum is broken - pim_register_send ((uint8_t *)&ip_hdr, sizeof (struct ip), rpg, 1); + pim_register_send ((uint8_t *)&ip_hdr, sizeof (struct ip), + pim_ifp->primary_address, rpg, 1); break; default: break; From 51e828334e98310b1763c9f9514d9684aba17f76 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 22 Aug 2016 14:59:24 -0400 Subject: [PATCH 115/386] pimd: On RP Allow no output interfaces On the RP when we receive a register packet for the same interface that we received the *,G join on allow the RP to receive the packets but to do nothing with them. Additionally check the last_used values even if the ioctl fails. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 6 +++++- pimd/pim_upstream.c | 3 +-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 65696f6d33..32d48748ab 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -364,6 +364,10 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) //No if channel, but upstream we are at the RP. pim_nexthop_lookup (&source, up->upstream_register); pim_register_stop_send(source.interface, &sg, pim_ifp->primary_address, up->upstream_register); + if (!up->channel_oil) + up->channel_oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); + if (!up->channel_oil->installed) + pim_mroute_add (up->channel_oil); //Send S bit down the join. up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; } @@ -754,6 +758,7 @@ pim_mroute_update_counters (struct channel_oil *c_oil) c_oil->cc.oldwrong_if = c_oil->cc.wrong_if; c_oil->cc.oldlastused = c_oil->cc.lastused; + pim_zlookup_sg_statistics (c_oil); if (ioctl (qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) { char group_str[100]; @@ -771,7 +776,6 @@ pim_mroute_update_counters (struct channel_oil *c_oil) return; } - pim_zlookup_sg_statistics (c_oil); c_oil->cc.pktcnt = sgreq.pktcnt; c_oil->cc.bytecnt = sgreq.bytecnt; c_oil->cc.wrong_if = sgreq.wrong_if; diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 034878d20d..e69fec0793 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1058,8 +1058,7 @@ pim_upstream_inherited_olist (struct pim_upstream *up) } } - if (output_intf) - pim_upstream_switch (up, PIM_UPSTREAM_JOINED); + pim_upstream_switch (up, PIM_UPSTREAM_JOINED); return output_intf; } From 3565202d74795b4918a8ac20f5e72658b1fdb17e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 23 Aug 2016 10:35:16 -0400 Subject: [PATCH 116/386] pimd: Move pim_mroute_connected_to_source to pim_iface.c Move the pim_mroute_conected_to_source function to pim_iface.c because this is a interface question not a mroute question. Signed-off-by: Donald Sharp --- pimd/pim_iface.c | 23 +++++++++++++++++++++++ pimd/pim_iface.h | 2 ++ pimd/pim_mroute.c | 27 ++------------------------- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index fae11b674a..dab2e0e1e7 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -1249,3 +1249,26 @@ void pim_if_create_pimreg (void) pim_if_new(pim_regiface, 0, 0); } } + +int +pim_if_connected_to_source (struct interface *ifp, struct in_addr src) +{ + struct listnode *cnode; + struct connected *c; + struct prefix p; + + p.family = AF_INET; + p.u.prefix4 = src; + p.prefixlen = IPV4_MAX_BITLEN; + + for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) + { + if ((c->address->family == AF_INET) && + prefix_match (CONNECTED_PREFIX (c), &p)) + { + return 1; + } + } + + return 0; +} diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index 75b85c306a..0be4918d72 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -167,4 +167,6 @@ void pim_if_update_join_desired(struct pim_interface *pim_ifp); void pim_if_update_assert_tracking_desired(struct interface *ifp); void pim_if_create_pimreg(void); + +int pim_if_connected_to_source (struct interface *ifp, struct in_addr src); #endif /* PIM_IFACE_H */ diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 32d48748ab..3fb69bc86a 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -75,29 +75,6 @@ static int pim_mroute_set(int fd, int enable) return 0; } -static int -pim_mroute_connected_to_source (struct interface *ifp, struct in_addr src) -{ - struct listnode *cnode; - struct connected *c; - struct prefix p; - - p.family = AF_INET; - p.u.prefix4 = src; - p.prefixlen = IPV4_MAX_BITLEN; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) - { - if ((c->address->family == AF_INET) && - prefix_match (CONNECTED_PREFIX (c), &p)) - { - return 1; - } - } - - return 0; -} - static const char *igmpmsgtype2str[IGMPMSG_WRVIFWHOLE + 1] = { "", "NOCACHE", @@ -129,7 +106,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg * If we've received a multicast packet that isn't connected to * us */ - if (!pim_mroute_connected_to_source (ifp, msg->im_src)) + if (!pim_if_connected_to_source (ifp, msg->im_src)) { if (PIM_DEBUG_MROUTE_DETAIL) zlog_debug ("%s: Received incoming packet that doesn't originate on our seg", @@ -384,7 +361,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) return -2; } - if (pim_mroute_connected_to_source (ifp, sg.src)) + if (pim_if_connected_to_source (ifp, sg.src)) up->fhr = 1; pim_ifp = ifp->info; From 4e85d20983cddd6655a263bb5b074df04d65fa32 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 23 Aug 2016 12:25:55 -0400 Subject: [PATCH 117/386] pimd: Fix crash on RP. When register stop was received but the upstream creation fails we are not handling it properly. Note and return. Signed-off-by: Donald Sharp --- pimd/pim_register.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index bd41f1f4f0..46601c0dcb 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -323,7 +323,11 @@ pim_register_recv (struct interface *ifp, if (!upstream) { upstream = pim_upstream_add (&sg, ifp); - + if (!upstream) + { + zlog_warn ("Failure to crate upstream state"); + return 1; + } upstream->upstream_register = src_addr; pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.src, sg.grp); pim_nexthop_lookup (&upstream->rpf.source_nexthop, From bb6e291f3bab84ae623d6c4c05de2bc7eba837c9 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 23 Aug 2016 17:39:48 +0000 Subject: [PATCH 118/386] pimd: Fix bad state no FHR after quagga restart If on the FHR we have an established stream between interested parties and we stop the stream and restart quagga we were not coming back up into the correct state. For the multicast stream. Ticket: CM-12462 Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index e69fec0793..03ca3b6edc 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -186,12 +186,6 @@ pim_upstream_send_join (struct pim_upstream *up) } } - /* - * In the case of a FHR we will not have anyone to send this to. - */ - if (up->fhr) - return; - /* send Join(S,G) to the current upstream neighbor */ pim_joinprune_send(up->rpf.source_nexthop.interface, up->rpf.rpf_addr, @@ -207,9 +201,16 @@ static int on_join_timer(struct thread *t) up = THREAD_ARG(t); zassert(up); + up->t_join_timer = NULL; + + /* + * In the case of a HFR we will not ahve anyone to send this to. + */ + if (up->fhr) + return 0; + pim_upstream_send_join (up); - up->t_join_timer = NULL; join_timer_start(up); return 0; @@ -373,6 +374,18 @@ static void forward_off(struct pim_upstream *up) } /* scan iflist */ } +static int +pim_upstream_could_register (struct pim_upstream *up) +{ + struct pim_interface *pim_ifp = up->rpf.source_nexthop.interface->info; + + if (PIM_I_am_DR (pim_ifp) && + pim_if_connected_to_source (up->rpf.source_nexthop.interface, up->sg.src)) + return 1; + + return 0; +} + void pim_upstream_switch(struct pim_upstream *up, enum pim_upstream_state new_state) @@ -414,9 +427,22 @@ pim_upstream_switch(struct pim_upstream *up, if (new_state == PIM_UPSTREAM_JOINED) { if (old_state != PIM_UPSTREAM_JOINED) { + int old_fhr = up->fhr; forward_on(up); - pim_upstream_send_join (up); - join_timer_start(up); + up->fhr = pim_upstream_could_register (up); + if (up->fhr) + { + if (!old_fhr) + { + pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); + pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); + } + } + else + { + pim_upstream_send_join (up); + join_timer_start (up); + } } else { From 00d07c6fda1ef744eb2e7481beeb85aa31bf61d6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 23 Aug 2016 16:22:14 -0400 Subject: [PATCH 119/386] pimd: Add "show ip pim rp-info" command List the RP information we have configured. Fix bug where we were not properly initializing some code Ticket: CM-12617 Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 14 ++++++++++++++ pimd/pim_rp.c | 42 ++++++++++++++++++++++++++++++++++++++++++ pimd/pim_rp.h | 2 ++ pimd/pim_zebra.c | 2 ++ 4 files changed, 60 insertions(+) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index bd3a85abb0..bbc1de3443 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2004,6 +2004,19 @@ DEFUN (show_ip_pim_upstream_rpf, return CMD_SUCCESS; } +DEFUN (show_ip_pim_rp, + show_ip_pim_rp_cmd, + "show ip pim rp-info ", + SHOW_STR + IP_STR + PIM_STR + "PIM RP information\n") +{ + pim_rp_show_information (vty); + + return CMD_SUCCESS; +} + DEFUN (show_ip_pim_rpf, show_ip_pim_rpf_cmd, "show ip pim rpf", @@ -4863,6 +4876,7 @@ void pim_cmd_init() install_element (VIEW_NODE, &show_ip_pim_upstream_cmd); install_element (VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd); install_element (VIEW_NODE, &show_ip_pim_upstream_rpf_cmd); + install_element (VIEW_NODE, &show_ip_pim_rp_cmd); install_element (VIEW_NODE, &show_ip_multicast_cmd); install_element (VIEW_NODE, &show_ip_mroute_cmd); install_element (VIEW_NODE, &show_ip_mroute_count_cmd); diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 84de870764..7a356a7689 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -26,6 +26,8 @@ #include "linklist.h" #include "prefix.h" #include "memory.h" +#include "vty.h" +#include "vrf.h" #include "pimd.h" #include "pim_vty.h" @@ -35,6 +37,7 @@ #include "pim_rpf.h" #include "pim_sock.h" #include "pim_memory.h" +#include "pim_iface.h" struct rp_info { @@ -148,6 +151,24 @@ pim_rp_find_match_group (struct prefix *group) return NULL; } +static void +pim_rp_check_interfaces (struct rp_info *rp_info) +{ + struct listnode *node; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) + { + struct pim_interface *pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->primary_address.s_addr == rp_info->rp.rpf_addr.s_addr) + rp_info->i_am_rp = 1; + } +} + int pim_rp_new (const char *rp, const char *group_range) { @@ -185,6 +206,7 @@ pim_rp_new (const char *rp, const char *group_range) XFREE (MTYPE_PIM_RP, rp_info); if (!pim_rp_setup ()) return -2; + pim_rp_check_interfaces (rp_all); return 0; } @@ -210,6 +232,7 @@ pim_rp_new (const char *rp, const char *group_range) if (!pim_rp_setup ()) return -2; + pim_rp_check_interfaces (rp_info); return 0; } @@ -453,3 +476,22 @@ pim_rp_check_is_my_ip_address (struct in_addr group, struct in_addr dest_addr) return 0; } + +void +pim_rp_show_information (struct vty *vty) +{ + struct rp_info *rp_info; + struct listnode *node; + + vty_out (vty, "RP Addr Group Oif I_am_RP%s", VTY_NEWLINE); + for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) + { + char buf[48]; + vty_out (vty, "%-10s %-10s %-10s%-10d%s", + inet_ntoa (rp_info->rp.rpf_addr), + prefix2str(&rp_info->group, buf, 48), + rp_info->rp.source_nexthop.interface->name, + rp_info->i_am_rp, VTY_NEWLINE); + } + return; +} diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index be50bbb18b..c9dfa201f1 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -42,4 +42,6 @@ struct pim_rpf *pim_rp_g (struct in_addr group); #define I_am_RP(G) pim_rp_i_am_rp ((G)) #define RP(G) pim_rp_g ((G)) + +void pim_rp_show_information (struct vty *vty); #endif diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index b171fbb702..aa1121c8a2 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -506,6 +506,7 @@ static int on_rpf_cache_refresh(struct thread *t) qpim_rpf_cache_refresh_last = pim_time_monotonic_sec(); ++qpim_rpf_cache_refresh_events; + pim_rp_setup (); return 0; } @@ -659,6 +660,7 @@ static int redist_read_ipv4_route(int command, struct zclient *zclient, sched_rpf_cache_refresh(); + pim_rp_setup (); return 0; } From 6abb1fc25fc21382c511b93d0736d1e9425940db Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 24 Aug 2016 08:20:38 -0400 Subject: [PATCH 120/386] pimd: Fix double close of socket. When a interface bounces fix the double close from happening Signed-off-by: Donald Sharp --- pimd/pim_pim.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index f58e326d16..4924acea74 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -90,7 +90,10 @@ static void sock_close(struct interface *ifp) pim_ifp->pim_sock_fd, ifp->name); } - if (close(pim_ifp->pim_sock_fd)) { + /* + * If the fd is already deleted no need to do anything here + */ + if (pim_ifp->pim_sock_fd > 0 && close(pim_ifp->pim_sock_fd)) { zlog_warn("Failure closing PIM socket fd=%d on interface %s: errno=%d: %s", pim_ifp->pim_sock_fd, ifp->name, errno, safe_strerror(errno)); @@ -98,11 +101,6 @@ static void sock_close(struct interface *ifp) pim_ifp->pim_sock_fd = -1; pim_ifp->pim_sock_creation = 0; - - zassert(pim_ifp->pim_sock_fd < 0); - zassert(!pim_ifp->t_pim_sock_read); - zassert(!pim_ifp->t_pim_hello_timer); - zassert(!pim_ifp->pim_sock_creation); } void pim_sock_delete(struct interface *ifp, const char *delete_message) From 359175704f9f4b1c2e4eae435a193db39c6db0c2 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 24 Aug 2016 08:29:24 -0400 Subject: [PATCH 121/386] pimd: Fix crash with interface not configed under pim. When the RP's address in PIM is not under the loopback, we can have a situation where this causes PIM to crash. Check for NULL pointers. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 03ca3b6edc..ffb026603e 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -379,7 +379,7 @@ pim_upstream_could_register (struct pim_upstream *up) { struct pim_interface *pim_ifp = up->rpf.source_nexthop.interface->info; - if (PIM_I_am_DR (pim_ifp) && + if (pim_ifp && PIM_I_am_DR (pim_ifp) && pim_if_connected_to_source (up->rpf.source_nexthop.interface, up->sg.src)) return 1; From eb345962ceeb4c7eb30e7a54faf3d1c1449dd69f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 24 Aug 2016 09:26:54 -0400 Subject: [PATCH 122/386] pimd: Do not send join out loopback interfaces When we the join timer pops for a interface don't send the join out a loopback interface. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index ffb026603e..5c142a1674 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -209,7 +209,12 @@ static int on_join_timer(struct thread *t) if (up->fhr) return 0; - pim_upstream_send_join (up); + /* + * Don't send the join if the outgoing interface is a loopback + * But since this might change leave the join timer running + */ + if (!if_is_loopback (up->rpf.source_nexthop.interface)) + pim_upstream_send_join (up); join_timer_start(up); From 8d63c2d932fa938711fcf9c80be3a3e5d7e2224d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 24 Aug 2016 09:30:25 -0400 Subject: [PATCH 123/386] pimd: Fix unwrappered debug message When checking with zebra about lastused we were not protecting a debug message. Signed-off-by: Donald Sharp --- pimd/pim_zlookup.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 6cf6a6b2f7..5c17c50609 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -520,7 +520,8 @@ pim_zlookup_sg_statistics (struct channel_oil *c_oil) stream_get (&lastused, s, sizeof (lastused)); - zlog_debug ("Received %lld for %s", lastused, pim_str_sg_dump (&sg)); + if (PIM_DEBUG_ZEBRA) + zlog_debug ("Received %lld for %s", lastused, pim_str_sg_dump (&sg)); c_oil->cc.lastused = lastused; From c8507a162475df2494125cb9a38aaf70cb96eb3b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 24 Aug 2016 10:25:11 -0400 Subject: [PATCH 124/386] pimd: Turn on forwarding for a late added interface. If we receive a join for a upstream interface that hasn't yet been added to pim for working under it, we never go back and add the forwarding on when we get the interface added to pim. Ticket: CM-11800 Signed-off-by: Donald Sharp --- pimd/pim_iface.c | 1 + pimd/pim_ifchannel.c | 39 +++++++++++++++++++++++++++++++++++++++ pimd/pim_ifchannel.h | 1 + 3 files changed, 41 insertions(+) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index dab2e0e1e7..867f59679a 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -407,6 +407,7 @@ void pim_if_addr_add(struct connected *ifc) if (pim_ifp->mroute_vif_index < 0) { pim_if_add_vif(ifp); } + pim_ifchannel_scan_forward_start (ifp); } } diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 85bd178d9b..e2b145a5b2 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -25,6 +25,7 @@ #include "thread.h" #include "memory.h" #include "if.h" +#include "vrf.h" #include "pimd.h" #include "pim_str.h" @@ -980,3 +981,41 @@ void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch) } } } + +/* + * If we have a new pim interface, check to + * see if any of the pre-existing channels have + * their upstream out that way and turn on forwarding + * for that ifchannel then. + */ +void +pim_ifchannel_scan_forward_start (struct interface *new_ifp) +{ + struct listnode *ifnode; + struct interface *ifp; + struct pim_interface *new_pim_ifp = new_ifp->info; + + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) + { + struct pim_interface *loop_pim_ifp = ifp->info; + struct listnode *ch_node; + struct pim_ifchannel *ch; + + if (!loop_pim_ifp) + continue; + + if (new_pim_ifp == loop_pim_ifp) + continue; + + for (ALL_LIST_ELEMENTS_RO (loop_pim_ifp->pim_ifchannel_list, ch_node, ch)) + { + if (ch->ifjoin_state == PIM_IFJOIN_JOIN) + { + struct pim_upstream *up = ch->upstream; + if ((!up->channel_oil) && + (up->rpf.source_nexthop.interface == new_ifp)) + pim_forward_start (ch); + } + } + } +} diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 7036131e56..0c39210642 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -136,4 +136,5 @@ void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch); void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch); void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch); +void pim_ifchannel_scan_forward_start (struct interface *new_ifp); #endif /* PIM_IFCHANNEL_H */ From 75395e6a326881b564916961e2771ad404f23a1d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 24 Aug 2016 11:23:41 -0400 Subject: [PATCH 125/386] pimd: Fix crash in channel_oil_add_oif Remove assert, warn user that there is a problem and move on. Ticket: CM-12614 Signed-off-by: Donald Sharp --- pimd/pim_oil.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index d3895ea286..e09dc3f089 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -212,7 +212,15 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, struct pim_interface *pim_ifp; int old_ttl; - zassert(channel_oil); + /* + * If we've gotten here we've gone bad, but let's + * not take down pim + */ + if (!channel_oil) + { + zlog_warn ("Attempt to Add OIF for non-existent channel oil"); + return -1; + } pim_ifp = oif->info; From dce1a92f31e22cea63ca7ca362fdfcfcd213befb Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 24 Aug 2016 15:32:57 -0400 Subject: [PATCH 126/386] pimd: Do not display placeholder for 'show ip pim rp-info' do not display the 224.0.0.0/4 rp information if none-have been provided. Signed-off-by: Donald Sharp --- pimd/pim_rp.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 7a356a7689..81c4a65abe 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -486,12 +486,15 @@ pim_rp_show_information (struct vty *vty) vty_out (vty, "RP Addr Group Oif I_am_RP%s", VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { - char buf[48]; - vty_out (vty, "%-10s %-10s %-10s%-10d%s", - inet_ntoa (rp_info->rp.rpf_addr), - prefix2str(&rp_info->group, buf, 48), - rp_info->rp.source_nexthop.interface->name, - rp_info->i_am_rp, VTY_NEWLINE); + if (rp_info->rp.rpf_addr.s_addr != INADDR_NONE) + { + char buf[48]; + vty_out (vty, "%-10s %-10s %-10s%-10d%s", + inet_ntoa (rp_info->rp.rpf_addr), + prefix2str(&rp_info->group, buf, 48), + rp_info->rp.source_nexthop.interface->name, + rp_info->i_am_rp, VTY_NEWLINE); + } } return; } From 3f07087b695d48f1985f2f7387315616dcf14436 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 24 Aug 2016 15:35:09 -0400 Subject: [PATCH 127/386] pimd: Do not crash when attempting to install a mroute. When installing a mroute on rpf change make sure that we have oil for it at this time. Ticket: CM-12636 Signed-off-by: Donald Sharp --- pimd/pim_zebra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index aa1121c8a2..8a466e4035 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -347,7 +347,7 @@ static void scan_upstream_rpf_cache() * where the mroute has not been installed * so install it. */ - if (!up->channel_oil->installed) + if (up->channel_oil && !up->channel_oil->installed) pim_mroute_add (up->channel_oil); /* From da55afba150315e38aabe15a1f1340fa121db072 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 24 Aug 2016 16:09:28 -0400 Subject: [PATCH 128/386] pimd: Another null pointer dereference When starting up with a large # of streams it is possible to have a timing where we do not yet have a pim_ifp. Ticket: CM-12636 Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 5c142a1674..0f86e8bdfd 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1070,7 +1070,7 @@ pim_upstream_inherited_olist (struct pim_upstream *up) int output_intf = 0; pim_ifp = up->rpf.source_nexthop.interface->info; - if (!up->channel_oil) + if (pim_ifp && !up->channel_oil) up->channel_oil = pim_channel_oil_add (&up->sg, pim_ifp->mroute_vif_index); for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) From 60dbe1a15adaa84f91a346e1e1832404dbe62ccc Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 25 Aug 2016 09:40:48 -0400 Subject: [PATCH 129/386] pimd: Remove unprotected debug log Upon receiving *,G joins from downstream we were outputing a unprotected debug. Signed-off-by: Donald Sharp --- pimd/pim_join.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pimd/pim_join.c b/pimd/pim_join.c index c7d54d3c04..0992457420 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -113,9 +113,10 @@ static void recv_join(struct interface *ifp, char buff[100]; strcpy (buff, pim_str_sg_dump (&up->sg)); - zlog_debug("%s %s: Join(S,G)=%s from %s", - __FILE__, __PRETTY_FUNCTION__, - buff, pim_str_sg_dump (&sg)); + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s %s: Join(S,G)=%s from %s", + __FILE__, __PRETTY_FUNCTION__, + buff, pim_str_sg_dump (&sg)); if (pim_upstream_evaluate_join_desired (child)) { From 284b4301e4e7d50e06f79d9a4d87c76c1b1a30d9 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 26 Aug 2016 12:38:18 +0000 Subject: [PATCH 130/386] pimd: Track the # of times we ask for nexthp information Keep an idea of how many times we are asking zebra for nexthop information. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 6 ++++-- pimd/pim_zlookup.c | 2 ++ pimd/pimd.c | 1 + pimd/pimd.h | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index bbc1de3443..a717188d1c 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1102,12 +1102,14 @@ static void show_rpf_refresh_stats(struct vty *vty, time_t now) "RPF Cache Refresh Timer: %ld msecs%s" "RPF Cache Refresh Requests: %lld%s" "RPF Cache Refresh Events: %lld%s" - "RPF Cache Refresh Last: %s%s", + "RPF Cache Refresh Last: %s%s" + "Nexthop Lookups: %lld%s", qpim_rpf_cache_refresh_delay_msec, VTY_NEWLINE, pim_time_timer_remain_msec(qpim_rpf_cache_refresher), VTY_NEWLINE, (long long)qpim_rpf_cache_refresh_requests, VTY_NEWLINE, (long long)qpim_rpf_cache_refresh_events, VTY_NEWLINE, - refresh_uptime, VTY_NEWLINE); + refresh_uptime, VTY_NEWLINE, + (long long) qpim_nexthop_lookups, VTY_NEWLINE); } static void show_scan_oil_stats(struct vty *vty, time_t now) diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 5c17c50609..aed2a8a2c9 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -358,6 +358,8 @@ zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], uint32_t route_metric = 0xFFFFFFFF; uint8_t protocol_distance = 0xFF; + qpim_nexthop_lookups++; + for (lookup = 0; lookup < max_lookup; ++lookup) { int num_ifindex; int first_ifindex; diff --git a/pimd/pimd.c b/pimd/pimd.c index c00baa3596..3d1648c270 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -71,6 +71,7 @@ int64_t qpim_mroute_del_last = 0; struct list *qpim_static_route_list = NULL; unsigned int qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; signed int qpim_rp_keep_alive_time = 0; +int64_t qpim_nexthop_lookups = 0; int32_t qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; int32_t qpim_register_probe_time = PIM_REGISTER_PROBE_TIME_DEFAULT; diff --git a/pimd/pimd.h b/pimd/pimd.h index 268b5ca60f..cbc95c2eee 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -103,6 +103,7 @@ int64_t qpim_mroute_add_events; int64_t qpim_mroute_add_last; int64_t qpim_mroute_del_events; int64_t qpim_mroute_del_last; +int64_t qpim_nexthop_lookups; struct list *qpim_static_route_list; /* list of routes added statically */ extern unsigned int qpim_keep_alive_time; extern signed int qpim_rp_keep_alive_time; From 483eef9dd2ff45524bfd0fe8eba1b8ba1fad58a4 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 26 Aug 2016 09:40:08 -0400 Subject: [PATCH 131/386] pimd: Further refinement of switch on a stick The original modification to allow the RP to receive packets on the incoming interface when it has no outgoing interfaces was a bit aggressive and turned all register events into a join event. This further divides up the code to do the right thing in each situation. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 0f86e8bdfd..84b64fd709 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1089,7 +1089,16 @@ pim_upstream_inherited_olist (struct pim_upstream *up) } } - pim_upstream_switch (up, PIM_UPSTREAM_JOINED); + /* + * If we have output_intf switch state to Join and work like normal + * If we don't have an output_intf that means we are probably a + * switch on a stick so turn on forwarding to just accept the + * incoming packets so we don't bother the other stuff! + */ + if (output_intf) + pim_upstream_switch (up, PIM_UPSTREAM_JOINED); + else + forward_on (up); return output_intf; } From ff67a92351fb493b98beee2cfc35c811c0aa9af3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 26 Aug 2016 14:09:41 -0400 Subject: [PATCH 132/386] pimd: Fix debugs to be more logical The rpf debugs really should be zebra debugs instead of trace debugs. Additionally fix a return 0; to return NULL; Signed-off-by: Donald Sharp --- pimd/pim_iface.c | 2 +- pimd/pim_rpf.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 867f59679a..503be0d0bc 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -908,7 +908,7 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp, addr_str, ifp->name); } - return 0; + return NULL; } long pim_if_t_suppressed_msec(struct interface *ifp) diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index e81e262cd6..da5f16240a 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -88,7 +88,7 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr) /* debug warning only, do not return */ } - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_ZEBRA) { char nexthop_str[100]; char addr_str[100]; pim_inet4_dump("", nexthop_tab[0].nexthop_addr, nexthop_str, sizeof(nexthop_str)); @@ -136,7 +136,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_ } rpf->rpf_addr = pim_rpf_find_rpf_addr(up); - if (PIM_INADDR_IS_ANY(rpf->rpf_addr) && PIM_DEBUG_PIM_EVENTS) { + if (PIM_INADDR_IS_ANY(rpf->rpf_addr) && PIM_DEBUG_ZEBRA) { /* RPF'(S,G) not found */ zlog_debug("%s %s: RPF'%s not found: won't send join upstream", __FILE__, __PRETTY_FUNCTION__, @@ -147,7 +147,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_ /* detect change in pim_nexthop */ if (nexthop_mismatch(&rpf->source_nexthop, &save_nexthop)) { - if (PIM_DEBUG_PIM_EVENTS) { + if (PIM_DEBUG_ZEBRA) { char nhaddr_str[100]; pim_inet4_dump("", rpf->source_nexthop.mrib_nexthop_addr, nhaddr_str, sizeof(nhaddr_str)); zlog_debug("%s %s: (S,G)=%s source nexthop now is: interface=%s address=%s pref=%d metric=%d", @@ -167,7 +167,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_ /* detect change in RPF_interface(S) */ if (save_nexthop.interface != rpf->source_nexthop.interface) { - if (PIM_DEBUG_PIM_EVENTS) { + if (PIM_DEBUG_ZEBRA) { zlog_debug("%s %s: (S,G)=%s RPF_interface(S) changed from %s to %s", __FILE__, __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg), From d3dd1804063b2c2125d6463a1b0ec734af44dd68 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 29 Aug 2016 10:49:47 -0400 Subject: [PATCH 133/386] pimd: trigger on nbr up to look at rpf cache If a neighbor comes up *after* igmp joins and *after* all the routes are installed into the kernel, then we never go back and fix up the rpf cache information. So joins never go out for those igmp joins. Ticket: CM-12613 Signed-off-by: Donald Sharp --- pimd/pim_neighbor.c | 2 ++ pimd/pim_upstream.c | 30 +++++++++++++++++++++++++++++- pimd/pim_upstream.h | 3 +++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index 4d79388092..61e19d8005 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -462,6 +462,8 @@ struct pim_neighbor *pim_neighbor_add(struct interface *ifp, else pim_hello_restart_triggered(neigh->interface); + pim_upstream_find_new_rpf(); + return neigh; } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 84b64fd709..9a11eefd60 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -506,7 +506,7 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, up->rpf.source_nexthop.mrib_route_metric = qpim_infinite_assert_metric.route_metric; up->rpf.rpf_addr.s_addr = PIM_NET_INADDR_ANY; - rpf_result = pim_rpf_update(up, 0); + rpf_result = pim_rpf_update(up, NULL); if (rpf_result == PIM_RPF_FAILURE) { XFREE(MTYPE_PIM_UPSTREAM, up); return NULL; @@ -1102,3 +1102,31 @@ pim_upstream_inherited_olist (struct pim_upstream *up) return output_intf; } + +/* + * When we have a new neighbor, + * find upstreams that don't have their rpf_addr + * set and see if the new neighbor allows + * the join to be sent + */ +void +pim_upstream_find_new_rpf (void) +{ + struct listnode *up_node; + struct listnode *up_nextnode; + struct pim_upstream *up; + + /* + Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr + */ + for (ALL_LIST_ELEMENTS(qpim_upstream_list, up_node, up_nextnode, up)) + { + if (PIM_INADDR_IS_ANY(up->rpf.rpf_addr)) + { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug ("Upstream %s without a path to send join, checking", + pim_str_sg_dump (&up->sg)); + pim_rpf_update (up, NULL); + } + } +} diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 03dcd6bfd2..95492b27c1 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -160,4 +160,7 @@ void pim_upstream_switch (struct pim_upstream *up, enum pim_upstream_state new_s const char *pim_upstream_state2str (enum pim_upstream_state join_state); int pim_upstream_inherited_olist (struct pim_upstream *up); + +void pim_upstream_find_new_rpf (void); + #endif /* PIM_UPSTREAM_H */ From e8e277d564f26b230e1cd8b2619eab149ecd433f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 1 Sep 2016 08:33:02 -0400 Subject: [PATCH 134/386] pimd: Allow larger range for KAT(S,G) Allow the KAT(S,G) time be set to up to 60000 seconds. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index a717188d1c..ae9a3fd19e 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2467,7 +2467,7 @@ pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group) DEFUN (ip_pim_keep_alive, ip_pim_keep_alive_cmd, - "ip pim keep-alive-timer <31-600>", + "ip pim keep-alive-timer <31-60000>", IP_STR "pim multicast routing\n" "Keep alive Timer" @@ -2479,7 +2479,7 @@ DEFUN (ip_pim_keep_alive, DEFUN (no_ip_pim_keep_alive, no_ip_pim_keep_alive_cmd, - "no ip pim keep-alive-timer <31-600>", + "no ip pim keep-alive-timer <31-60000>", NO_STR IP_STR "pim multicast routing\n" @@ -2492,7 +2492,7 @@ DEFUN (no_ip_pim_keep_alive, DEFUN (ip_pim_rp_keep_alive, ip_pim_rp_keep_alive_cmd, - "ip pim rp keep-alive-timer <31-600>", + "ip pim rp keep-alive-timer <31-60000>", IP_STR "pim multicast routing\n" "Rendevous Point\n" @@ -2505,7 +2505,7 @@ DEFUN (ip_pim_rp_keep_alive, DEFUN (no_ip_pim_rp_keep_alive, no_ip_pim_rp_keep_alive_cmd, - "no ip pim rp keep-alive-timer <31-600>", + "no ip pim rp keep-alive-timer <31-60000>", NO_STR IP_STR "pim multicast routing\n" From 5f6f65b14c79cc7ab3d80cd48a03910001e0f90f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 31 Aug 2016 10:50:20 -0400 Subject: [PATCH 135/386] pimd: Fix creation of channel oil to happen 1st. This has 2 fixes: On nocache event, crate the channel oil first in case we don't need to actually create the upstream information on wrvifwhole, create the channel oil and install it, then only create the upstream information if we are connected to the source. Ticket: CM-12593 Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 69 ++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 3fb69bc86a..14221d3303 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -89,6 +89,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg struct pim_upstream *up; struct pim_rpf *rpg; struct prefix_sg sg; + struct channel_oil *oil; rpg = RP(msg->im_dst); /* @@ -123,6 +124,16 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); } + oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); + if (!oil) { + if (PIM_DEBUG_MROUTE) { + zlog_debug("%s: Failure to add channel oil for %s", + __PRETTY_FUNCTION__, + pim_str_sg_dump (&sg)); + } + return 0; + } + up = pim_upstream_add (&sg, ifp); if (!up) { if (PIM_DEBUG_MROUTE) { @@ -135,16 +146,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - up->channel_oil = pim_channel_oil_add(&sg, - pim_ifp->mroute_vif_index); - if (!up->channel_oil) { - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: Failure to add channel oil for %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg)); - } - return 0; - } + up->channel_oil = oil; up->channel_oil->cc.pktcnt++; up->fhr = 1; pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); @@ -304,6 +306,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) struct pim_ifchannel *ch; struct pim_upstream *up; struct prefix_sg sg; + struct channel_oil *oil; memset (&sg, 0, sizeof (struct prefix_sg)); sg.src = ip_hdr->ip_src; @@ -351,29 +354,33 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) return 0; } - up = pim_upstream_add (&sg, ifp); - - if (!up) - { - if (PIM_DEBUG_MROUTE) - zlog_debug ("%s: WRONGVIF%s unable to create upstream on interface", - pim_str_sg_dump (&sg), ifp->name); - return -2; - } - - if (pim_if_connected_to_source (ifp, sg.src)) - up->fhr = 1; - pim_ifp = ifp->info; - pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - up->channel_oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); - up->channel_oil->cc.pktcnt++; - pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); - up->join_state = PIM_UPSTREAM_JOINED; - pim_upstream_inherited_olist (up); + oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); + if (!oil->installed) + pim_mroute_add (oil); + if (pim_if_connected_to_source (ifp, sg.src)) + { + up = pim_upstream_add (&sg, ifp); - // Send the packet to the RP - pim_mroute_msg_wholepkt (fd, ifp, buf); + if (!up) + { + if (PIM_DEBUG_MROUTE) + zlog_debug ("%s: WRONGVIF%s unable to create upstream on interface", + pim_str_sg_dump (&sg), ifp->name); + return -2; + } + up->fhr = 1; + + pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); + up->channel_oil = oil; + up->channel_oil->cc.pktcnt++; + pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); + up->join_state = PIM_UPSTREAM_JOINED; + pim_upstream_inherited_olist (up); + + // Send the packet to the RP + pim_mroute_msg_wholepkt (fd, ifp, buf); + } return 0; } From 21391ed8d887a4c5967e73f50018b9433e717a83 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 1 Sep 2016 18:49:53 -0400 Subject: [PATCH 136/386] pimd: Allow interfaces to be unnumbered. Specify the ifindex of the interface that we want to turn on IP_MULTICAST_IF on instead of the address. If we pass in the address then the fact that we have multiple interfaces with the same ip address causes confusion in the kernel. Signed-off-by: Donald Sharp --- pimd/pim_sock.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index 8f8f4f191f..4312fe73b2 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -113,6 +113,7 @@ pim_socket_bind (int fd, struct interface *ifp) int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, u_char loop) { + struct ip_mreqn mreq; int fd; fd = pim_socket_raw(protocol); @@ -214,8 +215,10 @@ int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, u_char lo return PIM_SOCK_ERR_LOOP; } + memset (&mreq, 0, sizeof (mreq)); + mreq.imr_ifindex = ifindex; if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (void *) &ifaddr, sizeof(ifaddr))) { + (void *) &mreq, sizeof(mreq))) { zlog_warn("Could not set Outgoing Interface Option on socket fd=%d: errno=%d: %s", fd, errno, safe_strerror(errno)); close(fd); From 84a35fdf064bc0881e23354f10e605433e6e65da Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 2 Sep 2016 10:43:26 -0400 Subject: [PATCH 137/386] pimd: Fix duplicate code in zlookup In the nexthop lookup routine, fix the duplicate code to not check for too many indexes earlier. Signed-off-by: Donald Sharp --- pimd/pim_zlookup.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index aed2a8a2c9..7234790fab 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -230,18 +230,17 @@ static int zclient_read_nexthop(struct zclient *zlookup, nexthop_type = stream_getc(s); --length; - + if (num_ifindex >= tab_size) { + char addr_str[100]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_warn("%s %s: found too many nexthop ifindexes (%d > %d) for address %s", + __FILE__, __PRETTY_FUNCTION__, + (num_ifindex + 1), tab_size, addr_str); + return num_ifindex; + } switch (nexthop_type) { case NEXTHOP_TYPE_IFINDEX: case NEXTHOP_TYPE_IPV4_IFINDEX: - if (num_ifindex >= tab_size) { - char addr_str[100]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s %s: found too many nexthop ifindexes (%d > %d) for address %s", - __FILE__, __PRETTY_FUNCTION__, - (num_ifindex + 1), tab_size, addr_str); - return num_ifindex; - } if (nexthop_type == NEXTHOP_TYPE_IPV4_IFINDEX) { if (length < 4) { zlog_err("%s: socket %d short input expecting nexthop IPv4-addr: len=%d", @@ -260,14 +259,6 @@ static int zclient_read_nexthop(struct zclient *zlookup, ++num_ifindex; break; case NEXTHOP_TYPE_IPV4: - if (num_ifindex >= tab_size) { - char addr_str[100]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s %s: found too many nexthop ifindexes (%d > %d) for address %s", - __FILE__, __PRETTY_FUNCTION__, - (num_ifindex + 1), tab_size, addr_str); - return num_ifindex; - } nexthop_tab[num_ifindex].nexthop_addr.s_addr = stream_get_ipv4(s); length -= 4; nexthop_tab[num_ifindex].ifindex = 0; From e66dd14ae46f1dd3929bb6e8d3b436b3ac6fabce Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 2 Sep 2016 10:50:50 -0400 Subject: [PATCH 138/386] pimd: Add pim_addr_dump to facilitate v4 and v6 address dumping Allow pim_addr_dump to understand prefixes to print out. Signed-off-by: Donald Sharp --- pimd/pim_str.c | 14 ++++++++++++++ pimd/pim_str.h | 1 + 2 files changed, 15 insertions(+) diff --git a/pimd/pim_str.c b/pimd/pim_str.c index 8e1d7cec29..ca635c8a54 100644 --- a/pimd/pim_str.c +++ b/pimd/pim_str.c @@ -29,6 +29,20 @@ #include "pim_str.h" +void pim_addr_dump (const char *onfail, struct prefix *p, char *buf, int buf_size) +{ + int save_errno = errno; + + if (!inet_ntop(p->family, &p->u.prefix, buf, buf_size)) { + zlog_warn("pim_addr_dump: inet_ntop(buf_size=%d): errno=%d: %s", + buf_size, errno, safe_strerror(errno)); + if (onfail) + snprintf(buf, buf_size, "%s", onfail); + } + + errno = save_errno; +} + void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, int buf_size) { int save_errno = errno; diff --git a/pimd/pim_str.h b/pimd/pim_str.h index 3dff9fa1e9..15f5227de8 100644 --- a/pimd/pim_str.h +++ b/pimd/pim_str.h @@ -28,6 +28,7 @@ #include +void pim_addr_dump (const char *onfail, struct prefix *p, char *buf, int buf_size); void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, int buf_size); char *pim_str_sg_dump (const struct prefix_sg *sg); From ba634917bde686ae908f8b59b407d23d4c88c99f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 2 Sep 2016 10:56:29 -0400 Subject: [PATCH 139/386] pimd: Switch 'struct in_addr' to 'struct prefix' in pim_zlookup.h This is setup code to allow us to receive v6 addresses from a nexthop lookup from zebra. This will allow us to work with unnumbered interfaces. Signed-off-by: Donald Sharp --- pimd/pim_rpf.c | 4 ++-- pimd/pim_zlookup.c | 18 ++++++++++-------- pimd/pim_zlookup.h | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index da5f16240a..928629b0cf 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -91,7 +91,7 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr) if (PIM_DEBUG_ZEBRA) { char nexthop_str[100]; char addr_str[100]; - pim_inet4_dump("", nexthop_tab[0].nexthop_addr, nexthop_str, sizeof(nexthop_str)); + pim_addr_dump("", &nexthop_tab[0].nexthop_addr, nexthop_str, sizeof(nexthop_str)); pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_debug("%s %s: found nexthop %s for address %s: interface %s ifindex=%d metric=%d pref=%d", __FILE__, __PRETTY_FUNCTION__, @@ -103,7 +103,7 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr) /* update nextop data */ nexthop->interface = ifp; - nexthop->mrib_nexthop_addr = nexthop_tab[0].nexthop_addr; + nexthop->mrib_nexthop_addr = nexthop_tab[0].nexthop_addr.u.prefix4; nexthop->mrib_metric_preference = nexthop_tab[0].protocol_distance; nexthop->mrib_route_metric = nexthop_tab[0].route_metric; diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 7234790fab..c2160d8d9d 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -241,17 +241,18 @@ static int zclient_read_nexthop(struct zclient *zlookup, switch (nexthop_type) { case NEXTHOP_TYPE_IFINDEX: case NEXTHOP_TYPE_IPV4_IFINDEX: + nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; if (nexthop_type == NEXTHOP_TYPE_IPV4_IFINDEX) { if (length < 4) { zlog_err("%s: socket %d short input expecting nexthop IPv4-addr: len=%d", __func__, zlookup->sock, length); return -8; } - nexthop_tab[num_ifindex].nexthop_addr.s_addr = stream_get_ipv4(s); + nexthop_tab[num_ifindex].nexthop_addr.u.prefix4.s_addr = stream_get_ipv4(s); length -= 4; } else { - nexthop_tab[num_ifindex].nexthop_addr.s_addr = PIM_NET_INADDR_ANY; + nexthop_tab[num_ifindex].nexthop_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY; } nexthop_tab[num_ifindex].ifindex = stream_getl(s); nexthop_tab[num_ifindex].protocol_distance = distance; @@ -259,7 +260,8 @@ static int zclient_read_nexthop(struct zclient *zlookup, ++num_ifindex; break; case NEXTHOP_TYPE_IPV4: - nexthop_tab[num_ifindex].nexthop_addr.s_addr = stream_get_ipv4(s); + nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; + nexthop_tab[num_ifindex].nexthop_addr.u.prefix4.s_addr = stream_get_ipv4(s); length -= 4; nexthop_tab[num_ifindex].ifindex = 0; nexthop_tab[num_ifindex].protocol_distance = distance; @@ -268,7 +270,7 @@ static int zclient_read_nexthop(struct zclient *zlookup, char addr_str[100]; char nexthop_str[100]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - pim_inet4_dump("", nexthop_tab[num_ifindex].nexthop_addr, nexthop_str, sizeof(nexthop_str)); + pim_addr_dump("", &nexthop_tab[num_ifindex].nexthop_addr, nexthop_str, sizeof(nexthop_str)); zlog_debug("%s %s: zebra returned recursive nexthop %s for address %s", __FILE__, __PRETTY_FUNCTION__, nexthop_str, addr_str); @@ -354,7 +356,7 @@ zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], for (lookup = 0; lookup < max_lookup; ++lookup) { int num_ifindex; int first_ifindex; - struct in_addr nexthop_addr; + struct prefix nexthop_addr; num_ifindex = zclient_lookup_nexthop_once(nexthop_tab, PIM_NEXTHOP_IFINDEX_TAB_SIZE, addr); @@ -398,7 +400,7 @@ zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], } /* use last address as nexthop address */ - nexthop_tab[0].nexthop_addr = addr; + nexthop_tab[0].nexthop_addr.u.prefix4 = addr; /* report original route metric/distance */ nexthop_tab[0].route_metric = route_metric; @@ -412,7 +414,7 @@ zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], char addr_str[100]; char nexthop_str[100]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - pim_inet4_dump("", nexthop_addr, nexthop_str, sizeof(nexthop_str)); + pim_addr_dump("", &nexthop_addr, nexthop_str, sizeof(nexthop_str)); zlog_debug("%s %s: lookup=%d/%d: zebra returned recursive nexthop %s for address %s dist=%d met=%d", __FILE__, __PRETTY_FUNCTION__, lookup, max_lookup, nexthop_str, addr_str, @@ -420,7 +422,7 @@ zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], nexthop_tab[0].route_metric); } - addr = nexthop_addr; /* use nexthop addr for recursive lookup */ + addr = nexthop_addr.u.prefix4; /* use nexthop addr for recursive lookup */ } /* for (max_lookup) */ diff --git a/pimd/pim_zlookup.h b/pimd/pim_zlookup.h index 4dea5750c5..ce85c8eba9 100644 --- a/pimd/pim_zlookup.h +++ b/pimd/pim_zlookup.h @@ -29,7 +29,7 @@ #define PIM_NEXTHOP_LOOKUP_MAX (3) /* max. recursive route lookup */ struct pim_zlookup_nexthop { - struct in_addr nexthop_addr; + struct prefix nexthop_addr; ifindex_t ifindex; uint32_t route_metric; uint8_t protocol_distance; From bfea315d4f24d456b4ecff6a53cca2389d667eb3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 2 Sep 2016 11:03:43 -0400 Subject: [PATCH 140/386] pimd: Move rpf code into pim_rpf.h The pim_rpf code needs to be in pim_rpf.h as that it belongs in there. Signed-off-by: Donald Sharp --- pimd/pim_rpf.h | 32 ++++++++++++++++++++++++++++++++ pimd/pim_upstream.h | 32 ++------------------------------ 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/pimd/pim_rpf.h b/pimd/pim_rpf.h index ab16039a29..9e183a0895 100644 --- a/pimd/pim_rpf.h +++ b/pimd/pim_rpf.h @@ -27,6 +27,38 @@ #include "pim_upstream.h" #include "pim_neighbor.h" +/* + RFC 4601: + + Metric Preference + Preference value assigned to the unicast routing protocol that + provided the route to the multicast source or Rendezvous-Point. + + Metric + The unicast routing table metric associated with the route used to + reach the multicast source or Rendezvous-Point. The metric is in + units applicable to the unicast routing protocol used. +*/ +struct pim_nexthop { + struct interface *interface; /* RPF_interface(S) */ + struct in_addr mrib_nexthop_addr; /* MRIB.next_hop(S) */ + uint32_t mrib_metric_preference; /* MRIB.pref(S) */ + uint32_t mrib_route_metric; /* MRIB.metric(S) */ +}; + +struct pim_rpf { + struct pim_nexthop source_nexthop; + struct in_addr rpf_addr; /* RPF'(S,G) */ +}; + +enum pim_rpf_result { + PIM_RPF_OK = 0, + PIM_RPF_CHANGED, + PIM_RPF_FAILURE +}; + +struct pim_upstream; + int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr); enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_rpf_addr); diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 95492b27c1..cd30343492 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -25,6 +25,8 @@ #include #include +#include + #define PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED (1 << 0) #define PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED (2 << 0) @@ -37,36 +39,6 @@ #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) -/* - RFC 4601: - - Metric Preference - Preference value assigned to the unicast routing protocol that - provided the route to the multicast source or Rendezvous-Point. - - Metric - The unicast routing table metric associated with the route used to - reach the multicast source or Rendezvous-Point. The metric is in - units applicable to the unicast routing protocol used. -*/ -struct pim_nexthop { - struct interface *interface; /* RPF_interface(S) */ - struct in_addr mrib_nexthop_addr; /* MRIB.next_hop(S) */ - uint32_t mrib_metric_preference; /* MRIB.pref(S) */ - uint32_t mrib_route_metric; /* MRIB.metric(S) */ -}; - -struct pim_rpf { - struct pim_nexthop source_nexthop; - struct in_addr rpf_addr; /* RPF'(S,G) */ -}; - -enum pim_rpf_result { - PIM_RPF_OK = 0, - PIM_RPF_CHANGED, - PIM_RPF_FAILURE -}; - enum pim_upstream_state { PIM_UPSTREAM_NOTJOINED, PIM_UPSTREAM_JOINED, From 0252d82d06d7fd2405a107e95c2032ec05b00e91 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 2 Sep 2016 11:22:24 -0400 Subject: [PATCH 141/386] pimd: Use Quagga as official bug report place Signed-off-by: Donald Sharp --- pimd/pim_main.c | 2 +- pimd/pimd.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pimd/pim_main.c b/pimd/pim_main.c index 2fb4a22f07..337f925271 100644 --- a/pimd/pim_main.c +++ b/pimd/pim_main.c @@ -116,7 +116,7 @@ Daemon which manages PIM.\n\n\ "\ -h, --help Display this help and exit\n\ \n\ -Report bugs to %s\n", progname, PIMD_BUG_ADDRESS); +Report bugs to %s\n", progname, PACKAGE_BUGREPORT); } exit (status); diff --git a/pimd/pimd.h b/pimd/pimd.h index cbc95c2eee..f7a02f9376 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -30,7 +30,6 @@ #define PIMD_PROGNAME "pimd" #define PIMD_DEFAULT_CONFIG "pimd.conf" #define PIMD_VTY_PORT 2611 -#define PIMD_BUG_ADDRESS "https://github.com/udhos/qpimd" #define PIM_IP_HEADER_MIN_LEN (20) #define PIM_IP_HEADER_MAX_LEN (60) From 63c59d0c9ae695bd7d8f33e570eb1bf7f6729b4e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 2 Sep 2016 12:17:10 -0400 Subject: [PATCH 142/386] pimd: switch pim_rpf.h to use 'struct prefix' for address mrib_nexthop_addr and rpf_addr should be 'struct prefix' so that we can safely handle unnumbered data from a nexthop lookup in zebra Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 12 ++++---- pimd/pim_ifchannel.c | 14 ++++----- pimd/pim_join.c | 4 +-- pimd/pim_mroute.c | 4 +-- pimd/pim_msg.c | 2 +- pimd/pim_register.c | 6 ++-- pimd/pim_rp.c | 46 ++++++++++++++-------------- pimd/pim_rpf.c | 72 +++++++++++++++++++++++++++++++++----------- pimd/pim_rpf.h | 6 ++-- pimd/pim_upstream.c | 22 ++++++++------ pimd/pim_zebra.c | 2 +- 11 files changed, 117 insertions(+), 73 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index ae9a3fd19e..fd4da29291 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1076,8 +1076,8 @@ static void pim_show_upstream_rpf(struct vty *vty) pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); - pim_inet4_dump("", rpf->source_nexthop.mrib_nexthop_addr, rpf_nexthop_str, sizeof(rpf_nexthop_str)); - pim_inet4_dump("", rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); + pim_addr_dump("", &rpf->source_nexthop.mrib_nexthop_addr, rpf_nexthop_str, sizeof(rpf_nexthop_str)); + pim_addr_dump("", &rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : ""; @@ -1155,8 +1155,8 @@ static void pim_show_rpf(struct vty *vty) pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); - pim_inet4_dump("", rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); - pim_inet4_dump("", rpf->source_nexthop.mrib_nexthop_addr, rib_nexthop_str, sizeof(rib_nexthop_str)); + pim_addr_dump("", &rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); + pim_addr_dump("", &rpf->source_nexthop.mrib_nexthop_addr, rib_nexthop_str, sizeof(rib_nexthop_str)); rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : ""; @@ -2371,8 +2371,8 @@ DEFUN (show_ip_rib, vty_out(vty, "Address NextHop Interface Metric Preference%s", VTY_NEWLINE); - pim_inet4_dump("", nexthop.mrib_nexthop_addr, - nexthop_addr_str, sizeof(nexthop_addr_str)); + pim_addr_dump("", &nexthop.mrib_nexthop_addr, + nexthop_addr_str, sizeof(nexthop_addr_str)); vty_out(vty, "%-15s %-15s %-9s %6d %10d%s", addr_str, diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index e2b145a5b2..eaf7ab7096 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -512,7 +512,7 @@ static void check_recv_upstream(int is_join, /* Upstream (S,G) in Joined state */ - if (PIM_INADDR_IS_ANY(up->rpf.rpf_addr)) { + if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { /* RPF'(S,G) not found */ zlog_warn("%s %s: RPF'%s not found", __FILE__, __PRETTY_FUNCTION__, @@ -521,11 +521,11 @@ static void check_recv_upstream(int is_join, } /* upstream directed to RPF'(S,G) ? */ - if (upstream.s_addr != up->rpf.rpf_addr.s_addr) { + if (upstream.s_addr != up->rpf.rpf_addr.u.prefix4.s_addr) { char up_str[100]; char rpf_str[100]; pim_inet4_dump("", upstream, up_str, sizeof(up_str)); - pim_inet4_dump("", up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); + pim_addr_dump("", &up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); zlog_warn("%s %s: (S,G)=%s upstream=%s not directed to RPF'(S,G)=%s on interface %s", __FILE__, __PRETTY_FUNCTION__, pim_str_sg_dump (sg), @@ -536,7 +536,7 @@ static void check_recv_upstream(int is_join, if (is_join) { /* Join(S,G) to RPF'(S,G) */ - pim_upstream_join_suppress(up, up->rpf.rpf_addr, holdtime); + pim_upstream_join_suppress(up, up->rpf.rpf_addr.u.prefix4, holdtime); return; } @@ -546,19 +546,19 @@ static void check_recv_upstream(int is_join, if (source_flags & PIM_WILDCARD_BIT_MASK) { /* Prune(*,G) to RPF'(S,G) */ pim_upstream_join_timer_decrease_to_t_override("Prune(*,G)", - up, up->rpf.rpf_addr); + up, up->rpf.rpf_addr.u.prefix4); return; } /* Prune(S,G,rpt) to RPF'(S,G) */ pim_upstream_join_timer_decrease_to_t_override("Prune(S,G,rpt)", - up, up->rpf.rpf_addr); + up, up->rpf.rpf_addr.u.prefix4); return; } /* Prune(S,G) to RPF'(S,G) */ pim_upstream_join_timer_decrease_to_t_override("Prune(S,G)", up, - up->rpf.rpf_addr); + up->rpf.rpf_addr.u.prefix4); } static int nonlocal_upstream(int is_join, diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 0992457420..1f722e7637 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -90,7 +90,7 @@ static void recv_join(struct interface *ifp, * If the RP sent in the message is not * our RP for the group, drop the message */ - if (sg.src.s_addr != rp->rpf_addr.s_addr) + if (sg.src.s_addr != rp->rpf_addr.u.prefix4.s_addr) return; sg.src.s_addr = INADDR_ANY; @@ -162,7 +162,7 @@ static void recv_prune(struct interface *ifp, struct pim_rpf *rp = RP (sg.grp); // Ignoring Prune *,G's at the moment. - if (sg.src.s_addr != rp->rpf_addr.s_addr) + if (sg.src.s_addr != rp->rpf_addr.u.prefix4.s_addr) return; sg.src.s_addr = INADDR_ANY; diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 14221d3303..f498bfcd00 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -97,7 +97,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg * the Interface type is SSM we don't need to * do anything here */ - if ((rpg->rpf_addr.s_addr == INADDR_NONE) || + if ((pim_rpf_addr_is_inaddr_none (rpg)) || (!pim_ifp) || (!(PIM_I_am_DR(pim_ifp))) || (pim_ifp->itype == PIM_INTERFACE_SSM)) @@ -183,7 +183,7 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf) rpg = RP(sg.grp); - if ((rpg->rpf_addr.s_addr == INADDR_NONE) || + if ((pim_rpf_addr_is_inaddr_none (rpg)) || (!pim_ifp) || (!(PIM_I_am_DR(pim_ifp))) || (pim_ifp->itype == PIM_INTERFACE_SSM)) { diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index df7f7051d3..62e0bb1a36 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -181,7 +181,7 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, { struct pim_rpf *rpf = pim_rp_g (group); bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT | PIM_ENCODE_RPT_BIT; - stosend = rpf->rpf_addr; + stosend = rpf->rpf_addr.u.prefix4; } else { diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 46601c0dcb..4131c5ef01 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -155,7 +155,7 @@ pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct if (PIM_DEBUG_PIM_REG) { char rp_str[100]; - strcpy (rp_str, inet_ntoa (rpg->rpf_addr)); + strcpy (rp_str, inet_ntoa (rpg->rpf_addr.u.prefix4)); zlog_debug ("Sending %sRegister Packet to %s", null_register ? "NULL " : "", rp_str); } @@ -177,7 +177,7 @@ pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct if (pim_msg_send(pinfo->pim_sock_fd, src, - rpg->rpf_addr, + rpg->rpf_addr.u.prefix4, buffer, buf_size + PIM_MSG_REGISTER_LEN, ifp->name)) { @@ -296,7 +296,7 @@ pim_register_recv (struct interface *ifp, sg.src = ip_hdr->ip_src; sg.grp = ip_hdr->ip_dst; - if (I_am_RP (sg.grp) && (dest_addr.s_addr == ((RP (sg.grp))->rpf_addr.s_addr))) { + if (I_am_RP (sg.grp) && (dest_addr.s_addr == ((RP (sg.grp))->rpf_addr.u.prefix4.s_addr))) { sentRegisterStop = 0; if (*bits & PIM_REGISTER_BORDER_BIT) { diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 81c4a65abe..05b6623e8c 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -91,7 +91,8 @@ pim_rp_init (void) return; str2prefix ("224.0.0.0/4", &rp_info->group); - rp_info->rp.rpf_addr.s_addr = INADDR_NONE; + rp_info->rp.rpf_addr.family = AF_INET; + rp_info->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; tail = rp_info; listnode_add (qpim_rp_list, rp_info); @@ -112,7 +113,7 @@ pim_rp_find_exact (struct in_addr rp, struct prefix *group) for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { - if (rp.s_addr == rp_info->rp.rpf_addr.s_addr && + if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr && prefix_same (&rp_info->group, group)) return rp_info; } @@ -128,7 +129,7 @@ pim_rp_find_match (struct in_addr rp, struct prefix *group) for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { - if (rp.s_addr == rp_info->rp.rpf_addr.s_addr && + if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr && prefix_match (&rp_info->group, group)) return rp_info; } @@ -164,7 +165,7 @@ pim_rp_check_interfaces (struct rp_info *rp_info) if (!pim_ifp) continue; - if (pim_ifp->primary_address.s_addr == rp_info->rp.rpf_addr.s_addr) + if (pim_ifp->primary_address.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) rp_info->i_am_rp = 1; } } @@ -192,7 +193,7 @@ pim_rp_new (const char *rp, const char *group_range) if (!result) return -1; - result = inet_pton (AF_INET, rp, &rp_info->rp.rpf_addr.s_addr); + result = inet_pton (rp_info->rp.rpf_addr.family, rp, &rp_info->rp.rpf_addr.u.prefix); if (result <= 0) return -1; @@ -200,7 +201,7 @@ pim_rp_new (const char *rp, const char *group_range) * Take over the 224.0.0.0/4 group if the rp is INADDR_NONE */ if (prefix_same (&rp_all->group, &rp_info->group) && - rp_all->rp.rpf_addr.s_addr == INADDR_NONE) + pim_rpf_addr_is_inaddr_none (&rp_all->rp)) { rp_all->rp.rpf_addr = rp_info->rp.rpf_addr; XFREE (MTYPE_PIM_RP, rp_info); @@ -210,13 +211,13 @@ pim_rp_new (const char *rp, const char *group_range) return 0; } - if (pim_rp_find_exact (rp_info->rp.rpf_addr, &rp_info->group)) + if (pim_rp_find_exact (rp_info->rp.rpf_addr.u.prefix4, &rp_info->group)) { XFREE (MTYPE_PIM_RP, rp_info); return 0; } - if (pim_rp_find_match (rp_info->rp.rpf_addr, &rp_info->group)) + if (pim_rp_find_match (rp_info->rp.rpf_addr.u.prefix4, &rp_info->group)) { if (prefix_same (&group_all, &rp_info->group)) { @@ -267,7 +268,8 @@ pim_rp_del (const char *rp, const char *group_range) if (rp_all == rp_info) { - rp_all->rp.rpf_addr.s_addr = INADDR_NONE; + rp_all->rp.rpf_addr.family = AF_INET; + rp_all->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; rp_all->i_am_rp = 0; return 0; } @@ -285,7 +287,7 @@ pim_rp_setup (void) for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { - if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr) != 0) + if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4) != 0) { zlog_err ("Unable to lookup nexthop for rp specified"); ret++; @@ -316,20 +318,20 @@ pim_rp_check_rp (struct in_addr old, struct in_addr new) char sold[100]; char snew[100]; char rp[100]; - pim_inet4_dump("", rp_info->rp.rpf_addr, rp, sizeof(rp)); + pim_addr_dump("", &rp_info->rp.rpf_addr, rp, sizeof(rp)); pim_inet4_dump("", old, sold, sizeof(sold)); pim_inet4_dump("", new, snew, sizeof(snew)); zlog_debug("%s: %s for old %s new %s", __func__, rp, sold, snew ); } - if (rp_info->rp.rpf_addr.s_addr == INADDR_NONE) + if (pim_rpf_addr_is_inaddr_none (&rp_info->rp)) continue; - if (new.s_addr == rp_info->rp.rpf_addr.s_addr) + if (new.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) { rp_info->i_am_rp = 1; } - if (old.s_addr == rp_info->rp.rpf_addr.s_addr) + if (old.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) { rp_info->i_am_rp = 0; } @@ -381,7 +383,7 @@ pim_rp_g (struct in_addr group) if (rp_info) { - pim_nexthop_lookup(&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr); + pim_nexthop_lookup(&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4); return (&rp_info->rp); } @@ -410,14 +412,14 @@ pim_rp_set_upstream_addr (struct in_addr *up, struct in_addr source, struct in_a rp_info = pim_rp_find_match_group (&g); - if ((rp_info->rp.rpf_addr.s_addr == INADDR_NONE) && (source.s_addr == INADDR_ANY)) + if ((pim_rpf_addr_is_inaddr_none (&rp_info->rp)) && (source.s_addr == INADDR_ANY)) { if (PIM_DEBUG_PIM_TRACE) zlog_debug("%s: Received a (*,G) with no RP configured", __PRETTY_FUNCTION__); return 0; } - *up = (source.s_addr == INADDR_ANY) ? rp_info->rp.rpf_addr : source; + *up = (source.s_addr == INADDR_ANY) ? rp_info->rp.rpf_addr.u.prefix4 : source; return 1; } @@ -432,10 +434,10 @@ pim_rp_config_write (struct vty *vty) for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { - if (rp_info->rp.rpf_addr.s_addr == INADDR_NONE) + if (pim_rpf_addr_is_inaddr_none (&rp_info->rp)) continue; - if (rp_info->rp.rpf_addr.s_addr != INADDR_NONE) + if (!pim_rpf_addr_is_inaddr_none (&rp_info->rp)) { char buf[32]; vty_out(vty, "ip pim rp %s %s%s", inet_ntop(AF_INET, &rp_info->rp.rpf_addr, buffer, 32), @@ -467,7 +469,7 @@ pim_rp_check_is_my_ip_address (struct in_addr group, struct in_addr dest_addr) */ if (I_am_RP(group)) { - if (dest_addr.s_addr == rp_info->rp.rpf_addr.s_addr) + if (dest_addr.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) return 1; } @@ -486,11 +488,11 @@ pim_rp_show_information (struct vty *vty) vty_out (vty, "RP Addr Group Oif I_am_RP%s", VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { - if (rp_info->rp.rpf_addr.s_addr != INADDR_NONE) + if (!pim_rpf_addr_is_inaddr_none (&rp_info->rp)) { char buf[48]; vty_out (vty, "%-10s %-10s %-10s%-10d%s", - inet_ntoa (rp_info->rp.rpf_addr), + inet_ntoa (rp_info->rp.rpf_addr.u.prefix4), prefix2str(&rp_info->group, buf, 48), rp_info->rp.source_nexthop.interface->name, rp_info->i_am_rp, VTY_NEWLINE); diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 928629b0cf..662d4aaf52 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -102,10 +102,10 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr) } /* update nextop data */ - nexthop->interface = ifp; - nexthop->mrib_nexthop_addr = nexthop_tab[0].nexthop_addr.u.prefix4; - nexthop->mrib_metric_preference = nexthop_tab[0].protocol_distance; - nexthop->mrib_route_metric = nexthop_tab[0].route_metric; + nexthop->interface = ifp; + nexthop->mrib_nexthop_addr = nexthop_tab[0].nexthop_addr; + nexthop->mrib_metric_preference = nexthop_tab[0].protocol_distance; + nexthop->mrib_route_metric = nexthop_tab[0].route_metric; return 0; } @@ -113,18 +113,15 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr) static int nexthop_mismatch(const struct pim_nexthop *nh1, const struct pim_nexthop *nh2) { - return (nh1->interface != nh2->interface) - || - (nh1->mrib_nexthop_addr.s_addr != nh2->mrib_nexthop_addr.s_addr) - || - (nh1->mrib_metric_preference != nh2->mrib_metric_preference) - || + return (nh1->interface != nh2->interface) || + (nh1->mrib_nexthop_addr.u.prefix4.s_addr != nh2->mrib_nexthop_addr.u.prefix4.s_addr) || + (nh1->mrib_metric_preference != nh2->mrib_metric_preference) || (nh1->mrib_route_metric != nh2->mrib_route_metric); } enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_rpf_addr) { - struct in_addr save_rpf_addr; + struct prefix save_rpf_addr; struct pim_nexthop save_nexthop; struct pim_rpf *rpf = &up->rpf; @@ -135,8 +132,9 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_ return PIM_RPF_FAILURE; } - rpf->rpf_addr = pim_rpf_find_rpf_addr(up); - if (PIM_INADDR_IS_ANY(rpf->rpf_addr) && PIM_DEBUG_ZEBRA) { + rpf->rpf_addr.family = AF_INET; + rpf->rpf_addr.u.prefix4 = pim_rpf_find_rpf_addr(up); + if (pim_rpf_addr_is_inaddr_any(rpf) && PIM_DEBUG_ZEBRA) { /* RPF'(S,G) not found */ zlog_debug("%s %s: RPF'%s not found: won't send join upstream", __FILE__, __PRETTY_FUNCTION__, @@ -149,7 +147,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_ if (PIM_DEBUG_ZEBRA) { char nhaddr_str[100]; - pim_inet4_dump("", rpf->source_nexthop.mrib_nexthop_addr, nhaddr_str, sizeof(nhaddr_str)); + pim_addr_dump("", &rpf->source_nexthop.mrib_nexthop_addr, nhaddr_str, sizeof(nhaddr_str)); zlog_debug("%s %s: (S,G)=%s source nexthop now is: interface=%s address=%s pref=%d metric=%d", __FILE__, __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg), @@ -180,11 +178,11 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_ } /* detect change in RPF'(S,G) */ - if (save_rpf_addr.s_addr != rpf->rpf_addr.s_addr) { + if (save_rpf_addr.u.prefix4.s_addr != rpf->rpf_addr.u.prefix4.s_addr) { /* return old rpf to caller ? */ if (old_rpf_addr) - *old_rpf_addr = save_rpf_addr; + *old_rpf_addr = save_rpf_addr.u.prefix4; return PIM_RPF_CHANGED; } @@ -233,7 +231,7 @@ static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up) /* return NBR( RPF_interface(S), MRIB.next_hop( S ) ) */ neigh = pim_if_find_neighbor(up->rpf.source_nexthop.interface, - up->rpf.source_nexthop.mrib_nexthop_addr); + up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4); if (neigh) rpf_addr = neigh->source_addr; else @@ -241,3 +239,43 @@ static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up) return rpf_addr; } + +int +pim_rpf_addr_is_inaddr_none (struct pim_rpf *rpf) +{ + switch (rpf->rpf_addr.family) + { + case AFI_IP: + return rpf->rpf_addr.u.prefix4.s_addr == INADDR_NONE; + break; + case AFI_IP6: + zlog_warn ("%s: v6 Unimplmeneted", __PRETTY_FUNCTION__); + return 1; + break; + default: + return 0; + break; + } + + return 0; +} + +int +pim_rpf_addr_is_inaddr_any (struct pim_rpf *rpf) +{ + switch (rpf->rpf_addr.family) + { + case AFI_IP: + return rpf->rpf_addr.u.prefix4.s_addr == INADDR_ANY; + break; + case AFI_IP6: + zlog_warn ("%s: v6 Unimplmented", __PRETTY_FUNCTION__); + return 1; + break; + default: + return 0; + break; + } + + return 0; +} diff --git a/pimd/pim_rpf.h b/pimd/pim_rpf.h index 9e183a0895..fddc74a725 100644 --- a/pimd/pim_rpf.h +++ b/pimd/pim_rpf.h @@ -41,14 +41,14 @@ */ struct pim_nexthop { struct interface *interface; /* RPF_interface(S) */ - struct in_addr mrib_nexthop_addr; /* MRIB.next_hop(S) */ + struct prefix mrib_nexthop_addr; /* MRIB.next_hop(S) */ uint32_t mrib_metric_preference; /* MRIB.pref(S) */ uint32_t mrib_route_metric; /* MRIB.metric(S) */ }; struct pim_rpf { struct pim_nexthop source_nexthop; - struct in_addr rpf_addr; /* RPF'(S,G) */ + struct prefix rpf_addr; /* RPF'(S,G) */ }; enum pim_rpf_result { @@ -62,4 +62,6 @@ struct pim_upstream; int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr); enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_rpf_addr); +int pim_rpf_addr_is_inaddr_none (struct pim_rpf *rpf); +int pim_rpf_addr_is_inaddr_any (struct pim_rpf *rpf); #endif /* PIM_RPF_H */ diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 9a11eefd60..13e7c55c55 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -174,11 +174,11 @@ pim_upstream_send_join (struct pim_upstream *up) { if (PIM_DEBUG_PIM_TRACE) { char rpf_str[100]; - pim_inet4_dump("", up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); + pim_addr_dump("", &up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); zlog_debug ("%s: RPF'%s=%s(%s) for Interface %s", __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg), rpf_str, pim_upstream_state2str (up->join_state), up->rpf.source_nexthop.interface->name); - if (PIM_INADDR_IS_ANY(up->rpf.rpf_addr)) { + if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { zlog_debug("%s: can't send join upstream: RPF'%s=%s", __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg), rpf_str); @@ -188,7 +188,7 @@ pim_upstream_send_join (struct pim_upstream *up) /* send Join(S,G) to the current upstream neighbor */ pim_joinprune_send(up->rpf.source_nexthop.interface, - up->rpf.rpf_addr, + up->rpf.rpf_addr.u.prefix4, &up->sg, 1 /* join */); } @@ -457,7 +457,7 @@ pim_upstream_switch(struct pim_upstream *up, else { forward_off(up); pim_joinprune_send(up->rpf.source_nexthop.interface, - up->rpf.rpf_addr, + up->rpf.rpf_addr.u.prefix4, &up->sg, 0 /* prune */); if (up->t_join_timer) @@ -501,10 +501,12 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, up->sptbit = PIM_UPSTREAM_SPTBIT_FALSE; up->rpf.source_nexthop.interface = NULL; - up->rpf.source_nexthop.mrib_nexthop_addr.s_addr = PIM_NET_INADDR_ANY; + up->rpf.source_nexthop.mrib_nexthop_addr.family = AF_INET; + up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY; up->rpf.source_nexthop.mrib_metric_preference = qpim_infinite_assert_metric.metric_preference; up->rpf.source_nexthop.mrib_route_metric = qpim_infinite_assert_metric.route_metric; - up->rpf.rpf_addr.s_addr = PIM_NET_INADDR_ANY; + up->rpf.rpf_addr.family = AF_INET; + up->rpf.rpf_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY; rpf_result = pim_rpf_update(up, NULL); if (rpf_result == PIM_RPF_FAILURE) { @@ -703,7 +705,7 @@ void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr) char neigh_str[100]; char rpf_addr_str[100]; pim_inet4_dump("", neigh_addr, neigh_str, sizeof(neigh_str)); - pim_inet4_dump("", up->rpf.rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); + pim_addr_dump("", &up->rpf.rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); zlog_debug("%s: matching neigh=%s against upstream (S,G)=%s joined=%d rpf_addr=%s", __PRETTY_FUNCTION__, neigh_str, pim_str_sg_dump (&up->sg), @@ -716,7 +718,7 @@ void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr) continue; /* match RPF'(S,G)=neigh_addr */ - if (up->rpf.rpf_addr.s_addr != neigh_addr.s_addr) + if (up->rpf.rpf_addr.u.prefix4.s_addr != neigh_addr.s_addr) continue; pim_upstream_join_timer_decrease_to_t_override("RPF'(S,G) GenID change", @@ -878,7 +880,7 @@ pim_upstream_keep_alive_timer (struct thread *t) 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, + pim_joinprune_send (up->rpf.source_nexthop.interface, up->rpf.rpf_addr.u.prefix4, &up->sg, 0); pim_upstream_del (up); } @@ -1121,7 +1123,7 @@ pim_upstream_find_new_rpf (void) */ for (ALL_LIST_ELEMENTS(qpim_upstream_list, up_node, up_nextnode, up)) { - if (PIM_INADDR_IS_ANY(up->rpf.rpf_addr)) + if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { if (PIM_DEBUG_PIM_TRACE) zlog_debug ("Upstream %s without a path to send join, checking", diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 8a466e4035..68df086a1b 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -371,7 +371,7 @@ static void scan_upstream_rpf_cache() /* send Join(S,G) to the current upstream neighbor */ pim_joinprune_send(up->rpf.source_nexthop.interface, - up->rpf.rpf_addr, + up->rpf.rpf_addr.u.prefix4, &up->sg, 1 /* join */); From f97178866605d91bd46b41ebcb2770cb28c9b092 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 2 Sep 2016 12:55:18 -0400 Subject: [PATCH 143/386] pimd: Fix compile error on some platforms. Fix the failure to build vtysh information for pim on some platforms. Signed-off-by: Donald Sharp --- pimd/pim_upstream.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index cd30343492..35cd8dc014 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -25,7 +25,7 @@ #include #include -#include +#include #define PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED (1 << 0) #define PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED (2 << 0) From fa8da98c263029568e9842a457be542062801b07 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 2 Sep 2016 14:34:14 -0400 Subject: [PATCH 144/386] pimd: Fix up rp initialization breakage When I converted over to using 'struct prefix' I broke the initialization of the rp. In addition, I used the wrong AFI type to switch on in pim_rpf.c Signed-off-by: Donald Sharp --- pimd/pim_rp.c | 5 +++-- pimd/pim_rpf.c | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 05b6623e8c..612c08e1b7 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -91,6 +91,7 @@ pim_rp_init (void) return; str2prefix ("224.0.0.0/4", &rp_info->group); + rp_info->group.family = AF_INET; rp_info->rp.rpf_addr.family = AF_INET; rp_info->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; tail = rp_info; @@ -192,8 +193,8 @@ pim_rp_new (const char *rp, const char *group_range) if (!result) return -1; - - result = inet_pton (rp_info->rp.rpf_addr.family, rp, &rp_info->rp.rpf_addr.u.prefix); + rp_info->rp.rpf_addr.family = AF_INET; + result = inet_pton (rp_info->rp.rpf_addr.family, rp, &rp_info->rp.rpf_addr.u.prefix4); if (result <= 0) return -1; diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 662d4aaf52..f3bdb68305 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -245,10 +245,10 @@ pim_rpf_addr_is_inaddr_none (struct pim_rpf *rpf) { switch (rpf->rpf_addr.family) { - case AFI_IP: + case AF_INET: return rpf->rpf_addr.u.prefix4.s_addr == INADDR_NONE; break; - case AFI_IP6: + case AF_INET6: zlog_warn ("%s: v6 Unimplmeneted", __PRETTY_FUNCTION__); return 1; break; @@ -265,10 +265,10 @@ pim_rpf_addr_is_inaddr_any (struct pim_rpf *rpf) { switch (rpf->rpf_addr.family) { - case AFI_IP: + case AF_INET: return rpf->rpf_addr.u.prefix4.s_addr == INADDR_ANY; break; - case AFI_IP6: + case AF_INET6: zlog_warn ("%s: v6 Unimplmented", __PRETTY_FUNCTION__); return 1; break; From fb5d6e2f4176c36ef0c17676a93001968aa0a57a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 5 Sep 2016 08:31:46 -0400 Subject: [PATCH 145/386] pimd: Fix SA warning Restructure code to remove SA warning from clang build. For some reason, the Clang SA system thought that si.sin_port and si.sin_addr where not being set to anything. Fix this problem. Signed-off-by: Donald Sharp --- pimd/pim_sock.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index 4312fe73b2..8ba514a219 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -334,17 +334,14 @@ int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len, if (to) { struct sockaddr_in si; socklen_t si_len = sizeof(si); - - ((struct sockaddr_in *) to)->sin_family = AF_INET; - if (pim_socket_getsockname(fd, (struct sockaddr *) &si, &si_len) != PIM_SOCK_ERR_NONE) { - ((struct sockaddr_in *) to)->sin_port = ntohs(0); - ((struct sockaddr_in *) to)->sin_addr.s_addr = ntohl(0); - } - else { - ((struct sockaddr_in *) to)->sin_port = si.sin_port; - ((struct sockaddr_in *) to)->sin_addr = si.sin_addr; - } + memset (&si, 0, sizeof (si)); + to->sin_family = AF_INET; + + pim_socket_getsockname(fd, (struct sockaddr *) &si, &si_len); + + to->sin_port = si.sin_port; + to->sin_addr = si.sin_addr; if (tolen) *tolen = sizeof(si); From 89f1d91ecc20e0b8c1789e12b61f9ae20629443f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 7 Sep 2016 08:51:29 -0400 Subject: [PATCH 146/386] pimd: Refactor pim_find_primary_addr The pim_find_primary_addr function just called 1 static function that was called no where else. Signed-off-by: Donald Sharp --- pimd/pim_iface.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 503be0d0bc..43c5f4b142 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -573,7 +573,8 @@ void pim_if_addr_del_all_pim(struct interface *ifp) } } -static struct in_addr find_first_nonsec_addr(struct interface *ifp) +struct in_addr +pim_find_primary_addr (struct interface *ifp) { struct connected *ifc; struct listnode *node; @@ -602,11 +603,6 @@ static struct in_addr find_first_nonsec_addr(struct interface *ifp) return addr; } -struct in_addr pim_find_primary_addr(struct interface *ifp) -{ - return find_first_nonsec_addr(ifp); -} - static int pim_iface_vif_index = 0; static int From 60ce8d9b4c7e5d807f29f0a301b6237377bce884 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 7 Sep 2016 10:34:02 -0400 Subject: [PATCH 147/386] pimd: Fix display of rp information in 'show run' The recent conversion of in_addr_t to struct prefix caused a display issue in the 'show run' of the rp. Ticket: CM-12752 Signed-off-by: Donald Sharp --- pimd/pim_rp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 612c08e1b7..daf825f6d8 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -441,7 +441,7 @@ pim_rp_config_write (struct vty *vty) if (!pim_rpf_addr_is_inaddr_none (&rp_info->rp)) { char buf[32]; - vty_out(vty, "ip pim rp %s %s%s", inet_ntop(AF_INET, &rp_info->rp.rpf_addr, buffer, 32), + vty_out(vty, "ip pim rp %s %s%s", inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, buffer, 32), prefix2str(&rp_info->group, buf, 32), VTY_NEWLINE); count++; } From c305ed63eba226a78fff6179b2b9aef84826b728 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 8 Sep 2016 08:42:04 -0400 Subject: [PATCH 148/386] pimd: Allow breaking up of packet. When a packet is too large to send in one go, break it up. Ticket: CM-12768 Signed-off-by: Donald Sharp --- pimd/pim_pim.c | 84 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 27 deletions(-) diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 4924acea74..8b34a45576 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -480,14 +480,62 @@ void pim_sock_reset(struct interface *ifp) static uint16_t ip_id = 0; -int pim_msg_send(int fd, - struct in_addr src, - struct in_addr dst, - uint8_t *pim_msg, - int pim_msg_size, - const char *ifname) + +static int +pim_msg_send_frame (int fd, char *buf, size_t len, + struct sockaddr *dst, size_t salen) +{ + struct ip *ip = (struct ip *)buf; + + while (sendto (fd, buf, len, MSG_DONTWAIT, dst, salen) < 0) + { + char dst_str[100]; + + switch (errno) + { + case EMSGSIZE: + { + size_t hdrsize = sizeof (struct ip); + size_t newlen1 = ((len - hdrsize) / 2 ) & 0xFFF8; + size_t sendlen = newlen1 + hdrsize; + size_t offset = ntohs (ip->ip_off); + + ip->ip_len = htons (sendlen); + ip->ip_off = htons (offset | IP_MF); + if (pim_msg_send_frame (fd, buf, sendlen, dst, salen) == 0) + { + struct ip *ip2 = (struct ip *)(buf + newlen1); + size_t newlen2 = len - sendlen; + sendlen = newlen2 + hdrsize; + + memcpy (ip2, ip, hdrsize); + ip2->ip_len = htons (sendlen); + ip2->ip_off = htons (offset + (newlen1 >> 3)); + return pim_msg_send_frame (fd, (char *)ip2, sendlen, dst, salen); + } + } + + return -1; + break; + default: + pim_inet4_dump ("", ip->ip_dst, dst_str, sizeof (dst_str)); + zlog_warn ("%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s", + __PRETTY_FUNCTION__, + dst_str, fd, len, + errno, safe_strerror(errno)); + break; + return -1; + } + } + + return 0; +} + +int +pim_msg_send(int fd, struct in_addr src, + struct in_addr dst, uint8_t *pim_msg, + int pim_msg_size, const char *ifname) { - ssize_t sent; struct sockaddr_in to; socklen_t tolen; unsigned char buffer[3000]; @@ -528,26 +576,8 @@ int pim_msg_send(int fd, pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_size); } - sent = sendto(fd, buffer, sendlen, MSG_DONTWAIT, - (struct sockaddr *)&to, tolen); - if (sent != (ssize_t) sendlen) { - char dst_str[100]; - pim_inet4_dump("", dst, dst_str, sizeof(dst_str)); - if (sent < 0) { - zlog_warn("%s: sendto() failure to %s on %s: fd=%d msg_size=%d: errno=%d: %s", - __PRETTY_FUNCTION__, - dst_str, ifname, fd, pim_msg_size, - errno, safe_strerror(errno)); - } - else { - zlog_warn("%s: sendto() partial to %s on %s: fd=%d msg_size=%d: sent=%zd", - __PRETTY_FUNCTION__, - dst_str, ifname, fd, - pim_msg_size, sent); - } - return -1; - } - + pim_msg_send_frame (fd, (char *)buffer, sendlen, + (struct sockaddr *)&to, tolen); return 0; } From d8424057d97804284d0671076116ccc23d4d619c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 7 Sep 2016 09:06:47 -0400 Subject: [PATCH 149/386] pimd: Allow ip address selection for BGP unnumbered When a interface is configured as BGP unnumbered, it has a v6 LL address as well as no v4 addresses. In this case let's look at the lo's ip address as the primary address to use. Signed-off-by: Donald Sharp rebase --- pimd/pim_iface.c | 54 +++++++++++++++++++++++++++++++++++++++++++++--- pimd/pim_zebra.c | 37 ++++++++++++++++++++++++++++++--- 2 files changed, 85 insertions(+), 6 deletions(-) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 43c5f4b142..e55ef30b31 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -498,6 +498,8 @@ void pim_if_addr_add_all(struct interface *ifp) struct connected *ifc; struct listnode *node; struct listnode *nextnode; + int v4_addrs = 0; + int v6_addrs = 0; /* PIM/IGMP enabled ? */ if (!ifp->info) @@ -507,10 +509,35 @@ void pim_if_addr_add_all(struct interface *ifp) struct prefix *p = ifc->address; if (p->family != AF_INET) - continue; + { + v6_addrs++; + continue; + } + v4_addrs++; pim_if_addr_add(ifc); } + + if (!v4_addrs && v6_addrs && !if_is_loopback (ifp)) + { + struct pim_interface *pim_ifp = ifp->info; + + if (pim_ifp && PIM_IF_TEST_PIM(pim_ifp->options)) { + + /* Interface has a valid primary address ? */ + if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { + + /* Interface has a valid socket ? */ + if (pim_ifp->pim_sock_fd < 0) { + if (pim_sock_add(ifp)) { + zlog_warn("Failure creating PIM socket for interface %s", + ifp->name); + } + } + + } + } /* pim */ + } } void pim_if_addr_del_all(struct interface *ifp) @@ -579,12 +606,17 @@ pim_find_primary_addr (struct interface *ifp) struct connected *ifc; struct listnode *node; struct in_addr addr; + int v4_addrs = 0; + int v6_addrs = 0; for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { struct prefix *p = ifc->address; - + if (p->family != AF_INET) - continue; + { + v6_addrs++; + continue; + } if (PIM_INADDR_IS_ANY(p->u.prefix4)) { zlog_warn("%s: null IPv4 address connected to interface %s", @@ -592,12 +624,28 @@ pim_find_primary_addr (struct interface *ifp) continue; } + v4_addrs++; + if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) continue; return p->u.prefix4; } + /* + * If we have no v4_addrs and v6 is configured + * We probably are using unnumbered + * So let's grab the loopbacks v4 address + * and use that as the primary address + */ + if (!v4_addrs && v6_addrs && !if_is_loopback (ifp)) + { + struct interface *lo_ifp; + lo_ifp = if_lookup_by_name_vrf ("lo", VRF_DEFAULT); + if (lo_ifp) + return pim_find_primary_addr (lo_ifp); + } + addr.s_addr = PIM_NET_INADDR_ANY; return addr; diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 68df086a1b..f2789369bf 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -236,9 +236,7 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient, return 0; p = c->address; - if (p->family != AF_INET) - return 0; - + if (PIM_DEBUG_ZEBRA) { char buf[BUFSIZ]; prefix2str(p, buf, BUFSIZ); @@ -252,6 +250,27 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient, #endif } + if (p->family != AF_INET) + { + struct pim_interface *pim_ifp = c->ifp->info; + struct listnode *cnode; + struct connected *conn; + int v4addrs = 0; + + for (ALL_LIST_ELEMENTS_RO (c->ifp->connected, cnode, conn)) + { + if (conn->address->family == AF_INET) + v4addrs++; + } + if (!v4addrs && pim_ifp) + { + + pim_ifp->primary_address = pim_find_primary_addr (c->ifp); + pim_if_addr_add_all (c->ifp); + } + return 0; + } + pim_rp_check_rp (old, p->u.prefix4); if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) { @@ -278,6 +297,18 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient, pim_if_addr_add(c); + if (if_is_loopback (c->ifp)) + { + struct listnode *ifnode; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) + { + if (!if_is_loopback (ifp) && if_is_operative (ifp)) + pim_if_addr_add_all (ifp); + } + } + return 0; } From 99deb321fcbd6b0519d21ccc1498e88341bd6bd7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 7 Sep 2016 15:34:29 -0400 Subject: [PATCH 150/386] pimd: Add the ability to lookup neighbor on a interface On a specified interface return the single neighbor on that interface. Signed-off-by: Donald Sharp --- pimd/pim_neighbor.c | 16 ++++++++++++++++ pimd/pim_neighbor.h | 2 ++ 2 files changed, 18 insertions(+) diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index 61e19d8005..ba2fc753b3 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -403,6 +403,22 @@ struct pim_neighbor *pim_neighbor_find(struct interface *ifp, return 0; } +/* + * Find the *one* interface out + * this interface. If more than + * one return NULL + */ +struct pim_neighbor * +pim_neighbor_find_if (struct interface *ifp) +{ + struct pim_interface *pim_ifp = ifp->info; + + if (pim_ifp->pim_neighbor_list->count != 1) + return NULL; + + return listnode_head (pim_ifp->pim_neighbor_list); +} + struct pim_neighbor *pim_neighbor_add(struct interface *ifp, struct in_addr source_addr, pim_hello_options hello_options, diff --git a/pimd/pim_neighbor.h b/pimd/pim_neighbor.h index 4bf78d063e..3f5a121d4c 100644 --- a/pimd/pim_neighbor.h +++ b/pimd/pim_neighbor.h @@ -48,6 +48,8 @@ void pim_neighbor_free(struct pim_neighbor *neigh); struct pim_neighbor *pim_neighbor_find(struct interface *ifp, struct in_addr source_addr); +struct pim_neighbor *pim_neighbor_find_if (struct interface *ifp); + #define PIM_NEIGHBOR_SEND_DELAY 0 #define PIM_NEIGHBOR_SEND_NOW 1 From 12c7b75bce592022f8773bc1a3aaf07353ecd3e5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 7 Sep 2016 15:36:43 -0400 Subject: [PATCH 151/386] pimd, zebra: Allow v6 based nexthops to work in pim When we get a v6 address/ifindex combo back from a v4 lookup. Check to see if the outgoing interface only has one neighbor and if so use that neighbors loopback address as the route to use. Signed-off-by: Donald Sharp --- pimd/pim_zlookup.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index c2160d8d9d..8d73159466 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -217,19 +217,11 @@ static int zclient_read_nexthop(struct zclient *zlookup, return -6; } - length -= MIN_LEN; - for (i = 0; i < nexthop_num; ++i) { enum nexthop_types_t nexthop_type; + struct pim_neighbor *nbr; - if (length < 1) { - zlog_err("%s: socket %d empty input expecting nexthop_type: len=%d", - __func__, zlookup->sock, length); - return -7; - } - nexthop_type = stream_getc(s); - --length; if (num_ifindex >= tab_size) { char addr_str[100]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); @@ -243,13 +235,7 @@ static int zclient_read_nexthop(struct zclient *zlookup, case NEXTHOP_TYPE_IPV4_IFINDEX: nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; if (nexthop_type == NEXTHOP_TYPE_IPV4_IFINDEX) { - if (length < 4) { - zlog_err("%s: socket %d short input expecting nexthop IPv4-addr: len=%d", - __func__, zlookup->sock, length); - return -8; - } nexthop_tab[num_ifindex].nexthop_addr.u.prefix4.s_addr = stream_get_ipv4(s); - length -= 4; } else { nexthop_tab[num_ifindex].nexthop_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY; @@ -262,7 +248,6 @@ static int zclient_read_nexthop(struct zclient *zlookup, case NEXTHOP_TYPE_IPV4: nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; nexthop_tab[num_ifindex].nexthop_addr.u.prefix4.s_addr = stream_get_ipv4(s); - length -= 4; nexthop_tab[num_ifindex].ifindex = 0; nexthop_tab[num_ifindex].protocol_distance = distance; nexthop_tab[num_ifindex].route_metric = metric; @@ -277,6 +262,18 @@ static int zclient_read_nexthop(struct zclient *zlookup, } ++num_ifindex; break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET6; + stream_get (&nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, s, 16); + nexthop_tab[num_ifindex].ifindex = stream_getl (s); + nbr = pim_neighbor_find_if (if_lookup_by_index_vrf (nexthop_tab[num_ifindex].ifindex, VRF_DEFAULT)); + if (nbr) + { + nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; + nexthop_tab[num_ifindex].nexthop_addr.u.prefix4 = nbr->source_addr; + } + ++num_ifindex; + break; default: /* do nothing */ { From 4a4c0d0c551749fdb94e73447990d36067b09c89 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 7 Sep 2016 15:43:17 -0400 Subject: [PATCH 152/386] pimd: Fix unguarded log message In pim_rpf.c when we receive multiple paths for the rpf we are complaining that we are not sure what to do with it yet. Change the _info to _debug and don't print out unless we are debugging stuff. Signed-off-by: Donald Sharp --- pimd/pim_rpf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index f3bdb68305..6b4dd111e7 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -60,10 +60,10 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr) first_ifindex = nexthop_tab[0].ifindex; - if (num_ifindex > 1) { + if (num_ifindex > 1 && PIM_DEBUG_ZEBRA) { char addr_str[100]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_info("%s %s: FIXME ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)", + zlog_debug("%s %s: Ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)", __FILE__, __PRETTY_FUNCTION__, num_ifindex, addr_str, first_ifindex); /* debug warning only, do not return */ From 111285870d5ef9a6cd8394aae5d1662fd9c27925 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 8 Sep 2016 13:17:38 -0400 Subject: [PATCH 153/386] pimd: Add some MSDP infrastructure Add some very basic MSDP infrastructure to pim. Signed-off-by: Donald Sharp --- pimd/Makefile.am | 6 +++-- pimd/pim_main.c | 2 ++ pimd/pim_msdp.c | 32 +++++++++++++++++++++++++++ pimd/pim_msdp.h | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 pimd/pim_msdp.c create mode 100644 pimd/pim_msdp.h diff --git a/pimd/Makefile.am b/pimd/Makefile.am index eba05076d5..07679f2794 100644 --- a/pimd/Makefile.am +++ b/pimd/Makefile.am @@ -54,7 +54,8 @@ libpim_a_SOURCES = \ pim_hello.c pim_ifchannel.c pim_join.c pim_assert.c \ pim_msg.c pim_upstream.c pim_rpf.c pim_macro.c \ pim_ssmpingd.c pim_int.c pim_rp.c \ - pim_static.c pim_br.c pim_register.c pim_routemap.c + pim_static.c pim_br.c pim_register.c pim_routemap.c \ + pim_msdp.c noinst_HEADERS = \ pim_memory.h \ @@ -65,7 +66,8 @@ noinst_HEADERS = \ pim_hello.h pim_ifchannel.h pim_join.h pim_assert.h \ pim_msg.h pim_upstream.h pim_rpf.h pim_macro.h \ pim_igmp_join.h pim_ssmpingd.h pim_int.h pim_rp.h \ - pim_static.h pim_br.h pim_register.h + pim_static.h pim_br.h pim_register.h \ + pim_msdp.h pimd_SOURCES = \ pim_main.c $(libpim_a_SOURCES) diff --git a/pimd/pim_main.c b/pimd/pim_main.c index 337f925271..53c7e092aa 100644 --- a/pimd/pim_main.c +++ b/pimd/pim_main.c @@ -44,6 +44,7 @@ #include "pim_version.h" #include "pim_signals.h" #include "pim_zebra.h" +#include "pim_msdp.h" #ifdef PIM_ZCLIENT_DEBUG extern int zclient_debug; @@ -209,6 +210,7 @@ int main(int argc, char** argv, char** envp) { prefix_list_init (); pim_route_map_init (); pim_init(); + pim_msdp_init (); /* * Initialize zclient "update" and "lookup" sockets diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c new file mode 100644 index 0000000000..8cfe7864a3 --- /dev/null +++ b/pimd/pim_msdp.c @@ -0,0 +1,32 @@ +/* + * PIM for Quagga + * Copyright (C) 2016 Cumulus Networks, Inc. + * Donald Sharp + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include + +#include + +#include + +void +pim_msdp_init (void) +{ + return; +} diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h new file mode 100644 index 0000000000..c6c38be257 --- /dev/null +++ b/pimd/pim_msdp.h @@ -0,0 +1,57 @@ +/* + * PIM for Quagga + * Copyright (C) 2016 Cumulus Networks, Inc. + * Donald Sharp + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +#ifndef PIM_MSDP_H +#define PIM_MSDP_H + +enum pim_msdp_states_t + { + PIM_MSDP_DISABLED, + PIM_MSDP_INACTIVE, + PIM_MSDP_LISTEN, + PIM_MSDP_CONNECTING, + PIM_MSDP_ESTABLISHED + }; + +enum pim_msdp_tlv_t + { + PIM_MSDP_V4_SOURCE_ACTIVE = 1, + PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST, + PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE, + PIM_MSDP_KEEPALIVE, + PIM_MSDP_RESERVED, + PIM_MSDP_TRACEROUTE_PROGRESS, + PIM_MSDP_TRACEROUTE_REPLY, + }; + +struct pim_msdp_t +{ + enum pim_msdp_states_t state; + + struct prefix peer; + + struct thread *cr_timer; // 5.6 + struct thread *h_timer; // 5.4 + struct thread *ka_timer; // 5.5 + +}; + +void pim_msdp_init (void); +#endif From 44a13ae330902eafbd098f711f886ad44c88f664 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Fri, 9 Sep 2016 20:24:31 +0000 Subject: [PATCH 154/386] Unable to remove route-map from quagga Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-12816 pim was missing route-map hooks (cherry picked from commit 28b0c6b377e56e76c674c27e384238a755b173b2) Conflicts: pimd/pimd.c --- pimd/pimd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/pimd/pimd.c b/pimd/pimd.c index 3d1648c270..881c75dfb4 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -92,6 +92,7 @@ static void pim_free() pim_route_map_terminate(); pim_rp_free (); + pim_route_map_terminate(); } void pim_init() From 29444f8feebd0a15da246c22280010d63935e0b8 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 12 Sep 2016 09:01:46 -0400 Subject: [PATCH 155/386] pimd: Fix high cpu load of pim when interface goes down When a interface goes down we accidently put ourselves into an infinite loop. Ticket: CM-12803 Signed-off-by: Donald Sharp --- pimd/pim_pim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 8b34a45576..991bac8a2e 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -523,8 +523,8 @@ pim_msg_send_frame (int fd, char *buf, size_t len, __PRETTY_FUNCTION__, dst_str, fd, len, errno, safe_strerror(errno)); - break; return -1; + break; } } From f3f0c4f8ccefaf38470716bd4c38eae6e7937aa3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 12 Sep 2016 15:09:28 -0400 Subject: [PATCH 156/386] pimd: Startup does not need to assert When pim starts up there is no need to assert in pim_init if state is not set as wanted. Especially for qpim_debugs as that I would like to turn on debugs before we even start doing anything in the code. As for the PIM_MROUTE_IS_ENABLED, the variable is set right above it, so no need to assert on it. Signed-off-by: Donald Sharp --- pimd/pimd.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/pimd/pimd.c b/pimd/pimd.c index 881c75dfb4..94c8f20e97 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -139,9 +139,6 @@ void pim_init() qpim_mroute_socket_fd = -1; /* mark mroute as disabled */ qpim_mroute_oif_highest_vif_index = -1; - zassert(!qpim_debugs); - zassert(!PIM_MROUTE_IS_ENABLED); - qpim_inaddr_any.s_addr = PIM_NET_INADDR_ANY; /* From 80219b763ace68907c57257686b494919de84168 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 12 Sep 2016 19:30:27 -0400 Subject: [PATCH 157/386] pimd: Vif is not created in some startup conditions When rebooting a switch, if under unnumbered config there exists a situation where some interfaces may not create the vif in the kernel. Ticket: CM-12830 Signed-off-by: Donald Sharp --- pimd/pim_zebra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index f2789369bf..d4eb2d3252 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -264,9 +264,9 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient, } if (!v4addrs && pim_ifp) { - pim_ifp->primary_address = pim_find_primary_addr (c->ifp); pim_if_addr_add_all (c->ifp); + pim_if_add_vif (c->ifp); } return 0; } From 69ff3706d4be66227db1ea3f506b1df529219ab3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 12 Sep 2016 16:50:30 +0000 Subject: [PATCH 158/386] pimd: Allow flags to know if this is a FHR or not Start the switch of storing if the upstream (S,G) is located on the FHR or not. Signed-off-by: Donald Sharp --- pimd/pim_upstream.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 35cd8dc014..26a0cd0a7c 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -29,15 +29,19 @@ #define PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED (1 << 0) #define PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED (2 << 0) +#define PIM_UPSTREAM_FLAG_MASK_FHR (3 << 0) #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) +#define PIM_UPSTREAM_FLAG_TEST_FHR(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_FHR) #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) +#define PIM_UPSTREAM_FLAG_SET_FHR(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_FHR) #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) +#define PIM_UPSTREAM_FLAG_UNSET_FHR(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_FHR) enum pim_upstream_state { PIM_UPSTREAM_NOTJOINED, From 0bf27c5c4c3128ecfe5da881eb570d9d450cedc8 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 12 Sep 2016 17:02:53 +0000 Subject: [PATCH 159/386] pimd: Switch all up->fhr to use up->flags Allow up->flags to know if we are a FHR or not Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 6 +++--- pimd/pim_upstream.c | 10 +++++----- pimd/pim_upstream.h | 1 - 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index f498bfcd00..cf98f32c24 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -148,7 +148,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg up->channel_oil = oil; up->channel_oil->cc.pktcnt++; - up->fhr = 1; + PIM_UPSTREAM_FLAG_SET_FHR(up->flags); pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); up->join_state = PIM_UPSTREAM_JOINED; @@ -335,7 +335,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) * If we are the fhr that means we are getting a callback during * the pimreg period, so I believe we can ignore this packet */ - if (!up->fhr) + if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) { struct pim_nexthop source; struct pim_rpf *rpf = RP (sg.grp); @@ -369,7 +369,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) pim_str_sg_dump (&sg), ifp->name); return -2; } - up->fhr = 1; + PIM_UPSTREAM_FLAG_SET_FHR(up->flags); pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); up->channel_oil = oil; diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 13e7c55c55..24e45b576c 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -206,7 +206,7 @@ static int on_join_timer(struct thread *t) /* * In the case of a HFR we will not ahve anyone to send this to. */ - if (up->fhr) + if (PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) return 0; /* @@ -411,7 +411,7 @@ pim_upstream_switch(struct pim_upstream *up, switch (up->join_state) { case PIM_UPSTREAM_PRUNE: - if (!up->fhr) + if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) { up->join_state = new_state; up->state_transition = pim_time_monotonic_sec (); @@ -432,11 +432,11 @@ pim_upstream_switch(struct pim_upstream *up, if (new_state == PIM_UPSTREAM_JOINED) { if (old_state != PIM_UPSTREAM_JOINED) { - int old_fhr = up->fhr; + int old_fhr = PIM_UPSTREAM_FLAG_TEST_FHR(up->flags); forward_on(up); - up->fhr = pim_upstream_could_register (up); - if (up->fhr) + if (pim_upstream_could_register (up)) { + PIM_UPSTREAM_FLAG_SET_FHR(up->flags); if (!old_fhr) { pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 26a0cd0a7c..8fe3559c34 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -64,7 +64,6 @@ enum pim_upstream_sptbit { */ struct pim_upstream { struct pim_upstream *parent; - int fhr; struct in_addr upstream_addr;/* Who we are talking to */ struct in_addr upstream_register; /*Who we received a register from*/ struct prefix_sg sg; /* (S,G) group key */ From 1d3a62cdce1317f962f8646a9c4d1d279c8315b2 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 12 Sep 2016 23:51:02 +0000 Subject: [PATCH 160/386] pimd: Add some additional upstream sources Signed-off-by: Donald Sharp --- pimd/pim_upstream.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 8fe3559c34..f279714a85 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -30,18 +30,30 @@ #define PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED (1 << 0) #define PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED (2 << 0) #define PIM_UPSTREAM_FLAG_MASK_FHR (3 << 0) +#define PIM_UPSTREAM_FLAG_MASK_SRC_IGMP (4 << 0) +#define PIM_UPSTREAM_FLAG_MASK_SRC_PIM (5 << 0) +#define PIM_UPSTREAM_FLAG_MASK_SRC_STREAM (6 << 0) #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) #define PIM_UPSTREAM_FLAG_TEST_FHR(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_FHR) +#define PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) +#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_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) #define PIM_UPSTREAM_FLAG_SET_FHR(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_FHR) +#define PIM_UPSTREAM_FLAG_SET_SRC_IGMP(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) +#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_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) #define PIM_UPSTREAM_FLAG_UNSET_FHR(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_FHR) +#define PIM_UPSTREAM_FLAG_UNSET_SRC_IGMP(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) +#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) enum pim_upstream_state { PIM_UPSTREAM_NOTJOINED, From a9b5987989f65d214b4d3747dec55adab388981d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 13 Sep 2016 12:20:39 +0000 Subject: [PATCH 161/386] pimd: Start noticing where upstream state came from We need the ability to know where upstream state comes from and to do the right thing from there. ticket: CM-12771 Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 3 ++- pimd/pim_upstream.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index cf98f32c24..1bd1b4457e 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -143,6 +143,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg } return 0; } + PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); @@ -361,7 +362,6 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) if (pim_if_connected_to_source (ifp, sg.src)) { up = pim_upstream_add (&sg, ifp); - if (!up) { if (PIM_DEBUG_MROUTE) @@ -369,6 +369,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) pim_str_sg_dump (&sg), ifp->name); return -2; } + PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); PIM_UPSTREAM_FLAG_SET_FHR(up->flags); pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 24e45b576c..66c5268f98 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -437,7 +437,7 @@ pim_upstream_switch(struct pim_upstream *up, if (pim_upstream_could_register (up)) { PIM_UPSTREAM_FLAG_SET_FHR(up->flags); - if (!old_fhr) + if (!old_fhr && PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) { pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); @@ -882,6 +882,7 @@ pim_upstream_keep_alive_timer (struct thread *t) THREAD_OFF (up->t_join_timer); pim_joinprune_send (up->rpf.source_nexthop.interface, up->rpf.rpf_addr.u.prefix4, &up->sg, 0); + PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM (up->flags); pim_upstream_del (up); } else From dfe43e25d86672eef58044455be09a8c3840ca3a Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Tue, 13 Sep 2016 19:41:33 +0000 Subject: [PATCH 162/386] PIM: prefix-list support for selecting RP Signed-off-by: Daniel Walton Reviewed-by: CCR-5173 Ticket: CM-12819 --- pimd/pim_cmd.c | 98 +++++++++--- pimd/pim_join.c | 2 + pimd/pim_macro.c | 3 + pimd/pim_main.c | 4 + pimd/pim_memory.c | 1 + pimd/pim_memory.h | 1 + pimd/pim_mroute.c | 2 + pimd/pim_msg.c | 3 + pimd/pim_register.c | 2 + pimd/pim_rp.c | 358 ++++++++++++++++++++++++++++++++++---------- pimd/pim_rp.h | 5 +- pimd/pim_upstream.c | 2 + pimd/pim_vty.c | 3 + pimd/pim_zebra.c | 2 + pimd/pimd.c | 3 + pimd/pimd.h | 12 ++ 16 files changed, 406 insertions(+), 95 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index fd4da29291..9b58b891e1 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -25,6 +25,7 @@ #include "if.h" #include "prefix.h" #include "zclient.h" +#include "plist.h" #include "pimd.h" #include "pim_mroute.h" @@ -2439,27 +2440,52 @@ DEFUN (show_ip_ssmpingd, } static int -pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group) +pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, const char *plist) { int result; - result = pim_rp_new (rp, group); - if (result == -1) + result = pim_rp_new (rp, group, plist); + + if (result == PIM_MALLOC_FAIL) { - vty_out (vty, "%% Bad RP/group address specified: %s", rp); + vty_out (vty, "%% Out of memory%s", VTY_NEWLINE); return CMD_WARNING; } - if (result == -2) + if (result == PIM_GROUP_BAD_ADDRESS) { - vty_out (vty, "%% No Path to RP address specified: %s", rp); - return CMD_WARNING; + vty_out (vty, "%% Bad group address specified: %s%s", group, VTY_NEWLINE); + return CMD_WARNING; } - if (result == -3) + if (result == PIM_RP_BAD_ADDRESS) { - vty_out (vty, "%% Group range specified cannot overlap"); - return CMD_ERR_NO_MATCH; + vty_out (vty, "%% Bad RP address specified: %s%s", rp, VTY_NEWLINE); + return CMD_WARNING; + } + + if (result == PIM_RP_NO_PATH) + { + vty_out (vty, "%% No Path to RP address specified: %s%s", rp, VTY_NEWLINE); + return CMD_WARNING; + } + + if (result == PIM_GROUP_OVERLAP) + { + vty_out (vty, "%% Group range specified cannot overlap%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (result == PIM_GROUP_PFXLIST_OVERLAP) + { + vty_out (vty, "%% This group is already covered by a RP prefix-list%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (result == PIM_RP_PFXLIST_IN_USE) + { + vty_out (vty, "%% The same prefix-list cannot be applied to multiple RPs%s", VTY_NEWLINE); + return CMD_WARNING; } return CMD_SUCCESS; @@ -2526,23 +2552,43 @@ DEFUN (ip_pim_rp, "ip address of RP\n") { int idx_ipv4 = 3; - return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg); + return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL); +} + +DEFUN (ip_pim_rp_prefix_list, + ip_pim_rp_prefix_list_cmd, + "ip pim rp A.B.C.D prefix-list WORD", + IP_STR + "pim multicast routing\n" + "Rendevous Point\n" + "ip address of RP\n" + "group prefix-list filter\n" + "Name of a prefix-list\n") +{ + return pim_rp_cmd_worker (vty, argv[3]->arg, NULL, argv[5]->arg); } static int -pim_no_rp_cmd_worker (struct vty *vty, const char *rp, const char *group) +pim_no_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, + const char *plist) { - int result = pim_rp_del (rp, group); + int result = pim_rp_del (rp, group, plist); - if (result == -1) + if (result == PIM_GROUP_BAD_ADDRESS) { - vty_out (vty, "%% Unable to Decode specified RP"); + vty_out (vty, "%% Bad group address specified: %s%s", group, VTY_NEWLINE); return CMD_WARNING; } - if (result == -2) + if (result == PIM_RP_BAD_ADDRESS) { - vty_out (vty, "%% Unable to find specified RP"); + vty_out (vty, "%% Bad RP address specified: %s%s", rp, VTY_NEWLINE); + return CMD_WARNING; + } + + if (result == PIM_RP_NOT_FOUND) + { + vty_out (vty, "%% Unable to find specified RP%s", VTY_NEWLINE); return CMD_WARNING; } @@ -2559,7 +2605,21 @@ DEFUN (no_ip_pim_rp, "ip address of RP\n") { int idx_ipv4 = 4; - return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg); + return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL); +} + +DEFUN (no_ip_pim_rp_prefix_list, + no_ip_pim_rp_prefix_list_cmd, + "no ip pim rp A.B.C.D prefix-list WORD", + NO_STR + IP_STR + "pim multicast routing\n" + "Rendevous Point\n" + "ip address of RP\n" + "group prefix-list filter\n" + "Name of a prefix-list\n") +{ + return pim_no_rp_cmd_worker (vty, argv[4]->arg, NULL, argv[6]->arg); } DEFUN (ip_multicast_routing, @@ -4821,6 +4881,8 @@ void pim_cmd_init() install_element (CONFIG_NODE, &no_ip_multicast_routing_cmd); install_element (CONFIG_NODE, &ip_pim_rp_cmd); install_element (CONFIG_NODE, &no_ip_pim_rp_cmd); + install_element (CONFIG_NODE, &ip_pim_rp_prefix_list_cmd); + install_element (CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd); install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd); install_element (CONFIG_NODE, &no_ip_pim_keep_alive_cmd); install_element (CONFIG_NODE, &ip_pim_rp_keep_alive_cmd); diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 1f722e7637..7bec6c7eca 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -24,6 +24,8 @@ #include "log.h" #include "prefix.h" #include "if.h" +#include "vty.h" +#include "plist.h" #include "pimd.h" #include "pim_str.h" diff --git a/pimd/pim_macro.c b/pimd/pim_macro.c index 4bcb62a90e..177de66673 100644 --- a/pimd/pim_macro.c +++ b/pimd/pim_macro.c @@ -22,6 +22,9 @@ #include #include "log.h" +#include "prefix.h" +#include "vty.h" +#include "plist.h" #include "pim_macro.h" #include "pimd.h" diff --git a/pimd/pim_main.c b/pimd/pim_main.c index 53c7e092aa..1ddc1eac54 100644 --- a/pimd/pim_main.c +++ b/pimd/pim_main.c @@ -45,6 +45,7 @@ #include "pim_signals.h" #include "pim_zebra.h" #include "pim_msdp.h" +#include "pim_rp.h" #ifdef PIM_ZCLIENT_DEBUG extern int zclient_debug; @@ -208,6 +209,9 @@ int main(int argc, char** argv, char** envp) { vrf_init (); access_list_init(); prefix_list_init (); + prefix_list_add_hook (pim_rp_prefix_list_update); + prefix_list_delete_hook (pim_rp_prefix_list_update); + pim_route_map_init (); pim_init(); pim_msdp_init (); diff --git a/pimd/pim_memory.c b/pimd/pim_memory.c index 9994ea5d6b..219dd96816 100644 --- a/pimd/pim_memory.c +++ b/pimd/pim_memory.c @@ -40,3 +40,4 @@ DEFINE_MTYPE(PIMD, PIM_SSMPINGD, "PIM sspimgd socket") DEFINE_MTYPE(PIMD, PIM_STATIC_ROUTE, "PIM Static Route") DEFINE_MTYPE(PIMD, PIM_BR, "PIM Bridge Router info") DEFINE_MTYPE(PIMD, PIM_RP, "PIM RP info") +DEFINE_MTYPE(PIMD, PIM_FILTER_NAME, "PIM Filter Name") diff --git a/pimd/pim_memory.h b/pimd/pim_memory.h index 3d3f14467b..fc0dd91f85 100644 --- a/pimd/pim_memory.h +++ b/pimd/pim_memory.h @@ -39,5 +39,6 @@ DECLARE_MTYPE(PIM_SSMPINGD) DECLARE_MTYPE(PIM_STATIC_ROUTE) DECLARE_MTYPE(PIM_BR) DECLARE_MTYPE(PIM_RP) +DECLARE_MTYPE(PIM_FILTER_NAME) #endif /* _QUAGGA_PIM_MEMORY_H */ diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 1bd1b4457e..1f64a6e299 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -24,6 +24,8 @@ #include "privs.h" #include "if.h" #include "prefix.h" +#include "vty.h" +#include "plist.h" #include "pimd.h" #include "pim_rpf.h" diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index 62e0bb1a36..0eadb5eb38 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -23,6 +23,9 @@ #include "if.h" #include "log.h" +#include "prefix.h" +#include "vty.h" +#include "plist.h" #include "pimd.h" #include "pim_vty.h" diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 4131c5ef01..ebc46f60ea 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -25,6 +25,8 @@ #include "if.h" #include "thread.h" #include "prefix.h" +#include "vty.h" +#include "plist.h" #include "pimd.h" #include "pim_mroute.h" diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index daf825f6d8..78dc0e8550 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -28,6 +28,7 @@ #include "memory.h" #include "vty.h" #include "vrf.h" +#include "plist.h" #include "pimd.h" #include "pim_vty.h" @@ -44,6 +45,7 @@ struct rp_info struct prefix group; struct pim_rpf rp; int i_am_rp; + char *plist; }; static struct list *qpim_rp_list = NULL; @@ -70,6 +72,24 @@ pim_rp_list_cmp (void *v1, void *v2) if (rp1 && !rp2) return 1; + /* + * Sort by RP IP address + */ + if (rp1->rp.rpf_addr.u.prefix4.s_addr < rp2->rp.rpf_addr.u.prefix4.s_addr) + return -1; + + if (rp1->rp.rpf_addr.u.prefix4.s_addr > rp2->rp.rpf_addr.u.prefix4.s_addr) + return 1; + + /* + * Sort by group IP address + */ + if (rp1->group.u.prefix4.s_addr < rp2->group.u.prefix4.s_addr) + return -1; + + if (rp1->group.u.prefix4.s_addr > rp2->group.u.prefix4.s_addr) + return 1; + if (rp1 == tail) return 1; @@ -106,6 +126,50 @@ pim_rp_free (void) list_free (qpim_rp_list); } +/* + * Given an RP's prefix-list, return the RP's rp_info for that prefix-list + */ +static struct rp_info * +pim_rp_find_prefix_list (struct in_addr rp, const char *plist) +{ + struct listnode *node; + struct rp_info *rp_info; + + for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) + { + if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr && + rp_info->plist && strcmp(rp_info->plist, plist) == 0) + { + return rp_info; + } + } + + return NULL; +} + +/* + * Return true if plist is used by any rp_info + */ +static int +pim_rp_prefix_list_used (const char *plist) +{ + struct listnode *node; + struct rp_info *rp_info; + + for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) + { + if (rp_info->plist && strcmp(rp_info->plist, plist) == 0) + { + return 1; + } + } + + return 0; +} + +/* + * Given an RP's address, return the RP's rp_info that is an exact match for 'group' + */ static struct rp_info * pim_rp_find_exact (struct in_addr rp, struct prefix *group) { @@ -122,37 +186,67 @@ pim_rp_find_exact (struct in_addr rp, struct prefix *group) return NULL; } -static struct rp_info * -pim_rp_find_match (struct in_addr rp, struct prefix *group) -{ - struct listnode *node; - struct rp_info *rp_info; - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr && - prefix_match (&rp_info->group, group)) - return rp_info; - } - - return NULL; -} - +/* + * Given a group, return the rp_info for that group + */ static struct rp_info * pim_rp_find_match_group (struct prefix *group) { struct listnode *node; struct rp_info *rp_info; + struct prefix_list *plist; for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { - if (prefix_match (&rp_info->group, group)) - return rp_info; + if (rp_info->plist) + { + plist = prefix_list_lookup (AFI_IP, rp_info->plist); + + if (plist && prefix_list_apply (plist, group) == PREFIX_PERMIT) + return rp_info; + } + else + { + if (prefix_match (&rp_info->group, group)) + return rp_info; + } } return NULL; } +/* + * When the user makes "ip pim rp" configuration changes or if they change the + * prefix-list(s) used by these statements we must tickle the upstream state + * for each group to make them re-lookup who their RP should be. + * + * This is a placeholder function for now. + */ +static void +pim_rp_refresh_group_to_rp_mapping() +{ +} + +void +pim_rp_prefix_list_update (struct prefix_list *plist) +{ + struct listnode *node; + struct rp_info *rp_info; + int refresh_needed = 0; + + for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) + { + if (rp_info->plist && strcmp(rp_info->plist, prefix_list_name (plist)) == 0) + { + refresh_needed = 1; + break; + } + } + + if (refresh_needed) + pim_rp_refresh_group_to_rp_mapping(); +} + static void pim_rp_check_interfaces (struct rp_info *rp_info) { @@ -172,19 +266,19 @@ pim_rp_check_interfaces (struct rp_info *rp_info) } int -pim_rp_new (const char *rp, const char *group_range) +pim_rp_new (const char *rp, const char *group_range, const char *plist) { int result; struct rp_info *rp_info; struct rp_info *rp_all; struct prefix group_all; - - str2prefix ("224.0.0.0/4", &group_all); - rp_all = pim_rp_find_match_group(&group_all); + struct listnode *node, *nnode; + struct rp_info *tmp_rp_info; + char buffer[BUFSIZ]; rp_info = XCALLOC (MTYPE_PIM_RP, sizeof (*rp_info)); - if (!rp) - return -1; + if (!rp_info) + return PIM_MALLOC_FAIL; if (group_range == NULL) result = str2prefix ("224.0.0.0/4", &rp_info->group); @@ -192,54 +286,147 @@ pim_rp_new (const char *rp, const char *group_range) result = str2prefix (group_range, &rp_info->group); if (!result) - return -1; + { + XFREE (MTYPE_PIM_RP, rp_info); + return PIM_GROUP_BAD_ADDRESS; + } + rp_info->rp.rpf_addr.family = AF_INET; result = inet_pton (rp_info->rp.rpf_addr.family, rp, &rp_info->rp.rpf_addr.u.prefix4); + if (result <= 0) - return -1; - - /* - * Take over the 224.0.0.0/4 group if the rp is INADDR_NONE - */ - if (prefix_same (&rp_all->group, &rp_info->group) && - pim_rpf_addr_is_inaddr_none (&rp_all->rp)) - { - rp_all->rp.rpf_addr = rp_info->rp.rpf_addr; - XFREE (MTYPE_PIM_RP, rp_info); - if (!pim_rp_setup ()) - return -2; - pim_rp_check_interfaces (rp_all); - return 0; - } - - if (pim_rp_find_exact (rp_info->rp.rpf_addr.u.prefix4, &rp_info->group)) { XFREE (MTYPE_PIM_RP, rp_info); - return 0; + return PIM_RP_BAD_ADDRESS; } - if (pim_rp_find_match (rp_info->rp.rpf_addr.u.prefix4, &rp_info->group)) + if (plist) { - if (prefix_same (&group_all, &rp_info->group)) + /* + * Return if the prefix-list is already configured for this RP + */ + if (pim_rp_find_prefix_list (rp_info->rp.rpf_addr.u.prefix4, plist)) { - return 0; + XFREE (MTYPE_PIM_RP, rp_info); + return PIM_SUCCESS; } - XFREE (MTYPE_PIM_RP, rp_info); - return -3; + /* + * Barf if the prefix-list is already configured for an RP + */ + if (pim_rp_prefix_list_used (plist)) + { + XFREE (MTYPE_PIM_RP, rp_info); + return PIM_RP_PFXLIST_IN_USE; + } + + /* + * Free any existing rp_info entries for this RP + */ + for (ALL_LIST_ELEMENTS (qpim_rp_list, node, nnode, tmp_rp_info)) + { + if (rp_info->rp.rpf_addr.u.prefix4.s_addr == tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr) + { + if (tmp_rp_info->plist) + pim_rp_del (rp, NULL, tmp_rp_info->plist); + else + pim_rp_del (rp, prefix2str(&tmp_rp_info->group, buffer, BUFSIZ), NULL); + } + } + + rp_info->plist = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist); + } + else + { + str2prefix ("224.0.0.0/4", &group_all); + rp_all = pim_rp_find_match_group(&group_all); + + /* + * Barf if group is a non-multicast subnet + */ + if (! prefix_match (&rp_all->group, &rp_info->group)) + { + XFREE (MTYPE_PIM_RP, rp_info); + return PIM_GROUP_BAD_ADDRESS; + } + + /* + * Remove any prefix-list rp_info entries for this RP + */ + for (ALL_LIST_ELEMENTS (qpim_rp_list, node, nnode, tmp_rp_info)) + { + if (tmp_rp_info->plist && + rp_info->rp.rpf_addr.u.prefix4.s_addr == tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr) + { + pim_rp_del (rp, NULL, tmp_rp_info->plist); + } + } + + /* + * Take over the 224.0.0.0/4 group if the rp is INADDR_NONE + */ + if (prefix_same (&rp_all->group, &rp_info->group) && + pim_rpf_addr_is_inaddr_none (&rp_all->rp)) + { + rp_all->rp.rpf_addr = rp_info->rp.rpf_addr; + XFREE (MTYPE_PIM_RP, rp_info); + + if (!pim_rp_setup ()) + return PIM_RP_NO_PATH; + + pim_rp_check_interfaces (rp_all); + return PIM_SUCCESS; + } + + /* + * Return if the group is already configured for this RP + */ + if (pim_rp_find_exact (rp_info->rp.rpf_addr.u.prefix4, &rp_info->group)) + { + XFREE (MTYPE_PIM_RP, rp_info); + return PIM_SUCCESS; + } + + /* + * Barf if this group is already covered by some other RP + */ + tmp_rp_info = pim_rp_find_match_group (&rp_info->group); + + if (tmp_rp_info) + { + if (tmp_rp_info->plist) + { + XFREE (MTYPE_PIM_RP, rp_info); + return PIM_GROUP_PFXLIST_OVERLAP; + } + else + { + /* + * If the only RP that covers this group is an RP configured for + * 224.0.0.0/4 that is fine, ignore that one. For all others + * though we must return PIM_GROUP_OVERLAP + */ + if (! prefix_same (&group_all, &tmp_rp_info->group)) + { + XFREE (MTYPE_PIM_RP, rp_info); + return PIM_GROUP_OVERLAP; + } + } + } } listnode_add_sort (qpim_rp_list, rp_info); if (!pim_rp_setup ()) - return -2; + return PIM_RP_NO_PATH; pim_rp_check_interfaces (rp_info); - return 0; + pim_rp_refresh_group_to_rp_mapping(); + return PIM_SUCCESS; } int -pim_rp_del (const char *rp, const char *group_range) +pim_rp_del (const char *rp, const char *group_range, const char *plist) { struct prefix group; struct in_addr rp_addr; @@ -248,35 +435,46 @@ pim_rp_del (const char *rp, const char *group_range) struct rp_info *rp_all; int result; - str2prefix ("224.0.0.0/4", &g_all); if (group_range == NULL) result = str2prefix ("224.0.0.0/4", &group); else result = str2prefix (group_range, &group); if (!result) - return -1; - - rp_all = pim_rp_find_match_group (&g_all); + return PIM_GROUP_BAD_ADDRESS; result = inet_pton (AF_INET, rp, &rp_addr); if (result <= 0) - return -1; + return PIM_RP_BAD_ADDRESS; + + if (plist) + rp_info = pim_rp_find_prefix_list (rp_addr, plist); + else + rp_info = pim_rp_find_exact (rp_addr, &group); - rp_info = pim_rp_find_exact (rp_addr, &group); if (!rp_info) - return -2; + return PIM_RP_NOT_FOUND; + + if (rp_info->plist) + { + XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist); + rp_info->plist = NULL; + } + + str2prefix ("224.0.0.0/4", &g_all); + rp_all = pim_rp_find_match_group (&g_all); if (rp_all == rp_info) { rp_all->rp.rpf_addr.family = AF_INET; rp_all->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; rp_all->i_am_rp = 0; - return 0; + return PIM_SUCCESS; } listnode_delete (qpim_rp_list, rp_info); - return 0; + pim_rp_refresh_group_to_rp_mapping(); + return PIM_SUCCESS; } int @@ -430,7 +628,8 @@ pim_rp_config_write (struct vty *vty) { struct listnode *node; struct rp_info *rp_info; - char buffer[32]; + char rp_buffer[32]; + char group_buffer[32]; int count = 0; for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) @@ -438,13 +637,15 @@ pim_rp_config_write (struct vty *vty) if (pim_rpf_addr_is_inaddr_none (&rp_info->rp)) continue; - if (!pim_rpf_addr_is_inaddr_none (&rp_info->rp)) - { - char buf[32]; - vty_out(vty, "ip pim rp %s %s%s", inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, buffer, 32), - prefix2str(&rp_info->group, buf, 32), VTY_NEWLINE); - count++; - } + if (rp_info->plist) + vty_out(vty, "ip pim rp %s prefix-list %s%s", + inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, rp_buffer, 32), + rp_info->plist, VTY_NEWLINE); + else + vty_out(vty, "ip pim rp %s %s%s", + inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, rp_buffer, 32), + prefix2str(&rp_info->group, group_buffer, 32), VTY_NEWLINE); + count++; } return count; @@ -486,18 +687,25 @@ pim_rp_show_information (struct vty *vty) struct rp_info *rp_info; struct listnode *node; - vty_out (vty, "RP Addr Group Oif I_am_RP%s", VTY_NEWLINE); + vty_out (vty, "RP address group/prefix-list OIF I am RP%s", VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { if (!pim_rpf_addr_is_inaddr_none (&rp_info->rp)) { char buf[48]; - vty_out (vty, "%-10s %-10s %-10s%-10d%s", - inet_ntoa (rp_info->rp.rpf_addr.u.prefix4), - prefix2str(&rp_info->group, buf, 48), - rp_info->rp.source_nexthop.interface->name, - rp_info->i_am_rp, VTY_NEWLINE); + vty_out (vty, "%-15s ", inet_ntoa (rp_info->rp.rpf_addr.u.prefix4)); + + if (rp_info->plist) + vty_out (vty, "%-18s ", rp_info->plist); + else + vty_out (vty, "%-18s ", prefix2str(&rp_info->group, buf, 48)); + + vty_out (vty, "%-10s ", rp_info->rp.source_nexthop.interface->name); + + if (rp_info->i_am_rp) + vty_out (vty, "yes%s", VTY_NEWLINE); + else + vty_out (vty, "no%s", VTY_NEWLINE); } } - return; } diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index c9dfa201f1..230f4f08ff 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -24,8 +24,9 @@ void pim_rp_init (void); void pim_rp_free (void); -int pim_rp_new (const char *rp, const char *group); -int pim_rp_del (const char *rp, const char *group); +int pim_rp_new (const char *rp, const char *group, const char *plist); +int pim_rp_del (const char *rp, const char *group, const char *plist); +void pim_rp_prefix_list_update (struct prefix_list *plist); int pim_rp_config_write (struct vty *vty); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 66c5268f98..7f1357783a 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -28,6 +28,8 @@ #include "memory.h" #include "thread.h" #include "linklist.h" +#include "vty.h" +#include "plist.h" #include "pimd.h" #include "pim_pim.h" diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 85df83287b..3eb04d347e 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -23,7 +23,10 @@ #include "if.h" #include "linklist.h" +#include "prefix.h" +#include "vty.h" #include "vrf.h" +#include "plist.h" #include "pimd.h" #include "pim_vty.h" diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index d4eb2d3252..cfdc447fc3 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -29,6 +29,8 @@ #include "zclient.h" #include "stream.h" #include "network.h" +#include "vty.h" +#include "plist.h" #include "pimd.h" #include "pim_pim.h" diff --git a/pimd/pimd.c b/pimd/pimd.c index 94c8f20e97..dff3f75aed 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -24,6 +24,9 @@ #include "log.h" #include "memory.h" #include "if.h" +#include "prefix.h" +#include "vty.h" +#include "plist.h" #include "pimd.h" #include "pim_cmd.h" diff --git a/pimd/pimd.h b/pimd/pimd.h index f7a02f9376..46b3e5ce78 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -71,6 +71,18 @@ #define PIM_MASK_STATIC (1 << 17) #define PIM_MASK_PIM_REG (1 << 18) + +/* PIM error codes */ +#define PIM_SUCCESS 0 +#define PIM_MALLOC_FAIL -1 +#define PIM_GROUP_BAD_ADDRESS -2 +#define PIM_GROUP_OVERLAP -3 +#define PIM_GROUP_PFXLIST_OVERLAP -4 +#define PIM_RP_BAD_ADDRESS -5 +#define PIM_RP_NO_PATH -6 +#define PIM_RP_NOT_FOUND -7 +#define PIM_RP_PFXLIST_IN_USE -8 + const char *const PIM_ALL_SYSTEMS; const char *const PIM_ALL_ROUTERS; const char *const PIM_ALL_PIM_ROUTERS; From 9bf3c63317478b9a9e954019eb04b87c9f128b1b Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 14 Sep 2016 15:12:13 +0000 Subject: [PATCH 163/386] PIM: json support for "show ip pim" commands Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-12865 --- pimd/pim_cmd.c | 672 +++++++++++++++++++++++++++++++++++++------------ pimd/pim_rp.c | 74 +++++- pimd/pim_rp.h | 2 +- 3 files changed, 575 insertions(+), 173 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 9b58b891e1..a3ff7c25ed 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -21,6 +21,7 @@ #include +#include "lib/json.h" #include "command.h" #include "if.h" #include "prefix.h" @@ -558,20 +559,27 @@ static void show_interface_address(struct vty *vty) } } -static void pim_show_dr(struct vty *vty) +static void pim_show_dr(struct vty *vty, u_char uj) { struct listnode *node; struct interface *ifp; time_t now; + json_object *json = NULL; + json_object *json_row = NULL; now = pim_time_monotonic_sec(); - vty_out(vty, - "NonPri: Number of neighbors missing DR Priority hello option%s" - "DrPri: Designated Router Priority sent%s%s", - VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, + "NonPri: Number of neighbors missing DR Priority hello option%s" + "DrPri: Designated Router Priority sent%s%s", + VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); - vty_out(vty, "Interface Address DR Uptime Elections Changes NonPri DrPri%s", VTY_NEWLINE); + vty_out(vty, "Interface Address DR Uptime Elections Changes NonPri DrPri%s", VTY_NEWLINE); + } + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { struct pim_interface *pim_ifp; @@ -595,28 +603,52 @@ static void pim_show_dr(struct vty *vty) pim_inet4_dump("", pim_ifp->pim_dr_addr, dr_str, sizeof(dr_str)); - vty_out(vty, "%-9s %-15s %-15s %8s %9d %7d %6d %10d%s", - ifp->name, - inet_ntoa(ifaddr), - dr_str, - dr_uptime, - pim_ifp->pim_dr_election_count, - pim_ifp->pim_dr_election_changes, - pim_ifp->pim_dr_num_nondrpri_neighbors, - pim_ifp->pim_dr_priority, - VTY_NEWLINE); + if (uj) { + json_row = json_object_new_object(); + json_object_string_add(json_row, "interface", ifp->name); + json_object_string_add(json_row, "address", inet_ntoa(ifaddr)); + json_object_string_add(json_row, "drAddress", dr_str); + json_object_string_add(json_row, "drUpTime", dr_uptime); + json_object_int_add(json_row, "drElections", pim_ifp->pim_dr_election_count); + json_object_int_add(json_row, "drChanges", pim_ifp->pim_dr_election_changes); + json_object_int_add(json_row, "drPriorityMissing", pim_ifp->pim_dr_num_nondrpri_neighbors); + json_object_int_add(json_row, "drPrioritySent", pim_ifp->pim_dr_priority); + json_object_object_add(json, ifp->name, json_row); + } else { + vty_out(vty, "%-9s %-15s %-15s %8s %9d %7d %6d %10d%s", + ifp->name, + inet_ntoa(ifaddr), + dr_str, + dr_uptime, + pim_ifp->pim_dr_election_count, + pim_ifp->pim_dr_election_changes, + pim_ifp->pim_dr_num_nondrpri_neighbors, + pim_ifp->pim_dr_priority, + VTY_NEWLINE); + } + } + + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); } } -static void pim_show_hello(struct vty *vty) +static void pim_show_hello(struct vty *vty, u_char uj) { struct listnode *node; struct interface *ifp; time_t now; + json_object *json = NULL; + json_object *json_row = NULL; now = pim_time_monotonic_sec(); - vty_out(vty, "Interface Address Period Timer StatStart Recv Rfail Send Sfail LGenid%s", VTY_NEWLINE); + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, "Interface Address Period Timer StatStart Recv Rfail Send Sfail LGenid%s", VTY_NEWLINE); + } for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { struct pim_interface *pim_ifp; @@ -639,7 +671,21 @@ static void pim_show_hello(struct vty *vty) pim_time_mmss(hello_period, sizeof(hello_period), pim_ifp->pim_hello_period); pim_time_uptime(stat_uptime, sizeof(stat_uptime), now - pim_ifp->pim_ifstat_start); - vty_out(vty, "%-9s %-15s %6s %5s %9s %4u %5u %4u %5u %08x%s", + if (uj) { + json_row = json_object_new_object(); + json_object_string_add(json_row, "interface", ifp->name); + json_object_string_add(json_row, "address", inet_ntoa(ifaddr)); + json_object_int_add(json_row, "helloPeriod", pim_ifp->pim_hello_period); + json_object_string_add(json_row, "timer", hello_timer); + json_object_string_add(json_row, "statStart", stat_uptime); + json_object_int_add(json_row, "received", pim_ifp->pim_ifstat_hello_recv); + json_object_int_add(json_row, "receivedFail", pim_ifp->pim_ifstat_hello_recvfail); + json_object_int_add(json_row, "send", pim_ifp->pim_ifstat_hello_sent); + json_object_int_add(json_row, "sendFail", pim_ifp->pim_ifstat_hello_sendfail); + json_object_int_add(json_row, "generationId", pim_ifp->pim_generation_id); + json_object_object_add(json, ifp->name, json_row); + } else { + vty_out(vty, "%-9s %-15s %6s %5s %9s %4u %5u %4u %5u %08x%s", ifp->name, inet_ntoa(ifaddr), hello_period, @@ -651,18 +697,29 @@ static void pim_show_hello(struct vty *vty) pim_ifp->pim_ifstat_hello_sendfail, pim_ifp->pim_generation_id, VTY_NEWLINE); + } + } + + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); } } -static void pim_show_interfaces(struct vty *vty) +static void pim_show_interfaces(struct vty *vty, u_char uj) { struct listnode *node; struct interface *ifp; time_t now; + json_object *json = NULL; + json_object *json_row = NULL; now = pim_time_monotonic_sec(); - vty_out(vty, "Interface Address ifIndex Socket Uptime Multi Broad MLoop AllMu Prmsc Del%s", VTY_NEWLINE); + if (uj) + json = json_object_new_object(); + else + vty_out(vty, "Interface Address ifIndex Socket Uptime Multi Broad MLoop AllMu Prmsc Del%s", VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { struct pim_interface *pim_ifp; @@ -684,19 +741,52 @@ static void pim_show_interfaces(struct vty *vty) mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); - vty_out(vty, "%-9s %-15s %7d %6d %8s %5s %5s %5s %5s %5s %3s%s", - ifp->name, - inet_ntoa(ifaddr), - ifp->ifindex, - pim_ifp->pim_sock_fd, - uptime, - if_is_multicast(ifp) ? "yes" : "no", - if_is_broadcast(ifp) ? "yes" : "no", - (mloop < 0) ? "?" : (mloop ? "yes" : "no"), - (ifp->flags & IFF_ALLMULTI) ? "yes" : "no", - (ifp->flags & IFF_PROMISC) ? "yes" : "no", - PIM_IF_IS_DELETED(ifp) ? "yes" : "no", - VTY_NEWLINE); + if (uj) { + json_row = json_object_new_object(); + json_object_string_add(json_row, "address", inet_ntoa(ifaddr)); + json_object_int_add(json_row, "ifIndex", ifp->ifindex); + json_object_int_add(json_row, "socket", pim_ifp->pim_sock_fd); + json_object_string_add(json_row, "upTime", uptime); + + if (if_is_multicast(ifp)) + json_object_boolean_true_add(json_row, "multicast"); + + if (if_is_broadcast(ifp)) + json_object_boolean_true_add(json_row, "broadcast"); + + json_object_int_add(json_row, "loopToLocalSocket", mloop); + + if (ifp->flags & IFF_ALLMULTI) + json_object_boolean_true_add(json_row, "allMulticast"); + + if (ifp->flags & IFF_PROMISC) + json_object_boolean_true_add(json_row, "promiscuous"); + + if (PIM_IF_IS_DELETED(ifp)) + json_object_boolean_true_add(json_row, "deleted"); + + json_object_object_add(json, ifp->name, json_row); + + } else { + vty_out(vty, "%-9s %-15s %7d %6d %8s %5s %5s %5s %5s %5s %3s%s", + ifp->name, + inet_ntoa(ifaddr), + ifp->ifindex, + pim_ifp->pim_sock_fd, + uptime, + if_is_multicast(ifp) ? "yes" : "no", + if_is_broadcast(ifp) ? "yes" : "no", + (mloop < 0) ? "?" : (mloop ? "yes" : "no"), + (ifp->flags & IFF_ALLMULTI) ? "yes" : "no", + (ifp->flags & IFF_PROMISC) ? "yes" : "no", + PIM_IF_IS_DELETED(ifp) ? "yes" : "no", + VTY_NEWLINE); + } + } + + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); } } @@ -758,20 +848,27 @@ static void pim_show_join(struct vty *vty) } -static void pim_show_neighbors(struct vty *vty) +static void pim_show_neighbors(struct vty *vty, u_char uj) { struct listnode *node; struct interface *ifp; time_t now; - + json_object *json = NULL; + json_object *json_ifp_rows = NULL; + json_object *json_row = NULL; + now = pim_time_monotonic_sec(); - vty_out(vty, - "Recv flags: H=holdtime L=lan_prune_delay P=dr_priority G=generation_id A=address_list%s" - " T=can_disable_join_suppression%s%s", - VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, + "Recv flags: H=holdtime L=lan_prune_delay P=dr_priority G=generation_id A=address_list%s" + " T=can_disable_join_suppression%s%s", + VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); - vty_out(vty, "Interface Address Neighbor Uptime Timer Holdt DrPri GenId Recv %s", VTY_NEWLINE); + vty_out(vty, "Interface Address Neighbor Uptime Timer Holdt DrPri GenId Recv %s", VTY_NEWLINE); + } for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { struct pim_interface *pim_ifp; @@ -780,13 +877,16 @@ static void pim_show_neighbors(struct vty *vty) struct pim_neighbor *neigh; pim_ifp = ifp->info; - + if (!pim_ifp) continue; if (pim_ifp->pim_sock_fd < 0) continue; + if (uj) + json_ifp_rows = json_object_new_object(); + ifaddr = pim_ifp->primary_address; for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { @@ -802,28 +902,69 @@ static void pim_show_neighbors(struct vty *vty) pim_time_mmss(holdtime, sizeof(holdtime), neigh->holdtime); pim_time_timer_to_mmss(expire, sizeof(expire), neigh->t_expire_timer); - recv[0] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_HOLDTIME) ? 'H' : ' '; - recv[1] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY) ? 'L' : ' '; - recv[2] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY) ? 'P' : ' '; - recv[3] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_GENERATION_ID) ? 'G' : ' '; - recv[4] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_ADDRESS_LIST) ? 'A' : ' '; - recv[5] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION) ? 'T' : ' '; - recv[6] = '\0'; + if (uj) { + json_row = json_object_new_object(); + json_object_string_add(json_row, "interface", ifp->name); + json_object_string_add(json_row, "address", inet_ntoa(ifaddr)); + json_object_string_add(json_row, "neighbor", neigh_src_str); + json_object_string_add(json_row, "upTime", uptime); + json_object_string_add(json_row, "timer", expire); + json_object_string_add(json_row, "holdTime", holdtime); + json_object_int_add(json_row, "drPriority", neigh->dr_priority); + json_object_int_add(json_row, "generationId", neigh->generation_id); - vty_out(vty, "%-9s %-15s %-15s %8s %5s %5s %5u %08x %6s%s", - ifp->name, - inet_ntoa(ifaddr), - neigh_src_str, - uptime, - expire, - holdtime, - neigh->dr_priority, - neigh->generation_id, - recv, - VTY_NEWLINE); + if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_HOLDTIME)) + json_object_boolean_true_add(json_row, "flagHoldtime"); + + if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY)) + json_object_boolean_true_add(json_row, "flagLanPruneDelay"); + + if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY)) + json_object_boolean_true_add(json_row, "flagDrPriority"); + + if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_GENERATION_ID)) + json_object_boolean_true_add(json_row, "flagGenerationId"); + + if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_ADDRESS_LIST)) + json_object_boolean_true_add(json_row, "flagAddressList"); + + if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)) + json_object_boolean_true_add(json_row, "flagCanDisableJoinSuppression"); + + json_object_object_add(json_ifp_rows, neigh_src_str, json_row); + + } else { + recv[0] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_HOLDTIME) ? 'H' : ' '; + recv[1] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY) ? 'L' : ' '; + recv[2] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY) ? 'P' : ' '; + recv[3] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_GENERATION_ID) ? 'G' : ' '; + recv[4] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_ADDRESS_LIST) ? 'A' : ' '; + recv[5] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION) ? 'T' : ' '; + recv[6] = '\0'; + + vty_out(vty, "%-9s %-15s %-15s %8s %5s %5s %5u %08x %6s%s", + ifp->name, + inet_ntoa(ifaddr), + neigh_src_str, + uptime, + expire, + holdtime, + neigh->dr_priority, + neigh->generation_id, + recv, + VTY_NEWLINE); + } } + if (uj) { + json_object_object_add(json, ifp->name, json_ifp_rows); + json_ifp_rows = NULL; + } + } + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); } } @@ -976,58 +1117,130 @@ static void pim_show_neighbors_secondary(struct vty *vty) } } -static void pim_show_upstream(struct vty *vty) +static void +pim_json_add_upstream_flags (struct pim_upstream *up, json_object *json_row) +{ + if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED) + json_object_boolean_true_add(json_row, "drJoinDesired"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED) + json_object_boolean_true_add(json_row, "drJoinDesiredUpdated"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) + json_object_boolean_true_add(json_row, "firstHopRouter"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) + json_object_boolean_true_add(json_row, "sourceIgmp"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_PIM) + json_object_boolean_true_add(json_row, "sourcePim"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) + json_object_boolean_true_add(json_row, "sourceStream"); +} + +static void pim_show_upstream(struct vty *vty, u_char uj) { struct listnode *upnode; struct pim_upstream *up; + struct pim_upstream *prev_up = NULL; time_t now; + char prev_grp_str[100]; + json_object *json = NULL; + json_object *json_group_rows = NULL; + json_object *json_row = NULL; now = pim_time_monotonic_sec(); - vty_out(vty, "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt%s", VTY_NEWLINE); + if (uj) + json = json_object_new_object(); + else + vty_out(vty, "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt%s", VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) { - char src_str[100]; - char grp_str[100]; - char uptime[10]; - char join_timer[10]; - char rs_timer[10]; - char ka_timer[10]; + char src_str[100]; + char grp_str[100]; + char uptime[10]; + char join_timer[10]; + char rs_timer[10]; + char ka_timer[10]; - pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); - pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); - pim_time_timer_to_hhmmss (join_timer, sizeof(join_timer), up->t_join_timer); - pim_time_timer_to_hhmmss (rs_timer, sizeof (rs_timer), up->t_rs_timer); - pim_time_timer_to_hhmmss (ka_timer, sizeof (ka_timer), up->t_ka_timer); + pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); + pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); + pim_time_timer_to_hhmmss (join_timer, sizeof(join_timer), up->t_join_timer); + pim_time_timer_to_hhmmss (rs_timer, sizeof (rs_timer), up->t_rs_timer); + pim_time_timer_to_hhmmss (ka_timer, sizeof (ka_timer), up->t_ka_timer); + if (uj) { + + if (prev_up && strcmp(prev_grp_str, grp_str) != 0) { + json_object_object_add(json, prev_grp_str, json_group_rows); + json_group_rows = NULL; + } + + if (!json_group_rows) + json_group_rows = json_object_new_object(); + + json_row = json_object_new_object(); + json_object_string_add(json_row, "inboundInterface", up->rpf.source_nexthop.interface->name); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "state", pim_upstream_state2str (up->join_state)); + json_object_string_add(json_row, "upTime", uptime); + json_object_string_add(json_row, "joinTimer", join_timer); + json_object_string_add(json_row, "resetTimer", rs_timer); + json_object_string_add(json_row, "keepaliveTimer", ka_timer); + json_object_int_add(json_row, "refCount", up->ref_count); + pim_json_add_upstream_flags (up, json_row); + json_object_object_add(json_group_rows, src_str, json_row); + strcpy(prev_grp_str, grp_str); + prev_up = up; + } else { vty_out(vty, "%-10s%-15s %-15s %-5s %-8s %-9s %-9s %-9s %6d%s", - up->rpf.source_nexthop.interface->name, - src_str, - grp_str, - pim_upstream_state2str (up->join_state), - uptime, - join_timer, - rs_timer, + up->rpf.source_nexthop.interface->name, + src_str, + grp_str, + pim_upstream_state2str (up->join_state), + uptime, + join_timer, + rs_timer, ka_timer, - up->ref_count, - VTY_NEWLINE); + up->ref_count, + VTY_NEWLINE); + } + } + + if (uj) { + if (prev_up && json_group_rows) + json_object_object_add(json, prev_grp_str, json_group_rows); + + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); } } -static void pim_show_join_desired(struct vty *vty) +static void pim_show_join_desired(struct vty *vty, u_char uj) { struct listnode *ifnode; struct listnode *chnode; struct interface *ifp; struct pim_interface *pim_ifp; struct pim_ifchannel *ch; + struct pim_upstream *prev_up = NULL; char src_str[100]; char grp_str[100]; + char prev_grp_str[100]; + json_object *json = NULL; + json_object *json_group_rows = NULL; + json_object *json_row = NULL; - vty_out(vty, - "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD%s", - VTY_NEWLINE); + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD%s", + VTY_NEWLINE); /* scan all interfaces */ for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { @@ -1042,28 +1255,77 @@ static void pim_show_join_desired(struct vty *vty) pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); - vty_out(vty, "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s%s", - ifp->name, - src_str, - grp_str, - pim_macro_ch_lost_assert(ch) ? "yes" : "no", - pim_macro_chisin_joins(ch) ? "yes" : "no", - pim_macro_chisin_pim_include(ch) ? "yes" : "no", - PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags) ? "yes" : "no", - pim_upstream_evaluate_join_desired(up) ? "yes" : "no", - VTY_NEWLINE); + if (uj) { + if (prev_up && strcmp(prev_grp_str, grp_str) != 0) { + json_object_object_add(json, prev_grp_str, json_group_rows); + json_group_rows = NULL; + } + + if (!json_group_rows) + json_group_rows = json_object_new_object(); + + json_row = json_object_new_object(); + json_object_string_add(json_row, "interface", ifp->name); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + pim_json_add_upstream_flags (up, json_row); + + if (pim_macro_ch_lost_assert(ch)) + json_object_boolean_true_add(json_row, "lostAssert"); + + if (pim_macro_chisin_joins(ch)) + json_object_boolean_true_add(json_row, "joins"); + + if (pim_macro_chisin_pim_include(ch)) + json_object_boolean_true_add(json_row, "pimInclude"); + + if (pim_upstream_evaluate_join_desired(up)) + json_object_boolean_true_add(json_row, "evaluateJoinDesired"); + + json_object_object_add(json_group_rows, src_str, json_row); + strcpy(prev_grp_str, grp_str); + prev_up = up; + + } else { + vty_out(vty, "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s%s", + ifp->name, + src_str, + grp_str, + pim_macro_ch_lost_assert(ch) ? "yes" : "no", + pim_macro_chisin_joins(ch) ? "yes" : "no", + pim_macro_chisin_pim_include(ch) ? "yes" : "no", + PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags) ? "yes" : "no", + pim_upstream_evaluate_join_desired(up) ? "yes" : "no", + VTY_NEWLINE); + } } } + + if (uj) { + if (prev_up && json_group_rows) + json_object_object_add(json, prev_grp_str, json_group_rows); + + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); + } } -static void pim_show_upstream_rpf(struct vty *vty) +static void pim_show_upstream_rpf(struct vty *vty, u_char uj) { struct listnode *upnode; struct pim_upstream *up; + struct pim_upstream *prev_up = NULL; + char prev_grp_str[100]; + json_object *json = NULL; + json_object *json_group_rows = NULL; + json_object *json_row = NULL; - vty_out(vty, - "Source Group RpfIface RibNextHop RpfAddress %s", - VTY_NEWLINE); + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "Source Group RpfIface RibNextHop RpfAddress %s", + VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) { char src_str[100]; @@ -1072,45 +1334,84 @@ static void pim_show_upstream_rpf(struct vty *vty) char rpf_addr_str[100]; struct pim_rpf *rpf; const char *rpf_ifname; - + rpf = &up->rpf; - + pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); pim_addr_dump("", &rpf->source_nexthop.mrib_nexthop_addr, rpf_nexthop_str, sizeof(rpf_nexthop_str)); pim_addr_dump("", &rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); - + rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : ""; - - vty_out(vty, "%-15s %-15s %-8s %-15s %-15s%s", - src_str, - grp_str, - rpf_ifname, - rpf_nexthop_str, - rpf_addr_str, - VTY_NEWLINE); + + if (uj) { + + if (prev_up && strcmp(prev_grp_str, grp_str) != 0) { + json_object_object_add(json, prev_grp_str, json_group_rows); + json_group_rows = NULL; + } + + if (!json_group_rows) + json_group_rows = json_object_new_object(); + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "rpfInterface", rpf_ifname); + json_object_string_add(json_row, "ribNexthop", rpf_nexthop_str); + json_object_string_add(json_row, "rpfAddress", rpf_addr_str); + pim_json_add_upstream_flags (up, json_row); + json_object_object_add(json_group_rows, src_str, json_row); + strcpy(prev_grp_str, grp_str); + prev_up = up; + } else { + vty_out(vty, "%-15s %-15s %-8s %-15s %-15s%s", + src_str, + grp_str, + rpf_ifname, + rpf_nexthop_str, + rpf_addr_str, + VTY_NEWLINE); + } + } + + if (uj) { + if (prev_up && json_group_rows) + json_object_object_add(json, prev_grp_str, json_group_rows); + + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); } } -static void show_rpf_refresh_stats(struct vty *vty, time_t now) +static void show_rpf_refresh_stats(struct vty *vty, time_t now, json_object *json) { char refresh_uptime[10]; pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now, qpim_rpf_cache_refresh_last); - vty_out(vty, - "RPF Cache Refresh Delay: %ld msecs%s" - "RPF Cache Refresh Timer: %ld msecs%s" - "RPF Cache Refresh Requests: %lld%s" - "RPF Cache Refresh Events: %lld%s" - "RPF Cache Refresh Last: %s%s" - "Nexthop Lookups: %lld%s", - qpim_rpf_cache_refresh_delay_msec, VTY_NEWLINE, - pim_time_timer_remain_msec(qpim_rpf_cache_refresher), VTY_NEWLINE, - (long long)qpim_rpf_cache_refresh_requests, VTY_NEWLINE, - (long long)qpim_rpf_cache_refresh_events, VTY_NEWLINE, - refresh_uptime, VTY_NEWLINE, - (long long) qpim_nexthop_lookups, VTY_NEWLINE); + if (json) { + json_object_int_add(json, "rpfCacheRefreshDelayMsecs", qpim_rpf_cache_refresh_delay_msec); + json_object_int_add(json, "rpfCacheRefreshTimer", pim_time_timer_remain_msec(qpim_rpf_cache_refresher)); + json_object_int_add(json, "rpfCacheRefreshRequests", qpim_rpf_cache_refresh_requests); + json_object_int_add(json, "rpfCacheRefreshEvents", qpim_rpf_cache_refresh_events); + json_object_string_add(json, "rpfCacheRefreshLast", refresh_uptime); + json_object_int_add(json, "nexthopLookups", qpim_nexthop_lookups); + } else { + vty_out(vty, + "RPF Cache Refresh Delay: %ld msecs%s" + "RPF Cache Refresh Timer: %ld msecs%s" + "RPF Cache Refresh Requests: %lld%s" + "RPF Cache Refresh Events: %lld%s" + "RPF Cache Refresh Last: %s%s" + "Nexthop Lookups: %lld%s", + qpim_rpf_cache_refresh_delay_msec, VTY_NEWLINE, + pim_time_timer_remain_msec(qpim_rpf_cache_refresher), VTY_NEWLINE, + (long long)qpim_rpf_cache_refresh_requests, VTY_NEWLINE, + (long long)qpim_rpf_cache_refresh_events, VTY_NEWLINE, + refresh_uptime, VTY_NEWLINE, + (long long) qpim_nexthop_lookups, VTY_NEWLINE); + } } static void show_scan_oil_stats(struct vty *vty, time_t now) @@ -1132,19 +1433,28 @@ static void show_scan_oil_stats(struct vty *vty, time_t now) uptime_mroute_del, (long long) qpim_mroute_del_events, VTY_NEWLINE); } -static void pim_show_rpf(struct vty *vty) +static void pim_show_rpf(struct vty *vty, u_char uj) { struct listnode *up_node; struct pim_upstream *up; + struct pim_upstream *prev_up = NULL; time_t now = pim_time_monotonic_sec(); + char prev_grp_str[100]; + json_object *json = NULL; + json_object *json_group_rows = NULL; + json_object *json_row = NULL; - show_rpf_refresh_stats(vty, now); - vty_out(vty, "%s", VTY_NEWLINE); - - vty_out(vty, - "Source Group RpfIface RpfAddress RibNextHop Metric Pref%s", - VTY_NEWLINE); + if (uj) { + json = json_object_new_object(); + show_rpf_refresh_stats(vty, now, json); + } else { + show_rpf_refresh_stats(vty, now, json); + vty_out(vty, "%s", VTY_NEWLINE); + vty_out(vty, + "Source Group RpfIface RpfAddress RibNextHop Metric Pref%s", + VTY_NEWLINE); + } for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, up_node, up)) { char src_str[100]; @@ -1161,15 +1471,46 @@ static void pim_show_rpf(struct vty *vty) rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : ""; - vty_out(vty, "%-15s %-15s %-8s %-15s %-15s %6d %4d%s", - src_str, - grp_str, - rpf_ifname, - rpf_addr_str, - rib_nexthop_str, - rpf->source_nexthop.mrib_route_metric, - rpf->source_nexthop.mrib_metric_preference, - VTY_NEWLINE); + if (uj) { + if (prev_up && strcmp(prev_grp_str, grp_str) != 0) { + json_object_object_add(json, prev_grp_str, json_group_rows); + json_group_rows = NULL; + } + + if (!json_group_rows) + json_group_rows = json_object_new_object(); + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "rpfInterface", rpf_ifname); + json_object_string_add(json_row, "rpfAddress", rpf_addr_str); + json_object_string_add(json_row, "ribNexthop", rib_nexthop_str); + json_object_int_add(json_row, "routeMetric", rpf->source_nexthop.mrib_route_metric); + json_object_int_add(json_row, "routePreference", rpf->source_nexthop.mrib_metric_preference); + + json_object_object_add(json_group_rows, src_str, json_row); + strcpy(prev_grp_str, grp_str); + prev_up = up; + } else { + vty_out(vty, "%-15s %-15s %-8s %-15s %-15s %6d %4d%s", + src_str, + grp_str, + rpf_ifname, + rpf_addr_str, + rib_nexthop_str, + rpf->source_nexthop.mrib_route_metric, + rpf->source_nexthop.mrib_metric_preference, + VTY_NEWLINE); + } + } + + if (uj) { + if (prev_up && json_group_rows) + json_object_object_add(json, prev_grp_str, json_group_rows); + + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); } } @@ -1853,39 +2194,42 @@ DEFUN (show_ip_pim_assert_winner_metric, DEFUN (show_ip_pim_dr, show_ip_pim_dr_cmd, - "show ip pim designated-router", + "show ip pim designated-router [json]", SHOW_STR IP_STR PIM_STR "PIM interface designated router\n") { - pim_show_dr(vty); + u_char uj = use_json(argc, argv); + pim_show_dr(vty, uj); return CMD_SUCCESS; } DEFUN (show_ip_pim_hello, show_ip_pim_hello_cmd, - "show ip pim hello", + "show ip pim hello [json]", SHOW_STR IP_STR PIM_STR "PIM interface hello information\n") { - pim_show_hello(vty); + u_char uj = use_json(argc, argv); + pim_show_hello(vty, uj); return CMD_SUCCESS; } DEFUN (show_ip_pim_interface, show_ip_pim_interface_cmd, - "show ip pim interface", + "show ip pim interface [json]", SHOW_STR IP_STR PIM_STR "PIM interface information\n") { - pim_show_interfaces(vty); + u_char uj = use_json(argc, argv); + pim_show_interfaces(vty, uj); return CMD_SUCCESS; } @@ -1944,13 +2288,14 @@ DEFUN (show_ip_pim_jp_override_interval, DEFUN (show_ip_pim_neighbor, show_ip_pim_neighbor_cmd, - "show ip pim neighbor", + "show ip pim neighbor [json]", SHOW_STR IP_STR PIM_STR "PIM neighbor information\n") { - pim_show_neighbors(vty); + u_char uj = use_json(argc, argv); + pim_show_neighbors(vty, uj); return CMD_SUCCESS; } @@ -1970,65 +2315,70 @@ DEFUN (show_ip_pim_secondary, DEFUN (show_ip_pim_upstream, show_ip_pim_upstream_cmd, - "show ip pim upstream", + "show ip pim upstream [json]", SHOW_STR IP_STR PIM_STR "PIM upstream information\n") { - pim_show_upstream(vty); + u_char uj = use_json(argc, argv); + pim_show_upstream(vty, uj); return CMD_SUCCESS; } DEFUN (show_ip_pim_upstream_join_desired, show_ip_pim_upstream_join_desired_cmd, - "show ip pim upstream-join-desired", + "show ip pim upstream-join-desired [json]", SHOW_STR IP_STR PIM_STR "PIM upstream join-desired\n") { - pim_show_join_desired(vty); + u_char uj = use_json(argc, argv); + pim_show_join_desired(vty, uj); return CMD_SUCCESS; } DEFUN (show_ip_pim_upstream_rpf, show_ip_pim_upstream_rpf_cmd, - "show ip pim upstream-rpf", + "show ip pim upstream-rpf [json]", SHOW_STR IP_STR PIM_STR "PIM upstream source rpf\n") { - pim_show_upstream_rpf(vty); + u_char uj = use_json(argc, argv); + pim_show_upstream_rpf(vty, uj); return CMD_SUCCESS; } DEFUN (show_ip_pim_rp, show_ip_pim_rp_cmd, - "show ip pim rp-info ", + "show ip pim rp-info [json]", SHOW_STR IP_STR PIM_STR "PIM RP information\n") { - pim_rp_show_information (vty); + u_char uj = use_json(argc, argv); + pim_rp_show_information (vty, uj); return CMD_SUCCESS; } DEFUN (show_ip_pim_rpf, show_ip_pim_rpf_cmd, - "show ip pim rpf", + "show ip pim rpf [json]", SHOW_STR IP_STR PIM_STR "PIM cached source rpf information\n") { - pim_show_rpf(vty); + u_char uj = use_json(argc, argv); + pim_show_rpf(vty, uj); return CMD_SUCCESS; } @@ -2137,7 +2487,7 @@ DEFUN (show_ip_multicast, vty_out(vty, "%s", VTY_NEWLINE); - show_rpf_refresh_stats(vty, now); + show_rpf_refresh_stats(vty, now, NULL); vty_out(vty, "%s", VTY_NEWLINE); diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 78dc0e8550..ae2ce6e476 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -20,6 +20,7 @@ */ #include +#include "lib/json.h" #include "log.h" #include "network.h" #include "if.h" @@ -682,30 +683,81 @@ pim_rp_check_is_my_ip_address (struct in_addr group, struct in_addr dest_addr) } void -pim_rp_show_information (struct vty *vty) +pim_rp_show_information (struct vty *vty, u_char uj) { struct rp_info *rp_info; + struct rp_info *prev_rp_info = NULL; struct listnode *node; - vty_out (vty, "RP address group/prefix-list OIF I am RP%s", VTY_NEWLINE); + json_object *json = NULL; + json_object *json_rp_rows = NULL; + json_object *json_row = NULL; + + if (uj) + json = json_object_new_object(); + else + vty_out (vty, "RP address group/prefix-list OIF I am RP%s", VTY_NEWLINE); + for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { if (!pim_rpf_addr_is_inaddr_none (&rp_info->rp)) { char buf[48]; - vty_out (vty, "%-15s ", inet_ntoa (rp_info->rp.rpf_addr.u.prefix4)); - if (rp_info->plist) - vty_out (vty, "%-18s ", rp_info->plist); + if (uj) + { + /* + * If we have moved on to a new RP then add the entry for the previous RP + */ + if (prev_rp_info && + prev_rp_info->rp.rpf_addr.u.prefix4.s_addr != rp_info->rp.rpf_addr.u.prefix4.s_addr) + { + json_object_object_add(json, inet_ntoa (prev_rp_info->rp.rpf_addr.u.prefix4), json_rp_rows); + json_rp_rows = NULL; + } + + if (!json_rp_rows) + json_rp_rows = json_object_new_array(); + + json_row = json_object_new_object(); + json_object_string_add(json_row, "outboundInterface", rp_info->rp.source_nexthop.interface->name); + + if (rp_info->i_am_rp) + json_object_boolean_true_add(json_row, "iAmRP"); + + if (rp_info->plist) + json_object_string_add(json_row, "prefixList", rp_info->plist); + else + json_object_string_add(json_row, "group", prefix2str(&rp_info->group, buf, 48)); + + json_object_array_add(json_rp_rows, json_row); + } else - vty_out (vty, "%-18s ", prefix2str(&rp_info->group, buf, 48)); + { + vty_out (vty, "%-15s ", inet_ntoa (rp_info->rp.rpf_addr.u.prefix4)); - vty_out (vty, "%-10s ", rp_info->rp.source_nexthop.interface->name); + if (rp_info->plist) + vty_out (vty, "%-18s ", rp_info->plist); + else + vty_out (vty, "%-18s ", prefix2str(&rp_info->group, buf, 48)); - if (rp_info->i_am_rp) - vty_out (vty, "yes%s", VTY_NEWLINE); - else - vty_out (vty, "no%s", VTY_NEWLINE); + vty_out (vty, "%-10s ", rp_info->rp.source_nexthop.interface->name); + + if (rp_info->i_am_rp) + vty_out (vty, "yes%s", VTY_NEWLINE); + else + vty_out (vty, "no%s", VTY_NEWLINE); + } + + prev_rp_info = rp_info; } } + + if (uj) { + if (prev_rp_info && json_rp_rows) + json_object_object_add(json, inet_ntoa (prev_rp_info->rp.rpf_addr.u.prefix4), json_rp_rows); + + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); + } } diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index 230f4f08ff..1e1912ff96 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -44,5 +44,5 @@ struct pim_rpf *pim_rp_g (struct in_addr group); #define I_am_RP(G) pim_rp_i_am_rp ((G)) #define RP(G) pim_rp_g ((G)) -void pim_rp_show_information (struct vty *vty); +void pim_rp_show_information (struct vty *vty, u_char uj); #endif From 7b2c4d167e1b6ac3e8391f2492cfadc756126542 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 14 Sep 2016 11:24:06 -0400 Subject: [PATCH 164/386] pimd: Use MULTIPATH_NUM for maxpaths When looking up nexthops for a address, just use the MULTIPATH_NUM as the number allowed to receive instead of an arbitrary limit of 20 paths. Signed-off-by: Donald Sharp --- pimd/pim_pim.h | 2 -- pimd/pim_rpf.c | 6 +++--- pimd/pim_zebra.c | 4 ++-- pimd/pim_zlookup.c | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/pimd/pim_pim.h b/pimd/pim_pim.h index fad572a125..abb3e50c00 100644 --- a/pimd/pim_pim.h +++ b/pimd/pim_pim.h @@ -29,8 +29,6 @@ #define PIM_PIM_BUFSIZE_READ (20000) #define PIM_PIM_BUFSIZE_WRITE (20000) -#define PIM_NEXTHOP_IFINDEX_TAB_SIZE (20) - #define PIM_DEFAULT_HELLO_PERIOD (30) /* seconds, RFC 4601: 4.11 */ #define PIM_DEFAULT_TRIGGERED_HELLO_DELAY (5) /* seconds, RFC 4601: 4.11 */ #define PIM_DEFAULT_DR_PRIORITY (1) /* RFC 4601: 4.3.1 */ diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 6b4dd111e7..2e93162694 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -39,15 +39,15 @@ static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up); int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr) { - struct pim_zlookup_nexthop nexthop_tab[PIM_NEXTHOP_IFINDEX_TAB_SIZE]; + struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; int num_ifindex; struct interface *ifp; int first_ifindex; - memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * PIM_NEXTHOP_IFINDEX_TAB_SIZE); + memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM); num_ifindex = zclient_lookup_nexthop(nexthop_tab, - PIM_NEXTHOP_IFINDEX_TAB_SIZE, + MULTIPATH_NUM, addr, PIM_NEXTHOP_LOOKUP_MAX); if (num_ifindex < 1) { char addr_str[100]; diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index cfdc447fc3..addccef82b 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -792,13 +792,13 @@ void igmp_anysource_forward_stop(struct igmp_group *group) static int fib_lookup_if_vif_index(struct in_addr addr) { - struct pim_zlookup_nexthop nexthop_tab[PIM_NEXTHOP_IFINDEX_TAB_SIZE]; + struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; int num_ifindex; int vif_index; ifindex_t first_ifindex; num_ifindex = zclient_lookup_nexthop(nexthop_tab, - PIM_NEXTHOP_IFINDEX_TAB_SIZE, addr, + MULTIPATH_NUM, addr, PIM_NEXTHOP_LOOKUP_MAX); if (num_ifindex < 1) { char addr_str[100]; diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 8d73159466..f649098060 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -356,7 +356,7 @@ zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], struct prefix nexthop_addr; num_ifindex = zclient_lookup_nexthop_once(nexthop_tab, - PIM_NEXTHOP_IFINDEX_TAB_SIZE, addr); + tab_size, addr); if (num_ifindex < 1) { if (PIM_DEBUG_ZEBRA) { char addr_str[100]; From d4a2bc11adc87fb6dc7d460080d65fde017a964f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 14 Sep 2016 19:17:54 -0400 Subject: [PATCH 165/386] pimd, zebra: Pass the ifindex for NEXTHOP_TYPE_IPV4 NEXTHOP_TYPE_IPV4 has the ifindex of the route. Pass it along so the other side can use it if it is needed. This will make pim much happier in that we will need to do less recursive lookups. Signed-off-by: Donald Sharp --- pimd/pim_zlookup.c | 21 +++------------------ zebra/zserv.c | 2 -- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index f649098060..f81c6e8781 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -233,8 +233,10 @@ static int zclient_read_nexthop(struct zclient *zlookup, switch (nexthop_type) { case NEXTHOP_TYPE_IFINDEX: case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4: nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; - if (nexthop_type == NEXTHOP_TYPE_IPV4_IFINDEX) { + if (nexthop_type == NEXTHOP_TYPE_IPV4_IFINDEX || + nexthop_type == NEXTHOP_TYPE_IPV4) { nexthop_tab[num_ifindex].nexthop_addr.u.prefix4.s_addr = stream_get_ipv4(s); } else { @@ -245,23 +247,6 @@ static int zclient_read_nexthop(struct zclient *zlookup, nexthop_tab[num_ifindex].route_metric = metric; ++num_ifindex; break; - case NEXTHOP_TYPE_IPV4: - nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; - nexthop_tab[num_ifindex].nexthop_addr.u.prefix4.s_addr = stream_get_ipv4(s); - nexthop_tab[num_ifindex].ifindex = 0; - nexthop_tab[num_ifindex].protocol_distance = distance; - nexthop_tab[num_ifindex].route_metric = metric; - if (PIM_DEBUG_ZEBRA) { - char addr_str[100]; - char nexthop_str[100]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - pim_addr_dump("", &nexthop_tab[num_ifindex].nexthop_addr, nexthop_str, sizeof(nexthop_str)); - zlog_debug("%s %s: zebra returned recursive nexthop %s for address %s", - __FILE__, __PRETTY_FUNCTION__, - nexthop_str, addr_str); - } - ++num_ifindex; - break; case NEXTHOP_TYPE_IPV6_IFINDEX: nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET6; stream_get (&nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, s, 16); diff --git a/zebra/zserv.c b/zebra/zserv.c index 44e29a8bb0..bdfa03e1ee 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -786,8 +786,6 @@ zsend_write_nexthop (struct stream *s, struct nexthop *nexthop) switch (nexthop->type) { case NEXTHOP_TYPE_IPV4: - stream_put_in_addr (s, &nexthop->gate.ipv4); - break; case NEXTHOP_TYPE_IPV4_IFINDEX: stream_put_in_addr (s, &nexthop->gate.ipv4); stream_putl (s, nexthop->ifindex); From 6971955465caf063b451146fe76eeadce101a88a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 14 Sep 2016 20:45:00 -0400 Subject: [PATCH 166/386] pimd: Don't assert when looking up a neighbor Do not assert when looking up a neighbor, we don't know if we have a neighbor don't punish us. Signed-off-by: Donald Sharp --- pimd/pim_neighbor.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index ba2fc753b3..dee9689209 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -392,7 +392,8 @@ struct pim_neighbor *pim_neighbor_find(struct interface *ifp, struct pim_neighbor *neigh; pim_ifp = ifp->info; - zassert(pim_ifp); + if (!pim_ifp) + return NULL; for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { if (source_addr.s_addr == neigh->source_addr.s_addr) { @@ -400,7 +401,7 @@ struct pim_neighbor *pim_neighbor_find(struct interface *ifp, } } - return 0; + return NULL; } /* @@ -413,7 +414,7 @@ pim_neighbor_find_if (struct interface *ifp) { struct pim_interface *pim_ifp = ifp->info; - if (pim_ifp->pim_neighbor_list->count != 1) + if (!pim_ifp || pim_ifp->pim_neighbor_list->count != 1) return NULL; return listnode_head (pim_ifp->pim_neighbor_list); From d8ba2f4a309507867a678f524934d8279bdab319 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 14 Sep 2016 20:51:28 -0400 Subject: [PATCH 167/386] pimd: Only use paths that we have nbrs on When looking up nexthops for a path, we should only allow nexthops that we actually have neighbors formed for. Otherwise when we send join/prune messages they will do nothing. Ticket:CM-12754 Signed-off-by: Donald Sharp --- pimd/pim_zlookup.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index f81c6e8781..d269c04254 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -332,6 +332,7 @@ zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], int lookup; uint32_t route_metric = 0xFFFFFFFF; uint8_t protocol_distance = 0xFF; + int i; qpim_nexthop_lookups++; @@ -360,9 +361,13 @@ zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], } /* - FIXME: Non-recursive nexthop ensured only for first ifindex. - However, recursive route lookup should really be fixed in zebra daemon. - See also TODO T24. + * FIXME: Non-recursive nexthop ensured only for first ifindex. + * However, recursive route lookup should really be fixed in zebra daemon. + * See also TODO T24. + * + * So Zebra for NEXTHOP_TYPE_IPV4 returns the ifindex now since + * it was being stored. This Doesn't solve all cases of + * recursive lookup but for the most common types it does. */ first_ifindex = nexthop_tab[0].ifindex; nexthop_addr = nexthop_tab[0].nexthop_addr; @@ -389,6 +394,27 @@ zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], nexthop_tab[0].protocol_distance = protocol_distance; } + /* + * Let's see if any of the nexthops can actually be used. + * We need to check them against the neighbors that we + * have formed. As that we shouldn't be sending + * j/p messages upstream towards non-neighbors + */ + for (i = 0; i < num_ifindex ; i++) + { + struct interface *ifp; + struct pim_neighbor *nbr; + + ifp = if_lookup_by_index_vrf (nexthop_tab[i].ifindex, VRF_DEFAULT); + nbr = pim_neighbor_find (ifp, nexthop_tab[i].nexthop_addr.u.prefix4); + if (!nbr) + { + num_ifindex--; + if (i != num_ifindex) + memcpy (&nexthop_tab[i], &nexthop_tab[i+1], sizeof (nexthop_tab[i])); + i--; + } + } return num_ifindex; } From e446de6a16dc81920d8e9e410e26d1c8432a2e8d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 15 Sep 2016 08:00:42 -0400 Subject: [PATCH 168/386] pimd: Resolve rp after neighbor come up When a neighbor comes up, see if we suddenly have a path to the RP. Signed-off-by: Donald Sharp --- pimd/pim_neighbor.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index dee9689209..3696d2d47e 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -25,6 +25,8 @@ #include "prefix.h" #include "memory.h" #include "if.h" +#include "vty.h" +#include "plist.h" #include "pimd.h" #include "pim_neighbor.h" @@ -34,6 +36,7 @@ #include "pim_pim.h" #include "pim_upstream.h" #include "pim_ifchannel.h" +#include "pim_rp.h" static void dr_election_by_addr(struct interface *ifp) { @@ -481,6 +484,7 @@ struct pim_neighbor *pim_neighbor_add(struct interface *ifp, pim_upstream_find_new_rpf(); + pim_rp_setup (); return neigh; } From 690324215e276a2edae4143f1909a04265b4fe04 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 15 Sep 2016 09:03:51 -0400 Subject: [PATCH 169/386] pimd: Allow loopbacks to resolve When doing a rpf check ensure that if we've considered the RP to be a loopback allow there to be no neighbor on the other side. Signed-off-by: Donald Sharp --- pimd/pim_zlookup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index d269c04254..636552abd7 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -407,7 +407,7 @@ zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], ifp = if_lookup_by_index_vrf (nexthop_tab[i].ifindex, VRF_DEFAULT); nbr = pim_neighbor_find (ifp, nexthop_tab[i].nexthop_addr.u.prefix4); - if (!nbr) + if (ifp->info && !nbr && !if_is_loopback (ifp)) { num_ifindex--; if (i != num_ifindex) From 63b8f7a35e2a374081d563235cd617690339b425 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 15 Sep 2016 14:18:28 +0000 Subject: [PATCH 170/386] pimd: Rework approach for needing nbrs Pim sometimes needs the upstream rpf lookup to only take into account if we have a nbr out the selected interface or not. Move the code for this to a better spot so we can make a more intelligent decision here. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 2 +- pimd/pim_mroute.c | 2 +- pimd/pim_register.c | 13 +++-- pimd/pim_rp.c | 4 +- pimd/pim_rpf.c | 113 ++++++++++++++++++++++++++------------------ pimd/pim_rpf.h | 2 +- pimd/pim_zlookup.c | 22 --------- 7 files changed, 81 insertions(+), 77 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index a3ff7c25ed..76d42f3614 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2713,7 +2713,7 @@ DEFUN (show_ip_rib, return CMD_WARNING; } - if (pim_nexthop_lookup(&nexthop, addr)) { + if (pim_nexthop_lookup(&nexthop, addr, 0)) { vty_out(vty, "Failure querying RIB nexthop for unicast address %s%s", addr_str, VTY_NEWLINE); return CMD_WARNING; diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 1f64a6e299..dd3ae3117d 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -345,7 +345,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) pim_ifp = rpf->source_nexthop.interface->info; //No if channel, but upstream we are at the RP. - pim_nexthop_lookup (&source, up->upstream_register); + pim_nexthop_lookup (&source, up->upstream_register, 1); pim_register_stop_send(source.interface, &sg, pim_ifp->primary_address, up->upstream_register); if (!up->channel_oil) up->channel_oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); diff --git a/pimd/pim_register.c b/pimd/pim_register.c index ebc46f60ea..f8144557c8 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -162,9 +162,16 @@ pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct } ifp = rpg->source_nexthop.interface; + if (!ifp) + { + if (PIM_DEBUG_PIM_REG) + zlog_debug ("%s: No interface to transmit register on", __PRETTY_FUNCTION__); + return; + } pinfo = (struct pim_interface *)ifp->info; if (!pinfo) { - zlog_debug("%s: No pinfo!\n", __PRETTY_FUNCTION__); + if (PIM_DEBUG_PIM_REG) + zlog_debug("%s: Interface: %s not configured for pim to trasmit on!\n", __PRETTY_FUNCTION__, ifp->name); return; } @@ -327,13 +334,13 @@ pim_register_recv (struct interface *ifp, upstream = pim_upstream_add (&sg, ifp); if (!upstream) { - zlog_warn ("Failure to crate upstream state"); + zlog_warn ("Failure to create upstream state"); return 1; } upstream->upstream_register = src_addr; pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.src, sg.grp); pim_nexthop_lookup (&upstream->rpf.source_nexthop, - upstream->upstream_addr); + upstream->upstream_addr, 1); upstream->sg.src = sg.src; upstream->rpf.rpf_addr = upstream->rpf.source_nexthop.mrib_nexthop_addr; diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index ae2ce6e476..b5c5ad55b9 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -487,7 +487,7 @@ pim_rp_setup (void) for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { - if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4) != 0) + if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1) != 0) { zlog_err ("Unable to lookup nexthop for rp specified"); ret++; @@ -583,7 +583,7 @@ pim_rp_g (struct in_addr group) if (rp_info) { - pim_nexthop_lookup(&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4); + pim_nexthop_lookup(&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1); return (&rp_info->rp); } diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 2e93162694..44acde0c9e 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -37,15 +37,16 @@ static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up); -int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr) +int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int neighbor_needed) { struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; int num_ifindex; struct interface *ifp; int first_ifindex; + int found = 0; + int i = 0; memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM); - num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr, PIM_NEXTHOP_LOOKUP_MAX); @@ -58,56 +59,73 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr) return -1; } - first_ifindex = nexthop_tab[0].ifindex; + while (!found) + { + first_ifindex = nexthop_tab[i].ifindex; - if (num_ifindex > 1 && PIM_DEBUG_ZEBRA) { - char addr_str[100]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s %s: Ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)", - __FILE__, __PRETTY_FUNCTION__, - num_ifindex, addr_str, first_ifindex); - /* debug warning only, do not return */ - } + ifp = if_lookup_by_index(first_ifindex); + if (!ifp) + { + if (PIM_DEBUG_ZEBRA) + { + char addr_str[100]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_debug("%s %s: could not find interface for ifindex %d (address %s)", + __FILE__, __PRETTY_FUNCTION__, + first_ifindex, addr_str); + } + return -2; + } - ifp = if_lookup_by_index(first_ifindex); - if (!ifp) { - char addr_str[100]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s %s: could not find interface for ifindex %d (address %s)", - __FILE__, __PRETTY_FUNCTION__, - first_ifindex, addr_str); - return -2; - } + if (!ifp->info && PIM_DEBUG_ZEBRA) + { + char addr_str[100]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_debug("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", + __PRETTY_FUNCTION__, + ifp->name, first_ifindex, addr_str); + } - if (!ifp->info) { - char addr_str[100]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", - __PRETTY_FUNCTION__, - ifp->name, first_ifindex, addr_str); - /* debug warning only, do not return */ - } + if (neighbor_needed) + { + struct pim_neighbor *nbr; - if (PIM_DEBUG_ZEBRA) { - char nexthop_str[100]; - char addr_str[100]; - pim_addr_dump("", &nexthop_tab[0].nexthop_addr, nexthop_str, sizeof(nexthop_str)); - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s %s: found nexthop %s for address %s: interface %s ifindex=%d metric=%d pref=%d", - __FILE__, __PRETTY_FUNCTION__, - nexthop_str, addr_str, - ifp->name, first_ifindex, - nexthop_tab[0].route_metric, - nexthop_tab[0].protocol_distance); - } + nbr = pim_neighbor_find (ifp, nexthop_tab[i].nexthop_addr.u.prefix4); + if (PIM_DEBUG_ZEBRA) + zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr); + if (!nbr && !if_is_loopback (ifp)) + i++; + else + found = 1; + } + else + found = 1; + } - /* update nextop data */ - nexthop->interface = ifp; - nexthop->mrib_nexthop_addr = nexthop_tab[0].nexthop_addr; - nexthop->mrib_metric_preference = nexthop_tab[0].protocol_distance; - nexthop->mrib_route_metric = nexthop_tab[0].route_metric; + if (found) + { + if (PIM_DEBUG_ZEBRA) { + char nexthop_str[100]; + char addr_str[100]; + pim_addr_dump("", &nexthop_tab[0].nexthop_addr, nexthop_str, sizeof(nexthop_str)); + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_debug("%s %s: found nexthop %s for address %s: interface %s ifindex=%d metric=%d pref=%d", + __FILE__, __PRETTY_FUNCTION__, + nexthop_str, addr_str, + ifp->name, first_ifindex, + nexthop_tab[0].route_metric, + nexthop_tab[0].protocol_distance); + } + /* update nextop data */ + nexthop->interface = ifp; + nexthop->mrib_nexthop_addr = nexthop_tab[0].nexthop_addr; + nexthop->mrib_metric_preference = nexthop_tab[0].protocol_distance; + nexthop->mrib_route_metric = nexthop_tab[0].route_metric; - return 0; + return 0; + } + else + return -1; } static int nexthop_mismatch(const struct pim_nexthop *nh1, @@ -128,7 +146,8 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_ save_nexthop = rpf->source_nexthop; /* detect change in pim_nexthop */ save_rpf_addr = rpf->rpf_addr; /* detect change in RPF'(S,G) */ - if (pim_nexthop_lookup(&rpf->source_nexthop, up->upstream_addr)) { + if (pim_nexthop_lookup(&rpf->source_nexthop, + up->upstream_addr, !PIM_UPSTREAM_FLAG_TEST_FHR (up->flags))) { return PIM_RPF_FAILURE; } diff --git a/pimd/pim_rpf.h b/pimd/pim_rpf.h index fddc74a725..b93c934116 100644 --- a/pimd/pim_rpf.h +++ b/pimd/pim_rpf.h @@ -59,7 +59,7 @@ enum pim_rpf_result { struct pim_upstream; -int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr); +int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int neighbor_needed); enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_rpf_addr); int pim_rpf_addr_is_inaddr_none (struct pim_rpf *rpf); diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 636552abd7..bee9c63e96 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -332,7 +332,6 @@ zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], int lookup; uint32_t route_metric = 0xFFFFFFFF; uint8_t protocol_distance = 0xFF; - int i; qpim_nexthop_lookups++; @@ -394,27 +393,6 @@ zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], nexthop_tab[0].protocol_distance = protocol_distance; } - /* - * Let's see if any of the nexthops can actually be used. - * We need to check them against the neighbors that we - * have formed. As that we shouldn't be sending - * j/p messages upstream towards non-neighbors - */ - for (i = 0; i < num_ifindex ; i++) - { - struct interface *ifp; - struct pim_neighbor *nbr; - - ifp = if_lookup_by_index_vrf (nexthop_tab[i].ifindex, VRF_DEFAULT); - nbr = pim_neighbor_find (ifp, nexthop_tab[i].nexthop_addr.u.prefix4); - if (ifp->info && !nbr && !if_is_loopback (ifp)) - { - num_ifindex--; - if (i != num_ifindex) - memcpy (&nexthop_tab[i], &nexthop_tab[i+1], sizeof (nexthop_tab[i])); - i--; - } - } return num_ifindex; } From ca973133ec850f16b8ac5274612ea7785d56c4cd Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 15 Sep 2016 11:14:53 -0400 Subject: [PATCH 171/386] pimd: Bad Bit shifts I programmed the bit shifts improperly. Signed-off-by: Donald Sharp --- pimd/pim_upstream.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index f279714a85..6d30349bd6 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -28,11 +28,11 @@ #include #define PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED (1 << 0) -#define PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED (2 << 0) -#define PIM_UPSTREAM_FLAG_MASK_FHR (3 << 0) -#define PIM_UPSTREAM_FLAG_MASK_SRC_IGMP (4 << 0) -#define PIM_UPSTREAM_FLAG_MASK_SRC_PIM (5 << 0) -#define PIM_UPSTREAM_FLAG_MASK_SRC_STREAM (6 << 0) +#define PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED (1 << 1) +#define PIM_UPSTREAM_FLAG_MASK_FHR (1 << 2) +#define PIM_UPSTREAM_FLAG_MASK_SRC_IGMP (1 << 3) +#define PIM_UPSTREAM_FLAG_MASK_SRC_PIM (1 << 4) +#define PIM_UPSTREAM_FLAG_MASK_SRC_STREAM (1 << 5) #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) From a268493f6b5d4a677589d0a872e19e6f8b709932 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Thu, 15 Sep 2016 17:16:36 +0000 Subject: [PATCH 172/386] pimd: show ip pim int WORD, show ip pim nei WORD, show ip igmp int WORD Signed-off-by: Daniel Walton Ticket: CM-11812 --- pimd/pim_cmd.c | 1232 ++++++++++++++++++++++++++---------------------- 1 file changed, 658 insertions(+), 574 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 76d42f3614..9e7a326a7c 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -417,17 +417,67 @@ static void pim_show_membership(struct vty *vty) } -static void igmp_show_interfaces(struct vty *vty) +static void pim_print_ifp_flags(struct vty *vty, struct interface *ifp, int mloop) +{ + vty_out(vty, "Flags%s", VTY_NEWLINE); + vty_out(vty, "-----%s", VTY_NEWLINE); + vty_out(vty, "All Multicast : %s%s", (ifp->flags & IFF_ALLMULTI) ? "yes" : "no", VTY_NEWLINE); + vty_out(vty, "Broadcast : %s%s", if_is_broadcast(ifp)? "yes" : "no", VTY_NEWLINE); + vty_out(vty, "Deleted : %s%s", PIM_IF_IS_DELETED(ifp) ? "yes" : "no", VTY_NEWLINE); + vty_out(vty, "Interface Index : %d%s", ifp->ifindex, VTY_NEWLINE); + vty_out(vty, "Multicast : %s%s", if_is_multicast(ifp) ? "yes" : "no", VTY_NEWLINE); + vty_out(vty, "Multicast Loop : %d%s", mloop, VTY_NEWLINE); + vty_out(vty, "Promiscuous : %s%s", (ifp->flags & IFF_PROMISC) ? "yes" : "no", VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); +} + +static void pim_json_ifp(struct json_object *json, struct interface *ifp) +{ + struct pim_interface *pim_ifp; + + pim_ifp = ifp->info; + json_object_string_add(json, "name", ifp->name); + json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down"); + json_object_string_add(json, "address", inet_ntoa(pim_ifp->primary_address)); + + if (if_is_multicast(ifp)) + json_object_boolean_true_add(json, "flagMulticast"); + + if (if_is_broadcast(ifp)) + json_object_boolean_true_add(json, "flagBroadcast"); + + json_object_int_add(json, "index", ifp->ifindex); + + if (ifp->flags & IFF_ALLMULTI) + json_object_boolean_true_add(json, "flagAllMulticast"); + + if (ifp->flags & IFF_PROMISC) + json_object_boolean_true_add(json, "flagPromiscuous"); + + if (PIM_IF_IS_DELETED(ifp)) + json_object_boolean_true_add(json, "flagDeleted"); + + if (pim_if_lan_delay_enabled(ifp)) + json_object_boolean_true_add(json, "lanDelayEnabled"); +} + +static void igmp_show_interfaces(struct vty *vty, u_char uj) { struct listnode *node; struct interface *ifp; time_t now; - + json_object *json = NULL; + json_object *json_row = NULL; + now = pim_time_monotonic_sec(); - vty_out(vty, - "Interface Address ifIndex Socket Uptime Multi Broad MLoop AllMu Prmsc Del%s", - VTY_NEWLINE); + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "Interface State Address Querier Query Timer Uptime%s", + VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { struct pim_interface *pim_ifp; @@ -435,33 +485,173 @@ static void igmp_show_interfaces(struct vty *vty) struct igmp_sock *igmp; pim_ifp = ifp->info; - + if (!pim_ifp) continue; for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { char uptime[10]; - int mloop; + char query_hhmmss[10]; pim_time_uptime(uptime, sizeof(uptime), now - igmp->sock_creation); + pim_time_timer_to_hhmmss(query_hhmmss, sizeof(query_hhmmss), igmp->t_igmp_query_timer); - mloop = pim_socket_mcastloop_get(igmp->fd); - - vty_out(vty, "%-9s %-15s %7d %6d %8s %5s %5s %5s %5s %5s %3s%s", - ifp->name, - inet_ntoa(igmp->ifaddr), - ifp->ifindex, - igmp->fd, - uptime, - if_is_multicast(ifp) ? "yes" : "no", - if_is_broadcast(ifp) ? "yes" : "no", - (mloop < 0) ? "?" : (mloop ? "yes" : "no"), - (ifp->flags & IFF_ALLMULTI) ? "yes" : "no", - (ifp->flags & IFF_PROMISC) ? "yes" : "no", - PIM_IF_IS_DELETED(ifp) ? "yes" : "no", - VTY_NEWLINE); + if (uj) { + json_row = json_object_new_object(); + pim_json_ifp(json_row, ifp); + json_object_string_add(json_row, "upTime", uptime); + + if (igmp->t_igmp_query_timer) { + json_object_boolean_true_add(json_row, "querier"); + json_object_string_add(json_row, "queryTimer", query_hhmmss); + } + + json_object_object_add(json, ifp->name, json_row); + + } else { + vty_out(vty, "%-9s %5s %15s %7s %11s %8s%s", + ifp->name, + if_is_up(ifp) ? "up" : "down", + inet_ntoa(igmp->ifaddr), + igmp->t_igmp_query_timer ? "local" : "other", + query_hhmmss, + uptime, + VTY_NEWLINE); + } } } + + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); + } +} + +static void igmp_show_interfaces_single(struct vty *vty, const char *ifname, u_char uj) +{ + struct igmp_sock *igmp; + struct interface *ifp; + struct listnode *node; + struct listnode *sock_node; + struct pim_interface *pim_ifp; + char uptime[10]; + char query_hhmmss[10]; + char other_hhmmss[10]; + int found_ifname = 0; + int sqi; + int mloop; + long gmi_msec; /* Group Membership Interval */ + long lmqt_msec; + long ohpi_msec; + long oqpi_msec; /* Other Querier Present Interval */ + long qri_msec; + time_t now; + + json_object *json = NULL; + json_object *json_row = NULL; + + now = pim_time_monotonic_sec(); + + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (strcmp(ifname, ifp->name)) + continue; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { + found_ifname = 1; + pim_time_uptime(uptime, sizeof(uptime), now - igmp->sock_creation); + pim_time_timer_to_hhmmss(query_hhmmss, sizeof(query_hhmmss), igmp->t_igmp_query_timer); + pim_time_timer_to_hhmmss(other_hhmmss, sizeof(other_hhmmss), igmp->t_other_querier_timer); + + gmi_msec = PIM_IGMP_GMI_MSEC(igmp->querier_robustness_variable, + igmp->querier_query_interval, + pim_ifp->igmp_query_max_response_time_dsec); + + sqi = PIM_IGMP_SQI(pim_ifp->igmp_default_query_interval); + + oqpi_msec = PIM_IGMP_OQPI_MSEC(igmp->querier_robustness_variable, + igmp->querier_query_interval, + pim_ifp->igmp_query_max_response_time_dsec); + + lmqt_msec = PIM_IGMP_LMQT_MSEC(pim_ifp->igmp_query_max_response_time_dsec, + igmp->querier_robustness_variable); + + ohpi_msec = PIM_IGMP_OHPI_DSEC(igmp->querier_robustness_variable, + igmp->querier_query_interval, + pim_ifp->igmp_query_max_response_time_dsec) * 100; + + qri_msec = pim_ifp->igmp_query_max_response_time_dsec * 100; + mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); + + if (uj) { + json = json_object_new_object(); + json_row = json_object_new_object(); + pim_json_ifp(json_row, ifp); + + json_object_string_add(json_row, "upTime", uptime); + json_object_string_add(json_row, "querier", igmp->t_igmp_query_timer ? "local" : "other"); + json_object_int_add(json_row, "queryStartCount", igmp->startup_query_count); + json_object_string_add(json_row, "queryQueryTimer", query_hhmmss); + json_object_string_add(json_row, "queryOtherTimer", other_hhmmss); + json_object_int_add(json_row, "timerGroupMembershipIntervalMsec", gmi_msec); + json_object_int_add(json_row, "timerLastMemberQueryMsec", lmqt_msec); + json_object_int_add(json_row, "timerOlderHostPresentIntervalMsec", ohpi_msec); + json_object_int_add(json_row, "timerOtherQuerierPresentIntervalMsec", oqpi_msec); + json_object_int_add(json_row, "timerQueryInterval", igmp->querier_query_interval); + json_object_int_add(json_row, "timerQueryResponseIntervalMsec", qri_msec); + json_object_int_add(json_row, "timerRobustnessVariable", igmp->querier_robustness_variable); + json_object_int_add(json_row, "timerStartupQueryInterval", sqi); + + json_object_object_add(json, ifp->name, json_row); + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); + + } else { + vty_out(vty, "Interface : %s%s", ifp->name, VTY_NEWLINE); + vty_out(vty, "State : %s%s", if_is_up(ifp) ? "up" : "down", VTY_NEWLINE); + vty_out(vty, "Address : %s%s", inet_ntoa(pim_ifp->primary_address), VTY_NEWLINE); + vty_out(vty, "Uptime : %s%s", uptime, VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + + vty_out(vty, "Querier%s", VTY_NEWLINE); + vty_out(vty, "-------%s", VTY_NEWLINE); + vty_out(vty, "Querier : %s%s", igmp->t_igmp_query_timer ? "local" : "other", VTY_NEWLINE); + vty_out(vty, "Start Count : %d%s", igmp->startup_query_count, VTY_NEWLINE); + vty_out(vty, "Query Timer : %s%s", query_hhmmss, VTY_NEWLINE); + vty_out(vty, "Other Timer : %s%s", other_hhmmss, VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + + vty_out(vty, "Timers%s", VTY_NEWLINE); + vty_out(vty, "------%s", VTY_NEWLINE); + vty_out(vty, "Group Membership Interval : %lis%s", gmi_msec/1000, VTY_NEWLINE); + vty_out(vty, "Last Member Query Time : %lis%s", lmqt_msec/1000, VTY_NEWLINE); + vty_out(vty, "Older Host Present Interval : %lis%s", ohpi_msec/1000, VTY_NEWLINE); + vty_out(vty, "Other Querier Present Interval : %lis%s", oqpi_msec/1000, VTY_NEWLINE); + vty_out(vty, "Query Interval : %ds%s", igmp->querier_query_interval, VTY_NEWLINE); + vty_out(vty, "Query Response Interval : %lis%s", qri_msec/1000, VTY_NEWLINE); + vty_out(vty, "Robustness Variable : %d%s", igmp->querier_robustness_variable, VTY_NEWLINE); + vty_out(vty, "Startup Query Interval : %ds%s", sqi, VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + + pim_print_ifp_flags(vty, ifp, mloop); + } + } + } + + if (!found_ifname) + { + if (uj) + vty_out (vty, "{}%s", VTY_NEWLINE); + else + vty_out (vty, "%% No such interface%s", VTY_NEWLINE); + } } static void igmp_show_interface_join(struct vty *vty) @@ -517,216 +707,278 @@ static void igmp_show_interface_join(struct vty *vty) } -static void show_interface_address(struct vty *vty) +static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_char uj) { - struct listnode *ifpnode; + struct in_addr ifaddr; struct interface *ifp; - - vty_out(vty, - "Interface Primary Secondary %s", - VTY_NEWLINE); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifpnode, ifp)) { - struct listnode *ifcnode; - struct connected *ifc; - struct in_addr pri_addr; - char pri_addr_str[100]; - - pri_addr = pim_find_primary_addr(ifp); - - pim_inet4_dump("", pri_addr, pri_addr_str, sizeof(pri_addr_str)); - - for (ALL_LIST_ELEMENTS_RO(ifp->connected, ifcnode, ifc)) { - char sec_addr_str[100]; - struct prefix *p = ifc->address; - - if (p->family != AF_INET) - continue; - - if (p->u.prefix4.s_addr == pri_addr.s_addr) { - sec_addr_str[0] = '\0'; - } - else { - pim_inet4_dump("", p->u.prefix4, sec_addr_str, sizeof(sec_addr_str)); - } - - vty_out(vty, "%-9s %-15s %-15s%s", - ifp->name, - pri_addr_str, - sec_addr_str, - VTY_NEWLINE); - } - } -} - -static void pim_show_dr(struct vty *vty, u_char uj) -{ - struct listnode *node; - struct interface *ifp; - time_t now; + struct listnode *neighnode; + struct listnode*node; + struct listnode *upnode; + struct pim_interface *pim_ifp; + struct pim_neighbor *neigh; + struct pim_upstream *up; + time_t now; + char dr_str[100]; + char dr_uptime[10]; + char expire[10]; + char grp_str[100]; + char hello_period[10]; + char hello_timer[10]; + char neigh_src_str[100]; + char src_str[100]; + char stat_uptime[10]; + char uptime[10]; + int mloop; + int found_ifname = 0; + int print_header; json_object *json = NULL; json_object *json_row = NULL; - + json_object *json_pim_neighbor = NULL; + json_object *json_pim_neighbors = NULL; + json_object *json_group = NULL; + json_object *json_fhr_sources = NULL; + json_object *json_group_source = NULL; + now = pim_time_monotonic_sec(); - if (uj) { - json = json_object_new_object(); - } else { - vty_out(vty, - "NonPri: Number of neighbors missing DR Priority hello option%s" - "DrPri: Designated Router Priority sent%s%s", - VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); - - vty_out(vty, "Interface Address DR Uptime Elections Changes NonPri DrPri%s", VTY_NEWLINE); - } - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - struct pim_interface *pim_ifp; - struct in_addr ifaddr; - char dr_str[100]; - char dr_uptime[10]; - pim_ifp = ifp->info; - + if (!pim_ifp) continue; if (pim_ifp->pim_sock_fd < 0) continue; - ifaddr = pim_ifp->primary_address; - - pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), - now, pim_ifp->pim_dr_election_last); - - pim_inet4_dump("", pim_ifp->pim_dr_addr, - dr_str, sizeof(dr_str)); - - if (uj) { - json_row = json_object_new_object(); - json_object_string_add(json_row, "interface", ifp->name); - json_object_string_add(json_row, "address", inet_ntoa(ifaddr)); - json_object_string_add(json_row, "drAddress", dr_str); - json_object_string_add(json_row, "drUpTime", dr_uptime); - json_object_int_add(json_row, "drElections", pim_ifp->pim_dr_election_count); - json_object_int_add(json_row, "drChanges", pim_ifp->pim_dr_election_changes); - json_object_int_add(json_row, "drPriorityMissing", pim_ifp->pim_dr_num_nondrpri_neighbors); - json_object_int_add(json_row, "drPrioritySent", pim_ifp->pim_dr_priority); - json_object_object_add(json, ifp->name, json_row); - } else { - vty_out(vty, "%-9s %-15s %-15s %8s %9d %7d %6d %10d%s", - ifp->name, - inet_ntoa(ifaddr), - dr_str, - dr_uptime, - pim_ifp->pim_dr_election_count, - pim_ifp->pim_dr_election_changes, - pim_ifp->pim_dr_num_nondrpri_neighbors, - pim_ifp->pim_dr_priority, - VTY_NEWLINE); - } - } - - if (uj) { - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); - json_object_free(json); - } -} - -static void pim_show_hello(struct vty *vty, u_char uj) -{ - struct listnode *node; - struct interface *ifp; - time_t now; - json_object *json = NULL; - json_object *json_row = NULL; - - now = pim_time_monotonic_sec(); - - if (uj) { - json = json_object_new_object(); - } else { - vty_out(vty, "Interface Address Period Timer StatStart Recv Rfail Send Sfail LGenid%s", VTY_NEWLINE); - } - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - struct pim_interface *pim_ifp; - struct in_addr ifaddr; - char hello_period[10]; - char hello_timer[10]; - char stat_uptime[10]; - - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (pim_ifp->pim_sock_fd < 0) + if (strcmp(ifname, ifp->name)) continue; + found_ifname = 1; ifaddr = pim_ifp->primary_address; - - pim_time_timer_to_mmss(hello_timer, sizeof(hello_timer), pim_ifp->t_pim_hello_timer); + pim_inet4_dump("", pim_ifp->pim_dr_addr, dr_str, sizeof(dr_str)); + pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now, pim_ifp->pim_dr_election_last); + pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer), pim_ifp->t_pim_hello_timer); pim_time_mmss(hello_period, sizeof(hello_period), pim_ifp->pim_hello_period); pim_time_uptime(stat_uptime, sizeof(stat_uptime), now - pim_ifp->pim_ifstat_start); + mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); if (uj) { + json = json_object_new_object(); json_row = json_object_new_object(); - json_object_string_add(json_row, "interface", ifp->name); - json_object_string_add(json_row, "address", inet_ntoa(ifaddr)); + + pim_json_ifp(json_row, ifp); + + // PIM neighbors + if (pim_ifp->pim_neighbor_list->count) { + json_pim_neighbors = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { + json_pim_neighbor = json_object_new_object(); + pim_inet4_dump("", neigh->source_addr, neigh_src_str, sizeof(neigh_src_str)); + pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); + pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer); + + json_object_string_add(json_pim_neighbor, "address", neigh_src_str); + json_object_string_add(json_pim_neighbor, "upTime", uptime); + json_object_string_add(json_pim_neighbor, "holdtime", expire); + + json_object_object_add(json_pim_neighbors, neigh_src_str, json_pim_neighbor); + } + + json_object_object_add(json_row, "neighbors", json_pim_neighbors); + } + + json_object_string_add(json_row, "drAddress", dr_str); + json_object_int_add(json_row, "drPriority", pim_ifp->pim_dr_priority); + json_object_string_add(json_row, "drUptime", dr_uptime); + json_object_int_add(json_row, "drElections", pim_ifp->pim_dr_election_count); + json_object_int_add(json_row, "drChanges", pim_ifp->pim_dr_election_changes); + + // FHR + for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) { + if (strcmp(ifp->name, up->rpf.source_nexthop.interface->name) == 0) { + if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) { + if (!json_fhr_sources) { + json_fhr_sources = json_object_new_object(); + } + + pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); + pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); + + /* Does this group live in json_fhr_sources? If not create it. */ + json_group = json_object_object_get(json_fhr_sources, grp_str); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json_fhr_sources, grp_str, json_group); + } + + json_group_source = json_object_new_object(); + json_object_string_add(json_group_source, "source", src_str); + json_object_string_add(json_group_source, "group", grp_str); + json_object_string_add(json_group_source, "upTime", uptime); + json_object_object_add(json_group, src_str, json_group_source); + } + } + } + + if (json_fhr_sources) { + json_object_object_add(json_row, "firstHopRouter", json_fhr_sources); + } + json_object_int_add(json_row, "helloPeriod", pim_ifp->pim_hello_period); - json_object_string_add(json_row, "timer", hello_timer); - json_object_string_add(json_row, "statStart", stat_uptime); - json_object_int_add(json_row, "received", pim_ifp->pim_ifstat_hello_recv); - json_object_int_add(json_row, "receivedFail", pim_ifp->pim_ifstat_hello_recvfail); - json_object_int_add(json_row, "send", pim_ifp->pim_ifstat_hello_sent); - json_object_int_add(json_row, "sendFail", pim_ifp->pim_ifstat_hello_sendfail); - json_object_int_add(json_row, "generationId", pim_ifp->pim_generation_id); + json_object_string_add(json_row, "helloTimer", hello_timer); + json_object_string_add(json_row, "helloStatStart", stat_uptime); + json_object_int_add(json_row, "helloReceived", pim_ifp->pim_ifstat_hello_recv); + json_object_int_add(json_row, "helloReceivedFailed", pim_ifp->pim_ifstat_hello_recvfail); + json_object_int_add(json_row, "helloSend", pim_ifp->pim_ifstat_hello_sent); + json_object_int_add(json_row, "hellosendFailed", pim_ifp->pim_ifstat_hello_sendfail); + json_object_int_add(json_row, "helloGenerationId", pim_ifp->pim_generation_id); + json_object_int_add(json_row, "flagMulticastLoop", mloop); + + json_object_int_add(json_row, "effectivePropagationDelay", pim_if_effective_propagation_delay_msec(ifp)); + json_object_int_add(json_row, "effectiveOverrideInterval", pim_if_effective_override_interval_msec(ifp)); + json_object_int_add(json_row, "joinPruneOverrideInterval", pim_if_jp_override_interval_msec(ifp)); + + json_object_int_add(json_row, "propagationDelay", pim_ifp->pim_propagation_delay_msec); + json_object_int_add(json_row, "propagationDelayHighest", pim_ifp->pim_neighbors_highest_propagation_delay_msec); + json_object_int_add(json_row, "overrideInterval", pim_ifp->pim_override_interval_msec); + json_object_int_add(json_row, "overrideIntervalHighest", pim_ifp->pim_neighbors_highest_override_interval_msec); + json_object_object_add(json, ifp->name, json_row); + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); + } else { - vty_out(vty, "%-9s %-15s %6s %5s %9s %4u %5u %4u %5u %08x%s", - ifp->name, - inet_ntoa(ifaddr), - hello_period, - hello_timer, - stat_uptime, - pim_ifp->pim_ifstat_hello_recv, - pim_ifp->pim_ifstat_hello_recvfail, - pim_ifp->pim_ifstat_hello_sent, - pim_ifp->pim_ifstat_hello_sendfail, - pim_ifp->pim_generation_id, - VTY_NEWLINE); + vty_out(vty, "Interface : %s%s", ifp->name, VTY_NEWLINE); + vty_out(vty, "State : %s%s", if_is_up(ifp) ? "up" : "down", VTY_NEWLINE); + vty_out(vty, "Address : %s%s", inet_ntoa(ifaddr), VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + + // PIM neighbors + print_header = 1; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { + + if (print_header) { + vty_out(vty, "PIM Neighbors%s", VTY_NEWLINE); + vty_out(vty, "-------------%s", VTY_NEWLINE); + print_header = 0; + } + + pim_inet4_dump("", neigh->source_addr, neigh_src_str, sizeof(neigh_src_str)); + pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); + pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer); + vty_out(vty, "%-15s : up for %s, holdtime expires in %s%s", neigh_src_str, uptime, expire, VTY_NEWLINE); + } + + if (!print_header) { + vty_out(vty, "%s", VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + } + + vty_out(vty, "Designated Router%s", VTY_NEWLINE); + vty_out(vty, "-----------------%s", VTY_NEWLINE); + vty_out(vty, "Address : %s%s", dr_str, VTY_NEWLINE); + vty_out(vty, "Priority : %d%s", pim_ifp->pim_dr_priority, VTY_NEWLINE); + vty_out(vty, "Uptime : %s%s", dr_uptime, VTY_NEWLINE); + vty_out(vty, "Elections : %d%s", pim_ifp->pim_dr_election_count, VTY_NEWLINE); + vty_out(vty, "Changes : %d%s", pim_ifp->pim_dr_election_changes, VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + + // FHR + print_header = 1; + for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) { + if (strcmp(ifp->name, up->rpf.source_nexthop.interface->name) == 0) { + if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) { + + if (print_header) { + vty_out(vty, "FHR - First Hop Router%s", VTY_NEWLINE); + vty_out(vty, "----------------------%s", VTY_NEWLINE); + print_header = 0; + } + + pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); + pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); + vty_out(vty, "%s : %s is a source, uptime is %s%s", grp_str, src_str, uptime, VTY_NEWLINE); + } + } + } + + if (!print_header) { + vty_out(vty, "%s", VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + } + + vty_out(vty, "Hellos%s", VTY_NEWLINE); + vty_out(vty, "------%s", VTY_NEWLINE); + vty_out(vty, "Period : %d%s", pim_ifp->pim_hello_period, VTY_NEWLINE); + vty_out(vty, "Timer : %s%s", hello_timer, VTY_NEWLINE); + vty_out(vty, "StatStart : %s%s", stat_uptime, VTY_NEWLINE); + vty_out(vty, "Receive : %d%s", pim_ifp->pim_ifstat_hello_recv, VTY_NEWLINE); + vty_out(vty, "Receive Failed : %d%s", pim_ifp->pim_ifstat_hello_recvfail, VTY_NEWLINE); + vty_out(vty, "Send : %d%s", pim_ifp->pim_ifstat_hello_sent, VTY_NEWLINE); + vty_out(vty, "Send Failed : %d%s", pim_ifp->pim_ifstat_hello_sendfail, VTY_NEWLINE); + vty_out(vty, "Generation ID : %08x%s", pim_ifp->pim_generation_id, VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + + pim_print_ifp_flags(vty, ifp, mloop); + + vty_out(vty, "Join Prune Interval%s", VTY_NEWLINE); + vty_out(vty, "-------------------%s", VTY_NEWLINE); + vty_out(vty, "LAN Delay : %s%s", pim_if_lan_delay_enabled(ifp) ? "yes" : "no", VTY_NEWLINE); + vty_out(vty, "Effective Propagation Delay : %d msec%s", pim_if_effective_propagation_delay_msec(ifp), VTY_NEWLINE); + vty_out(vty, "Effective Override Interval : %d msec%s", pim_if_effective_override_interval_msec(ifp), VTY_NEWLINE); + vty_out(vty, "Join Prune Override Interval : %d msec%s", pim_if_jp_override_interval_msec(ifp), VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + + vty_out(vty, "LAN Prune Delay%s", VTY_NEWLINE); + vty_out(vty, "---------------%s", VTY_NEWLINE); + vty_out(vty, "Propagation Delay : %d msec%s", pim_ifp->pim_propagation_delay_msec, VTY_NEWLINE); + vty_out(vty, "Propagation Delay (Highest) : %d msec%s", pim_ifp->pim_neighbors_highest_propagation_delay_msec, VTY_NEWLINE); + vty_out(vty, "Override Interval : %d msec%s", pim_ifp->pim_override_interval_msec, VTY_NEWLINE); + vty_out(vty, "Override Interval (Highest) : %d msec%s", pim_ifp->pim_neighbors_highest_override_interval_msec, VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); } } - if (uj) { - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); - json_object_free(json); - } + if (!found_ifname) + { + if (uj) + vty_out (vty, "{}%s", VTY_NEWLINE); + else + vty_out (vty, "%% No such interface%s", VTY_NEWLINE); + } } + static void pim_show_interfaces(struct vty *vty, u_char uj) { - struct listnode *node; + struct in_addr ifaddr; struct interface *ifp; - time_t now; + struct listnode *node; + struct listnode *upnode; + struct pim_interface *pim_ifp; + struct pim_upstream *up; + int fhr = 0; + int pim_dr_local = 0; + int pim_nbrs = 0; json_object *json = NULL; json_object *json_row = NULL; - now = pim_time_monotonic_sec(); - - if (uj) + if (uj) { json = json_object_new_object(); - else - vty_out(vty, "Interface Address ifIndex Socket Uptime Multi Broad MLoop AllMu Prmsc Del%s", VTY_NEWLINE); + } else { + vty_out(vty, "Interface State Address PIM Nbrs PIM DR FHR%s", VTY_NEWLINE); + } for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - struct pim_interface *pim_ifp; - struct in_addr ifaddr; - char uptime[10]; - int mloop; - pim_ifp = ifp->info; if (!pim_ifp) @@ -736,50 +988,37 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) continue; ifaddr = pim_ifp->primary_address; + pim_nbrs = pim_ifp->pim_neighbor_list->count; + pim_dr_local = 0; + fhr = 0; - pim_time_uptime(uptime, sizeof(uptime), now - pim_ifp->pim_sock_creation); + if (pim_ifp->pim_dr_addr.s_addr == pim_ifp->primary_address.s_addr) + pim_dr_local = 1; + + for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) + if (strcmp(ifp->name, up->rpf.source_nexthop.interface->name) == 0) + if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) + fhr++; - mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); - if (uj) { json_row = json_object_new_object(); + json_object_string_add(json_row, "name", ifp->name); + json_object_string_add(json_row, "state", if_is_up(ifp) ? "up" : "down"); json_object_string_add(json_row, "address", inet_ntoa(ifaddr)); json_object_int_add(json_row, "ifIndex", ifp->ifindex); - json_object_int_add(json_row, "socket", pim_ifp->pim_sock_fd); - json_object_string_add(json_row, "upTime", uptime); - - if (if_is_multicast(ifp)) - json_object_boolean_true_add(json_row, "multicast"); - - if (if_is_broadcast(ifp)) - json_object_boolean_true_add(json_row, "broadcast"); - - json_object_int_add(json_row, "loopToLocalSocket", mloop); - - if (ifp->flags & IFF_ALLMULTI) - json_object_boolean_true_add(json_row, "allMulticast"); - - if (ifp->flags & IFF_PROMISC) - json_object_boolean_true_add(json_row, "promiscuous"); - - if (PIM_IF_IS_DELETED(ifp)) - json_object_boolean_true_add(json_row, "deleted"); - + json_object_int_add(json_row, "pimNeighbors", pim_nbrs); + json_object_int_add(json_row, "firstHopRouter", fhr); + json_object_string_add(json_row, "pimDesignatedRouter", inet_ntoa(pim_ifp->pim_dr_addr)); json_object_object_add(json, ifp->name, json_row); } else { - vty_out(vty, "%-9s %-15s %7d %6d %8s %5s %5s %5s %5s %5s %3s%s", + vty_out(vty, "%-9s %5s %15s %8d %15s %3d%s", ifp->name, + if_is_up(ifp) ? "up" : "down", inet_ntoa(ifaddr), - ifp->ifindex, - pim_ifp->pim_sock_fd, - uptime, - if_is_multicast(ifp) ? "yes" : "no", - if_is_broadcast(ifp) ? "yes" : "no", - (mloop < 0) ? "?" : (mloop ? "yes" : "no"), - (ifp->flags & IFF_ALLMULTI) ? "yes" : "no", - (ifp->flags & IFF_PROMISC) ? "yes" : "no", - PIM_IF_IS_DELETED(ifp) ? "yes" : "no", + pim_nbrs, + pim_dr_local ? "local" : inet_ntoa(pim_ifp->pim_dr_addr), + fhr, VTY_NEWLINE); } } @@ -848,11 +1087,163 @@ static void pim_show_join(struct vty *vty) } -static void pim_show_neighbors(struct vty *vty, u_char uj) +static void pim_show_neighbors_single(struct vty *vty, const char *neighbor, u_char uj) { struct listnode *node; + struct listnode *neighnode; struct interface *ifp; + struct pim_interface *pim_ifp; + struct pim_neighbor *neigh; time_t now; + int found_neighbor = 0; + int option_address_list; + int option_dr_priority; + int option_generation_id; + int option_holdtime; + int option_lan_prune_delay; + int option_t_bit; + char uptime[10]; + char expire[10]; + char neigh_src_str[100]; + + json_object *json = NULL; + json_object *json_ifp = NULL; + json_object *json_row = NULL; + + now = pim_time_monotonic_sec(); + + if (uj) + json = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->pim_sock_fd < 0) + continue; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { + pim_inet4_dump("", neigh->source_addr, + neigh_src_str, sizeof(neigh_src_str)); + + /* + * The user can specify either the interface name or the PIM neighbor IP. + * If this pim_ifp matches neither then skip. + */ + if (strcmp(neighbor, ifp->name) && strcmp(neighbor, neigh_src_str)) + continue; + + found_neighbor = 1; + pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); + pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer); + + option_address_list = 0; + option_dr_priority = 0; + option_generation_id = 0; + option_holdtime = 0; + option_lan_prune_delay = 0; + option_t_bit = 0; + + if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_ADDRESS_LIST)) + option_address_list = 1; + + if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY)) + option_dr_priority = 1; + + if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_GENERATION_ID)) + option_generation_id = 1; + + if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_HOLDTIME)) + option_holdtime = 1; + + if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY)) + option_lan_prune_delay = 1; + + if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)) + option_t_bit = 1; + + if (uj) { + + /* Does this ifp live in json? If not create it. */ + json_ifp = json_object_object_get(json, ifp->name); + + if (!json_ifp) { + json_ifp = json_object_new_object(); + json_object_object_add(json, ifp->name, json_ifp); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "interface", ifp->name); + json_object_string_add(json_row, "address", neigh_src_str); + json_object_string_add(json_row, "upTime", uptime); + json_object_string_add(json_row, "holdtime", expire); + json_object_int_add(json_row, "drPriority", neigh->dr_priority); + json_object_int_add(json_row, "generationId", neigh->generation_id); + + if (option_address_list) + json_object_boolean_true_add(json_row, "helloOptionAddressList"); + + if (option_dr_priority) + json_object_boolean_true_add(json_row, "helloOptionDrPriority"); + + if (option_generation_id) + json_object_boolean_true_add(json_row, "helloOptionGenerationId"); + + if (option_holdtime) + json_object_boolean_true_add(json_row, "helloOptionHoldtime"); + + if (option_lan_prune_delay) + json_object_boolean_true_add(json_row, "helloOptionLanPruneDelay"); + + if (option_t_bit) + json_object_boolean_true_add(json_row, "helloOptionTBit"); + + json_object_object_add(json_ifp, neigh_src_str, json_row); + + } else { + vty_out(vty, "Interface : %s%s", ifp->name, VTY_NEWLINE); + vty_out(vty, "Neighbor : %s%s", neigh_src_str, VTY_NEWLINE); + vty_out(vty, " Uptime : %s%s", uptime, VTY_NEWLINE); + vty_out(vty, " Holdtime : %s%s", expire, VTY_NEWLINE); + vty_out(vty, " DR Priority : %d%s", neigh->dr_priority, VTY_NEWLINE); + vty_out(vty, " Generation ID : %08x%s", neigh->generation_id, VTY_NEWLINE); + vty_out(vty, " Override Interval (msec) : %d%s", neigh->override_interval_msec, VTY_NEWLINE); + vty_out(vty, " Propagation Delay (msec) : %d%s", neigh->propagation_delay_msec, VTY_NEWLINE); + vty_out(vty, " Hello Option - Address List : %s%s", option_address_list ? "yes" : "no", VTY_NEWLINE); + vty_out(vty, " Hello Option - DR Priority : %s%s", option_dr_priority ? "yes" : "no", VTY_NEWLINE); + vty_out(vty, " Hello Option - Generation ID : %s%s", option_generation_id? "yes" : "no", VTY_NEWLINE); + vty_out(vty, " Hello Option - Holdtime : %s%s", option_holdtime ? "yes" : "no", VTY_NEWLINE); + vty_out(vty, " Hello Option - LAN Prune Delay : %s%s", option_lan_prune_delay ? "yes" : "no", VTY_NEWLINE); + vty_out(vty, " Hello Option - T-bit : %s%s", option_t_bit ? "yes" : "no", VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + } + } + } + + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); + } else { + { + if (!found_neighbor) + vty_out (vty, "%% No such interface or neighbor%s", VTY_NEWLINE); + } + } +} + +static void pim_show_neighbors(struct vty *vty, u_char uj) +{ + struct listnode *node; + struct listnode *neighnode; + struct interface *ifp; + struct pim_interface *pim_ifp; + struct pim_neighbor *neigh; + time_t now; + char uptime[10]; + char expire[10]; + char neigh_src_str[100]; json_object *json = NULL; json_object *json_ifp_rows = NULL; json_object *json_row = NULL; @@ -862,20 +1253,10 @@ static void pim_show_neighbors(struct vty *vty, u_char uj) if (uj) { json = json_object_new_object(); } else { - vty_out(vty, - "Recv flags: H=holdtime L=lan_prune_delay P=dr_priority G=generation_id A=address_list%s" - " T=can_disable_join_suppression%s%s", - VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); - - vty_out(vty, "Interface Address Neighbor Uptime Timer Holdt DrPri GenId Recv %s", VTY_NEWLINE); + vty_out(vty, "Interface Neighbor Uptime Holdtime DR Pri%s", VTY_NEWLINE); } for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - struct pim_interface *pim_ifp; - struct in_addr ifaddr; - struct listnode *neighnode; - struct pim_neighbor *neigh; - pim_ifp = ifp->info; if (!pim_ifp) @@ -887,71 +1268,29 @@ static void pim_show_neighbors(struct vty *vty, u_char uj) if (uj) json_ifp_rows = json_object_new_object(); - ifaddr = pim_ifp->primary_address; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - char uptime[10]; - char holdtime[10]; - char expire[10]; - char neigh_src_str[100]; - char recv[7]; - pim_inet4_dump("", neigh->source_addr, neigh_src_str, sizeof(neigh_src_str)); pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); - pim_time_mmss(holdtime, sizeof(holdtime), neigh->holdtime); - pim_time_timer_to_mmss(expire, sizeof(expire), neigh->t_expire_timer); + pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer); if (uj) { json_row = json_object_new_object(); json_object_string_add(json_row, "interface", ifp->name); - json_object_string_add(json_row, "address", inet_ntoa(ifaddr)); json_object_string_add(json_row, "neighbor", neigh_src_str); json_object_string_add(json_row, "upTime", uptime); - json_object_string_add(json_row, "timer", expire); - json_object_string_add(json_row, "holdTime", holdtime); + json_object_string_add(json_row, "holdTime", expire); + json_object_int_add(json_row, "holdTimeMax", neigh->holdtime); json_object_int_add(json_row, "drPriority", neigh->dr_priority); - json_object_int_add(json_row, "generationId", neigh->generation_id); - - if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_HOLDTIME)) - json_object_boolean_true_add(json_row, "flagHoldtime"); - - if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY)) - json_object_boolean_true_add(json_row, "flagLanPruneDelay"); - - if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY)) - json_object_boolean_true_add(json_row, "flagDrPriority"); - - if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_GENERATION_ID)) - json_object_boolean_true_add(json_row, "flagGenerationId"); - - if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_ADDRESS_LIST)) - json_object_boolean_true_add(json_row, "flagAddressList"); - - if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)) - json_object_boolean_true_add(json_row, "flagCanDisableJoinSuppression"); - json_object_object_add(json_ifp_rows, neigh_src_str, json_row); } else { - recv[0] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_HOLDTIME) ? 'H' : ' '; - recv[1] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY) ? 'L' : ' '; - recv[2] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY) ? 'P' : ' '; - recv[3] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_GENERATION_ID) ? 'G' : ' '; - recv[4] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_ADDRESS_LIST) ? 'A' : ' '; - recv[5] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION) ? 'T' : ' '; - recv[6] = '\0'; - - vty_out(vty, "%-9s %-15s %-15s %8s %5s %5s %5u %08x %6s%s", + vty_out(vty, "%-9s %15s %8s %8s %6d%s", ifp->name, - inet_ntoa(ifaddr), neigh_src_str, uptime, expire, - holdtime, neigh->dr_priority, - neigh->generation_id, - recv, VTY_NEWLINE); } } @@ -968,101 +1307,6 @@ static void pim_show_neighbors(struct vty *vty, u_char uj) } } -static void pim_show_lan_prune_delay(struct vty *vty) -{ - struct listnode *node; - struct interface *ifp; - - vty_out(vty, - "PrDly=propagation_delay (msec) OvInt=override_interval (msec)%s" - "HiDly=highest_propagation_delay (msec) HiInt=highest_override_interval (msec)%s" - "NoDly=number_of_non_lan_delay_neighbors%s" - "T=t_bit LPD=lan_prune_delay_hello_option%s%s", - VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); - - vty_out(vty, "Interface Address PrDly OvInt NoDly HiDly HiInt T | Neighbor LPD PrDly OvInt T%s", VTY_NEWLINE); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - struct pim_interface *pim_ifp; - struct in_addr ifaddr; - struct listnode *neighnode; - struct pim_neighbor *neigh; - - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (pim_ifp->pim_sock_fd < 0) - continue; - - ifaddr = pim_ifp->primary_address; - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - char neigh_src_str[100]; - - pim_inet4_dump("", neigh->source_addr, - neigh_src_str, sizeof(neigh_src_str)); - - vty_out(vty, "%-9s %-15s %5u %5u %5u %5u %5u %1u | %-15s %-3s %5u %5u %1u%s", - ifp->name, - inet_ntoa(ifaddr), - pim_ifp->pim_propagation_delay_msec, - pim_ifp->pim_override_interval_msec, - pim_ifp->pim_number_of_nonlandelay_neighbors, - pim_ifp->pim_neighbors_highest_propagation_delay_msec, - pim_ifp->pim_neighbors_highest_override_interval_msec, - PIM_FORCE_BOOLEAN(PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)), - neigh_src_str, - PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY) ? "yes" : "no", - neigh->propagation_delay_msec, - neigh->override_interval_msec, - PIM_FORCE_BOOLEAN(PIM_OPTION_IS_SET(neigh->hello_options, - PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)), - VTY_NEWLINE); - } - - } -} - -static void pim_show_jp_override_interval(struct vty *vty) -{ - struct listnode *node; - struct interface *ifp; - - vty_out(vty, - "EffPDelay=effective_propagation_delay (msec)%s" - "EffOvrInt=override_interval (msec)%s" - "JPOvrInt=jp_override_interval (msec)%s%s", - VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); - - vty_out(vty, "Interface Address LAN_Delay EffPDelay EffOvrInt JPOvrInt%s", VTY_NEWLINE); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - struct pim_interface *pim_ifp; - struct in_addr ifaddr; - - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (pim_ifp->pim_sock_fd < 0) - continue; - - ifaddr = pim_ifp->primary_address; - - vty_out(vty, "%-9s %-15s %-9s %9u %9u %8u%s", - ifp->name, - inet_ntoa(ifaddr), - pim_if_lan_delay_enabled(ifp) ? "enabled" : "disabled", - pim_if_effective_propagation_delay_msec(ifp), - pim_if_effective_override_interval_msec(ifp), - pim_if_jp_override_interval_msec(ifp), - VTY_NEWLINE); - } -} - static void pim_show_neighbors_secondary(struct vty *vty) { struct listnode *node; @@ -1514,40 +1758,6 @@ static void pim_show_rpf(struct vty *vty, u_char uj) } } -static void igmp_show_querier(struct vty *vty) -{ - struct listnode *node; - struct interface *ifp; - - vty_out(vty, "Interface Address Querier StartCount Query-Timer Other-Timer%s", VTY_NEWLINE); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - struct pim_interface *pim_ifp = ifp->info; - struct listnode *sock_node; - struct igmp_sock *igmp; - - if (!pim_ifp) - continue; - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - char query_hhmmss[10]; - char other_hhmmss[10]; - - pim_time_timer_to_hhmmss(query_hhmmss, sizeof(query_hhmmss), igmp->t_igmp_query_timer); - pim_time_timer_to_hhmmss(other_hhmmss, sizeof(other_hhmmss), igmp->t_other_querier_timer); - - vty_out(vty, "%-9s %-15s %-7s %10d %11s %11s%s", - ifp->name, - inet_ntoa(igmp->ifaddr), - igmp->t_igmp_query_timer ? "THIS" : "OTHER", - igmp->startup_query_count, - query_hhmmss, - other_hhmmss, - VTY_NEWLINE); - } - } -} - static void igmp_show_groups(struct vty *vty) { struct listnode *ifnode; @@ -1658,80 +1868,6 @@ static void igmp_show_group_retransmission(struct vty *vty) } /* scan interfaces */ } -static void igmp_show_parameters(struct vty *vty) -{ - struct listnode *ifnode; - struct interface *ifp; - - vty_out(vty, - "QRV: Robustness Variable SQI: Startup Query Interval%s" - "QQI: Query Interval OQPI: Other Querier Present Interval%s" - "QRI: Query Response Interval LMQT: Last Member Query Time%s" - "GMI: Group Membership Interval OHPI: Older Host Present Interval%s%s", - VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); - - vty_out(vty, - "Interface Address QRV QQI QRI GMI SQI OQPI LMQT OHPI %s", - VTY_NEWLINE); - - /* scan interfaces */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - struct pim_interface *pim_ifp = ifp->info; - struct listnode *sock_node; - struct igmp_sock *igmp; - - if (!pim_ifp) - continue; - - /* scan igmp sockets */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - char ifaddr_str[100]; - long gmi_dsec; /* Group Membership Interval */ - long oqpi_dsec; /* Other Querier Present Interval */ - int sqi; - long lmqt_dsec; - long ohpi_dsec; - long qri_dsec; - - pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - - gmi_dsec = PIM_IGMP_GMI_MSEC(igmp->querier_robustness_variable, - igmp->querier_query_interval, - pim_ifp->igmp_query_max_response_time_dsec) / 100; - - sqi = PIM_IGMP_SQI(pim_ifp->igmp_default_query_interval); - - oqpi_dsec = PIM_IGMP_OQPI_MSEC(igmp->querier_robustness_variable, - igmp->querier_query_interval, - pim_ifp->igmp_query_max_response_time_dsec) / 100; - - lmqt_dsec = PIM_IGMP_LMQT_MSEC(pim_ifp->igmp_query_max_response_time_dsec, - igmp->querier_robustness_variable) / 100; - - ohpi_dsec = PIM_IGMP_OHPI_DSEC(igmp->querier_robustness_variable, - igmp->querier_query_interval, - pim_ifp->igmp_query_max_response_time_dsec); - - qri_dsec = pim_ifp->igmp_query_max_response_time_dsec; - - vty_out(vty, - "%-9s %-15s %3d %3d %3ld.%ld %3ld.%ld %3d %3ld.%ld %3ld.%ld %3ld.%ld%s", - ifp->name, - ifaddr_str, - igmp->querier_robustness_variable, - igmp->querier_query_interval, - qri_dsec / 10, qri_dsec % 10, - gmi_dsec / 10, gmi_dsec % 10, - sqi, - oqpi_dsec / 10, oqpi_dsec % 10, - lmqt_dsec / 10, lmqt_dsec % 10, - ohpi_dsec / 10, ohpi_dsec % 10, - VTY_NEWLINE); - - } /* scan igmp sockets */ - } /* scan interfaces */ -} - static void igmp_show_sources(struct vty *vty) { struct listnode *ifnode; @@ -2023,13 +2159,19 @@ DEFUN (clear_ip_pim_oil, DEFUN (show_ip_igmp_interface, show_ip_igmp_interface_cmd, - "show ip igmp interface", + "show ip igmp interface [WORD] [json]", SHOW_STR IP_STR IGMP_STR - "IGMP interface information\n") + "IGMP interface information\n" + "interface name\n" + "JavaScript Object Notation\n") { - igmp_show_interfaces(vty); + u_char uj = use_json(argc, argv); + if (argv[4]->arg) + igmp_show_interfaces_single(vty, argv[4]->arg, uj); + else + igmp_show_interfaces(vty, uj); return CMD_SUCCESS; } @@ -2074,19 +2216,6 @@ DEFUN (show_ip_igmp_groups_retransmissions, return CMD_SUCCESS; } -DEFUN (show_ip_igmp_parameters, - show_ip_igmp_parameters_cmd, - "show ip igmp parameters", - SHOW_STR - IP_STR - IGMP_STR - "IGMP parameters information\n") -{ - igmp_show_parameters(vty); - - return CMD_SUCCESS; -} - DEFUN (show_ip_igmp_sources, show_ip_igmp_sources_cmd, "show ip igmp sources", @@ -2114,32 +2243,6 @@ DEFUN (show_ip_igmp_sources_retransmissions, return CMD_SUCCESS; } -DEFUN (show_ip_igmp_querier, - show_ip_igmp_querier_cmd, - "show ip igmp querier", - SHOW_STR - IP_STR - IGMP_STR - "IGMP querier information\n") -{ - igmp_show_querier(vty); - - return CMD_SUCCESS; -} - -DEFUN (show_ip_pim_address, - show_ip_pim_address_cmd, - "show ip pim address", - SHOW_STR - IP_STR - PIM_STR - "PIM interface address\n") -{ - show_interface_address(vty); - - return CMD_SUCCESS; -} - DEFUN (show_ip_pim_assert, show_ip_pim_assert_cmd, "show ip pim assert", @@ -2222,14 +2325,19 @@ DEFUN (show_ip_pim_hello, DEFUN (show_ip_pim_interface, show_ip_pim_interface_cmd, - "show ip pim interface [json]", + "show ip pim interface [WORD] [json]", SHOW_STR IP_STR PIM_STR - "PIM interface information\n") + "PIM interface information\n" + "interface name\n" + "JavaScript Object Notation\n") { u_char uj = use_json(argc, argv); - pim_show_interfaces(vty, uj); + if (argv[4]->arg) + pim_show_interfaces_single(vty, argv[4]->arg, uj); + else + pim_show_interfaces(vty, uj); return CMD_SUCCESS; } @@ -2247,19 +2355,6 @@ DEFUN (show_ip_pim_join, return CMD_SUCCESS; } -DEFUN (show_ip_pim_lan_prune_delay, - show_ip_pim_lan_prune_delay_cmd, - "show ip pim lan-prune-delay", - SHOW_STR - IP_STR - PIM_STR - "PIM neighbors LAN prune delay parameters\n") -{ - pim_show_lan_prune_delay(vty); - - return CMD_SUCCESS; -} - DEFUN (show_ip_pim_local_membership, show_ip_pim_local_membership_cmd, "show ip pim local-membership", @@ -2273,29 +2368,21 @@ DEFUN (show_ip_pim_local_membership, return CMD_SUCCESS; } -DEFUN (show_ip_pim_jp_override_interval, - show_ip_pim_jp_override_interval_cmd, - "show ip pim jp-override-interval", - SHOW_STR - IP_STR - PIM_STR - "PIM interface J/P override interval\n") -{ - pim_show_jp_override_interval(vty); - - return CMD_SUCCESS; -} - DEFUN (show_ip_pim_neighbor, show_ip_pim_neighbor_cmd, - "show ip pim neighbor [json]", + "show ip pim neighbor [WORD] [json]", SHOW_STR IP_STR PIM_STR - "PIM neighbor information\n") + "PIM neighbor information\n" + "Name of interface or neighbor\n" + "JavaScript Object Notation\n") { u_char uj = use_json(argc, argv); - pim_show_neighbors(vty, uj); + if (argv[4]->arg) + pim_show_neighbors_single(vty, argv[4]->arg, uj); + else + pim_show_neighbors(vty, uj); return CMD_SUCCESS; } @@ -2319,7 +2406,8 @@ DEFUN (show_ip_pim_upstream, SHOW_STR IP_STR PIM_STR - "PIM upstream information\n") + "PIM upstream information\n" + "JavaScript Object Notation\n") { u_char uj = use_json(argc, argv); pim_show_upstream(vty, uj); @@ -2333,7 +2421,8 @@ DEFUN (show_ip_pim_upstream_join_desired, SHOW_STR IP_STR PIM_STR - "PIM upstream join-desired\n") + "PIM upstream join-desired\n" + "JavaScript Object Notation\n") { u_char uj = use_json(argc, argv); pim_show_join_desired(vty, uj); @@ -2347,7 +2436,8 @@ DEFUN (show_ip_pim_upstream_rpf, SHOW_STR IP_STR PIM_STR - "PIM upstream source rpf\n") + "PIM upstream source rpf\n" + "JavaScript Object Notation\n") { u_char uj = use_json(argc, argv); pim_show_upstream_rpf(vty, uj); @@ -2361,7 +2451,8 @@ DEFUN (show_ip_pim_rp, SHOW_STR IP_STR PIM_STR - "PIM RP information\n") + "PIM RP information\n" + "JavaScript Object Notation\n") { u_char uj = use_json(argc, argv); pim_rp_show_information (vty, uj); @@ -2375,7 +2466,8 @@ DEFUN (show_ip_pim_rpf, SHOW_STR IP_STR PIM_STR - "PIM cached source rpf information\n") + "PIM cached source rpf information\n" + "JavaScript Object Notation\n") { u_char uj = use_json(argc, argv); pim_show_rpf(vty, uj); @@ -5267,22 +5359,16 @@ void pim_cmd_init() install_element (VIEW_NODE, &show_ip_igmp_interface_cmd); install_element (VIEW_NODE, &show_ip_igmp_join_cmd); - install_element (VIEW_NODE, &show_ip_igmp_parameters_cmd); install_element (VIEW_NODE, &show_ip_igmp_groups_cmd); install_element (VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd); install_element (VIEW_NODE, &show_ip_igmp_sources_cmd); install_element (VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd); - install_element (VIEW_NODE, &show_ip_igmp_querier_cmd); install_element (VIEW_NODE, &show_ip_pim_assert_cmd); install_element (VIEW_NODE, &show_ip_pim_assert_internal_cmd); install_element (VIEW_NODE, &show_ip_pim_assert_metric_cmd); install_element (VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd); - install_element (VIEW_NODE, &show_ip_pim_dr_cmd); - install_element (VIEW_NODE, &show_ip_pim_hello_cmd); install_element (VIEW_NODE, &show_ip_pim_interface_cmd); install_element (VIEW_NODE, &show_ip_pim_join_cmd); - install_element (VIEW_NODE, &show_ip_pim_jp_override_interval_cmd); - install_element (VIEW_NODE, &show_ip_pim_lan_prune_delay_cmd); install_element (VIEW_NODE, &show_ip_pim_local_membership_cmd); install_element (VIEW_NODE, &show_ip_pim_neighbor_cmd); install_element (VIEW_NODE, &show_ip_pim_rpf_cmd); @@ -5298,8 +5384,6 @@ void pim_cmd_init() install_element (VIEW_NODE, &show_ip_ssmpingd_cmd); install_element (VIEW_NODE, &show_debugging_pim_cmd); - install_element (ENABLE_NODE, &show_ip_pim_address_cmd); - install_element (ENABLE_NODE, &clear_ip_interfaces_cmd); install_element (ENABLE_NODE, &clear_ip_igmp_interfaces_cmd); install_element (ENABLE_NODE, &clear_ip_mroute_cmd); From 02eccbc7385a3cc36b688040de3499ca59305fa8 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 15 Sep 2016 13:42:04 -0400 Subject: [PATCH 173/386] pimd: Turn off neighbor lookup for the moment Signed-off-by: Donald Sharp --- pimd/pim_rpf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 44acde0c9e..3d88f9e70b 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -46,6 +46,7 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei int found = 0; int i = 0; + neighbor_needed = 0; memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM); num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, From 9c2df635f5c6af34e34419b2f14ed2a3a7c056eb Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Thu, 15 Sep 2016 18:49:18 +0000 Subject: [PATCH 174/386] pimd: show ip pim int WORD, show ip pim nei WORD, show ip igmp int WORD Signed-off-by: Daniel Walton Ticket: CM-11812 --- pimd/pim_cmd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 9e7a326a7c..a10cfef503 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -807,7 +807,7 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); /* Does this group live in json_fhr_sources? If not create it. */ - json_group = json_object_object_get(json_fhr_sources, grp_str); + json_object_object_get_ex(json_fhr_sources, grp_str, &json_group); if (!json_group) { json_group = json_object_new_object(); @@ -1167,7 +1167,7 @@ static void pim_show_neighbors_single(struct vty *vty, const char *neighbor, u_c if (uj) { /* Does this ifp live in json? If not create it. */ - json_ifp = json_object_object_get(json, ifp->name); + json_object_object_get_ex(json, ifp->name, &json_ifp); if (!json_ifp) { json_ifp = json_object_new_object(); From e775c0a432dec3678110b254c2aa4b99efc10e12 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Sat, 17 Sep 2016 02:22:02 +0000 Subject: [PATCH 175/386] pimd: json support for "show ip pim" commands Signed-off-by: Daniel Walton Ticket: CM-12865 --- pimd/pim_cmd.c | 305 +++++++++++++++++++++++--------------------- pimd/pim_upstream.c | 8 +- 2 files changed, 167 insertions(+), 146 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index a10cfef503..c7b296b550 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -373,14 +373,49 @@ static void pim_show_assert_winner_metric(struct vty *vty) } /* scan interfaces */ } -static void pim_show_membership(struct vty *vty) +static void json_object_pim_ifp_add(struct json_object *json, struct interface *ifp) +{ + struct pim_interface *pim_ifp; + + pim_ifp = ifp->info; + json_object_string_add(json, "name", ifp->name); + json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down"); + json_object_string_add(json, "address", inet_ntoa(pim_ifp->primary_address)); + json_object_int_add(json, "index", ifp->ifindex); + + if (if_is_multicast(ifp)) + json_object_boolean_true_add(json, "flagMulticast"); + + if (if_is_broadcast(ifp)) + json_object_boolean_true_add(json, "flagBroadcast"); + + if (ifp->flags & IFF_ALLMULTI) + json_object_boolean_true_add(json, "flagAllMulticast"); + + if (ifp->flags & IFF_PROMISC) + json_object_boolean_true_add(json, "flagPromiscuous"); + + if (PIM_IF_IS_DELETED(ifp)) + json_object_boolean_true_add(json, "flagDeleted"); + + if (pim_if_lan_delay_enabled(ifp)) + json_object_boolean_true_add(json, "lanDelayEnabled"); +} + +static void pim_show_membership(struct vty *vty, u_char uj) { struct listnode *ifnode; struct interface *ifp; + json_object *json = NULL; + json_object *json_iface = NULL; + json_object *json_row = NULL; - vty_out(vty, - "Interface Address Source Group Membership%s", - VTY_NEWLINE); + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "Interface Address Source Group Membership%s", + VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { struct pim_interface *pim_ifp; @@ -404,17 +439,39 @@ static void pim_show_membership(struct vty *vty) pim_inet4_dump("", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str)); - vty_out(vty, "%-9s %-15s %-15s %-15s %-10s%s", - ifp->name, - inet_ntoa(ifaddr), - ch_src_str, - ch_grp_str, - ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO ? - "NOINFO" : "INCLUDE", - VTY_NEWLINE); + if (uj) { + json_object_object_get_ex(json, ifp->name, &json_iface); + + if (!json_iface) { + json_iface = json_object_new_object(); + json_object_pim_ifp_add(json_iface, ifp); + json_object_object_add(json, ifp->name, json_iface); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", ch_src_str); + json_object_string_add(json_row, "group", ch_grp_str); + json_object_string_add(json_row, "localMembership", + ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO ? "NOINFO" : "INCLUDE"); + json_object_object_add(json_iface, ch_grp_str, json_row); + + } else { + vty_out(vty, "%-9s %-15s %-15s %-15s %-10s%s", + ifp->name, + inet_ntoa(ifaddr), + ch_src_str, + ch_grp_str, + ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO ? + "NOINFO" : "INCLUDE", + VTY_NEWLINE); + } } /* scan interface channels */ } /* scan interfaces */ + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); + } } static void pim_print_ifp_flags(struct vty *vty, struct interface *ifp, int mloop) @@ -432,36 +489,6 @@ static void pim_print_ifp_flags(struct vty *vty, struct interface *ifp, int mloo vty_out(vty, "%s", VTY_NEWLINE); } -static void pim_json_ifp(struct json_object *json, struct interface *ifp) -{ - struct pim_interface *pim_ifp; - - pim_ifp = ifp->info; - json_object_string_add(json, "name", ifp->name); - json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down"); - json_object_string_add(json, "address", inet_ntoa(pim_ifp->primary_address)); - - if (if_is_multicast(ifp)) - json_object_boolean_true_add(json, "flagMulticast"); - - if (if_is_broadcast(ifp)) - json_object_boolean_true_add(json, "flagBroadcast"); - - json_object_int_add(json, "index", ifp->ifindex); - - if (ifp->flags & IFF_ALLMULTI) - json_object_boolean_true_add(json, "flagAllMulticast"); - - if (ifp->flags & IFF_PROMISC) - json_object_boolean_true_add(json, "flagPromiscuous"); - - if (PIM_IF_IS_DELETED(ifp)) - json_object_boolean_true_add(json, "flagDeleted"); - - if (pim_if_lan_delay_enabled(ifp)) - json_object_boolean_true_add(json, "lanDelayEnabled"); -} - static void igmp_show_interfaces(struct vty *vty, u_char uj) { struct listnode *node; @@ -498,7 +525,7 @@ static void igmp_show_interfaces(struct vty *vty, u_char uj) if (uj) { json_row = json_object_new_object(); - pim_json_ifp(json_row, ifp); + json_object_pim_ifp_add(json_row, ifp); json_object_string_add(json_row, "upTime", uptime); if (igmp->t_igmp_query_timer) { @@ -590,7 +617,7 @@ static void igmp_show_interfaces_single(struct vty *vty, const char *ifname, u_c if (uj) { json = json_object_new_object(); json_row = json_object_new_object(); - pim_json_ifp(json_row, ifp); + json_object_pim_ifp_add(json_row, ifp); json_object_string_add(json_row, "upTime", uptime); json_object_string_add(json_row, "querier", igmp->t_igmp_query_timer ? "local" : "other"); @@ -736,8 +763,8 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch json_object *json_pim_neighbor = NULL; json_object *json_pim_neighbors = NULL; json_object *json_group = NULL; - json_object *json_fhr_sources = NULL; json_object *json_group_source = NULL; + json_object *json_fhr_sources = NULL; now = pim_time_monotonic_sec(); @@ -765,8 +792,7 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch if (uj) { json = json_object_new_object(); json_row = json_object_new_object(); - - pim_json_ifp(json_row, ifp); + json_object_pim_ifp_add(json_row, ifp); // PIM neighbors if (pim_ifp->pim_neighbor_list->count) { @@ -1002,10 +1028,7 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) if (uj) { json_row = json_object_new_object(); - json_object_string_add(json_row, "name", ifp->name); - json_object_string_add(json_row, "state", if_is_up(ifp) ? "up" : "down"); - json_object_string_add(json_row, "address", inet_ntoa(ifaddr)); - json_object_int_add(json_row, "ifIndex", ifp->ifindex); + json_object_pim_ifp_add(json_row, ifp); json_object_int_add(json_row, "pimNeighbors", pim_nbrs); json_object_int_add(json_row, "firstHopRouter", fhr); json_object_string_add(json_row, "pimDesignatedRouter", inet_ntoa(pim_ifp->pim_dr_addr)); @@ -1029,17 +1052,23 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) } } -static void pim_show_join(struct vty *vty) +static void pim_show_join(struct vty *vty, u_char uj) { struct listnode *ifnode; struct interface *ifp; time_t now; + json_object *json = NULL; + json_object *json_iface = NULL; + json_object *json_row = NULL; now = pim_time_monotonic_sec(); - vty_out(vty, - "Interface Address Source Group State Uptime Expire Prune%s", - VTY_NEWLINE); + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "Interface Address Source Group State Uptime Expire Prune%s", + VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { struct pim_interface *pim_ifp; @@ -1072,19 +1101,43 @@ static void pim_show_join(struct vty *vty) pim_time_timer_to_mmss(prune, sizeof(prune), ch->t_ifjoin_prune_pending_timer); - vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s%s", - ifp->name, - inet_ntoa(ifaddr), - ch_src_str, - ch_grp_str, - pim_ifchannel_ifjoin_name(ch->ifjoin_state), - uptime, - expire, - prune, - VTY_NEWLINE); + if (uj) { + json_object_object_get_ex(json, ifp->name, &json_iface); + + if (!json_iface) { + json_iface = json_object_new_object(); + json_object_pim_ifp_add(json_iface, ifp); + json_object_object_add(json, ifp->name, json_iface); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", ch_src_str); + json_object_string_add(json_row, "group", ch_grp_str); + json_object_string_add(json_row, "upTime", uptime); + json_object_string_add(json_row, "expire", expire); + json_object_string_add(json_row, "prune", prune); + json_object_string_add(json_row, "channelJoinName", pim_ifchannel_ifjoin_name(ch->ifjoin_state)); + json_object_object_add(json_iface, ch_grp_str, json_row); + + } else { + vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s%s", + ifp->name, + inet_ntoa(ifaddr), + ch_src_str, + ch_grp_str, + pim_ifchannel_ifjoin_name(ch->ifjoin_state), + uptime, + expire, + prune, + VTY_NEWLINE); + } } /* scan interface channels */ } /* scan interfaces */ + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); + } } static void pim_show_neighbors_single(struct vty *vty, const char *neighbor, u_char uj) @@ -1171,6 +1224,7 @@ static void pim_show_neighbors_single(struct vty *vty, const char *neighbor, u_c if (!json_ifp) { json_ifp = json_object_new_object(); + json_object_pim_ifp_add(json_ifp, ifp); json_object_object_add(json, ifp->name, json_ifp); } @@ -1362,36 +1416,34 @@ static void pim_show_neighbors_secondary(struct vty *vty) } static void -pim_json_add_upstream_flags (struct pim_upstream *up, json_object *json_row) +json_object_pim_upstream_add (json_object *json, struct pim_upstream *up) { if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED) - json_object_boolean_true_add(json_row, "drJoinDesired"); + json_object_boolean_true_add(json, "drJoinDesired"); if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED) - json_object_boolean_true_add(json_row, "drJoinDesiredUpdated"); + json_object_boolean_true_add(json, "drJoinDesiredUpdated"); if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) - json_object_boolean_true_add(json_row, "firstHopRouter"); + json_object_boolean_true_add(json, "firstHopRouter"); if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) - json_object_boolean_true_add(json_row, "sourceIgmp"); + json_object_boolean_true_add(json, "sourceIgmp"); if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_PIM) - json_object_boolean_true_add(json_row, "sourcePim"); + json_object_boolean_true_add(json, "sourcePim"); if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) - json_object_boolean_true_add(json_row, "sourceStream"); + json_object_boolean_true_add(json, "sourceStream"); } static void pim_show_upstream(struct vty *vty, u_char uj) { struct listnode *upnode; struct pim_upstream *up; - struct pim_upstream *prev_up = NULL; time_t now; - char prev_grp_str[100]; json_object *json = NULL; - json_object *json_group_rows = NULL; + json_object *json_group = NULL; json_object *json_row = NULL; now = pim_time_monotonic_sec(); @@ -1399,7 +1451,7 @@ static void pim_show_upstream(struct vty *vty, u_char uj) if (uj) json = json_object_new_object(); else - vty_out(vty, "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt%s", VTY_NEWLINE); + vty_out(vty, "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt%s", VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) { char src_str[100]; @@ -1417,16 +1469,15 @@ static void pim_show_upstream(struct vty *vty, u_char uj) pim_time_timer_to_hhmmss (ka_timer, sizeof (ka_timer), up->t_ka_timer); if (uj) { + json_object_object_get_ex(json, grp_str, &json_group); - if (prev_up && strcmp(prev_grp_str, grp_str) != 0) { - json_object_object_add(json, prev_grp_str, json_group_rows); - json_group_rows = NULL; + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, json_group); } - if (!json_group_rows) - json_group_rows = json_object_new_object(); - json_row = json_object_new_object(); + json_object_pim_upstream_add(json_row, up); json_object_string_add(json_row, "inboundInterface", up->rpf.source_nexthop.interface->name); json_object_string_add(json_row, "source", src_str); json_object_string_add(json_row, "group", grp_str); @@ -1436,12 +1487,9 @@ static void pim_show_upstream(struct vty *vty, u_char uj) json_object_string_add(json_row, "resetTimer", rs_timer); json_object_string_add(json_row, "keepaliveTimer", ka_timer); json_object_int_add(json_row, "refCount", up->ref_count); - pim_json_add_upstream_flags (up, json_row); - json_object_object_add(json_group_rows, src_str, json_row); - strcpy(prev_grp_str, grp_str); - prev_up = up; + json_object_object_add(json_group, src_str, json_row); } else { - vty_out(vty, "%-10s%-15s %-15s %-5s %-8s %-9s %-9s %-9s %6d%s", + vty_out(vty, "%-10s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d%s", up->rpf.source_nexthop.interface->name, src_str, grp_str, @@ -1456,9 +1504,6 @@ static void pim_show_upstream(struct vty *vty, u_char uj) } if (uj) { - if (prev_up && json_group_rows) - json_object_object_add(json, prev_grp_str, json_group_rows); - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); json_object_free(json); } @@ -1471,12 +1516,10 @@ static void pim_show_join_desired(struct vty *vty, u_char uj) struct interface *ifp; struct pim_interface *pim_ifp; struct pim_ifchannel *ch; - struct pim_upstream *prev_up = NULL; char src_str[100]; char grp_str[100]; - char prev_grp_str[100]; json_object *json = NULL; - json_object *json_group_rows = NULL; + json_object *json_group = NULL; json_object *json_row = NULL; if (uj) @@ -1500,19 +1543,18 @@ static void pim_show_join_desired(struct vty *vty, u_char uj) pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); if (uj) { - if (prev_up && strcmp(prev_grp_str, grp_str) != 0) { - json_object_object_add(json, prev_grp_str, json_group_rows); - json_group_rows = NULL; + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, json_group); } - if (!json_group_rows) - json_group_rows = json_object_new_object(); - json_row = json_object_new_object(); + json_object_pim_upstream_add(json_row, up); json_object_string_add(json_row, "interface", ifp->name); json_object_string_add(json_row, "source", src_str); json_object_string_add(json_row, "group", grp_str); - pim_json_add_upstream_flags (up, json_row); if (pim_macro_ch_lost_assert(ch)) json_object_boolean_true_add(json_row, "lostAssert"); @@ -1526,9 +1568,7 @@ static void pim_show_join_desired(struct vty *vty, u_char uj) if (pim_upstream_evaluate_join_desired(up)) json_object_boolean_true_add(json_row, "evaluateJoinDesired"); - json_object_object_add(json_group_rows, src_str, json_row); - strcpy(prev_grp_str, grp_str); - prev_up = up; + json_object_object_add(json_group, src_str, json_row); } else { vty_out(vty, "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s%s", @@ -1546,9 +1586,6 @@ static void pim_show_join_desired(struct vty *vty, u_char uj) } if (uj) { - if (prev_up && json_group_rows) - json_object_object_add(json, prev_grp_str, json_group_rows); - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); json_object_free(json); } @@ -1558,10 +1595,8 @@ static void pim_show_upstream_rpf(struct vty *vty, u_char uj) { struct listnode *upnode; struct pim_upstream *up; - struct pim_upstream *prev_up = NULL; - char prev_grp_str[100]; json_object *json = NULL; - json_object *json_group_rows = NULL; + json_object *json_group = NULL; json_object *json_row = NULL; if (uj) @@ -1589,25 +1624,21 @@ static void pim_show_upstream_rpf(struct vty *vty, u_char uj) rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : ""; if (uj) { + json_object_object_get_ex(json, grp_str, &json_group); - if (prev_up && strcmp(prev_grp_str, grp_str) != 0) { - json_object_object_add(json, prev_grp_str, json_group_rows); - json_group_rows = NULL; + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, json_group); } - if (!json_group_rows) - json_group_rows = json_object_new_object(); - json_row = json_object_new_object(); + json_object_pim_upstream_add(json_row, up); json_object_string_add(json_row, "source", src_str); json_object_string_add(json_row, "group", grp_str); json_object_string_add(json_row, "rpfInterface", rpf_ifname); json_object_string_add(json_row, "ribNexthop", rpf_nexthop_str); json_object_string_add(json_row, "rpfAddress", rpf_addr_str); - pim_json_add_upstream_flags (up, json_row); - json_object_object_add(json_group_rows, src_str, json_row); - strcpy(prev_grp_str, grp_str); - prev_up = up; + json_object_object_add(json_group, src_str, json_row); } else { vty_out(vty, "%-15s %-15s %-8s %-15s %-15s%s", src_str, @@ -1620,9 +1651,6 @@ static void pim_show_upstream_rpf(struct vty *vty, u_char uj) } if (uj) { - if (prev_up && json_group_rows) - json_object_object_add(json, prev_grp_str, json_group_rows); - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); json_object_free(json); } @@ -1681,14 +1709,11 @@ static void pim_show_rpf(struct vty *vty, u_char uj) { struct listnode *up_node; struct pim_upstream *up; - struct pim_upstream *prev_up = NULL; time_t now = pim_time_monotonic_sec(); - char prev_grp_str[100]; json_object *json = NULL; - json_object *json_group_rows = NULL; + json_object *json_group = NULL; json_object *json_row = NULL; - if (uj) { json = json_object_new_object(); show_rpf_refresh_stats(vty, now, json); @@ -1716,13 +1741,12 @@ static void pim_show_rpf(struct vty *vty, u_char uj) rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : ""; if (uj) { - if (prev_up && strcmp(prev_grp_str, grp_str) != 0) { - json_object_object_add(json, prev_grp_str, json_group_rows); - json_group_rows = NULL; - } + json_object_object_get_ex(json, grp_str, &json_group); - if (!json_group_rows) - json_group_rows = json_object_new_object(); + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, json_group); + } json_row = json_object_new_object(); json_object_string_add(json_row, "source", src_str); @@ -1732,10 +1756,8 @@ static void pim_show_rpf(struct vty *vty, u_char uj) json_object_string_add(json_row, "ribNexthop", rib_nexthop_str); json_object_int_add(json_row, "routeMetric", rpf->source_nexthop.mrib_route_metric); json_object_int_add(json_row, "routePreference", rpf->source_nexthop.mrib_metric_preference); + json_object_object_add(json_group, src_str, json_row); - json_object_object_add(json_group_rows, src_str, json_row); - strcpy(prev_grp_str, grp_str); - prev_up = up; } else { vty_out(vty, "%-15s %-15s %-8s %-15s %-15s %6d %4d%s", src_str, @@ -1750,9 +1772,6 @@ static void pim_show_rpf(struct vty *vty, u_char uj) } if (uj) { - if (prev_up && json_group_rows) - json_object_object_add(json, prev_grp_str, json_group_rows); - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); json_object_free(json); } @@ -2344,26 +2363,28 @@ DEFUN (show_ip_pim_interface, DEFUN (show_ip_pim_join, show_ip_pim_join_cmd, - "show ip pim join", + "show ip pim join [json]", SHOW_STR IP_STR PIM_STR "PIM interface join information\n") { - pim_show_join(vty); + u_char uj = use_json(argc, argv); + pim_show_join(vty, uj); return CMD_SUCCESS; } DEFUN (show_ip_pim_local_membership, show_ip_pim_local_membership_cmd, - "show ip pim local-membership", + "show ip pim local-membership [json]", SHOW_STR IP_STR PIM_STR "PIM interface local-membership\n") { - pim_show_membership(vty); + u_char uj = use_json(argc, argv); + pim_show_membership(vty, uj); return CMD_SUCCESS; } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 7f1357783a..625795092c 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -950,19 +950,19 @@ pim_upstream_state2str (enum pim_upstream_state join_state) switch (join_state) { case PIM_UPSTREAM_NOTJOINED: - return "NtJnd"; + return "NotJoined"; break; case PIM_UPSTREAM_JOINED: - return "Jnd"; + return "Joined"; break; case PIM_UPSTREAM_JOIN_PENDING: - return "JPend"; + return "JoinPending"; break; case PIM_UPSTREAM_PRUNE: return "Prune"; break; } - return "Unkwn"; + return "Unknown"; } static int From b3fb2c27cdea26f53ff361457dd391d5bbd7fca4 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Sat, 17 Sep 2016 03:52:58 +0000 Subject: [PATCH 176/386] pimd: JSON support for "show ip mroute" Signed-off-by: Daniel Walton Ticket: CM-12876 root@superm-redxp-05[pimd]# vtysh -c 'show ip mroute json' | pjson { "230.10.10.1": { "20.0.13.253": { "br1": { "swp1": { "group": "230.10.10.1", "iVifI": 1, "inboundInterface": "br1", "oVifI": 2, "outboundInterface": "swp1", "protocolPim": true, "source": "20.0.13.253", "ttl": 1, "upTime": "00:02:37" } } } }, "230.10.10.4": { "20.0.13.253": { "br1": {} } } } root@superm-redxp-05[pimd]# --- pimd/pim_cmd.c | 249 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 190 insertions(+), 59 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index c7b296b550..e6851089d6 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1451,7 +1451,7 @@ static void pim_show_upstream(struct vty *vty, u_char uj) if (uj) json = json_object_new_object(); else - vty_out(vty, "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt%s", VTY_NEWLINE); + vty_out(vty, "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt%s", VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) { char src_str[100]; @@ -2611,127 +2611,258 @@ DEFUN (show_ip_multicast, return CMD_SUCCESS; } -static void show_mroute(struct vty *vty) +static void show_mroute(struct vty *vty, u_char uj) { struct listnode *node; struct channel_oil *c_oil; struct static_route *s_route; time_t now; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_source = NULL; + json_object *json_ifp_in = NULL; + json_object *json_ifp_out = NULL; - vty_out(vty, "Proto: I=IGMP P=PIM S=STATIC O=SOURCE%s%s", VTY_NEWLINE, VTY_NEWLINE); - - vty_out(vty, "Source Group Proto Input iVifI Output oVifI TTL Uptime %s", - VTY_NEWLINE); + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, "Proto: I=IGMP P=PIM S=STATIC O=SOURCE%s%s", VTY_NEWLINE, VTY_NEWLINE); + vty_out(vty, "Source Group Proto Input iVifI Output oVifI TTL Uptime %s", + VTY_NEWLINE); + } now = pim_time_monotonic_sec(); /* print list of PIM and IGMP routes */ for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) { - char group_str[100]; - char source_str[100]; + char grp_str[100]; + char src_str[100]; + char in_ifname[16]; + char out_ifname[16]; int oif_vif_index; + char proto[5]; + struct interface *ifp_in; if (!c_oil->installed) continue; - pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - + 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); + + if (ifp_in) + strcpy(in_ifname, ifp_in->name); + else + strcpy(in_ifname, ""); + + if (uj) { + + /* Find the group, create it if it doesn't exist */ + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, json_group); + } + + /* Find the source nested under the group, create it if it doesn't exist */ + json_object_object_get_ex(json_group, src_str, &json_source); + + if (!json_source) { + json_source = json_object_new_object(); + json_object_object_add(json_group, src_str, json_source); + } + + /* Find the inbound interface nested under the source, create it if it doesn't exist */ + json_object_object_get_ex(json_source, in_ifname, &json_ifp_in); + + if (!json_ifp_in) { + json_ifp_in = json_object_new_object(); + json_object_object_add(json_source, in_ifname, json_ifp_in); + } + } + for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) { - struct interface *ifp_in; struct interface *ifp_out; char oif_uptime[10]; int ttl; - char proto[5]; ttl = c_oil->oil.mfcc_ttls[oif_vif_index]; if (ttl < 1) continue; - ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); ifp_out = pim_if_find_by_vif_index(oif_vif_index); - pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - c_oil->oif_creation[oif_vif_index]); - proto[0] = '\0'; - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) { - strcat(proto, "P"); - } - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) { - strcat(proto, "I"); - } - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) { - strcat(proto, "O"); - } + if (ifp_out) + strcpy(out_ifname, ifp_out->name); + else + strcpy(out_ifname, ""); - vty_out(vty, "%-15s %-15s %-5s %-5s %5d %-6s %5d %3d %8s %s", - source_str, - group_str, - proto, - ifp_in ? ifp_in->name : "", - c_oil->oil.mfcc_parent, - ifp_out ? ifp_out->name : "", - oif_vif_index, - ttl, - oif_uptime, - VTY_NEWLINE); + if (uj) { + json_ifp_out = json_object_new_object(); + json_object_string_add(json_ifp_out, "source", src_str); + json_object_string_add(json_ifp_out, "group", grp_str); + + if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) + json_object_boolean_true_add(json_ifp_out, "protocolPim"); + + if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) + json_object_boolean_true_add(json_ifp_out, "protocolIgmp"); + + if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) + json_object_boolean_true_add(json_ifp_out, "protocolSource"); + + 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); + json_object_int_add(json_ifp_out, "oVifI", oif_vif_index); + json_object_int_add(json_ifp_out, "ttl", ttl); + json_object_string_add(json_ifp_out, "upTime", oif_uptime); + json_object_object_add(json_ifp_in, out_ifname, json_ifp_out); + } else { + proto[0] = '\0'; + + if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) { + strcat(proto, "P"); + } + + if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) { + strcat(proto, "I"); + } + + if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) { + strcat(proto, "O"); + } + + vty_out(vty, "%-15s %-15s %-5s %-5s %5d %-6s %5d %3d %8s %s", + src_str, + grp_str, + proto, + in_ifname, + c_oil->oil.mfcc_parent, + out_ifname, + oif_vif_index, + ttl, + oif_uptime, + VTY_NEWLINE); + } } } /* Print list of static routes */ for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { - char group_str[100]; - char source_str[100]; + char grp_str[100]; + char src_str[100]; + char in_ifname[16]; + char out_ifname[16]; int oif_vif_index; + struct interface *ifp_in; + char proto[5]; if (!s_route->c_oil.installed) continue; - pim_inet4_dump("", s_route->group, group_str, sizeof(group_str)); - pim_inet4_dump("", s_route->source, source_str, sizeof(source_str)); + pim_inet4_dump("", s_route->group, grp_str, sizeof(grp_str)); + pim_inet4_dump("", s_route->source, src_str, sizeof(src_str)); + ifp_in = pim_if_find_by_vif_index(s_route->iif); + + if (ifp_in) + strcpy(in_ifname, ifp_in->name); + else + strcpy(in_ifname, ""); + + if (uj) { + + /* Find the group, create it if it doesn't exist */ + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, json_group); + } + + /* Find the source nested under the group, create it if it doesn't exist */ + json_object_object_get_ex(json_group, src_str, &json_source); + + if (!json_source) { + json_source = json_object_new_object(); + json_object_object_add(json_group, src_str, json_source); + } + + /* Find the inbound interface nested under the source, create it if it doesn't exist */ + json_object_object_get_ex(json_source, in_ifname, &json_ifp_in); + + if (!json_ifp_in) { + json_ifp_in = json_object_new_object(); + json_object_object_add(json_source, in_ifname, json_ifp_in); + } + + } else { + proto[0] = '\0'; + strcat(proto, "S"); + } for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) { - struct interface *ifp_in; struct interface *ifp_out; char oif_uptime[10]; int ttl; - char proto[5]; ttl = s_route->oif_ttls[oif_vif_index]; if (ttl < 1) continue; - ifp_in = pim_if_find_by_vif_index(s_route->iif); ifp_out = pim_if_find_by_vif_index(oif_vif_index); - pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - s_route->c_oil.oif_creation[oif_vif_index]); - proto[0] = '\0'; - strcat(proto, "S"); + if (ifp_out) + strcpy(out_ifname, ifp_out->name); + else + strcpy(out_ifname, ""); - vty_out(vty, "%-15s %-15s %-5s %-5s %5d %-6s %5d %3d %8s %s", - source_str, - group_str, - proto, - ifp_in ? ifp_in->name : "", - s_route->iif, - ifp_out ? ifp_out->name : "", - oif_vif_index, - ttl, - oif_uptime, - VTY_NEWLINE); + if (uj) { + json_ifp_out = json_object_new_object(); + json_object_string_add(json_ifp_out, "source", src_str); + json_object_string_add(json_ifp_out, "group", grp_str); + json_object_boolean_true_add(json_ifp_out, "protocolStatic"); + 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); + json_object_int_add(json_ifp_out, "oVifI", oif_vif_index); + json_object_int_add(json_ifp_out, "ttl", ttl); + json_object_string_add(json_ifp_out, "upTime", oif_uptime); + json_object_object_add(json_ifp_in, out_ifname, json_ifp_out); + } else { + vty_out(vty, "%-15s %-15s %-5s %-5s %5d %-6s %5d %3d %8s %s", + src_str, + grp_str, + proto, + in_ifname, + s_route->iif, + out_ifname, + oif_vif_index, + ttl, + oif_uptime, + VTY_NEWLINE); + } } } + + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); + } } DEFUN (show_ip_mroute, show_ip_mroute_cmd, - "show ip mroute", + "show ip mroute [json]", SHOW_STR IP_STR MROUTE_STR) { - show_mroute(vty); + u_char uj = use_json(argc, argv); + show_mroute(vty, uj); return CMD_SUCCESS; } From 91c6aec45fa92cfa1d00e1d3701c6b87dcd22d4c Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Sat, 17 Sep 2016 04:10:44 +0000 Subject: [PATCH 177/386] pimd: "show ip mroute" skips entries without an OIF Signed-off-by: Daniel Walton The entry for 230.10.10.4 was not being displayed root@superm-redxp-05[pimd]# ip mroute show (20.0.13.253, 230.10.10.4) Iif: br1 (20.0.13.253, 230.10.10.1) Iif: br1 Oifs: swp1 root@superm-redxp-05[pimd]# root@superm-redxp-05[pimd]# root@superm-redxp-05[pimd]# vtysh -c 'show ip mroute' Proto: I=IGMP P=PIM S=STATIC O=SOURCE Source Group Proto Input iVifI Output oVifI TTL Uptime 20.0.13.253 230.10.10.1 P br1 1 swp1 2 1 00:01:09 20.0.13.253 230.10.10.4 P br1 1 none 0 0 --:--:-- root@superm-redxp-05[pimd]# --- pimd/pim_cmd.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index e6851089d6..0c297271d0 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2622,6 +2622,7 @@ static void show_mroute(struct vty *vty, u_char uj) json_object *json_source = NULL; json_object *json_ifp_in = NULL; json_object *json_ifp_out = NULL; + int found_oif = 0; if (uj) { json = json_object_new_object(); @@ -2642,6 +2643,7 @@ static void show_mroute(struct vty *vty, u_char uj) int oif_vif_index; char proto[5]; struct interface *ifp_in; + found_oif = 0; if (!c_oil->installed) continue; @@ -2693,6 +2695,7 @@ static void show_mroute(struct vty *vty, u_char uj) ifp_out = pim_if_find_by_vif_index(oif_vif_index); pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - c_oil->oif_creation[oif_vif_index]); + found_oif = 1; if (ifp_out) strcpy(out_ifname, ifp_out->name); @@ -2748,6 +2751,20 @@ static void show_mroute(struct vty *vty, u_char uj) VTY_NEWLINE); } } + + if (!uj && !found_oif) { + vty_out(vty, "%-15s %-15s %-5s %-5s %5d %-6s %5d %3d %8s %s", + src_str, + grp_str, + proto, + in_ifname, + c_oil->oil.mfcc_parent, + "none", + 0, + 0, + "--:--:--", + VTY_NEWLINE); + } } /* Print list of static routes */ @@ -2766,6 +2783,7 @@ static void show_mroute(struct vty *vty, u_char uj) pim_inet4_dump("", s_route->group, grp_str, sizeof(grp_str)); pim_inet4_dump("", s_route->source, src_str, sizeof(src_str)); ifp_in = pim_if_find_by_vif_index(s_route->iif); + found_oif = 0; if (ifp_in) strcpy(in_ifname, ifp_in->name); @@ -2814,6 +2832,7 @@ static void show_mroute(struct vty *vty, u_char uj) ifp_out = pim_if_find_by_vif_index(oif_vif_index); pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - s_route->c_oil.oif_creation[oif_vif_index]); + found_oif = 1; if (ifp_out) strcpy(out_ifname, ifp_out->name); @@ -2846,6 +2865,20 @@ static void show_mroute(struct vty *vty, u_char uj) VTY_NEWLINE); } } + + if (!uj && !found_oif) { + vty_out(vty, "%-15s %-15s %-5s %-5s %5d %-6s %5d %3d %8s %s", + src_str, + grp_str, + proto, + in_ifname, + c_oil->oil.mfcc_parent, + "none", + 0, + 0, + "--:--:--", + VTY_NEWLINE); + } } if (uj) { From a6dc7de682358d6399100f1288acece81a163de8 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 19 Sep 2016 13:09:38 -0400 Subject: [PATCH 178/386] pimd: Add debug messages as to why a register packet is rejected. When we reject a register message from someone, give some reasoning as to the why of it being rejected to help in debugging the situation. Signed-off-by: Donald Sharp --- pimd/pim_register.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index f8144557c8..69a3d6167f 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -252,6 +252,7 @@ pim_register_recv (struct interface *ifp, struct ip *ip_hdr; struct prefix_sg sg; uint32_t *bits; + int i_am_rp = 0; #define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4 ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN); @@ -305,7 +306,8 @@ pim_register_recv (struct interface *ifp, sg.src = ip_hdr->ip_src; sg.grp = ip_hdr->ip_dst; - if (I_am_RP (sg.grp) && (dest_addr.s_addr == ((RP (sg.grp))->rpf_addr.u.prefix4.s_addr))) { + i_am_rp = I_am_RP (sg.grp); + if (i_am_rp && (dest_addr.s_addr == ((RP (sg.grp))->rpf_addr.u.prefix4.s_addr))) { sentRegisterStop = 0; if (*bits & PIM_REGISTER_BORDER_BIT) { @@ -373,6 +375,15 @@ pim_register_recv (struct interface *ifp, // This is taken care of by the kernel for us } } else { + if (PIM_DEBUG_PIM_REG) + { + if (!i_am_rp) + zlog_debug ("Received Register packet for %s, Rejecting packet because I am not the RP configured for group", + pim_str_sg_dump (&sg)); + else + zlog_debug ("Received Register packet for %s, Rejecting packet because the dst ip address is not the actual RP", + pim_str_sg_dump (&sg)); + } pim_register_stop_send (ifp, &sg, dest_addr, src_addr); } From 4a40c37aa4d4a4480e992bfa5b3e9234abc90c61 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 15 Sep 2016 16:50:08 -0400 Subject: [PATCH 179/386] pimd: Further work to fix rpf lookups and nbrs When we do a RPF lookup return a path that we have neighbors for in those cases where we need to have a neighbor to pass along the SG state via a pim join/prune message. Signed-off-by: Donald Sharp --- pimd/pim_assert.c | 2 +- pimd/pim_ifchannel.c | 11 ++++++----- pimd/pim_ifchannel.h | 2 +- pimd/pim_mroute.c | 4 ++-- pimd/pim_register.c | 2 +- pimd/pim_rpf.c | 7 ++++--- pimd/pim_upstream.c | 13 +++++++++---- pimd/pim_upstream.h | 2 +- 8 files changed, 25 insertions(+), 18 deletions(-) diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index 1add2ebb00..481a2851d5 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -150,7 +150,7 @@ static int dispatch_assert(struct interface *ifp, memset (&sg, 0, sizeof (struct prefix_sg)); sg.src = source_addr; sg.grp = group_addr; - ch = pim_ifchannel_add(ifp, &sg); + ch = pim_ifchannel_add(ifp, &sg, 0); if (!ch) { zlog_warn("%s: (S,G)=%s failure creating channel on interface %s", __PRETTY_FUNCTION__, diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index eaf7ab7096..1bc10f4cce 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -39,6 +39,7 @@ #include "pim_rpf.h" #include "pim_macro.h" #include "pim_oil.h" +#include "pim_upstream.h" /* * A (*,G) or a (*,*) is going away @@ -366,7 +367,7 @@ pim_ifchannel_find_parent (struct interface *ifp, struct pim_ifchannel * pim_ifchannel_add(struct interface *ifp, - struct prefix_sg *sg) + struct prefix_sg *sg, int flags) { struct pim_interface *pim_ifp; struct pim_ifchannel *ch; @@ -379,7 +380,7 @@ pim_ifchannel_add(struct interface *ifp, pim_ifp = ifp->info; zassert(pim_ifp); - up = pim_upstream_add(sg, NULL); + up = pim_upstream_add(sg, NULL, flags); if (!up) { zlog_err("%s: could not attach upstream (S,G)=%s on interface %s", __PRETTY_FUNCTION__, @@ -615,7 +616,7 @@ void pim_ifchannel_join_add(struct interface *ifp, return; } - ch = pim_ifchannel_add(ifp, sg); + ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); if (!ch) return; @@ -715,7 +716,7 @@ void pim_ifchannel_prune(struct interface *ifp, return; } - ch = pim_ifchannel_add(ifp, sg); + ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); if (!ch) return; @@ -772,7 +773,7 @@ void pim_ifchannel_local_membership_add(struct interface *ifp, if (!PIM_IF_TEST_PIM(pim_ifp->options)) return; - ch = pim_ifchannel_add(ifp, sg); + ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP); if (!ch) { return; } diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 0c39210642..8c542d17f2 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -105,7 +105,7 @@ void pim_ifchannel_delete_on_noinfo(struct interface *ifp); struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, struct prefix_sg *sg); struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, - struct prefix_sg *sg); + struct prefix_sg *sg, int flags); void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr, struct in_addr upstream, diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index dd3ae3117d..8ac1a708bb 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -136,7 +136,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg return 0; } - up = pim_upstream_add (&sg, ifp); + up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR); if (!up) { if (PIM_DEBUG_MROUTE) { zlog_debug("%s: Failure to add upstream information for %s", @@ -363,7 +363,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) pim_mroute_add (oil); if (pim_if_connected_to_source (ifp, sg.src)) { - up = pim_upstream_add (&sg, ifp); + up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR); if (!up) { if (PIM_DEBUG_MROUTE) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 69a3d6167f..c2e666f17b 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -333,7 +333,7 @@ pim_register_recv (struct interface *ifp, */ if (!upstream) { - upstream = pim_upstream_add (&sg, ifp); + upstream = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM); if (!upstream) { zlog_warn ("Failure to create upstream state"); diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 3d88f9e70b..46a6ef1ca4 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -46,7 +46,6 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei int found = 0; int i = 0; - neighbor_needed = 0; memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM); num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, @@ -87,7 +86,7 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei ifp->name, first_ifindex, addr_str); } - if (neighbor_needed) + if (neighbor_needed && !pim_if_connected_to_source (ifp, addr)) { struct pim_neighbor *nbr; @@ -148,7 +147,9 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_ save_rpf_addr = rpf->rpf_addr; /* detect change in RPF'(S,G) */ if (pim_nexthop_lookup(&rpf->source_nexthop, - up->upstream_addr, !PIM_UPSTREAM_FLAG_TEST_FHR (up->flags))) { + up->upstream_addr, + !PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) && + !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags))) { return PIM_RPF_FAILURE; } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 625795092c..b495f39182 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -468,7 +468,8 @@ pim_upstream_switch(struct pim_upstream *up, } static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, - struct interface *incoming) + struct interface *incoming, + int flags) { struct pim_upstream *up; enum pim_rpf_result rpf_result; @@ -492,7 +493,7 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, up->parent = pim_upstream_find_parent (sg); pim_upstream_find_new_children (up); - up->flags = 0; + up->flags = flags; up->ref_count = 1; up->t_join_timer = NULL; up->t_ka_timer = NULL; @@ -512,6 +513,9 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, rpf_result = pim_rpf_update(up, NULL); if (rpf_result == PIM_RPF_FAILURE) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug ("%s: Attempting to create upstream(%s), Unable to RPF for source", __PRETTY_FUNCTION__, + pim_str_sg_dump (&up->sg)); XFREE(MTYPE_PIM_UPSTREAM, up); return NULL; } @@ -557,7 +561,8 @@ struct pim_upstream *pim_upstream_find(struct prefix_sg *sg) } struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, - struct interface *incoming) + struct interface *incoming, + int flags) { struct pim_upstream *up; @@ -566,7 +571,7 @@ struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, ++up->ref_count; } else { - up = pim_upstream_new(sg, incoming); + up = pim_upstream_new(sg, incoming, flags); } return up; diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 6d30349bd6..3c9862fe98 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -113,7 +113,7 @@ void pim_upstream_delete(struct pim_upstream *up); struct pim_upstream *pim_upstream_find (struct prefix_sg *sg); struct pim_upstream *pim_upstream_find_non_any (struct prefix_sg *sg); struct pim_upstream *pim_upstream_add (struct prefix_sg *sg, - struct interface *ifp); + struct interface *ifp, int); void pim_upstream_del(struct pim_upstream *up); int pim_upstream_evaluate_join_desired(struct pim_upstream *up); From 7ef660465814ed12df05457ab8b8ae6b63fd2dc2 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 21 Sep 2016 16:16:43 -0400 Subject: [PATCH 180/386] pimd: Do not send register stop in some cases When we are disabling pim, there exists some race conditions where we are attempting to send a register stop out a interface that is not setup for pim yet. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index b495f39182..027a4ca0c4 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -999,6 +999,13 @@ pim_upstream_register_stop_timer (struct thread *t) break; case PIM_UPSTREAM_PRUNE: pim_ifp = up->rpf.source_nexthop.interface->info; + if (!pim_ifp) + { + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: Interface: %s is not configured for pim", + __PRETTY_FUNCTION__, up->rpf.source_nexthop.interface->name); + return 0; + } up->join_state = PIM_UPSTREAM_JOIN_PENDING; pim_upstream_start_register_stop_timer (up, 1); From 8971ccb29d558a90c53ce91239c95113b36fb243 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 20 Sep 2016 20:34:31 -0400 Subject: [PATCH 181/386] pimd: Allow igmp query to go out immediately on startup When starting up allow the 1st query to go out immediately, well ok 1 second, and then the next queries to go out in query_interval/4 seconds until startup mode is finished. Signed-off-by: Donald Sharp --- pimd/pim_igmp.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 6624edca59..e14ff29225 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -826,9 +826,6 @@ void pim_igmp_general_query_on(struct igmp_sock *igmp) int startup_mode; int query_interval; - zassert(igmp); - zassert(igmp->interface); - /* Since this socket is starting as querier, there should not exist a timer for other-querier-present. @@ -842,13 +839,24 @@ void pim_igmp_general_query_on(struct igmp_sock *igmp) The Startup Query Interval is the interval between General Queries sent by a Querier on startup. Default: 1/4 the Query Interval. + The first one should be sent out immediately instead of 125/4 + seconds from now. */ startup_mode = igmp->startup_query_count > 0; if (startup_mode) { - --igmp->startup_query_count; + /* + * If this is the first time we are sending a query on a + * newly configured igmp interface send it out in 1 second + * just to give the entire world a tiny bit of time to settle + * else the query interval is: + * query_interval = pim_ifp->igmp_default_query_interval >> 2; + */ + if (igmp->startup_query_count == igmp->querier_robustness_variable) + query_interval = 1; + else + query_interval = PIM_IGMP_SQI(pim_ifp->igmp_default_query_interval); - /* query_interval = pim_ifp->igmp_default_query_interval >> 2; */ - query_interval = PIM_IGMP_SQI(pim_ifp->igmp_default_query_interval); + --igmp->startup_query_count; } else { query_interval = igmp->querier_query_interval; @@ -864,7 +872,6 @@ void pim_igmp_general_query_on(struct igmp_sock *igmp) igmp->fd); } igmp->t_igmp_query_timer = NULL; - zassert(!igmp->t_igmp_query_timer); THREAD_TIMER_ON(master, igmp->t_igmp_query_timer, pim_igmp_general_query, igmp, query_interval); @@ -883,7 +890,6 @@ void pim_igmp_general_query_off(struct igmp_sock *igmp) } } THREAD_OFF(igmp->t_igmp_query_timer); - zassert(!igmp->t_igmp_query_timer); } /* Issue IGMP general query */ From 905d48fa7e0a17be2de0eb08f09abb96fc818360 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 22 Sep 2016 13:25:48 -0400 Subject: [PATCH 182/386] pimd: Stop join/prunes from crashing When we receive a join/prune for a upstream that we are unable to create, safely ignore the request until the situation resolves itself. Signed-off-by: Donald Sharp --- pimd/pim_join.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 7bec6c7eca..3de4389174 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -108,6 +108,15 @@ static void recv_join(struct interface *ifp, struct pim_upstream *child; struct listnode *up_node; + /* + * If we are unable to create upstream information + * Due to any number of reasons it is possible + * That we might have not created the ifchannel + * and upstream above. So just fall out gracefully + */ + if (!up) + return; + for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, up_node, child)) { if (child->parent == up) @@ -178,6 +187,13 @@ static void recv_prune(struct interface *ifp, struct pim_upstream *child; struct listnode *up_node; + /* + * If up is not found then there is nothing + * to do here (see recv_join above) + */ + if (!up) + return; + for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, up_node, child)) { if (child->parent == up) From 88d6652ede40f7675faaa1efe7dccbbf27af5568 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 22 Sep 2016 15:55:02 -0400 Subject: [PATCH 183/386] pimd: When sending a register stop don't need a nbr When you send a register stop it is not necessary to have a neighbor out the choosen interface. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 8ac1a708bb..bc351d8f7b 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -345,8 +345,8 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) pim_ifp = rpf->source_nexthop.interface->info; //No if channel, but upstream we are at the RP. - pim_nexthop_lookup (&source, up->upstream_register, 1); - pim_register_stop_send(source.interface, &sg, pim_ifp->primary_address, up->upstream_register); + if (pim_nexthop_lookup (&source, up->upstream_register, 0) == 0) + pim_register_stop_send(source.interface, &sg, pim_ifp->primary_address, up->upstream_register); if (!up->channel_oil) up->channel_oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); if (!up->channel_oil->installed) From 16b7259142467de43856bd7dcfe2667611434af0 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 23 Sep 2016 11:10:31 -0400 Subject: [PATCH 184/386] pimd: Track upstream state a bit better. Track the upstream state if we are adding a new state to a pre-existing upstream. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 1 + 1 file changed, 1 insertion(+) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 027a4ca0c4..138843405b 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -569,6 +569,7 @@ struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, up = pim_upstream_find(sg); if (up) { ++up->ref_count; + up->flags |= flags; } else { up = pim_upstream_new(sg, incoming, flags); From f59a8217d1875413b294d0061733f33c3c5078fe Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 22 Sep 2016 14:50:43 +0000 Subject: [PATCH 185/386] pimd: Fixup pim mroute output Cleanup the 'show ip mroute' command to be a bit more minimalistic. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 55 +++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 0c297271d0..07b913caf8 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -503,7 +503,7 @@ static void igmp_show_interfaces(struct vty *vty, u_char uj) json = json_object_new_object(); else vty_out(vty, - "Interface State Address Querier Query Timer Uptime%s", + "Interface State Address Querier Query Timer Uptime%s", VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { @@ -2623,12 +2623,12 @@ static void show_mroute(struct vty *vty, u_char uj) json_object *json_ifp_in = NULL; json_object *json_ifp_out = NULL; int found_oif = 0; + int first = 1; if (uj) { json = json_object_new_object(); } else { - vty_out(vty, "Proto: I=IGMP P=PIM S=STATIC O=SOURCE%s%s", VTY_NEWLINE, VTY_NEWLINE); - vty_out(vty, "Source Group Proto Input iVifI Output oVifI TTL Uptime %s", + vty_out(vty, "Source Group Proto Input Output TTL Uptime%s", VTY_NEWLINE); } @@ -2641,10 +2641,10 @@ static void show_mroute(struct vty *vty, u_char uj) char in_ifname[16]; char out_ifname[16]; int oif_vif_index; - char proto[5]; + char proto[100]; struct interface *ifp_in; found_oif = 0; - + first = 1; if (!c_oil->installed) continue; @@ -2724,44 +2724,46 @@ static void show_mroute(struct vty *vty, u_char uj) json_object_string_add(json_ifp_out, "upTime", oif_uptime); json_object_object_add(json_ifp_in, out_ifname, json_ifp_out); } else { - proto[0] = '\0'; - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) { - strcat(proto, "P"); + strcpy(proto, "PIM"); } if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) { - strcat(proto, "I"); + strcpy(proto, "IGMP"); } if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) { - strcat(proto, "O"); + strcpy(proto, "SRC"); } - vty_out(vty, "%-15s %-15s %-5s %-5s %5d %-6s %5d %3d %8s %s", + vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s%s", src_str, grp_str, proto, in_ifname, - c_oil->oil.mfcc_parent, out_ifname, - oif_vif_index, ttl, oif_uptime, VTY_NEWLINE); + + if (first) + { + src_str[0] = '\0'; + grp_str[0] = '\0'; + in_ifname[0] = '\0'; + first = 0; + } } } if (!uj && !found_oif) { - vty_out(vty, "%-15s %-15s %-5s %-5s %5d %-6s %5d %3d %8s %s", + vty_out(vty, "%-15s %-15s %-10s %-10s %-6s %-3d %8s%s", src_str, grp_str, proto, in_ifname, - c_oil->oil.mfcc_parent, "none", 0, - 0, "--:--:--", VTY_NEWLINE); } @@ -2775,7 +2777,8 @@ static void show_mroute(struct vty *vty, u_char uj) char out_ifname[16]; int oif_vif_index; struct interface *ifp_in; - char proto[5]; + char proto[100]; + first = 1; if (!s_route->c_oil.installed) continue; @@ -2817,8 +2820,7 @@ static void show_mroute(struct vty *vty, u_char uj) } } else { - proto[0] = '\0'; - strcat(proto, "S"); + strcpy(proto, "STATIC"); } for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) { @@ -2852,30 +2854,33 @@ static void show_mroute(struct vty *vty, u_char uj) json_object_string_add(json_ifp_out, "upTime", oif_uptime); json_object_object_add(json_ifp_in, out_ifname, json_ifp_out); } else { - vty_out(vty, "%-15s %-15s %-5s %-5s %5d %-6s %5d %3d %8s %s", + vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s%s", src_str, grp_str, proto, in_ifname, - s_route->iif, out_ifname, - oif_vif_index, ttl, oif_uptime, VTY_NEWLINE); + if (first) + { + src_str[0] = '\0'; + grp_str[0] = '\0'; + in_ifname[0] = '\0'; + first = 0; + } } } if (!uj && !found_oif) { - vty_out(vty, "%-15s %-15s %-5s %-5s %5d %-6s %5d %3d %8s %s", + vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s%s", src_str, grp_str, proto, in_ifname, - c_oil->oil.mfcc_parent, "none", 0, - 0, "--:--:--", VTY_NEWLINE); } From 5f0336ed0285863c240911891b53fd11a63ada6e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 23 Sep 2016 19:43:19 +0000 Subject: [PATCH 186/386] pimd: Fixup to use new lastused The kernel now reports lastused as the time in hz since we last saw any packets. So let's start tracking it that way. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 1 - pimd/pim_oil.h | 1 - pimd/pim_upstream.c | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index bc351d8f7b..a35c9898ce 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -743,7 +743,6 @@ pim_mroute_update_counters (struct channel_oil *c_oil) c_oil->cc.oldpktcnt = c_oil->cc.pktcnt; c_oil->cc.oldbytecnt = c_oil->cc.bytecnt; c_oil->cc.oldwrong_if = c_oil->cc.wrong_if; - c_oil->cc.oldlastused = c_oil->cc.lastused; pim_zlookup_sg_statistics (c_oil); if (ioctl (qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index 1bbd232e4d..4b23b211a9 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -53,7 +53,6 @@ struct channel_counts { unsigned long long lastused; - unsigned long long oldlastused; unsigned long pktcnt; unsigned long oldpktcnt; unsigned long bytecnt; diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 138843405b..64fffa3859 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -882,7 +882,7 @@ pim_upstream_keep_alive_timer (struct thread *t) pim_mroute_update_counters (up->channel_oil); if ((up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt) && - (up->channel_oil->cc.oldlastused >= up->channel_oil->cc.lastused)) + (up->channel_oil->cc.lastused/100 >= qpim_keep_alive_time)) { pim_mroute_del (up->channel_oil); THREAD_OFF (up->t_ka_timer); From eccf56d20e10be278ad5f6f733331c6f10fd911b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 23 Sep 2016 16:16:38 -0400 Subject: [PATCH 187/386] pimd: Fix 'show ip mroute count' Add the lastused data. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 07b913caf8..74effbaa69 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2912,7 +2912,7 @@ static void show_mroute_count(struct vty *vty) vty_out(vty, "%s", VTY_NEWLINE); - vty_out(vty, "Source Group Packets Bytes WrongIf %s", + vty_out(vty, "Source Group LastUsed Packets Bytes WrongIf %s", VTY_NEWLINE); /* Print PIM and IGMP route counts */ @@ -2928,9 +2928,10 @@ static void show_mroute_count(struct vty *vty) pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - vty_out(vty, "%-15s %-15s %7ld %10ld %7ld %s", + vty_out(vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld%s", source_str, group_str, + c_oil->cc.lastused/100, c_oil->cc.pktcnt, c_oil->cc.bytecnt, c_oil->cc.wrong_if, @@ -2950,9 +2951,10 @@ static void show_mroute_count(struct vty *vty) pim_inet4_dump("", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str)); pim_inet4_dump("", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str)); - vty_out(vty, "%-15s %-15s %7ld %10ld %7ld %s", + vty_out(vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld%s", source_str, group_str, + s_route->c_oil.cc.lastused, s_route->c_oil.cc.pktcnt, s_route->c_oil.cc.bytecnt, s_route->c_oil.cc.wrong_if, From 05ca4827a61512d6fdb4def75d24cf94121a6396 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 26 Sep 2016 18:39:54 -0400 Subject: [PATCH 188/386] pimd: Remove some more unprotected warnings/debugs Pim is outputting a bunch of unprotected debugs. In a system with a high # of events even with no logging we will receive lots of messages. Signed-off-by: Donald Sharp --- pimd/pim_join.c | 13 ++++++++----- pimd/pim_mroute.c | 9 +++++---- pimd/pim_zebra.c | 21 ++++++++++++--------- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 3de4389174..c92be18ddf 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -202,11 +202,14 @@ static void recv_prune(struct interface *ifp, struct pim_ifchannel *ch = pim_ifchannel_find (ifp, &child->sg); struct pim_interface *pim_ifp = ifp->info; - char buff[100]; - strcpy (buff, pim_str_sg_dump (&up->sg)); - zlog_debug("%s %s: Prune(S,G)=%s from %s", - __FILE__, __PRETTY_FUNCTION__, - buff, pim_str_sg_dump (&child->sg)); + if (PIM_DEBUG_PIM_TRACE) + { + char buff[100]; + strcpy (buff, pim_str_sg_dump (&up->sg)); + zlog_debug("%s %s: Prune(S,G)=%s from %s", + __FILE__, __PRETTY_FUNCTION__, + buff, pim_str_sg_dump (&child->sg)); + } if (!pim_upstream_evaluate_join_desired (child)) pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index a35c9898ce..c53a0393c0 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -719,10 +719,11 @@ int pim_mroute_del (struct channel_oil *c_oil) err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_MFC, &c_oil->oil, sizeof(c_oil->oil)); if (err) { - zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_MFC): errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, - qpim_mroute_socket_fd, - errno, safe_strerror(errno)); + if (PIM_DEBUG_MROUTE) + zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_MFC): errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, + qpim_mroute_socket_fd, + errno, safe_strerror(errno)); return -2; } diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index addccef82b..1738c5f6f4 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -888,15 +888,18 @@ static int del_oif(struct channel_oil *channel_oil, /* Prevent single protocol from unsubscribing same interface from channel (S,G) multiple times */ if (!(channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask)) { - char group_str[100]; - char source_str[100]; - 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: nonexistent protocol mask %u removed OIF %s (vif_index=%d, min_ttl=%d) from 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); + if (PIM_DEBUG_MROUTE) + { + char group_str[100]; + char source_str[100]; + 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: nonexistent protocol mask %u removed OIF %s (vif_index=%d, min_ttl=%d) from 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 -2; } From 82d64e8ef41be04a63dbbdd55e153441e7b15116 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 26 Sep 2016 22:27:37 -0400 Subject: [PATCH 189/386] zebra: Fix up the debug for receiving multicast routes Improve the netlink debug message. Signed-off-by: Donald Sharp --- zebra/rt_netlink.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 5dc9a10e29..b968a84e76 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -525,7 +525,6 @@ netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h ns_id_t ns_id) { int len; - unsigned long long lastused = 0; struct rtmsg *rtm; struct rtattr *tb[RTA_MAX + 1]; struct mcast_route_data *m; @@ -584,18 +583,20 @@ netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h if (IS_ZEBRA_DEBUG_KERNEL) { + struct interface *ifp; strcpy (sbuf, inet_ntoa (m->sg.src)); strcpy (gbuf, inet_ntoa (m->sg.grp)); for (count = 0; count < oif_count; count++) { - struct interface *ifp = if_lookup_by_index_vrf (oif[count], vrf); + ifp = if_lookup_by_index_vrf (oif[count], vrf); char temp[256]; sprintf (temp, "%s ", ifp->name); strcat (oif_list, temp); } - zlog_debug ("MCAST %s (%s,%s) IIF: %d OIF: %s jiffies: %lld", - nl_msg_type_to_str (h->nlmsg_type), sbuf, gbuf, iif, oif_list, lastused); + ifp = if_lookup_by_index_vrf (iif, vrf); + zlog_debug ("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld", + nl_msg_type_to_str(h->nlmsg_type), sbuf, gbuf, ifp->name, oif_list, m->lastused); } return 0; } From 5f8fec87289fbac9e0b1ece4c088bd7f305f8be9 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 26 Sep 2016 16:37:08 -0400 Subject: [PATCH 190/386] lib, pimd: Modify writen to retry on certain failures When writen fails, allow itto retry on certain failures until it succeeds. Ticket: CM-12986 Signed-off-by: Donald Sharp --- lib/network.c | 9 +++++++-- pimd/pim_zlookup.c | 8 ++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/network.c b/lib/network.c index 506e019136..2b6f2fbab5 100644 --- a/lib/network.c +++ b/lib/network.c @@ -62,8 +62,13 @@ writen(int fd, const u_char *ptr, int nbytes) while (nleft > 0) { nwritten = write(fd, ptr, nleft); - - if (nwritten <= 0) + + if (nwritten < 0) + { + if (!ERRNO_IO_RETRY(errno)) + return nwritten; + } + if (nwritten == 0) return (nwritten); nleft -= nwritten; diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index bee9c63e96..01e8ee0e5f 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -307,8 +307,8 @@ zclient_lookup_nexthop_once (struct pim_zlookup_nexthop nexthop_tab[], ret = writen(zlookup->sock, s->data, stream_get_endp(s)); if (ret < 0) { - zlog_err("%s %s: writen() failure writing to zclient lookup socket", - __FILE__, __PRETTY_FUNCTION__); + zlog_err("%s %s: writen() failure: %d writing to zclient lookup socket", + __FILE__, __PRETTY_FUNCTION__, errno); zclient_lookup_failed(zlookup); return -2; } @@ -461,8 +461,8 @@ pim_zlookup_sg_statistics (struct channel_oil *c_oil) ret = writen (zlookup->sock, s->data, count); if (ret <= 0) { - zlog_err("%s %s: writen() failure writing to zclient lookup socket", - __FILE__, __PRETTY_FUNCTION__); + zlog_err("%s %s: writen() failure: %d writing to zclient lookup socket", + __FILE__, __PRETTY_FUNCTION__, errno); return -1; } From 9a5aa7429f48ae47c035541a387af752c8ec6d09 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 26 Sep 2016 21:26:43 -0400 Subject: [PATCH 191/386] pimd,zebra: Pass back error message if received When zebra asks for mroute information let pim know that the request failed or succeeded. Signed-off-by: Donald Sharp --- pimd/pim_zlookup.c | 3 ++- zebra/zebra_mroute.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 01e8ee0e5f..8c8fb55ce2 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -500,9 +500,10 @@ pim_zlookup_sg_statistics (struct channel_oil *c_oil) } stream_get (&lastused, s, sizeof (lastused)); + ret = stream_getl (s); if (PIM_DEBUG_ZEBRA) - zlog_debug ("Received %lld for %s", lastused, pim_str_sg_dump (&sg)); + zlog_debug ("Received %lld for %s success: %d", lastused, pim_str_sg_dump (&sg), ret); c_oil->cc.lastused = lastused; diff --git a/zebra/zebra_mroute.c b/zebra/zebra_mroute.c index 8dddb4e507..d05c906704 100644 --- a/zebra/zebra_mroute.c +++ b/zebra/zebra_mroute.c @@ -37,6 +37,7 @@ zebra_ipmr_route_stats (struct zserv *client, int fd, u_short length, struct zeb { struct mcast_route_data mroute; struct stream *s; + int suc; char sbuf[40]; char gbuf[40]; @@ -49,7 +50,7 @@ zebra_ipmr_route_stats (struct zserv *client, int fd, u_short length, struct zeb strcpy (sbuf, inet_ntoa (mroute.sg.src)); strcpy (gbuf, inet_ntoa (mroute.sg.grp)); - netlink_get_ipmr_sg_stats (&mroute); + suc = netlink_get_ipmr_sg_stats (&mroute); s = client->obuf; @@ -59,6 +60,7 @@ zebra_ipmr_route_stats (struct zserv *client, int fd, u_short length, struct zeb stream_put_in_addr (s, &mroute.sg.src); stream_put_in_addr (s, &mroute.sg.grp); stream_put (s, &mroute.lastused, sizeof (mroute.lastused)); + stream_putl (s, suc); stream_putw_at (s, 0, stream_get_endp (s)); zebra_server_send_message (client); From c7b1183fc7aaef258c40074826de5325fca3c1f4 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 26 Sep 2016 23:13:42 -0400 Subject: [PATCH 192/386] pimd: Don't ask for information when you are notgoing to get an answer When we have intentionally not installed a mroute( for whatever reason ), do not ask for information about that mroute from the kernel when it happens. Ticket: CM-12986 Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 45 +++++++++++++++++++++++++++++++-------------- pimd/pim_zlookup.c | 8 +++++++- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index c53a0393c0..9ef29b6e42 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -737,29 +737,46 @@ pim_mroute_update_counters (struct channel_oil *c_oil) { struct sioc_sg_req sgreq; - memset (&sgreq, 0, sizeof(sgreq)); - sgreq.src = c_oil->oil.mfcc_origin; - sgreq.grp = c_oil->oil.mfcc_mcastgrp; - c_oil->cc.oldpktcnt = c_oil->cc.pktcnt; c_oil->cc.oldbytecnt = c_oil->cc.bytecnt; c_oil->cc.oldwrong_if = c_oil->cc.wrong_if; + if (!c_oil->installed) + { + c_oil->cc.lastused = 100 * qpim_keep_alive_time; + if (PIM_DEBUG_MROUTE) + { + struct prefix_sg sg; + + sg.src = c_oil->oil.mfcc_origin; + sg.grp = c_oil->oil.mfcc_mcastgrp; + if (PIM_DEBUG_MROUTE) + zlog_debug("Channel(%s) is not installed no need to collect data from kernel", + pim_str_sg_dump (&sg)); + } + return; + } + + memset (&sgreq, 0, sizeof(sgreq)); + sgreq.src = c_oil->oil.mfcc_origin; + sgreq.grp = c_oil->oil.mfcc_mcastgrp; + pim_zlookup_sg_statistics (c_oil); if (ioctl (qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) { - char group_str[100]; - char source_str[100]; + if (PIM_DEBUG_MROUTE) + { + struct prefix_sg sg; - pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); + sg.src = c_oil->oil.mfcc_origin; + sg.grp = c_oil->oil.mfcc_mcastgrp; - zlog_warn ("ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s,%s): errno=%d: %s", - (unsigned long)SIOCGETSGCNT, - source_str, - group_str, - errno, - safe_strerror(errno)); + zlog_warn ("ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s): errno=%d: %s", + (unsigned long)SIOCGETSGCNT, + pim_str_sg_dump (&sg), + errno, + safe_strerror(errno)); + } return; } diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 8c8fb55ce2..4e6c76f0b0 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -448,7 +448,13 @@ pim_zlookup_sg_statistics (struct channel_oil *c_oil) struct interface *ifp = pim_if_find_by_vif_index (c_oil->oil.mfcc_parent); if (PIM_DEBUG_ZEBRA) - zlog_debug ("Sending Request for New Channel Oil Information"); + { + struct prefix_sg more; + + more.src = c_oil->oil.mfcc_origin; + more.grp = c_oil->oil.mfcc_mcastgrp; + zlog_debug ("Sending Request for New Channel Oil Information(%s)", pim_str_sg_dump (&more)); + } stream_reset (s); zclient_create_header (s, ZEBRA_IPMR_ROUTE_STATS, VRF_DEFAULT); From 9b91bb50f849b929a90e398a189476d02f1758b5 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Tue, 27 Sep 2016 16:37:38 +0000 Subject: [PATCH 193/386] pimd: Added json to 'show ip igmp group' Signed-off-by: Daniel Walton root@superm-redxp-05[quagga-pim]# vtysh -c 'show ip igmp group' Interface Address Group Mode Timer Srcs V Uptime br1 20.0.13.1 230.40.40.1 EXCL 00:03:24 1 3 00:01:28 root@superm-redxp-05[quagga-pim]# root@superm-redxp-05[quagga-pim]# root@superm-redxp-05[quagga-pim]# vtysh -c 'show ip igmp group json' | python -m json.tool { "br1": { "230.40.40.1": { "group": "230.40.40.1", "mode": "EXCLUDE", "source": "20.0.13.1", "sourcesCount": 1, "timer": "00:03:23", "uptime": "00:01:30", "version": 3 }, "address": "20.0.13.1", "flagBroadcast": true, "flagMulticast": true, "index": 96, "lanDelayEnabled": true, "name": "br1", "state": "up" } } root@superm-redxp-05[quagga-pim]# --- pimd/pim_cmd.c | 121 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 79 insertions(+), 42 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 74effbaa69..d9b70139c2 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -577,6 +577,9 @@ static void igmp_show_interfaces_single(struct vty *vty, const char *ifname, u_c json_object *json = NULL; json_object *json_row = NULL; + if (uj) + json = json_object_new_object(); + now = pim_time_monotonic_sec(); for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { @@ -585,7 +588,7 @@ static void igmp_show_interfaces_single(struct vty *vty, const char *ifname, u_c if (!pim_ifp) continue; - if (strcmp(ifname, ifp->name)) + if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name)) continue; for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { @@ -615,7 +618,6 @@ static void igmp_show_interfaces_single(struct vty *vty, const char *ifname, u_c mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); if (uj) { - json = json_object_new_object(); json_row = json_object_new_object(); json_object_pim_ifp_add(json_row, ifp); @@ -634,8 +636,6 @@ static void igmp_show_interfaces_single(struct vty *vty, const char *ifname, u_c json_object_int_add(json_row, "timerStartupQueryInterval", sqi); json_object_object_add(json, ifp->name, json_row); - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); - json_object_free(json); } else { vty_out(vty, "Interface : %s%s", ifp->name, VTY_NEWLINE); @@ -672,13 +672,13 @@ static void igmp_show_interfaces_single(struct vty *vty, const char *ifname, u_c } } - if (!found_ifname) - { - if (uj) - vty_out (vty, "{}%s", VTY_NEWLINE); - else - vty_out (vty, "%% No such interface%s", VTY_NEWLINE); - } + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); + } else { + if (!found_ifname) + vty_out (vty, "%% No such interface%s", VTY_NEWLINE); + } } static void igmp_show_interface_join(struct vty *vty) @@ -768,6 +768,9 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch now = pim_time_monotonic_sec(); + if (uj) + json = json_object_new_object(); + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { pim_ifp = ifp->info; @@ -777,7 +780,7 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch if (pim_ifp->pim_sock_fd < 0) continue; - if (strcmp(ifname, ifp->name)) + if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name)) continue; found_ifname = 1; @@ -790,7 +793,6 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); if (uj) { - json = json_object_new_object(); json_row = json_object_new_object(); json_object_pim_ifp_add(json_row, ifp); @@ -871,10 +873,7 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch json_object_int_add(json_row, "propagationDelayHighest", pim_ifp->pim_neighbors_highest_propagation_delay_msec); json_object_int_add(json_row, "overrideInterval", pim_ifp->pim_override_interval_msec); json_object_int_add(json_row, "overrideIntervalHighest", pim_ifp->pim_neighbors_highest_override_interval_msec); - json_object_object_add(json, ifp->name, json_row); - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); - json_object_free(json); } else { vty_out(vty, "Interface : %s%s", ifp->name, VTY_NEWLINE); @@ -974,13 +973,13 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch } } - if (!found_ifname) - { - if (uj) - vty_out (vty, "{}%s", VTY_NEWLINE); - else - vty_out (vty, "%% No such interface%s", VTY_NEWLINE); - } + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); + } else { + if (!found_ifname) + vty_out (vty, "%% No such interface%s", VTY_NEWLINE); + } } @@ -1185,7 +1184,9 @@ static void pim_show_neighbors_single(struct vty *vty, const char *neighbor, u_c * The user can specify either the interface name or the PIM neighbor IP. * If this pim_ifp matches neither then skip. */ - if (strcmp(neighbor, ifp->name) && strcmp(neighbor, neigh_src_str)) + if (strcmp(neighbor, "detail") && + strcmp(neighbor, ifp->name) && + strcmp(neighbor, neigh_src_str)) continue; found_neighbor = 1; @@ -1777,15 +1778,21 @@ static void pim_show_rpf(struct vty *vty, u_char uj) } } -static void igmp_show_groups(struct vty *vty) +static void igmp_show_groups(struct vty *vty, u_char uj) { struct listnode *ifnode; struct interface *ifp; time_t now; + json_object *json = NULL; + json_object *json_iface = NULL; + json_object *json_row = NULL; now = pim_time_monotonic_sec(); - vty_out(vty, "Interface Address Group Mode Timer Srcs V Uptime %s", VTY_NEWLINE); + if (uj) + json = json_object_new_object(); + else + vty_out(vty, "Interface Address Group Mode Timer Srcs V Uptime %s", VTY_NEWLINE); /* scan interfaces */ for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { @@ -1814,20 +1821,45 @@ static void igmp_show_groups(struct vty *vty) pim_time_timer_to_hhmmss(hhmmss, sizeof(hhmmss), grp->t_group_timer); pim_time_uptime(uptime, sizeof(uptime), now - grp->group_creation); - vty_out(vty, "%-9s %-15s %-15s %4s %8s %4d %d %8s%s", - ifp->name, - ifaddr_str, - group_str, - grp->group_filtermode_isexcl ? "EXCL" : "INCL", - hhmmss, - grp->group_source_list ? listcount(grp->group_source_list) : 0, - igmp_group_compat_mode(igmp, grp), - uptime, - VTY_NEWLINE); + if (uj) { + json_object_object_get_ex(json, ifp->name, &json_iface); + if (!json_iface) { + json_iface = json_object_new_object(); + json_object_pim_ifp_add(json_iface, ifp); + json_object_object_add(json, ifp->name, json_iface); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", ifaddr_str); + json_object_string_add(json_row, "group", group_str); + json_object_string_add(json_row, "mode", grp->group_filtermode_isexcl ? "EXCLUDE" : "INCLUDE"); + json_object_string_add(json_row, "timer", hhmmss); + json_object_int_add(json_row, "sourcesCount", grp->group_source_list ? listcount(grp->group_source_list) : 0); + json_object_int_add(json_row, "version", igmp_group_compat_mode(igmp, grp)); + json_object_string_add(json_row, "uptime", uptime); + json_object_object_add(json_iface, group_str, json_row); + + } else { + vty_out(vty, "%-9s %-15s %-15s %4s %8s %4d %d %8s%s", + ifp->name, + ifaddr_str, + group_str, + grp->group_filtermode_isexcl ? "EXCL" : "INCL", + hhmmss, + grp->group_source_list ? listcount(grp->group_source_list) : 0, + igmp_group_compat_mode(igmp, grp), + uptime, + VTY_NEWLINE); + } } /* scan igmp groups */ } /* scan igmp sockets */ } /* scan interfaces */ + + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); + } } static void igmp_show_group_retransmission(struct vty *vty) @@ -2178,11 +2210,12 @@ DEFUN (clear_ip_pim_oil, DEFUN (show_ip_igmp_interface, show_ip_igmp_interface_cmd, - "show ip igmp interface [WORD] [json]", + "show ip igmp interface [detail|WORD] [json]", SHOW_STR IP_STR IGMP_STR "IGMP interface information\n" + "Detailed output\n" "interface name\n" "JavaScript Object Notation\n") { @@ -2210,13 +2243,15 @@ DEFUN (show_ip_igmp_join, DEFUN (show_ip_igmp_groups, show_ip_igmp_groups_cmd, - "show ip igmp groups", + "show ip igmp groups [json]", SHOW_STR IP_STR IGMP_STR - IGMP_GROUP_STR) + IGMP_GROUP_STR + "JavaScript Object Notation\n") { - igmp_show_groups(vty); + u_char uj = use_json(argc, argv); + igmp_show_groups(vty, uj); return CMD_SUCCESS; } @@ -2344,11 +2379,12 @@ DEFUN (show_ip_pim_hello, DEFUN (show_ip_pim_interface, show_ip_pim_interface_cmd, - "show ip pim interface [WORD] [json]", + "show ip pim interface [detail|WORD] [json]", SHOW_STR IP_STR PIM_STR "PIM interface information\n" + "Detailed output\n" "interface name\n" "JavaScript Object Notation\n") { @@ -2391,11 +2427,12 @@ DEFUN (show_ip_pim_local_membership, DEFUN (show_ip_pim_neighbor, show_ip_pim_neighbor_cmd, - "show ip pim neighbor [WORD] [json]", + "show ip pim neighbor [detail|WORD] [json]", SHOW_STR IP_STR PIM_STR "PIM neighbor information\n" + "Detailed output\n" "Name of interface or neighbor\n" "JavaScript Object Notation\n") { From 98906696cf441ee242bf093b1c847fc65cc422b4 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 26 Sep 2016 19:59:48 -0400 Subject: [PATCH 194/386] pimd: Add debug wrapping around rp nexthop lookup When looking up the RP only print debugs when debugging is turned on. Signed-off-by: Donald Sharp --- pimd/pim_rp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index b5c5ad55b9..98fc2eaabd 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -489,7 +489,8 @@ pim_rp_setup (void) { if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1) != 0) { - zlog_err ("Unable to lookup nexthop for rp specified"); + if (PIM_DEBUG_PIM_TRACE) + zlog_debug ("Unable to lookup nexthop for rp specified"); ret++; } } From 0d4f730c5877c3f71395055f19f2672197b5af48 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 28 Sep 2016 00:14:22 +0000 Subject: [PATCH 195/386] pimd: sort qpim_channel_oil_list and qpim_upstream_list Signed-off-by: Daniel Walton This allows "show ip mroute" and "show ip pim upstream" to display the groups in order. --- pimd/pim_oil.c | 2 +- pimd/pim_upstream.c | 2 +- pimd/pimd.c | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index e09dc3f089..9728d6304f 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -77,7 +77,7 @@ pim_add_channel_oil (struct prefix_sg *sg, c_oil->oil_ref_count = 1; c_oil->installed = 0; - listnode_add(qpim_channel_oil_list, c_oil); + listnode_add_sort(qpim_channel_oil_list, c_oil); return c_oil; } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 64fffa3859..eb69f63459 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -520,7 +520,7 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, return NULL; } - listnode_add(qpim_upstream_list, up); + listnode_add_sort(qpim_upstream_list, up); return up; } diff --git a/pimd/pimd.c b/pimd/pimd.c index dff3f75aed..3a010e81a1 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -98,6 +98,42 @@ static void pim_free() pim_route_map_terminate(); } +static int +pim_channel_oil_compare (struct channel_oil *c1, struct channel_oil *c2) +{ + if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) < ntohl(c2->oil.mfcc_mcastgrp.s_addr)) + return -1; + + if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) > ntohl(c2->oil.mfcc_mcastgrp.s_addr)) + return 1; + + if (ntohl(c1->oil.mfcc_origin.s_addr) < ntohl(c2->oil.mfcc_origin.s_addr)) + return -1; + + if (ntohl(c1->oil.mfcc_origin.s_addr) > ntohl(c2->oil.mfcc_origin.s_addr)) + return 1; + + return 0; +} + +static int +pim_upstream_compare (struct pim_upstream *up1, struct pim_upstream *up2) +{ + if (ntohl(up1->sg.grp.s_addr) < ntohl(up2->sg.grp.s_addr)) + return -1; + + if (ntohl(up1->sg.grp.s_addr) > ntohl(up2->sg.grp.s_addr)) + return 1; + + if (ntohl(up1->sg.src.s_addr) < ntohl(up2->sg.src.s_addr)) + return -1; + + if (ntohl(up1->sg.src.s_addr) > ntohl(up2->sg.src.s_addr)) + return 1; + + return 0; +} + void pim_init() { srandom(time(NULL)); @@ -121,6 +157,7 @@ void pim_init() return; } qpim_channel_oil_list->del = (void (*)(void *)) pim_channel_oil_free; + qpim_channel_oil_list->cmp = (int (*)(void *, void *)) pim_channel_oil_compare; qpim_upstream_list = list_new(); if (!qpim_upstream_list) { @@ -130,6 +167,7 @@ void pim_init() return; } qpim_upstream_list->del = (void (*)(void *)) pim_upstream_free; + qpim_upstream_list->cmp = (int (*)(void *, void *)) pim_upstream_compare; qpim_static_route_list = list_new(); if (!qpim_static_route_list) { From bbd64ce1e7b71c8412dc71aa21bc5c5fda8b3165 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 28 Sep 2016 00:40:58 +0000 Subject: [PATCH 196/386] pimd: sort pim_ifchannel_list Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp --- pimd/pim_iface.c | 19 +++++++++++++++++++ pimd/pim_ifchannel.c | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index e55ef30b31..b6012d1ed1 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -72,6 +72,24 @@ static void *if_list_clean(struct pim_interface *pim_ifp) return 0; } +static int +pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2) +{ + if (ntohl(ch1->sg.grp.s_addr) < ntohl(ch2->sg.grp.s_addr)) + return -1; + + if (ntohl(ch1->sg.grp.s_addr) > ntohl(ch2->sg.grp.s_addr)) + return 1; + + if (ntohl(ch1->sg.src.s_addr) < ntohl(ch2->sg.src.s_addr)) + return -1; + + if (ntohl(ch1->sg.src.s_addr) > ntohl(ch2->sg.src.s_addr)) + return 1; + + return 0; +} + struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim) { struct pim_interface *pim_ifp; @@ -142,6 +160,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim) return if_list_clean(pim_ifp); } pim_ifp->pim_ifchannel_list->del = (void (*)(void *)) pim_ifchannel_free; + pim_ifp->pim_ifchannel_list->cmp = (int (*)(void *, void *)) pim_ifchannel_compare; ifp->info = pim_ifp; diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 1bc10f4cce..ee388b7d68 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -429,7 +429,7 @@ pim_ifchannel_add(struct interface *ifp, PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); /* Attach to list */ - listnode_add(pim_ifp->pim_ifchannel_list, ch); + listnode_add_sort(pim_ifp->pim_ifchannel_list, ch); zassert(IFCHANNEL_NOINFO(ch)); From c0a06968b22154559a8b0bb0bea0de5919de2ca4 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 27 Sep 2016 11:06:12 -0400 Subject: [PATCH 197/386] pimd: Print '*' for INADDR_ANY When INADDR_ANY is sent to the pim dump function, return "*" Signed-off-by: Donald Sharp --- pimd/pim_str.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/pimd/pim_str.c b/pimd/pim_str.c index ca635c8a54..2dffe8c2b8 100644 --- a/pimd/pim_str.c +++ b/pimd/pim_str.c @@ -47,11 +47,16 @@ void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, int buf_ { int save_errno = errno; - if (!inet_ntop(AF_INET, &addr, buf, buf_size)) { - zlog_warn("pim_inet4_dump: inet_ntop(AF_INET,buf_size=%d): errno=%d: %s", - buf_size, errno, safe_strerror(errno)); - if (onfail) - snprintf(buf, buf_size, "%s", onfail); + if (addr.s_addr == INADDR_ANY) + strcpy(buf, "*"); + else + { + if (!inet_ntop(AF_INET, &addr, buf, buf_size)) { + zlog_warn("pim_inet4_dump: inet_ntop(AF_INET,buf_size=%d): errno=%d: %s", + buf_size, errno, safe_strerror(errno)); + if (onfail) + snprintf(buf, buf_size, "%s", onfail); + } } errno = save_errno; From 31a21c9cd1532768787956a9f1410eee45f8909e Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 28 Sep 2016 01:33:33 +0000 Subject: [PATCH 198/386] pimd: initial "show ip pim state" Signed-off-by: Daniel Walton Ticket: CM-11812 superm-redxp-05# show ip pim state Source Group IIF OIL 20.0.13.253 230.10.10.1 br1 swp1 20.0.13.253 230.20.20.1 br1 0.0.0.0 230.40.40.1 swp1 br1 0.0.0.0 230.42.42.1 swp1 br1 0.0.0.0 230.42.43.1 swp1 br1 superm-redxp-05# superm-redxp-05# show ip pim state 20.0.13.253 Source Group IIF OIL 20.0.13.253 230.10.10.1 br1 swp1 20.0.13.253 230.20.20.1 br1 superm-redxp-05# show ip pim state 20.0.13.253 230.10.10.1 Source Group IIF OIL 20.0.13.253 230.10.10.1 br1 swp1 superm-redxp-05# superm-redxp-05# show ip pim state 230.40.40.1 Source Group IIF OIL 0.0.0.0 230.40.40.1 swp1 br1 superm-redxp-05# show ip pim state 230.40.40.1 json { "230.40.40.1":{ "0.0.0.0":{ "swp1":{ "br1":{ "source":"0.0.0.0", "group":"230.40.40.1", "inboundInterface":"swp1", "outboundInterface":"br1" } } } } } superm-redxp-05# --- pimd/pim_cmd.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 157 insertions(+), 2 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index d9b70139c2..77e3641cf6 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1288,6 +1288,137 @@ static void pim_show_neighbors_single(struct vty *vty, const char *neighbor, u_c } } +static void +pim_show_state(struct vty *vty, const char *src_or_group, const char *group, u_char uj) +{ + struct channel_oil *c_oil; + struct listnode *node; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_ifp_in = NULL; + json_object *json_ifp_out = NULL; + json_object *json_source = NULL; + time_t now; + int first_oif; + now = pim_time_monotonic_sec(); + + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, "%sSource Group IIF OIL%s", VTY_NEWLINE, VTY_NEWLINE); + } + + for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) { + char grp_str[100]; + char src_str[100]; + char in_ifname[16]; + char out_ifname[16]; + int oif_vif_index; + 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); + + if (ifp_in) + strcpy(in_ifname, ifp_in->name); + else + strcpy(in_ifname, ""); + + if (src_or_group) + { + if (strcmp(src_or_group, src_str) && strcmp(src_or_group, grp_str)) + continue; + + if (group && strcmp(group, grp_str)) + continue; + } + + if (uj) { + + /* Find the group, create it if it doesn't exist */ + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, json_group); + } + + /* Find the source nested under the group, create it if it doesn't exist */ + json_object_object_get_ex(json_group, src_str, &json_source); + + if (!json_source) { + json_source = json_object_new_object(); + json_object_object_add(json_group, src_str, json_source); + } + + /* Find the inbound interface nested under the source, create it if it doesn't exist */ + json_object_object_get_ex(json_source, in_ifname, &json_ifp_in); + + if (!json_ifp_in) { + json_ifp_in = json_object_new_object(); + json_object_object_add(json_source, in_ifname, json_ifp_in); + } + } else { + vty_out(vty, "%-15s %-15s %-5s ", + src_str, + grp_str, + ifp_in->name); + } + + for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) { + struct interface *ifp_out; + char oif_uptime[10]; + int ttl; + + ttl = c_oil->oil.mfcc_ttls[oif_vif_index]; + if (ttl < 1) + continue; + + ifp_out = pim_if_find_by_vif_index(oif_vif_index); + pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - c_oil->oif_creation[oif_vif_index]); + + if (ifp_out) + strcpy(out_ifname, ifp_out->name); + else + strcpy(out_ifname, ""); + + if (uj) { + json_ifp_out = json_object_new_object(); + json_object_string_add(json_ifp_out, "source", src_str); + 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_object_add(json_ifp_in, out_ifname, json_ifp_out); + } else { + if (first_oif) + { + first_oif = 0; + vty_out(vty, "%s", out_ifname); + } + else + vty_out(vty, ",%s", out_ifname); + } + } + + if (!uj) + vty_out(vty, "%s", VTY_NEWLINE); + } + + + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + json_object_free(json); + } else { + vty_out(vty, "%s", VTY_NEWLINE); + } +} + static void pim_show_neighbors(struct vty *vty, u_char uj) { struct listnode *node; @@ -2458,6 +2589,29 @@ DEFUN (show_ip_pim_secondary, return CMD_SUCCESS; } +DEFUN (show_ip_pim_state, + show_ip_pim_state_cmd, + "show ip pim state [A.B.C.D] [A.B.C.D] [json]", + SHOW_STR + IP_STR + PIM_STR + "PIM state information\n" + "Unicast or Multicast address\n" + "Multicast address\n" + "JavaScript Object Notation\n") +{ + const char *src_or_group = NULL; + const char *group = NULL; + u_char uj = use_json(argc, argv); + + src_or_group = argv[4]->arg; + group = argv[5]->arg; + + pim_show_state(vty, src_or_group, group, uj); + + return CMD_SUCCESS; +} + DEFUN (show_ip_pim_upstream, show_ip_pim_upstream_cmd, "show ip pim upstream [json]", @@ -2794,10 +2948,10 @@ static void show_mroute(struct vty *vty, u_char uj) } if (!uj && !found_oif) { - vty_out(vty, "%-15s %-15s %-10s %-10s %-6s %-3d %8s%s", + vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s%s", src_str, grp_str, - proto, + "none", in_ifname, "none", 0, @@ -5602,6 +5756,7 @@ void pim_cmd_init() install_element (VIEW_NODE, &show_ip_pim_neighbor_cmd); install_element (VIEW_NODE, &show_ip_pim_rpf_cmd); install_element (VIEW_NODE, &show_ip_pim_secondary_cmd); + install_element (VIEW_NODE, &show_ip_pim_state_cmd); install_element (VIEW_NODE, &show_ip_pim_upstream_cmd); install_element (VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd); install_element (VIEW_NODE, &show_ip_pim_upstream_rpf_cmd); From 72b39b9ec5b458c22009cc64cb8ba918c36f8659 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Tue, 27 Sep 2016 18:35:22 -0700 Subject: [PATCH 199/386] pimd: 'show ip pim state json' use JSON_C_TO_STRING_PRETTY Signed-off-by: Daniel Walton Ticket: CM-11812 --- pimd/pim_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 77e3641cf6..cb7047a9fb 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1412,7 +1412,7 @@ pim_show_state(struct vty *vty, const char *src_or_group, const char *group, u_c if (uj) { - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); json_object_free(json); } else { vty_out(vty, "%s", VTY_NEWLINE); From 17b52be189693345f113da1710b64d23d410cccb Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 28 Sep 2016 01:43:20 +0000 Subject: [PATCH 200/386] pimd: use JSON_C_TO_STRING_PRETTY everywhere Signed-off-by: Daniel Walton --- pimd/pim_cmd.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index cb7047a9fb..dd34e55894 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -469,7 +469,7 @@ static void pim_show_membership(struct vty *vty, u_char uj) } /* scan interfaces */ if (uj) { - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); json_object_free(json); } } @@ -549,7 +549,7 @@ static void igmp_show_interfaces(struct vty *vty, u_char uj) } if (uj) { - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); json_object_free(json); } } @@ -673,7 +673,7 @@ static void igmp_show_interfaces_single(struct vty *vty, const char *ifname, u_c } if (uj) { - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); json_object_free(json); } else { if (!found_ifname) @@ -974,7 +974,7 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch } if (uj) { - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); json_object_free(json); } else { if (!found_ifname) @@ -1046,7 +1046,7 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) } if (uj) { - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); json_object_free(json); } } @@ -1134,7 +1134,7 @@ static void pim_show_join(struct vty *vty, u_char uj) } /* scan interfaces */ if (uj) { - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); json_object_free(json); } } @@ -1278,7 +1278,7 @@ static void pim_show_neighbors_single(struct vty *vty, const char *neighbor, u_c } if (uj) { - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); json_object_free(json); } else { { @@ -1488,7 +1488,7 @@ static void pim_show_neighbors(struct vty *vty, u_char uj) } if (uj) { - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); json_object_free(json); } } @@ -1636,7 +1636,7 @@ static void pim_show_upstream(struct vty *vty, u_char uj) } if (uj) { - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); json_object_free(json); } } @@ -1718,7 +1718,7 @@ static void pim_show_join_desired(struct vty *vty, u_char uj) } if (uj) { - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); json_object_free(json); } } @@ -1783,7 +1783,7 @@ static void pim_show_upstream_rpf(struct vty *vty, u_char uj) } if (uj) { - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); json_object_free(json); } } @@ -1904,7 +1904,7 @@ static void pim_show_rpf(struct vty *vty, u_char uj) } if (uj) { - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); json_object_free(json); } } @@ -1988,7 +1988,7 @@ static void igmp_show_groups(struct vty *vty, u_char uj) } /* scan interfaces */ if (uj) { - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); json_object_free(json); } } @@ -3078,7 +3078,7 @@ static void show_mroute(struct vty *vty, u_char uj) } if (uj) { - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); json_object_free(json); } } From 8151e2865c405e569ad180074a2be7b7c0d71425 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 28 Sep 2016 22:57:31 +0000 Subject: [PATCH 201/386] pimd: 'sh ip pim int' showed local IP as the DR Signed-off-by: Daniel Walton --- pimd/pim_cmd.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index dd34e55894..4f685eca3d 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -996,6 +996,8 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) int pim_nbrs = 0; json_object *json = NULL; json_object *json_row = NULL; + char local_ip[INET_ADDRSTRLEN]; + char dr_ip[INET_ADDRSTRLEN]; if (uj) { json = json_object_new_object(); @@ -1034,12 +1036,14 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) json_object_object_add(json, ifp->name, json_row); } else { + strcpy(local_ip, inet_ntoa(ifaddr)); + strcpy(dr_ip, inet_ntoa(pim_ifp->pim_dr_addr)); vty_out(vty, "%-9s %5s %15s %8d %15s %3d%s", ifp->name, if_is_up(ifp) ? "up" : "down", - inet_ntoa(ifaddr), + local_ip, pim_nbrs, - pim_dr_local ? "local" : inet_ntoa(pim_ifp->pim_dr_addr), + pim_dr_local ? "local" : dr_ip, fhr, VTY_NEWLINE); } From 8ccbc80f01ca6181e1b00c033389a79d87dbc70e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 27 Sep 2016 19:59:34 -0400 Subject: [PATCH 202/386] pimd: Fix crash when looking at S,G from *,G When looping over S,G's associated with a *,G, there can exist situations where we have not created the channel oil for the S,G yet. Don't allow this to crash the system. Signed-off-by: Donald Sharp --- pimd/pim_join.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pimd/pim_join.c b/pimd/pim_join.c index c92be18ddf..08c1c7b93a 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -210,6 +210,8 @@ static void recv_prune(struct interface *ifp, __FILE__, __PRETTY_FUNCTION__, buff, pim_str_sg_dump (&child->sg)); } + if (!c_oil) + continue; if (!pim_upstream_evaluate_join_desired (child)) pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); From 19e550954bfdddf304c36fee4b24f85cf3180f5b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 3 Oct 2016 18:42:59 -0400 Subject: [PATCH 203/386] pimd: Allow bigger packet sizes when receiving callbacks. When receiving callbacks from the kernel allow bigger packet sizes than 3k to be handled appropriately. Signed-off-by: Donald Sharp --- pimd/pim_pim.c | 4 ++-- pimd/pim_register.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 991bac8a2e..b10528536e 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -538,11 +538,11 @@ pim_msg_send(int fd, struct in_addr src, { struct sockaddr_in to; socklen_t tolen; - unsigned char buffer[3000]; + unsigned char buffer[10000]; unsigned char *msg_start; struct ip *ip; - memset (buffer, 0, 3000); + memset (buffer, 0, 10000); int sendlen = sizeof (struct ip) + pim_msg_size; msg_start = buffer + sizeof (struct ip); diff --git a/pimd/pim_register.c b/pimd/pim_register.c index c2e666f17b..6fb42bcd6a 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -51,7 +51,7 @@ pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, struct in_addr src, struct in_addr originator) { struct pim_interface *pinfo; - unsigned char buffer[3000]; + unsigned char buffer[10000]; unsigned int b1length = 0; unsigned int length; uint8_t *b1; @@ -63,7 +63,7 @@ pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, pim_str_sg_dump (sg), inet_ntoa(originator), ifp->name); } - memset (buffer, 0, 3000); + memset (buffer, 0, 10000); b1 = (uint8_t *)buffer + PIM_MSG_REGISTER_STOP_LEN; length = pim_encode_addr_group (b1, AFI_IP, 0, 0, sg->grp); @@ -149,7 +149,7 @@ pim_register_stop_recv (uint8_t *buf, int buf_size) void pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct pim_rpf *rpg, int null_register) { - unsigned char buffer[3000]; + unsigned char buffer[10000]; unsigned char *b1; struct pim_interface *pinfo; struct interface *ifp; @@ -175,7 +175,7 @@ pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct return; } - memset(buffer, 0, 3000); + memset(buffer, 0, 10000); b1 = buffer + PIM_MSG_HEADER_LEN; *b1 |= null_register << 6; b1 = buffer + PIM_MSG_REGISTER_LEN; From 6f782ed29d414d4546bd2df5f98648956505b61b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 7 Oct 2016 09:05:28 -0400 Subject: [PATCH 204/386] zebra: Fix include order for build --- zebra/zebra_vty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index e5f9b17e81..1fe55b072e 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -31,7 +31,6 @@ #include "nexthop.h" #include "vrf.h" #include "mpls.h" -#include "lib/json.h" #include "routemap.h" #include "zebra/zserv.h" @@ -41,6 +40,7 @@ #include "zebra/redistribute.h" #include "zebra/zebra_routemap.h" #include "zebra/zebra_static.h" +#include "lib/json.h" extern int allow_delete; From 5b668dd747b49b51008ac5814c31ffe33a39b863 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 4 Oct 2016 07:56:09 -0400 Subject: [PATCH 205/386] pimd: Fix LHR both a receiver and a sender Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 1 + pimd/pim_mroute.c | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index ee388b7d68..165ea1fe32 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -653,6 +653,7 @@ void pim_ifchannel_join_add(struct interface *ifp, case PIM_IFJOIN_NOINFO: pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN); if (pim_macro_chisin_oiflist(ch)) { + pim_upstream_inherited_olist (ch->upstream); pim_forward_start(ch); } break; diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 9ef29b6e42..32d99ab1fe 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -349,12 +349,19 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) pim_register_stop_send(source.interface, &sg, pim_ifp->primary_address, up->upstream_register); if (!up->channel_oil) up->channel_oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); + pim_upstream_inherited_olist (up); if (!up->channel_oil->installed) pim_mroute_add (up->channel_oil); //Send S bit down the join. up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; } - return 0; + else + { + pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); + pim_upstream_inherited_olist (up); + pim_mroute_msg_wholepkt (fd, ifp, buf); + } + return 0; } pim_ifp = ifp->info; From eab2a327179d9c36ba08d7b42f3cc3b379f8638e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 10 Oct 2016 15:31:27 -0400 Subject: [PATCH 206/386] pimd: Fix message size read from kernel When we read data from the kernel allow for larger packet sizes to be sent to us. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 32d99ab1fe..6f748db256 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -424,7 +424,7 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size) if (PIM_DEBUG_MROUTE) { 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", + zlog_warn("%s: kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%s,%s) on %s vifi=%d size=%d", __PRETTY_FUNCTION__, igmpmsgtype2str[msg->im_msgtype], msg->im_msgtype, @@ -433,7 +433,7 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size) src_str, grp_str, ifp->name, - msg->im_vif); + msg->im_vif, buf_size); } switch (msg->im_msgtype) { @@ -458,7 +458,7 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size) static int mroute_read_msg(int fd) { - char buf[2000]; + char buf[10000]; int rd; rd = read(fd, buf, sizeof(buf)); From 5ce794664d7404450a381c2dfc4abe408ba9aaba Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 12 Oct 2016 19:18:19 -0400 Subject: [PATCH 207/386] pimd: Only delete on KAT when created by stream When we have pim_mroute.c or pim_register.c create the upstream state, only delete it then when the KAT timer expires, else we will not have the refcount right and we will do bad things. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 1 + pimd/pim_mroute.c | 3 ++- pimd/pim_register.c | 2 ++ pimd/pim_upstream.c | 3 ++- pimd/pim_upstream.h | 4 ++++ 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 165ea1fe32..eb127338e4 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -128,6 +128,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) } pim_upstream_del(ch->upstream); + ch->upstream = NULL; THREAD_OFF(ch->t_ifjoin_expiry_timer); THREAD_OFF(ch->t_ifjoin_prune_pending_timer); diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 6f748db256..b9c97557c5 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -146,6 +146,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg return 0; } PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); + PIM_UPSTREAM_FLAG_SET_CREATED_BY_UPSTREAM(up->flags); pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); @@ -379,7 +380,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) return -2; } PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); - PIM_UPSTREAM_FLAG_SET_FHR(up->flags); + PIM_UPSTREAM_FLAG_SET_CREATED_BY_UPSTREAM(up->flags); pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); up->channel_oil = oil; diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 6fb42bcd6a..216e3390a6 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -339,6 +339,8 @@ pim_register_recv (struct interface *ifp, zlog_warn ("Failure to create upstream state"); return 1; } + PIM_UPSTREAM_FLAG_SET_CREATED_BY_UPSTREAM(upstream->flags); + upstream->upstream_register = src_addr; pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.src, sg.grp); pim_nexthop_lookup (&upstream->rpf.source_nexthop, diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index eb69f63459..cbc8e50508 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -891,7 +891,8 @@ pim_upstream_keep_alive_timer (struct thread *t) pim_joinprune_send (up->rpf.source_nexthop.interface, up->rpf.rpf_addr.u.prefix4, &up->sg, 0); PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM (up->flags); - pim_upstream_del (up); + if (PIM_UPSTREAM_FLAG_TEST_CREATED_BY_UPSTREAM(up->flags)) + pim_upstream_del (up); } else { diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 3c9862fe98..61f9d3226a 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -33,6 +33,7 @@ #define PIM_UPSTREAM_FLAG_MASK_SRC_IGMP (1 << 3) #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_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) @@ -40,6 +41,7 @@ #define PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) #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_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) @@ -47,6 +49,7 @@ #define PIM_UPSTREAM_FLAG_SET_SRC_IGMP(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) #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_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) @@ -54,6 +57,7 @@ #define PIM_UPSTREAM_FLAG_UNSET_SRC_IGMP(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) #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) enum pim_upstream_state { PIM_UPSTREAM_NOTJOINED, From 0f5889897125e5ba5d62bc1151cec3c7d6c6d404 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 7 Oct 2016 14:25:08 +0000 Subject: [PATCH 208/386] pimd: Add hash lookups for upstream --- pimd/pim_cmd.c | 21 ++++--- pimd/pim_ifchannel.c | 4 +- pimd/pim_join.c | 4 +- pimd/pim_upstream.c | 127 +++++++++++++++++++++++++++++-------------- pimd/pim_upstream.h | 6 +- pimd/pim_zebra.c | 2 +- pimd/pimd.c | 32 +---------- pimd/pimd.h | 1 - 8 files changed, 108 insertions(+), 89 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 4f685eca3d..a12a7a230e 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -823,8 +823,8 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch json_object_int_add(json_row, "drChanges", pim_ifp->pim_dr_election_changes); // FHR - for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) { - if (strcmp(ifp->name, up->rpf.source_nexthop.interface->name) == 0) { + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { + if (ifp == up->rpf.source_nexthop.interface) { if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) { if (!json_fhr_sources) { json_fhr_sources = json_object_new_object(); @@ -915,7 +915,7 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch // FHR print_header = 1; - for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) { + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { if (strcmp(ifp->name, up->rpf.source_nexthop.interface->name) == 0) { if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) { @@ -982,12 +982,11 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch } } - static void pim_show_interfaces(struct vty *vty, u_char uj) { struct in_addr ifaddr; struct interface *ifp; - struct listnode *node; + struct listnode *node; struct listnode *upnode; struct pim_interface *pim_ifp; struct pim_upstream *up; @@ -998,7 +997,7 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) json_object *json_row = NULL; char local_ip[INET_ADDRSTRLEN]; char dr_ip[INET_ADDRSTRLEN]; - + if (uj) { json = json_object_new_object(); } else { @@ -1022,8 +1021,8 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) if (pim_ifp->pim_dr_addr.s_addr == pim_ifp->primary_address.s_addr) pim_dr_local = 1; - for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) - if (strcmp(ifp->name, up->rpf.source_nexthop.interface->name) == 0) + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) + if (ifp == up->rpf.source_nexthop.interface) if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) fhr++; @@ -1589,7 +1588,7 @@ static void pim_show_upstream(struct vty *vty, u_char uj) else vty_out(vty, "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt%s", VTY_NEWLINE); - for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) { + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { char src_str[100]; char grp_str[100]; char uptime[10]; @@ -1742,7 +1741,7 @@ static void pim_show_upstream_rpf(struct vty *vty, u_char uj) "Source Group RpfIface RibNextHop RpfAddress %s", VTY_NEWLINE); - for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) { + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { char src_str[100]; char grp_str[100]; char rpf_nexthop_str[100]; @@ -1861,7 +1860,7 @@ static void pim_show_rpf(struct vty *vty, u_char uj) VTY_NEWLINE); } - for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, up_node, up)) { + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) { char src_str[100]; char grp_str[100]; char rpf_addr_str[100]; diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index eb127338e4..2f9e9b5981 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -790,7 +790,7 @@ void pim_ifchannel_local_membership_add(struct interface *ifp, struct pim_upstream *child; struct listnode *up_node; - for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, up_node, child)) + for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, up_node, child)) { if (child->parent == up) { @@ -839,7 +839,7 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, struct pim_upstream *child; struct listnode *up_node; - for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, up_node, child)) + for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, up_node, child)) { if (child->parent == up) { diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 08c1c7b93a..0a00be9e60 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -117,7 +117,7 @@ static void recv_join(struct interface *ifp, if (!up) return; - for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, up_node, child)) + for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, up_node, child)) { if (child->parent == up) { @@ -194,7 +194,7 @@ static void recv_prune(struct interface *ifp, if (!up) return; - for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, up_node, child)) + for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, up_node, child)) { if (child->parent == up) { diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index cbc8e50508..88755ec9fd 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -30,6 +30,8 @@ #include "linklist.h" #include "vty.h" #include "plist.h" +#include "hash.h" +#include "jhash.h" #include "pimd.h" #include "pim_pim.h" @@ -49,6 +51,9 @@ #include "pim_br.h" #include "pim_register.h" +struct hash *pim_upstream_hash = NULL; +struct list *pim_upstream_list = NULL; + static void join_timer_start(struct pim_upstream *up); static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up); @@ -73,7 +78,7 @@ pim_upstream_remove_children (struct pim_upstream *up) (up->sg.grp.s_addr != INADDR_ANY)) return; - for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, ch_node, child)) + for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, ch_node, child)) { if (child->parent == up) child->parent = NULL; @@ -99,10 +104,10 @@ pim_upstream_find_new_children (struct pim_upstream *up) (up->sg.grp.s_addr == INADDR_ANY)) return; - for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, ch_node, child)) + for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, ch_node, child)) { if ((up->sg.grp.s_addr != INADDR_ANY) && - (child->sg.grp.s_addr == up->sg.grp.s_addr) && + (child->sg.grp.s_addr == up->sg.grp.s_addr) && (child != up)) child->parent = up; } @@ -166,7 +171,8 @@ void pim_upstream_delete(struct pim_upstream *up) into pim_upstream_free() because the later is called by list_delete_all_node() */ - listnode_delete(qpim_upstream_list, up); + listnode_delete (pim_upstream_list, up); + hash_release (pim_upstream_hash, up); pim_upstream_free(up); } @@ -482,6 +488,7 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, } up->sg = *sg; + up = hash_get (pim_upstream_hash, up, hash_alloc_intern); if (!pim_rp_set_upstream_addr (&up->upstream_addr, sg->src, sg->grp)) { if (PIM_DEBUG_PIM_TRACE) @@ -520,44 +527,19 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, return NULL; } - listnode_add_sort(qpim_upstream_list, up); + listnode_add_sort(pim_upstream_list, up); return up; } -/* - * For a given sg, find any non * source - */ -struct pim_upstream *pim_upstream_find_non_any (struct prefix_sg *sg) -{ - struct listnode *up_node; - struct prefix_sg any = *sg; - struct pim_upstream *up; - - any.src.s_addr = INADDR_ANY; - - for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, up_node, up)) - { - if ((any.grp.s_addr == up->sg.grp.s_addr) && - (up->sg.src.s_addr != any.src.s_addr)) - return up; - } - - return NULL; -} - struct pim_upstream *pim_upstream_find(struct prefix_sg *sg) { - struct listnode *up_node; - struct pim_upstream *up; + struct pim_upstream lookup; + struct pim_upstream *up = NULL; - for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, up_node, up)) { - if ((sg->grp.s_addr == up->sg.grp.s_addr) && - (sg->src.s_addr == up->sg.src.s_addr)) - return up; - } - - return NULL; + lookup.sg = *sg; + up = hash_lookup (pim_upstream_hash, &lookup); + return up; } struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, @@ -705,9 +687,9 @@ void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr) struct pim_upstream *up; /* - Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr - */ - for (ALL_LIST_ELEMENTS(qpim_upstream_list, up_node, up_nextnode, up)) { + * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr + */ + for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { if (PIM_DEBUG_PIM_TRACE) { char neigh_str[100]; @@ -1136,9 +1118,9 @@ pim_upstream_find_new_rpf (void) struct pim_upstream *up; /* - Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr - */ - for (ALL_LIST_ELEMENTS(qpim_upstream_list, up_node, up_nextnode, up)) + * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr + */ + for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { @@ -1149,3 +1131,66 @@ pim_upstream_find_new_rpf (void) } } } + +static int +pim_upstream_compare (const void *arg1, const void *arg2) +{ + const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; + const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; + + if (ntohl(up1->sg.grp.s_addr) < ntohl(up2->sg.grp.s_addr)) + return -1; + + if (ntohl(up1->sg.grp.s_addr) > ntohl(up2->sg.grp.s_addr)) + return 1; + + if (ntohl(up1->sg.src.s_addr) < ntohl(up2->sg.src.s_addr)) + return -1; + + if (ntohl(up1->sg.src.s_addr) > ntohl(up2->sg.src.s_addr)) + return 1; + + return 0; +} + +static unsigned int +pim_upstream_hash_key (void *arg) +{ + struct pim_upstream *up = (struct pim_upstream *)arg; + + return jhash_2words (up->sg.src.s_addr, up->sg.grp.s_addr, 0); +} + +void pim_upstream_terminate (void) +{ + if (pim_upstream_list) + list_free (pim_upstream_list); + pim_upstream_list = NULL; + + if (pim_upstream_hash) + hash_free (pim_upstream_hash); +} + +static int +pim_upstream_equal (const void *arg1, const void *arg2) +{ + const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; + const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; + + if ((up1->sg.grp.s_addr == up2->sg.grp.s_addr) && + (up1->sg.src.s_addr == up2->sg.src.s_addr)) + return 1; + + return 0; +} + +void pim_upstream_init (void) +{ + pim_upstream_hash = hash_create_size (8192, pim_upstream_hash_key, + pim_upstream_equal); + + pim_upstream_list = list_new (); + pim_upstream_list->del = (void (*)(void *)) pim_upstream_free; + pim_upstream_list->cmp = (int (*)(void *, void *)) pim_upstream_compare; + +} diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 61f9d3226a..70b5b01062 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -112,10 +112,12 @@ struct pim_upstream { int64_t state_transition; /* Record current state uptime */ }; +struct list *pim_upstream_list; +struct hash *pim_upstream_hash; + void pim_upstream_free(struct pim_upstream *up); void pim_upstream_delete(struct pim_upstream *up); struct pim_upstream *pim_upstream_find (struct prefix_sg *sg); -struct pim_upstream *pim_upstream_find_non_any (struct prefix_sg *sg); struct pim_upstream *pim_upstream_add (struct prefix_sg *sg, struct interface *ifp, int); void pim_upstream_del(struct pim_upstream *up); @@ -154,4 +156,6 @@ int pim_upstream_inherited_olist (struct pim_upstream *up); void pim_upstream_find_new_rpf (void); +void pim_upstream_init (void); +void pim_upstream_terminate (void); #endif /* PIM_UPSTREAM_H */ diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 1738c5f6f4..6115bcbf6e 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -362,7 +362,7 @@ static void scan_upstream_rpf_cache() struct listnode *up_nextnode; struct pim_upstream *up; - for (ALL_LIST_ELEMENTS(qpim_upstream_list, up_node, up_nextnode, up)) { + for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { struct in_addr old_rpf_addr; struct interface *old_interface; enum pim_rpf_result rpf_result; diff --git a/pimd/pimd.c b/pimd/pimd.c index 3a010e81a1..82ecdc9fc5 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -54,7 +54,6 @@ struct thread *qpim_mroute_socket_reader = NULL; int qpim_mroute_oif_highest_vif_index = -1; struct list *qpim_channel_oil_list = NULL; int qpim_t_periodic = PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */ -struct list *qpim_upstream_list = NULL; struct zclient *qpim_zclient_update = NULL; struct pim_assert_metric qpim_infinite_assert_metric; long qpim_rpf_cache_refresh_delay_msec = 2000; @@ -86,8 +85,7 @@ static void pim_free() if (qpim_channel_oil_list) list_free(qpim_channel_oil_list); - if (qpim_upstream_list) - list_free(qpim_upstream_list); + pim_upstream_terminate (); if (qpim_static_route_list) list_free(qpim_static_route_list); @@ -116,24 +114,6 @@ pim_channel_oil_compare (struct channel_oil *c1, struct channel_oil *c2) return 0; } -static int -pim_upstream_compare (struct pim_upstream *up1, struct pim_upstream *up2) -{ - if (ntohl(up1->sg.grp.s_addr) < ntohl(up2->sg.grp.s_addr)) - return -1; - - if (ntohl(up1->sg.grp.s_addr) > ntohl(up2->sg.grp.s_addr)) - return 1; - - if (ntohl(up1->sg.src.s_addr) < ntohl(up2->sg.src.s_addr)) - return -1; - - if (ntohl(up1->sg.src.s_addr) > ntohl(up2->sg.src.s_addr)) - return 1; - - return 0; -} - void pim_init() { srandom(time(NULL)); @@ -159,15 +139,7 @@ void pim_init() qpim_channel_oil_list->del = (void (*)(void *)) pim_channel_oil_free; qpim_channel_oil_list->cmp = (int (*)(void *, void *)) pim_channel_oil_compare; - qpim_upstream_list = list_new(); - if (!qpim_upstream_list) { - zlog_err("%s %s: failure: upstream_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - pim_free(); - return; - } - qpim_upstream_list->del = (void (*)(void *)) pim_upstream_free; - qpim_upstream_list->cmp = (int (*)(void *, void *)) pim_upstream_compare; + pim_upstream_init (); qpim_static_route_list = list_new(); if (!qpim_static_route_list) { diff --git a/pimd/pimd.h b/pimd/pimd.h index 46b3e5ce78..f435072325 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -97,7 +97,6 @@ int qpim_mroute_oif_highest_vif_index; struct list *qpim_channel_oil_list; /* list of struct channel_oil */ struct in_addr qpim_all_pim_routers_addr; int qpim_t_periodic; /* Period between Join/Prune Messages */ -struct list *qpim_upstream_list; /* list of struct pim_upstream */ struct zclient *qpim_zclient_update; struct pim_assert_metric qpim_infinite_assert_metric; long qpim_rpf_cache_refresh_delay_msec; From 040d86ade76e3791ea42d25a2b0261791e2f579b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 13 Oct 2016 08:34:48 -0400 Subject: [PATCH 209/386] pimd: Create channel_oil hash for quicker lookup When looking up the channel_oil use a hash to find it. Keep the list around for quick walks of the channel oils. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 10 ++--- pimd/pim_oil.c | 95 +++++++++++++++++++++++++++++++++++++++------ pimd/pim_oil.h | 5 +++ pimd/pim_upstream.c | 3 +- pimd/pim_zebra.c | 2 +- pimd/pimd.c | 31 +-------------- pimd/pimd.h | 1 - 7 files changed, 99 insertions(+), 48 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index a12a7a230e..5ea8887faf 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1311,7 +1311,7 @@ pim_show_state(struct vty *vty, const char *src_or_group, const char *group, u_c vty_out(vty, "%sSource Group IIF OIL%s", VTY_NEWLINE, VTY_NEWLINE); } - for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) { + for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { char grp_str[100]; char src_str[100]; char in_ifname[16]; @@ -2232,7 +2232,7 @@ static void mroute_add_all() struct listnode *node; struct channel_oil *c_oil; - for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) { + for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { if (pim_mroute_add(c_oil)) { /* just log warning */ char source_str[100]; @@ -2251,7 +2251,7 @@ static void mroute_del_all() struct listnode *node; struct channel_oil *c_oil; - for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) { + for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { if (pim_mroute_del(c_oil)) { /* just log warning */ char source_str[100]; @@ -2829,7 +2829,7 @@ static void show_mroute(struct vty *vty, u_char uj) now = pim_time_monotonic_sec(); /* print list of PIM and IGMP routes */ - for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) { + for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { char grp_str[100]; char src_str[100]; char in_ifname[16]; @@ -3110,7 +3110,7 @@ static void show_mroute_count(struct vty *vty) VTY_NEWLINE); /* Print PIM and IGMP route counts */ - for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) { + for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { char group_str[100]; char source_str[100]; diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 9728d6304f..7fe4d8af32 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -25,6 +25,8 @@ #include "memory.h" #include "linklist.h" #include "if.h" +#include "hash.h" +#include "jhash.h" #include "pimd.h" #include "pim_oil.h" @@ -32,6 +34,75 @@ #include "pim_iface.h" #include "pim_time.h" +struct list *pim_channel_oil_list = NULL; +struct hash *pim_channel_oil_hash = NULL; + +static int +pim_channel_oil_compare (struct channel_oil *c1, struct channel_oil *c2) +{ + if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) < ntohl(c2->oil.mfcc_mcastgrp.s_addr)) + return -1; + + if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) > ntohl(c2->oil.mfcc_mcastgrp.s_addr)) + return 1; + + if (ntohl(c1->oil.mfcc_origin.s_addr) < ntohl(c2->oil.mfcc_origin.s_addr)) + return -1; + + if (ntohl(c1->oil.mfcc_origin.s_addr) > ntohl(c2->oil.mfcc_origin.s_addr)) + return 1; + + return 0; +} + +static int +pim_oil_equal (const void *arg1, const void *arg2) +{ + const struct channel_oil *c1 = (const struct channel_oil *)arg1; + const struct channel_oil *c2 = (const struct channel_oil *)arg2; + + if ((c1->oil.mfcc_mcastgrp.s_addr == c2->oil.mfcc_mcastgrp.s_addr) && + (c2->oil.mfcc_origin.s_addr == c2->oil.mfcc_origin.s_addr)) + return 1; + + return 0; +} + +static unsigned int +pim_oil_hash_key (void *arg) +{ + struct channel_oil *oil = (struct channel_oil *)arg; + + return jhash_2words (oil->oil.mfcc_mcastgrp.s_addr, oil->oil.mfcc_origin.s_addr, 0); +} + +void +pim_oil_init (void) +{ + pim_channel_oil_hash = hash_create_size (8192, pim_oil_hash_key, + pim_oil_equal); + + pim_channel_oil_list = list_new(); + if (!pim_channel_oil_list) { + zlog_err("%s %s: failure: channel_oil_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return; + } + pim_channel_oil_list->del = (void (*)(void *)) pim_channel_oil_free; + pim_channel_oil_list->cmp = (int (*)(void *, void *)) pim_channel_oil_compare; +} + +void +pim_oil_terminate (void) +{ + if (pim_channel_oil_list) + list_free(pim_channel_oil_list); + pim_channel_oil_list = NULL; + + if (pim_channel_oil_hash) + hash_free (pim_upstream_hash); +} + void pim_channel_oil_free(struct channel_oil *c_oil) { XFREE(MTYPE_PIM_CHANNEL_OIL, c_oil); @@ -45,7 +116,8 @@ pim_del_channel_oil (struct channel_oil *c_oil) into pim_channel_oil_free() because the later is called by list_delete_all_node() */ - listnode_delete(qpim_channel_oil_list, c_oil); + listnode_delete(pim_channel_oil_list, c_oil); + hash_release (pim_channel_oil_hash, c_oil); pim_channel_oil_free(c_oil); } @@ -73,27 +145,28 @@ pim_add_channel_oil (struct prefix_sg *sg, c_oil->oil.mfcc_mcastgrp = sg->grp; c_oil->oil.mfcc_origin = sg->src; + c_oil = hash_get (pim_channel_oil_hash, c_oil, hash_alloc_intern); + c_oil->oil.mfcc_parent = input_vif_index; c_oil->oil_ref_count = 1; c_oil->installed = 0; - listnode_add_sort(qpim_channel_oil_list, c_oil); + listnode_add_sort(pim_channel_oil_list, c_oil); return c_oil; } static struct channel_oil *pim_find_channel_oil(struct prefix_sg *sg) { - struct listnode *node; - struct channel_oil *c_oil; + struct channel_oil *c_oil = NULL; + struct channel_oil lookup; - for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) { - if ((sg->grp.s_addr == c_oil->oil.mfcc_mcastgrp.s_addr) && - (sg->src.s_addr == c_oil->oil.mfcc_origin.s_addr)) - return c_oil; - } - - return 0; + lookup.oil.mfcc_mcastgrp = sg->grp; + lookup.oil.mfcc_origin = sg->src; + + c_oil = hash_lookup (pim_channel_oil_hash, &lookup); + + return c_oil; } struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg, diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index 4b23b211a9..0c99afb625 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -78,6 +78,11 @@ struct channel_oil { struct channel_counts cc; }; +extern struct list *pim_channel_oil_list; + +void pim_oil_init (void); +void pim_oil_terminate (void); + void pim_channel_oil_free(struct channel_oil *c_oil); struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg, int input_vif_index); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 88755ec9fd..a7e40da948 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1184,7 +1184,8 @@ pim_upstream_equal (const void *arg1, const void *arg2) return 0; } -void pim_upstream_init (void) +void +pim_upstream_init (void) { pim_upstream_hash = hash_create_size (8192, pim_upstream_hash_key, pim_upstream_equal); diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 6115bcbf6e..cd0dd5c452 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -519,7 +519,7 @@ void pim_scan_oil() qpim_scan_oil_last = pim_time_monotonic_sec(); ++qpim_scan_oil_events; - for (ALL_LIST_ELEMENTS(qpim_channel_oil_list, node, nextnode, c_oil)) + for (ALL_LIST_ELEMENTS(pim_channel_oil_list, node, nextnode, c_oil)) pim_scan_individual_oil (c_oil); } diff --git a/pimd/pimd.c b/pimd/pimd.c index 82ecdc9fc5..1608f2d07e 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -52,7 +52,6 @@ int qpim_mroute_socket_fd = -1; int64_t qpim_mroute_socket_creation = 0; /* timestamp of creation */ struct thread *qpim_mroute_socket_reader = NULL; int qpim_mroute_oif_highest_vif_index = -1; -struct list *qpim_channel_oil_list = NULL; int qpim_t_periodic = PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */ struct zclient *qpim_zclient_update = NULL; struct pim_assert_metric qpim_infinite_assert_metric; @@ -82,8 +81,7 @@ static void pim_free() { pim_ssmpingd_destroy(); - if (qpim_channel_oil_list) - list_free(qpim_channel_oil_list); + pim_oil_terminate (); pim_upstream_terminate (); @@ -96,24 +94,6 @@ static void pim_free() pim_route_map_terminate(); } -static int -pim_channel_oil_compare (struct channel_oil *c1, struct channel_oil *c2) -{ - if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) < ntohl(c2->oil.mfcc_mcastgrp.s_addr)) - return -1; - - if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) > ntohl(c2->oil.mfcc_mcastgrp.s_addr)) - return 1; - - if (ntohl(c1->oil.mfcc_origin.s_addr) < ntohl(c2->oil.mfcc_origin.s_addr)) - return -1; - - if (ntohl(c1->oil.mfcc_origin.s_addr) > ntohl(c2->oil.mfcc_origin.s_addr)) - return 1; - - return 0; -} - void pim_init() { srandom(time(NULL)); @@ -130,14 +110,7 @@ void pim_init() return; } - qpim_channel_oil_list = list_new(); - if (!qpim_channel_oil_list) { - zlog_err("%s %s: failure: channel_oil_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return; - } - qpim_channel_oil_list->del = (void (*)(void *)) pim_channel_oil_free; - qpim_channel_oil_list->cmp = (int (*)(void *, void *)) pim_channel_oil_compare; + pim_oil_init (); pim_upstream_init (); diff --git a/pimd/pimd.h b/pimd/pimd.h index f435072325..fb9cb14ca1 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -94,7 +94,6 @@ int qpim_mroute_socket_fd; int64_t qpim_mroute_socket_creation; /* timestamp of creation */ struct thread *qpim_mroute_socket_reader; int qpim_mroute_oif_highest_vif_index; -struct list *qpim_channel_oil_list; /* list of struct channel_oil */ struct in_addr qpim_all_pim_routers_addr; int qpim_t_periodic; /* Period between Join/Prune Messages */ struct zclient *qpim_zclient_update; From b1d15e151a3a640d6b0bb4c6f47eeb85f12f946b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 13 Oct 2016 11:31:07 -0400 Subject: [PATCH 210/386] pimd: Allow mroute to return if incoming interface comes back If the incoming interface comes back, reinstall the channel oil if the mroute is not installed. Signed-off-by: Donald Sharp --- pimd/pim_zebra.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index cd0dd5c452..e8460044e1 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -450,6 +450,9 @@ pim_scan_individual_oil (struct channel_oil *c_oil) if (input_iface_vif_index == c_oil->oil.mfcc_parent) { + if (!c_oil->installed) + pim_mroute_add (c_oil); + /* RPF unchanged */ return; } From eb7a976a9d89f49ce455b1394fa64d08fbc2af39 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 17 Oct 2016 20:10:12 -0400 Subject: [PATCH 211/386] pimd: Allow debugs entered in conf t mode to persist When entering debug commands under 'conf t' mode allow the debugs to be saved for future fun and adventure. Ticket: CM-13213 Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 5ea8887faf..e9b3a4e131 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -67,6 +67,13 @@ static struct cmd_node interface_node = { 1 /* vtysh ? yes */ }; +static struct cmd_node debug_node = +{ + DEBUG_NODE, + "", + 1 +}; + static void pim_if_membership_clear(struct interface *ifp) { struct pim_interface *pim_ifp; @@ -5705,6 +5712,8 @@ void pim_cmd_init() install_node (&interface_node, pim_interface_config_write); /* INTERFACE_NODE */ if_cmd_init (); + install_node (&debug_node, pim_debug_config_write); + install_element (CONFIG_NODE, &ip_multicast_routing_cmd); install_element (CONFIG_NODE, &no_ip_multicast_routing_cmd); install_element (CONFIG_NODE, &ip_pim_rp_cmd); From b05b72e80b840fd8628b890cb6fa5c8ca7d73dd3 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Thu, 20 Oct 2016 13:34:29 +0000 Subject: [PATCH 212/386] pimd: add support for IGMPv2 Signed-off-by: Daniel Walton Ticket: CM-7962 --- pimd/Makefile.am | 4 +- pimd/pim_cmd.c | 76 +++++- pimd/pim_iface.c | 1 + pimd/pim_iface.h | 1 + pimd/pim_igmp.c | 592 +++++++++------------------------------------- pimd/pim_igmp.h | 20 ++ pimd/pim_igmpv2.c | 190 +++++++++++++++ pimd/pim_igmpv2.h | 41 ++++ pimd/pim_igmpv3.c | 467 ++++++++++++++++++++++++++---------- pimd/pim_igmpv3.h | 44 ++-- pimd/pim_mroute.c | 114 ++++++--- pimd/pim_vty.c | 9 + 12 files changed, 889 insertions(+), 670 deletions(-) create mode 100644 pimd/pim_igmpv2.c create mode 100644 pimd/pim_igmpv2.h diff --git a/pimd/Makefile.am b/pimd/Makefile.am index 07679f2794..bb3d1844c5 100644 --- a/pimd/Makefile.am +++ b/pimd/Makefile.am @@ -48,7 +48,7 @@ noinst_PROGRAMS = test_igmpv3_join libpim_a_SOURCES = \ pim_memory.c \ pimd.c pim_version.c pim_cmd.c pim_signals.c pim_iface.c \ - pim_vty.c pim_igmp.c pim_sock.c pim_zebra.c \ + pim_vty.c pim_igmp.c pim_sock.c pim_zebra.c pim_igmpv2.c \ pim_igmpv3.c pim_str.c pim_mroute.c pim_util.c pim_time.c \ pim_oil.c pim_zlookup.c pim_pim.c pim_tlv.c pim_neighbor.c \ pim_hello.c pim_ifchannel.c pim_join.c pim_assert.c \ @@ -60,7 +60,7 @@ libpim_a_SOURCES = \ noinst_HEADERS = \ pim_memory.h \ pimd.h pim_version.h pim_cmd.h pim_signals.h pim_iface.h \ - pim_vty.h pim_igmp.h pim_sock.h pim_zebra.h \ + pim_vty.h pim_igmp.h pim_sock.h pim_zebra.h pim_igmpv2.h \ pim_igmpv3.h pim_str.h pim_mroute.h pim_util.h pim_time.h \ pim_oil.h pim_zlookup.h pim_pim.h pim_tlv.h pim_neighbor.h \ pim_hello.h pim_ifchannel.h pim_join.h pim_assert.h \ diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index e9b3a4e131..c6390271f1 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -510,7 +510,7 @@ static void igmp_show_interfaces(struct vty *vty, u_char uj) json = json_object_new_object(); else vty_out(vty, - "Interface State Address Querier Query Timer Uptime%s", + "Interface State Address V Querier Query Timer Uptime%s", VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { @@ -534,6 +534,7 @@ static void igmp_show_interfaces(struct vty *vty, u_char uj) json_row = json_object_new_object(); json_object_pim_ifp_add(json_row, ifp); json_object_string_add(json_row, "upTime", uptime); + json_object_int_add(json_row, "version", pim_ifp->igmp_version); if (igmp->t_igmp_query_timer) { json_object_boolean_true_add(json_row, "querier"); @@ -543,10 +544,11 @@ static void igmp_show_interfaces(struct vty *vty, u_char uj) json_object_object_add(json, ifp->name, json_row); } else { - vty_out(vty, "%-9s %5s %15s %7s %11s %8s%s", + vty_out(vty, "%-9s %5s %15s %d %7s %11s %8s%s", ifp->name, if_is_up(ifp) ? "up" : "down", inet_ntoa(igmp->ifaddr), + pim_ifp->igmp_version, igmp->t_igmp_query_timer ? "local" : "other", query_hhmmss, uptime, @@ -627,12 +629,12 @@ static void igmp_show_interfaces_single(struct vty *vty, const char *ifname, u_c if (uj) { json_row = json_object_new_object(); json_object_pim_ifp_add(json_row, ifp); - json_object_string_add(json_row, "upTime", uptime); json_object_string_add(json_row, "querier", igmp->t_igmp_query_timer ? "local" : "other"); json_object_int_add(json_row, "queryStartCount", igmp->startup_query_count); json_object_string_add(json_row, "queryQueryTimer", query_hhmmss); json_object_string_add(json_row, "queryOtherTimer", other_hhmmss); + json_object_int_add(json_row, "version", pim_ifp->igmp_version); json_object_int_add(json_row, "timerGroupMembershipIntervalMsec", gmi_msec); json_object_int_add(json_row, "timerLastMemberQueryMsec", lmqt_msec); json_object_int_add(json_row, "timerOlderHostPresentIntervalMsec", ohpi_msec); @@ -649,6 +651,7 @@ static void igmp_show_interfaces_single(struct vty *vty, const char *ifname, u_c vty_out(vty, "State : %s%s", if_is_up(ifp) ? "up" : "down", VTY_NEWLINE); vty_out(vty, "Address : %s%s", inet_ntoa(pim_ifp->primary_address), VTY_NEWLINE); vty_out(vty, "Uptime : %s%s", uptime, VTY_NEWLINE); + vty_out(vty, "Version : %d%s", pim_ifp->igmp_version, VTY_NEWLINE); vty_out(vty, "%s", VTY_NEWLINE); vty_out(vty, "%s", VTY_NEWLINE); @@ -1974,10 +1977,13 @@ static void igmp_show_groups(struct vty *vty, u_char uj) json_row = json_object_new_object(); json_object_string_add(json_row, "source", ifaddr_str); json_object_string_add(json_row, "group", group_str); - json_object_string_add(json_row, "mode", grp->group_filtermode_isexcl ? "EXCLUDE" : "INCLUDE"); + + if (grp->igmp_version == 3) + json_object_string_add(json_row, "mode", grp->group_filtermode_isexcl ? "EXCLUDE" : "INCLUDE"); + json_object_string_add(json_row, "timer", hhmmss); json_object_int_add(json_row, "sourcesCount", grp->group_source_list ? listcount(grp->group_source_list) : 0); - json_object_int_add(json_row, "version", igmp_group_compat_mode(igmp, grp)); + json_object_int_add(json_row, "version", grp->igmp_version); json_object_string_add(json_row, "uptime", uptime); json_object_object_add(json_iface, group_str, json_row); @@ -1986,10 +1992,10 @@ static void igmp_show_groups(struct vty *vty, u_char uj) ifp->name, ifaddr_str, group_str, - grp->group_filtermode_isexcl ? "EXCL" : "INCL", + grp->igmp_version == 3 ? (grp->group_filtermode_isexcl ? "EXCL" : "INCL") : "----", hhmmss, grp->group_source_list ? listcount(grp->group_source_list) : 0, - igmp_group_compat_mode(igmp, grp), + grp->igmp_version, uptime, VTY_NEWLINE); } @@ -3914,6 +3920,56 @@ DEFUN (interface_no_ip_igmp_query_interval, return CMD_SUCCESS; } +DEFUN (interface_ip_igmp_version, + interface_ip_igmp_version_cmd, + "ip igmp version <2-3>", + IP_STR + IFACE_IGMP_STR + "IGMP version\n" + "IGMP version number\n") +{ + VTY_DECLVAR_CONTEXT(interface,ifp); + struct pim_interface *pim_ifp; + int igmp_version; + + pim_ifp = ifp->info; + + if (!pim_ifp) { + vty_out(vty, + "IGMP not enabled on interface %s. Please enable IGMP first.%s", + ifp->name, + VTY_NEWLINE); + return CMD_WARNING; + } + + igmp_version = atoi(argv[3]->arg); + pim_ifp->igmp_version = igmp_version; + + return CMD_SUCCESS; +} + +DEFUN (interface_no_ip_igmp_version, + interface_no_ip_igmp_version_cmd, + "no ip igmp version <2-3>", + NO_STR + IP_STR + IFACE_IGMP_STR + "IGMP version\n" + "IGMP version number\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp; + + pim_ifp = ifp->info; + + if (!pim_ifp) + return CMD_SUCCESS; + + pim_ifp->igmp_version = IGMP_DEFAULT_VERSION; + + return CMD_SUCCESS; +} + #define IGMP_QUERY_MAX_RESPONSE_TIME_MIN (1) #define IGMP_QUERY_MAX_RESPONSE_TIME_MAX (25) @@ -5073,7 +5129,7 @@ DEFUN (test_igmp_receive_report, igmp_msg = buf + ip_hlen; group_record = igmp_msg + IGMP_V3_REPORT_GROUPPRECORD_OFFSET; *igmp_msg = PIM_IGMP_V3_MEMBERSHIP_REPORT; /* type */ - *(uint16_t *) (igmp_msg + IGMP_V3_CHECKSUM_OFFSET) = 0; /* for computing checksum */ + *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET) = 0; /* for computing checksum */ *(uint16_t *) (igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET) = htons(1); /* one group record */ *(uint8_t *) (group_record + IGMP_V3_GROUP_RECORD_TYPE_OFFSET) = record_type; memcpy(group_record + IGMP_V3_GROUP_RECORD_GROUP_OFFSET, &grp_addr, sizeof(struct in_addr)); @@ -5097,7 +5153,7 @@ DEFUN (test_igmp_receive_report, igmp_msg_len = IGMP_V3_MSG_MIN_SIZE + (num_sources << 4); /* v3 report for one single group record */ /* compute checksum */ - *(uint16_t *)(igmp_msg + IGMP_V3_CHECKSUM_OFFSET) = in_cksum(igmp_msg, igmp_msg_len); + *(uint16_t *)(igmp_msg + IGMP_CHECKSUM_OFFSET) = in_cksum(igmp_msg, igmp_msg_len); /* "receive" message */ @@ -5731,6 +5787,8 @@ void pim_cmd_init() install_element (INTERFACE_NODE, &interface_no_ip_igmp_cmd); install_element (INTERFACE_NODE, &interface_ip_igmp_join_cmd); install_element (INTERFACE_NODE, &interface_no_ip_igmp_join_cmd); + install_element (INTERFACE_NODE, &interface_ip_igmp_version_cmd); + install_element (INTERFACE_NODE, &interface_no_ip_igmp_version_cmd); install_element (INTERFACE_NODE, &interface_ip_igmp_query_interval_cmd); install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_interval_cmd); install_element (INTERFACE_NODE, &interface_ip_igmp_query_max_response_time_cmd); diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index b6012d1ed1..ceab93edff 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -106,6 +106,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim) pim_ifp->options = 0; pim_ifp->mroute_vif_index = -1; + pim_ifp->igmp_version = IGMP_DEFAULT_VERSION; pim_ifp->igmp_default_robustness_variable = IGMP_DEFAULT_ROBUSTNESS_VARIABLE; pim_ifp->igmp_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL; pim_ifp->igmp_query_max_response_time_dsec = IGMP_QUERY_MAX_RESPONSE_TIME_DSEC; diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index 0be4918d72..87530c6026 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -65,6 +65,7 @@ struct pim_interface { ifindex_t mroute_vif_index; struct in_addr primary_address; /* remember addr to detect change */ + int igmp_version; /* IGMP version */ int igmp_default_robustness_variable; /* IGMPv3 QRV */ int igmp_default_query_interval; /* IGMPv3 secs between general queries */ int igmp_query_max_response_time_dsec; /* IGMPv3 Max Response Time in dsecs for general queries */ diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index e14ff29225..56f2457f97 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -27,6 +27,7 @@ #include "pimd.h" #include "pim_igmp.h" +#include "pim_igmpv2.h" #include "pim_igmpv3.h" #include "pim_iface.h" #include "pim_sock.h" @@ -36,34 +37,31 @@ #include "pim_time.h" #include "pim_zebra.h" -#define IGMP_GRP_REC_TYPE_MODE_IS_INCLUDE (1) -#define IGMP_GRP_REC_TYPE_MODE_IS_EXCLUDE (2) -#define IGMP_GRP_REC_TYPE_CHANGE_TO_INCLUDE_MODE (3) -#define IGMP_GRP_REC_TYPE_CHANGE_TO_EXCLUDE_MODE (4) -#define IGMP_GRP_REC_TYPE_ALLOW_NEW_SOURCES (5) -#define IGMP_GRP_REC_TYPE_BLOCK_OLD_SOURCES (6) - static void group_timer_off(struct igmp_group *group); +/* This socket is used for TXing IGMP packets only, IGMP RX happens + * in pim_mroute_msg() + */ static int igmp_sock_open(struct in_addr ifaddr, ifindex_t ifindex, uint32_t pim_options) { int fd; int join = 0; struct in_addr group; - fd = pim_socket_mcast(IPPROTO_IGMP, ifaddr, ifindex, 1 /* loop=true */); + fd = pim_socket_mcast(IPPROTO_IGMP, ifaddr, ifindex, 0 /* loop=false */); + if (fd < 0) return -1; if (PIM_IF_TEST_IGMP_LISTEN_ALLROUTERS(pim_options)) { if (inet_aton(PIM_ALL_ROUTERS, &group)) { if (!pim_socket_join(fd, group, ifaddr, ifindex)) - ++join; + ++join; } else { zlog_warn("%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), - PIM_ALL_ROUTERS, errno, safe_strerror(errno)); + __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), + PIM_ALL_ROUTERS, errno, safe_strerror(errno)); } } @@ -77,8 +75,8 @@ static int igmp_sock_open(struct in_addr ifaddr, ifindex_t ifindex, uint32_t pim } else { zlog_warn("%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), - PIM_ALL_SYSTEMS, errno, safe_strerror(errno)); + __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), + PIM_ALL_SYSTEMS, errno, safe_strerror(errno)); } if (inet_aton(PIM_ALL_IGMP_ROUTERS, &group)) { @@ -88,13 +86,13 @@ static int igmp_sock_open(struct in_addr ifaddr, ifindex_t ifindex, uint32_t pim } else { zlog_warn("%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), - PIM_ALL_IGMP_ROUTERS, errno, safe_strerror(errno)); + __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), + PIM_ALL_IGMP_ROUTERS, errno, safe_strerror(errno)); } if (!join) { zlog_err("IGMP socket fd=%d could not join any group on interface address %s", - fd, inet_ntoa(ifaddr)); + fd, inet_ntoa(ifaddr)); close(fd); fd = -1; } @@ -271,31 +269,27 @@ void pim_igmp_other_querier_timer_off(struct igmp_sock *igmp) zassert(!igmp->t_other_querier_timer); } -static int recv_igmp_query(struct igmp_sock *igmp, int query_version, - int max_resp_code, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len) +static int +igmp_recv_query(struct igmp_sock *igmp, int query_version, + int max_resp_code, + struct in_addr from, const char *from_str, + char *igmp_msg, int igmp_msg_len) { struct interface *ifp; struct pim_interface *pim_ifp; - uint8_t resv_s_qrv = 0; - uint8_t s_flag = 0; - uint8_t qrv = 0; struct in_addr group_addr; uint16_t recv_checksum; uint16_t checksum; - int i; - //group_addr = *(struct in_addr *)(igmp_msg + 4); memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); ifp = igmp->interface; pim_ifp = ifp->info; - recv_checksum = *(uint16_t *) (igmp_msg + IGMP_V3_CHECKSUM_OFFSET); + recv_checksum = *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET); /* for computing checksum */ - *(uint16_t *) (igmp_msg + IGMP_V3_CHECKSUM_OFFSET) = 0; + *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET) = 0; checksum = in_cksum(igmp_msg, igmp_msg_len); if (checksum != recv_checksum) { @@ -304,12 +298,33 @@ static int recv_igmp_query(struct igmp_sock *igmp, int query_version, return -1; } + /* RFC 3376 defines some guidelines on operating in backwards compatibility + * with older versions of IGMP but there are some gaps in the logic: + * + * - once we drop from say version 3 to version 2 we will never go back to + * version 3 even if the node that TXed an IGMP v2 query upgrades to v3 + * + * - The node with the lowest IP is the querier so we will only know to drop + * from v3 to v2 if the node that is the querier is also the one that is + * running igmp v2. If a non-querier only supports igmp v2 we will have + * no way of knowing. + * + * For now we will simplify things and inform the user that they need to + * configure all PIM routers to use the same version of IGMP. + */ + if (query_version != pim_ifp->igmp_version) { + zlog_warn("Recv IGMP query v%d from %s on %s but we are using v%d, please " + "configure all PIM routers on this subnet to use the same " + "IGMP version", + query_version, from_str, ifp->name, pim_ifp->igmp_version); + return 0; + } + if (PIM_DEBUG_IGMP_PACKETS) { char group_str[100]; pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - zlog_debug("Recv IGMP query v%d from %s on %s: size=%d checksum=%x group=%s", - query_version, from_str, ifp->name, - igmp_msg_len, checksum, group_str); + zlog_debug("Recv IGMP query v%d from %s on %s for group %s", + query_version, from_str, ifp->name, group_str); } /* @@ -321,7 +336,7 @@ static int recv_igmp_query(struct igmp_sock *igmp, int query_version, elected querier. */ if (ntohl(from.s_addr) < ntohl(igmp->ifaddr.s_addr)) { - + if (PIM_DEBUG_IGMP_TRACE) { char ifaddr_str[100]; pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); @@ -334,272 +349,11 @@ static int recv_igmp_query(struct igmp_sock *igmp, int query_version, pim_igmp_other_querier_timer_on(igmp); } + /* IGMP version 3 is the only one where we process the RXed query */ if (query_version == 3) { - /* - RFC 3376: 4.1.6. QRV (Querier's Robustness Variable) - - Routers adopt the QRV value from the most recently received Query - as their own [Robustness Variable] value, unless that most - recently received QRV was zero, in which case the receivers use - the default [Robustness Variable] value specified in section 8.1 - or a statically configured value. - */ - resv_s_qrv = igmp_msg[8]; - qrv = 7 & resv_s_qrv; - igmp->querier_robustness_variable = qrv ? qrv : pim_ifp->igmp_default_robustness_variable; + igmp_v3_recv_query(igmp, from_str, igmp_msg); } - /* - RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code) - - Multicast routers that are not the current querier adopt the QQI - value from the most recently received Query as their own [Query - Interval] value, unless that most recently received QQI was zero, - in which case the receiving routers use the default. - */ - if (igmp->t_other_querier_timer && query_version == 3) { - /* other querier present */ - uint8_t qqic; - uint16_t qqi; - qqic = igmp_msg[9]; - qqi = igmp_msg_decode8to16(qqic); - igmp->querier_query_interval = qqi ? qqi : pim_ifp->igmp_default_query_interval; - - if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[100]; - pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("Querier %s new query interval is %s QQI=%u sec (recv QQIC=%02x from %s)", - ifaddr_str, - qqi ? "recv-non-default" : "default", - igmp->querier_query_interval, - qqic, - from_str); - } - } - - /* - RFC 3376: 6.6.1. Timer Updates - - When a router sends or receives a query with a clear Suppress - Router-Side Processing flag, it must update its timers to reflect - the correct timeout values for the group or sources being queried. - - General queries don't trigger timer update. - */ - if (query_version == 3) { - s_flag = (1 << 3) & resv_s_qrv; - } - else { - /* Neither V1 nor V2 have this field. Pimd should really go into - * a compatibility mode here and run as V2 (or V1) but it doesn't - * so for now, lets just set the flag to suppress these timer updates. - */ - s_flag = 1; - } - - if (!s_flag) { - /* s_flag is clear */ - - if (PIM_INADDR_IS_ANY(group_addr)) { - /* this is a general query */ - - /* log that general query should have the s_flag set */ - zlog_warn("General IGMP query v%d from %s on %s: Suppress Router-Side Processing flag is clear", - query_version, from_str, ifp->name); - } - else { - struct igmp_group *group; - - /* this is a non-general query: perform timer updates */ - - group = find_group_by_addr(igmp, group_addr); - if (group) { - int recv_num_sources = ntohs(*(uint16_t *)(igmp_msg + IGMP_V3_NUMSOURCES_OFFSET)); - - /* - RFC 3376: 6.6.1. Timer Updates - Query Q(G,A): Source Timer for sources in A are lowered to LMQT - Query Q(G): Group Timer is lowered to LMQT - */ - if (recv_num_sources < 1) { - /* Query Q(G): Group Timer is lowered to LMQT */ - - igmp_group_timer_lower_to_lmqt(group); - } - else { - /* Query Q(G,A): Source Timer for sources in A are lowered to LMQT */ - - /* Scan sources in query and lower their timers to LMQT */ - struct in_addr *sources = (struct in_addr *)(igmp_msg + IGMP_V3_SOURCES_OFFSET); - for (i = 0; i < recv_num_sources; ++i) { - //struct in_addr src_addr = sources[i]; - //struct igmp_source *src = igmp_find_source_by_addr(group, src_addr); - struct in_addr src_addr; - struct igmp_source *src; - memcpy(&src_addr, sources + i, sizeof(struct in_addr)); - src = igmp_find_source_by_addr(group, src_addr); - if (src) { - igmp_source_timer_lower_to_lmqt(src); - } - } - } - - } - else { - char group_str[100]; - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - zlog_warn("IGMP query v%d from %s on %s: could not find group %s for timer update", - query_version, from_str, ifp->name, group_str); - } - } - } /* s_flag is clear: timer updates */ - - return 0; -} - -static int igmp_v3_report(struct igmp_sock *igmp, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len) -{ - uint16_t recv_checksum; - uint16_t checksum; - int num_groups; - uint8_t *group_record; - uint8_t *report_pastend = (uint8_t *) igmp_msg + igmp_msg_len; - struct interface *ifp = igmp->interface; - int i; - int local_ncb = 0; - - if (igmp_msg_len < IGMP_V3_MSG_MIN_SIZE) { - zlog_warn("Recv IGMP report v3 from %s on %s: size=%d shorter than minimum=%d", - from_str, ifp->name, igmp_msg_len, IGMP_V3_MSG_MIN_SIZE); - return -1; - } - - recv_checksum = *(uint16_t *) (igmp_msg + IGMP_V3_CHECKSUM_OFFSET); - - /* for computing checksum */ - *(uint16_t *) (igmp_msg + IGMP_V3_CHECKSUM_OFFSET) = 0; - - checksum = in_cksum(igmp_msg, igmp_msg_len); - if (checksum != recv_checksum) { - zlog_warn("Recv IGMP report v3 from %s on %s: checksum mismatch: received=%x computed=%x", - from_str, ifp->name, recv_checksum, checksum); - return -1; - } - - num_groups = ntohs(*(uint16_t *) (igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET)); - if (num_groups < 1) { - zlog_warn("Recv IGMP report v3 from %s on %s: missing group records", - from_str, ifp->name); - return -1; - } - - if (PIM_DEBUG_IGMP_PACKETS) { - zlog_debug("Recv IGMP report v3 from %s on %s: size=%d checksum=%x groups=%d", - from_str, ifp->name, igmp_msg_len, checksum, num_groups); - } - - group_record = (uint8_t *) igmp_msg + IGMP_V3_REPORT_GROUPPRECORD_OFFSET; - - /* Scan groups */ - for (i = 0; i < num_groups; ++i) { - struct in_addr rec_group; - uint8_t *sources; - uint8_t *src; - int rec_type; - int rec_auxdatalen; - int rec_num_sources; - int j; - struct prefix lncb; - struct prefix g; - - if ((group_record + IGMP_V3_GROUP_RECORD_MIN_SIZE) > report_pastend) { - zlog_warn("Recv IGMP report v3 from %s on %s: group record beyond report end", - from_str, ifp->name); - return -1; - } - - rec_type = group_record[IGMP_V3_GROUP_RECORD_TYPE_OFFSET]; - rec_auxdatalen = group_record[IGMP_V3_GROUP_RECORD_AUXDATALEN_OFFSET]; - rec_num_sources = ntohs(* (uint16_t *) (group_record + IGMP_V3_GROUP_RECORD_NUMSOURCES_OFFSET)); - - //rec_group = *(struct in_addr *)(group_record + IGMP_V3_GROUP_RECORD_GROUP_OFFSET); - memcpy(&rec_group, group_record + IGMP_V3_GROUP_RECORD_GROUP_OFFSET, sizeof(struct in_addr)); - - if (PIM_DEBUG_IGMP_PACKETS) { - zlog_debug("Recv IGMP report v3 from %s on %s: record=%d type=%d auxdatalen=%d sources=%d group=%s", - from_str, ifp->name, i, rec_type, rec_auxdatalen, rec_num_sources, inet_ntoa(rec_group)); - } - - /* Scan sources */ - - sources = group_record + IGMP_V3_GROUP_RECORD_SOURCE_OFFSET; - - for (j = 0, src = sources; j < rec_num_sources; ++j, src += 4) { - - if ((src + 4) > report_pastend) { - zlog_warn("Recv IGMP report v3 from %s on %s: group source beyond report end", - from_str, ifp->name); - return -1; - } - - if (PIM_DEBUG_IGMP_PACKETS) { - char src_str[200]; - - if (!inet_ntop(AF_INET, src, src_str , sizeof(src_str))) - sprintf(src_str, ""); - - zlog_debug("Recv IGMP report v3 from %s on %s: record=%d group=%s source=%s", - from_str, ifp->name, i, inet_ntoa(rec_group), src_str); - } - } /* for (sources) */ - - - lncb.family = AF_INET; - lncb.u.prefix4.s_addr = 0x000000E0; - lncb.prefixlen = 24; - - g.family = AF_INET; - g.u.prefix4 = rec_group; - g.prefixlen = 32; - /* - * If we receive a igmp report with the group in 224.0.0.0/24 - * then we should ignore it - */ - if (prefix_match(&lncb, &g)) - local_ncb = 1; - - if (!local_ncb) - switch (rec_type) { - case IGMP_GRP_REC_TYPE_MODE_IS_INCLUDE: - igmpv3_report_isin(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); - break; - case IGMP_GRP_REC_TYPE_MODE_IS_EXCLUDE: - igmpv3_report_isex(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); - break; - case IGMP_GRP_REC_TYPE_CHANGE_TO_INCLUDE_MODE: - igmpv3_report_toin(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); - break; - case IGMP_GRP_REC_TYPE_CHANGE_TO_EXCLUDE_MODE: - igmpv3_report_toex(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); - break; - case IGMP_GRP_REC_TYPE_ALLOW_NEW_SOURCES: - igmpv3_report_allow(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); - break; - case IGMP_GRP_REC_TYPE_BLOCK_OLD_SOURCES: - igmpv3_report_block(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); - break; - default: - zlog_warn("Recv IGMP report v3 from %s on %s: unknown record type: type=%d", - from_str, ifp->name, rec_type); - } - - group_record += 8 + (rec_num_sources << 2) + (rec_auxdatalen << 2); - local_ncb = 0; - - } /* for (group records) */ - return 0; } @@ -614,66 +368,10 @@ static void on_trace(const char *label, } } -static int igmp_v2_report(struct igmp_sock *igmp, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len) -{ - struct interface *ifp = igmp->interface; - struct igmp_group *group; - struct in_addr group_addr; - - on_trace(__PRETTY_FUNCTION__, igmp->interface, from); - - if (igmp_msg_len != IGMP_V12_MSG_SIZE) { - zlog_warn("Recv IGMP report v2 from %s on %s: size=%d other than correct=%d", - from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); - return -1; - } - - if (PIM_DEBUG_IGMP_TRACE) { - zlog_warn("%s %s: FIXME WRITEME", - __FILE__, __PRETTY_FUNCTION__); - } - - //group_addr = *(struct in_addr *)(igmp_msg + 4); - memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); - - /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr); - if (!group) { - return -1; - } - - group->last_igmp_v2_report_dsec = pim_time_monotonic_dsec(); - - return 0; -} - -static int igmp_v2_leave(struct igmp_sock *igmp, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len) -{ - struct interface *ifp = igmp->interface; - - on_trace(__PRETTY_FUNCTION__, igmp->interface, from); - - if (igmp_msg_len != IGMP_V12_MSG_SIZE) { - zlog_warn("Recv IGMP leave v2 from %s on %s: size=%d other than correct=%d", - from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); - return -1; - } - - if (PIM_DEBUG_IGMP_TRACE) { - zlog_warn("%s %s: FIXME WRITEME", - __FILE__, __PRETTY_FUNCTION__); - } - - return 0; -} - -static int igmp_v1_report(struct igmp_sock *igmp, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len) +static int +igmp_v1_recv_report (struct igmp_sock *igmp, + struct in_addr from, const char *from_str, + char *igmp_msg, int igmp_msg_len) { struct interface *ifp = igmp->interface; struct igmp_group *group; @@ -692,7 +390,6 @@ static int igmp_v1_report(struct igmp_sock *igmp, __FILE__, __PRETTY_FUNCTION__); } - //group_addr = *(struct in_addr *)(igmp_msg + 4); memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); /* non-existant group is created as INCLUDE {empty} */ @@ -791,26 +488,26 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len) return -1; } - return recv_igmp_query(igmp, query_version, max_resp_code, + return igmp_recv_query(igmp, query_version, max_resp_code, ip_hdr->ip_src, from_str, igmp_msg, igmp_msg_len); } case PIM_IGMP_V3_MEMBERSHIP_REPORT: - return igmp_v3_report(igmp, ip_hdr->ip_src, from_str, - igmp_msg, igmp_msg_len); + return igmp_v3_recv_report(igmp, ip_hdr->ip_src, from_str, + igmp_msg, igmp_msg_len); case PIM_IGMP_V2_MEMBERSHIP_REPORT: - return igmp_v2_report(igmp, ip_hdr->ip_src, from_str, - igmp_msg, igmp_msg_len); + return igmp_v2_recv_report(igmp, ip_hdr->ip_src, from_str, + igmp_msg, igmp_msg_len); case PIM_IGMP_V1_MEMBERSHIP_REPORT: - return igmp_v1_report(igmp, ip_hdr->ip_src, from_str, - igmp_msg, igmp_msg_len); + return igmp_v1_recv_report(igmp, ip_hdr->ip_src, from_str, + igmp_msg, igmp_msg_len); case PIM_IGMP_V2_LEAVE_GROUP: - return igmp_v2_leave(igmp, ip_hdr->ip_src, from_str, - igmp_msg, igmp_msg_len); + return igmp_v2_recv_leave(igmp, ip_hdr->ip_src, from_str, + igmp_msg, igmp_msg_len); } zlog_warn("Ignoring unsupported IGMP message type: %d", msg_type); @@ -895,11 +592,11 @@ void pim_igmp_general_query_off(struct igmp_sock *igmp) /* Issue IGMP general query */ static int pim_igmp_general_query(struct thread *t) { - char query_buf[PIM_IGMP_BUFSIZE_WRITE]; struct igmp_sock *igmp; struct in_addr dst_addr; struct in_addr group_addr; struct pim_interface *pim_ifp; + int query_buf_size; zassert(t); @@ -911,6 +608,14 @@ static int pim_igmp_general_query(struct thread *t) pim_ifp = igmp->interface->info; + if (pim_ifp->igmp_version == 3) { + query_buf_size = PIM_IGMP_BUFSIZE_WRITE; + } else { + query_buf_size = IGMP_V12_MSG_SIZE; + } + + char query_buf[query_buf_size]; + /* RFC3376: 4.1.12. IP Destination Addresses for Queries @@ -933,124 +638,25 @@ static int pim_igmp_general_query(struct thread *t) querier_str, dst_str, igmp->interface->name); } - pim_igmp_send_membership_query(0 /* igmp_group */, - igmp->fd, - igmp->interface->name, - query_buf, - sizeof(query_buf), - 0 /* num_sources */, - dst_addr, - group_addr, - pim_ifp->igmp_query_max_response_time_dsec, - 1 /* s_flag: always set for general queries */, - igmp->querier_robustness_variable, - igmp->querier_query_interval); + igmp_send_query (pim_ifp->igmp_version, + 0 /* igmp_group */, + igmp->fd, + igmp->interface->name, + query_buf, + sizeof(query_buf), + 0 /* num_sources */, + dst_addr, + group_addr, + pim_ifp->igmp_query_max_response_time_dsec, + 1 /* s_flag: always set for general queries */, + igmp->querier_robustness_variable, + igmp->querier_query_interval); pim_igmp_general_query_on(igmp); return 0; } -static int pim_igmp_read(struct thread *t); - -static void igmp_read_on(struct igmp_sock *igmp) -{ - zassert(igmp); - - if (PIM_DEBUG_IGMP_TRACE_DETAIL) { - zlog_debug("Scheduling READ event on IGMP socket fd=%d", - igmp->fd); - } - igmp->t_igmp_read = NULL; - zassert(!igmp->t_igmp_read); - THREAD_READ_ON(master, igmp->t_igmp_read, pim_igmp_read, igmp, igmp->fd); -} - -static int pim_igmp_read(struct thread *t) -{ - struct igmp_sock *igmp; - int fd; - struct sockaddr_in from; - struct sockaddr_in to; - socklen_t fromlen = sizeof(from); - socklen_t tolen = sizeof(to); - uint8_t buf[PIM_IGMP_BUFSIZE_READ]; - int len; - ifindex_t ifindex = -1; - int result = -1; /* defaults to bad */ - - zassert(t); - - igmp = THREAD_ARG(t); - - zassert(igmp); - - fd = THREAD_FD(t); - - zassert(fd == igmp->fd); - - len = pim_socket_recvfromto(fd, buf, sizeof(buf), - &from, &fromlen, - &to, &tolen, - &ifindex); - if (len < 0) { - zlog_warn("Failure receiving IP IGMP packet on fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - goto done; - } - - if (PIM_DEBUG_IGMP_PACKETS) { - char from_str[100]; - char to_str[100]; - - if (!inet_ntop(AF_INET, &from.sin_addr, from_str, sizeof(from_str))) - sprintf(from_str, ""); - if (!inet_ntop(AF_INET, &to.sin_addr, to_str, sizeof(to_str))) - sprintf(to_str, ""); - - zlog_debug("Recv IP IGMP pkt size=%d from %s to %s on fd=%d on ifindex=%d (sock_ifindex=%d)", - len, from_str, to_str, fd, ifindex, igmp->interface->ifindex); - } - -#ifdef PIM_CHECK_RECV_IFINDEX_SANITY - /* ifindex sanity check */ - if (ifindex != igmp->interface->ifindex) { - char from_str[100]; - char to_str[100]; - struct interface *ifp; - - if (!inet_ntop(AF_INET, &from.sin_addr, from_str , sizeof(from_str))) - sprintf(from_str, ""); - if (!inet_ntop(AF_INET, &to.sin_addr, to_str , sizeof(to_str))) - sprintf(to_str, ""); - - ifp = if_lookup_by_index(ifindex); - if (ifp) { - zassert(ifindex == ifp->ifindex); - } - -#ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH - zlog_warn("Interface mismatch: recv IGMP pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)", - from_str, to_str, fd, - ifindex, ifp ? ifp->name : "", - igmp->interface->ifindex, igmp->interface->name); -#endif - goto done; - } -#endif - - if (pim_igmp_packet(igmp, (char *)buf, len)) { - goto done; - } - - result = 0; /* good */ - - done: - igmp_read_on(igmp); - - return result; -} - static void sock_close(struct igmp_sock *igmp) { pim_igmp_other_querier_timer_off(igmp); @@ -1219,8 +825,6 @@ static struct igmp_sock *igmp_sock_new(int fd, igmp->querier_query_interval = pim_ifp->igmp_default_query_interval; */ igmp_startup_mode_on(igmp); - - igmp_read_on(igmp); pim_igmp_general_query_on(igmp); return igmp; @@ -1421,6 +1025,7 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, group->last_igmp_v1_report_dsec = -1; group->last_igmp_v2_report_dsec = -1; group->group_creation = pim_time_monotonic_sec(); + group->igmp_version = IGMP_DEFAULT_VERSION; /* initialize new group as INCLUDE {empty} */ group->group_filtermode_isexcl = 0; /* 0=INCLUDE, 1=EXCLUDE */ @@ -1449,3 +1054,32 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, return group; } + +void +igmp_send_query (int igmp_version, + struct igmp_group *group, + int fd, + const char *ifname, + char *query_buf, + int query_buf_size, + int num_sources, + struct in_addr dst_addr, + struct in_addr group_addr, + int query_max_response_time_dsec, + uint8_t s_flag, + uint8_t querier_robustness_variable, + uint16_t querier_query_interval) +{ + if (igmp_version == 3) { + igmp_v3_send_query (group, fd, ifname, query_buf, + query_buf_size, num_sources, + dst_addr, group_addr, + query_max_response_time_dsec, s_flag, + querier_robustness_variable, + querier_query_interval); + } else if (igmp_version == 2) { + igmp_v2_send_query (group, fd, ifname, query_buf, + dst_addr, group_addr, + query_max_response_time_dsec); + } +} diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h index 2067bb30aa..fa2c255dd0 100644 --- a/pimd/pim_igmp.h +++ b/pimd/pim_igmp.h @@ -52,6 +52,7 @@ #define IGMP_V3_GROUP_RECORD_NUMSOURCES_OFFSET (2) #define IGMP_V3_GROUP_RECORD_GROUP_OFFSET (4) #define IGMP_V3_GROUP_RECORD_SOURCE_OFFSET (8) +#define IGMP_CHECKSUM_OFFSET (2) /* RFC 3376: 8.1. Robustness Variable - Default: 2 */ #define IGMP_DEFAULT_ROBUSTNESS_VARIABLE (2) @@ -65,6 +66,8 @@ /* RFC 3376: 8.8. Last Member Query Interval - Default: 10 deciseconds */ #define IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC (10) +#define IGMP_DEFAULT_VERSION (3) + struct igmp_join { struct in_addr group_addr; struct in_addr source_addr; @@ -152,6 +155,9 @@ struct igmp_group { since sources have their counters) */ int group_specific_query_retransmit_count; + /* compatibility mode - igmp v1, v2 or v3 */ + int igmp_version; + struct in_addr group_addr; int group_filtermode_isexcl; /* 0=INCLUDE, 1=EXCLUDE */ struct list *group_source_list; /* list of struct igmp_source */ @@ -176,4 +182,18 @@ void igmp_group_timer_on(struct igmp_group *group, struct igmp_source * source_new (struct igmp_group *group, struct in_addr src_addr); + +void igmp_send_query(int igmp_version, + struct igmp_group *group, + int fd, + const char *ifname, + char *query_buf, + int query_buf_size, + int num_sources, + struct in_addr dst_addr, + struct in_addr group_addr, + int query_max_response_time_dsec, + uint8_t s_flag, + uint8_t querier_robustness_variable, + uint16_t querier_query_interval); #endif /* PIM_IGMP_H */ diff --git a/pimd/pim_igmpv2.c b/pimd/pim_igmpv2.c new file mode 100644 index 0000000000..cc78f18d7c --- /dev/null +++ b/pimd/pim_igmpv2.c @@ -0,0 +1,190 @@ +/* + * PIM for Quagga + * Copyright (C) 2016 Cumulus Networks, Inc. + * Daniel Walton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include "pimd.h" +#include "pim_igmp.h" +#include "pim_igmpv2.h" +#include "pim_igmpv3.h" +#include "pim_str.h" +#include "pim_time.h" +#include "pim_util.h" + + +static void +on_trace (const char *label, + struct interface *ifp, struct in_addr from) +{ + if (PIM_DEBUG_IGMP_TRACE) { + char from_str[100]; + pim_inet4_dump("", from, from_str, sizeof(from_str)); + zlog_debug("%s: from %s on %s", + label, from_str, ifp->name); + } +} + +void +igmp_v2_send_query (struct igmp_group *group, + int fd, + const char *ifname, + char *query_buf, + struct in_addr dst_addr, + struct in_addr group_addr, + int query_max_response_time_dsec) +{ + ssize_t msg_size = 8; + uint8_t max_resp_code; + ssize_t sent; + struct sockaddr_in to; + socklen_t tolen; + uint16_t checksum; + + /* max_resp_code must be non-zero else this will look like an IGMP v1 query */ + max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec); + zassert(max_resp_code > 0); + + query_buf[0] = PIM_IGMP_MEMBERSHIP_QUERY; + query_buf[1] = max_resp_code; + *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = 0; /* for computing checksum */ + memcpy(query_buf+4, &group_addr, sizeof(struct in_addr)); + + checksum = in_cksum(query_buf, msg_size); + *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum; + + if (PIM_DEBUG_IGMP_PACKETS) { + char dst_str[100]; + char group_str[100]; + pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); + pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); + zlog_debug("Send IGMPv2 QUERY to %s on %s for group %s", + dst_str, ifname, group_str); + } + + memset(&to, 0, sizeof(to)); + to.sin_family = AF_INET; + to.sin_addr = dst_addr; + tolen = sizeof(to); + + sent = sendto(fd, query_buf, msg_size, MSG_DONTWAIT, + (struct sockaddr *)&to, tolen); + if (sent != (ssize_t) msg_size) { + char dst_str[100]; + char group_str[100]; + pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); + pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); + if (sent < 0) { + zlog_warn("Send IGMPv2 QUERY failed due to %s on %s: group=%s msg_size=%zd: errno=%d: %s", + dst_str, ifname, group_str, msg_size, errno, safe_strerror(errno)); + } + else { + zlog_warn("Send IGMPv2 QUERY failed due to %s on %s: group=%s msg_size=%zd: sent=%zd", + dst_str, ifname, group_str, msg_size, sent); + } + return; + } +} + +int +igmp_v2_recv_report (struct igmp_sock *igmp, + struct in_addr from, const char *from_str, + char *igmp_msg, int igmp_msg_len) +{ + struct interface *ifp = igmp->interface; + struct in_addr group_addr; + char group_str[100]; + + on_trace(__PRETTY_FUNCTION__, igmp->interface, from); + + if (igmp_msg_len != IGMP_V12_MSG_SIZE) { + zlog_warn("Recv IGMPv2 REPORT from %s on %s: size=%d other than correct=%d", + from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); + return -1; + } + + memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); + + if (PIM_DEBUG_IGMP_PACKETS) { + pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); + zlog_debug("Recv IGMPv2 REPORT from %s on %s for %s", + from_str, ifp->name, group_str); + } + + /* + * RFC 3376 + * 7.3.2. In the Presence of Older Version Group Members + * + * When Group Compatibility Mode is IGMPv2, a router internally + * translates the following IGMPv2 messages for that group to their + * IGMPv3 equivalents: + * + * IGMPv2 Message IGMPv3 Equivalent + * -------------- ----------------- + * Report IS_EX( {} ) + * Leave TO_IN( {} ) + */ + igmpv3_report_isex (igmp, from, group_addr, 0, NULL, 1); + + return 0; +} + +int +igmp_v2_recv_leave (struct igmp_sock *igmp, + struct in_addr from, const char *from_str, + char *igmp_msg, int igmp_msg_len) +{ + struct interface *ifp = igmp->interface; + struct in_addr group_addr; + char group_str[100]; + + on_trace(__PRETTY_FUNCTION__, igmp->interface, from); + + if (igmp_msg_len != IGMP_V12_MSG_SIZE) { + zlog_warn("Recv IGMPv2 LEAVE from %s on %s: size=%d other than correct=%d", + from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); + return -1; + } + + memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); + + if (PIM_DEBUG_IGMP_PACKETS) { + pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); + zlog_debug("Recv IGMPv2 LEAVE from %s on %s for %s", + from_str, ifp->name, group_str); + } + + memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); + + /* + * RFC 3376 + * 7.3.2. In the Presence of Older Version Group Members + * + * When Group Compatibility Mode is IGMPv2, a router internally + * translates the following IGMPv2 messages for that group to their + * IGMPv3 equivalents: + * + * IGMPv2 Message IGMPv3 Equivalent + * -------------- ----------------- + * Report IS_EX( {} ) + * Leave TO_IN( {} ) + */ + igmpv3_report_toin (igmp, from, group_addr, 0, NULL); + + return 0; +} diff --git a/pimd/pim_igmpv2.h b/pimd/pim_igmpv2.h new file mode 100644 index 0000000000..10a2477724 --- /dev/null +++ b/pimd/pim_igmpv2.h @@ -0,0 +1,41 @@ +/* + * PIM for Quagga + * Copyright (C) 2016 Cumulus Networks, Inc. + * Daniel Walton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifndef PIM_IGMPV2_H +#define PIM_IGMPV2_H + +void igmp_v2_send_query (struct igmp_group *group, + int fd, + const char *ifname, + char *query_buf, + struct in_addr dst_addr, + struct in_addr group_addr, + int query_max_response_time_dsec); + +int igmp_v2_recv_report (struct igmp_sock *igmp, + struct in_addr from, const char *from_str, + char *igmp_msg, int igmp_msg_len); + +int igmp_v2_recv_leave (struct igmp_sock *igmp, + struct in_addr from, const char *from_str, + char *igmp_msg, int igmp_msg_len); + +#endif /* PIM_IGMPV2_H */ diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index ba75fc221f..21a5176a9d 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -58,50 +58,6 @@ static void on_trace(const char *label, } } -int igmp_group_compat_mode(const struct igmp_sock *igmp, - const struct igmp_group *group) -{ - struct pim_interface *pim_ifp; - int64_t now_dsec; - long older_host_present_interval_dsec; - - zassert(igmp); - zassert(igmp->interface); - zassert(igmp->interface->info); - - pim_ifp = igmp->interface->info; - - /* - RFC 3376: 8.13. Older Host Present Interval - - This value MUST be ((the Robustness Variable) times (the Query - Interval)) plus (one Query Response Interval). - - older_host_present_interval_dsec = \ - igmp->querier_robustness_variable * \ - 10 * igmp->querier_query_interval + \ - pim_ifp->query_max_response_time_dsec; - */ - older_host_present_interval_dsec = - PIM_IGMP_OHPI_DSEC(igmp->querier_robustness_variable, - igmp->querier_query_interval, - pim_ifp->igmp_query_max_response_time_dsec); - - now_dsec = pim_time_monotonic_dsec(); - if (now_dsec < 1) { - /* broken timer logged by pim_time_monotonic_dsec() */ - return 3; - } - - if ((now_dsec - group->last_igmp_v1_report_dsec) < older_host_present_interval_dsec) - return 1; /* IGMPv1 */ - - if ((now_dsec - group->last_igmp_v2_report_dsec) < older_host_present_interval_dsec) - return 2; /* IGMPv2 */ - - return 3; /* IGMPv3 */ -} - void igmp_group_reset_gmi(struct igmp_group *group) { long group_membership_interval_msec; @@ -705,7 +661,8 @@ static void isex_incl(struct igmp_group *group, void igmpv3_report_isex(struct igmp_sock *igmp, struct in_addr from, struct in_addr group_addr, - int num_sources, struct in_addr *sources) + int num_sources, struct in_addr *sources, + int from_igmp_v2_report) { struct interface *ifp = igmp->interface; struct igmp_group *group; @@ -719,6 +676,10 @@ void igmpv3_report_isex(struct igmp_sock *igmp, struct in_addr from, return; } + /* So we can display how we learned the group in our show command output */ + if (from_igmp_v2_report) + group->igmp_version = 2; + if (group->group_filtermode_isexcl) { /* EXCLUDE mode */ isex_excl(group, num_sources, sources); @@ -1050,17 +1011,25 @@ void igmpv3_report_allow(struct igmp_sock *igmp, struct in_addr from, */ static void group_retransmit_group(struct igmp_group *group) { - char query_buf[PIM_IGMP_BUFSIZE_WRITE]; struct igmp_sock *igmp; struct pim_interface *pim_ifp; long lmqc; /* Last Member Query Count */ long lmqi_msec; /* Last Member Query Interval */ long lmqt_msec; /* Last Member Query Time */ int s_flag; + int query_buf_size; igmp = group->group_igmp_sock; pim_ifp = igmp->interface->info; + if (pim_ifp->igmp_version == 3) { + query_buf_size = PIM_IGMP_BUFSIZE_WRITE; + } else { + query_buf_size = IGMP_V12_MSG_SIZE; + } + + char query_buf[query_buf_size]; + lmqc = igmp->querier_robustness_variable; lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; lmqt_msec = lmqc * lmqi_msec; @@ -1090,18 +1059,19 @@ static void group_retransmit_group(struct igmp_group *group) interest. */ - pim_igmp_send_membership_query(group, - igmp->fd, - igmp->interface->name, - query_buf, - sizeof(query_buf), - 0 /* num_sources_tosend */, - group->group_addr /* dst_addr */, - group->group_addr /* group_addr */, - pim_ifp->igmp_specific_query_max_response_time_dsec, - s_flag, - igmp->querier_robustness_variable, - igmp->querier_query_interval); + igmp_send_query(pim_ifp->igmp_version, + group, + igmp->fd, + igmp->interface->name, + query_buf, + sizeof(query_buf), + 0 /* num_sources_tosend */, + group->group_addr /* dst_addr */, + group->group_addr /* group_addr */, + pim_ifp->igmp_specific_query_max_response_time_dsec, + s_flag, + igmp->querier_robustness_variable, + igmp->querier_query_interval); } /* @@ -1208,19 +1178,19 @@ static int group_retransmit_sources(struct igmp_group *group, interest. */ - pim_igmp_send_membership_query(group, - igmp->fd, - igmp->interface->name, - query_buf1, - sizeof(query_buf1), - num_sources_tosend1, - group->group_addr, - group->group_addr, - pim_ifp->igmp_specific_query_max_response_time_dsec, - 1 /* s_flag */, - igmp->querier_robustness_variable, - igmp->querier_query_interval); - + igmp_send_query(pim_ifp->igmp_version, + group, + igmp->fd, + igmp->interface->name, + query_buf1, + sizeof(query_buf1), + num_sources_tosend1, + group->group_addr, + group->group_addr, + pim_ifp->igmp_specific_query_max_response_time_dsec, + 1 /* s_flag */, + igmp->querier_robustness_variable, + igmp->querier_query_interval); } } /* send_with_sflag_set */ @@ -1250,19 +1220,19 @@ static int group_retransmit_sources(struct igmp_group *group, interest. */ - pim_igmp_send_membership_query(group, - igmp->fd, - igmp->interface->name, - query_buf2, - sizeof(query_buf2), - num_sources_tosend2, - group->group_addr, - group->group_addr, - pim_ifp->igmp_specific_query_max_response_time_dsec, - 0 /* s_flag */, - igmp->querier_robustness_variable, - igmp->querier_query_interval); - + igmp_send_query(pim_ifp->igmp_version, + group, + igmp->fd, + igmp->interface->name, + query_buf2, + sizeof(query_buf2), + num_sources_tosend2, + group->group_addr, + group->group_addr, + pim_ifp->igmp_specific_query_max_response_time_dsec, + 0 /* s_flag */, + igmp->querier_robustness_variable, + igmp->querier_query_interval); } } @@ -1623,32 +1593,19 @@ void igmp_source_timer_lower_to_lmqt(struct igmp_source *source) igmp_source_timer_on(group, source, lmqt_msec); } -/* - Copy sources to message: - - struct in_addr *sources = (struct in_addr *)(query_buf + IGMP_V3_SOURCES_OFFSET); - if (num_sources > 0) { - struct listnode *node; - struct igmp_source *src; - int i = 0; - - for (ALL_LIST_ELEMENTS_RO(source_list, node, src)) { - sources[i++] = src->source_addr; - } - } -*/ -void pim_igmp_send_membership_query(struct igmp_group *group, - int fd, - const char *ifname, - char *query_buf, - int query_buf_size, - int num_sources, - struct in_addr dst_addr, - struct in_addr group_addr, - int query_max_response_time_dsec, - uint8_t s_flag, - uint8_t querier_robustness_variable, - uint16_t querier_query_interval) +void +igmp_v3_send_query (struct igmp_group *group, + int fd, + const char *ifname, + char *query_buf, + int query_buf_size, + int num_sources, + struct in_addr dst_addr, + struct in_addr group_addr, + int query_max_response_time_dsec, + uint8_t s_flag, + uint8_t querier_robustness_variable, + uint16_t querier_query_interval) { ssize_t msg_size; uint8_t max_resp_code; @@ -1688,7 +1645,7 @@ void pim_igmp_send_membership_query(struct igmp_group *group, query_buf[0] = PIM_IGMP_MEMBERSHIP_QUERY; query_buf[1] = max_resp_code; - *(uint16_t *)(query_buf + IGMP_V3_CHECKSUM_OFFSET) = 0; /* for computing checksum */ + *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = 0; /* for computing checksum */ memcpy(query_buf+4, &group_addr, sizeof(struct in_addr)); query_buf[8] = (s_flag << 3) | querier_robustness_variable; @@ -1696,18 +1653,17 @@ void pim_igmp_send_membership_query(struct igmp_group *group, *(uint16_t *)(query_buf + IGMP_V3_NUMSOURCES_OFFSET) = htons(num_sources); checksum = in_cksum(query_buf, msg_size); - *(uint16_t *)(query_buf + IGMP_V3_CHECKSUM_OFFSET) = checksum; + *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum; if (PIM_DEBUG_IGMP_PACKETS) { char dst_str[100]; char group_str[100]; pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - zlog_debug("%s: to %s on %s: group=%s sources=%d msg_size=%zd s_flag=%x QRV=%u QQI=%u QQIC=%02x checksum=%x", - __PRETTY_FUNCTION__, - dst_str, ifname, group_str, num_sources, - msg_size, s_flag, querier_robustness_variable, - querier_query_interval, qqic, checksum); + zlog_debug("Send IGMPv3 query to %s on %s for group %s, sources=%d msg_size=%zd s_flag=%x QRV=%u QQI=%u QQIC=%02x", + dst_str, ifname, group_str, + num_sources, msg_size, s_flag, querier_robustness_variable, + querier_query_interval, qqic); } memset(&to, 0, sizeof(to)); @@ -1723,16 +1679,12 @@ void pim_igmp_send_membership_query(struct igmp_group *group, pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); if (sent < 0) { - zlog_warn("%s: sendto() failure to %s on %s: group=%s msg_size=%zd: errno=%d: %s", - __PRETTY_FUNCTION__, - dst_str, ifname, group_str, msg_size, - errno, safe_strerror(errno)); + zlog_warn("Send IGMPv3 query failed due to %s on %s: group=%s msg_size=%zd: errno=%d: %s", + dst_str, ifname, group_str, msg_size, errno, safe_strerror(errno)); } else { - zlog_warn("%s: sendto() partial to %s on %s: group=%s msg_size=%zd: sent=%zd", - __PRETTY_FUNCTION__, - dst_str, ifname, group_str, - msg_size, sent); + zlog_warn("Send IGMPv3 query failed due to %s on %s: group=%s msg_size=%zd: sent=%zd", + dst_str, ifname, group_str, msg_size, sent); } return; } @@ -1760,5 +1712,268 @@ void pim_igmp_send_membership_query(struct igmp_group *group, dst_str, ifname, group_str, num_sources); } } - +} + +void +igmp_v3_recv_query (struct igmp_sock *igmp, const char *from_str, char *igmp_msg) +{ + struct interface *ifp; + struct pim_interface *pim_ifp; + struct in_addr group_addr; + uint8_t resv_s_qrv = 0; + uint8_t s_flag = 0; + uint8_t qrv = 0; + int i; + + memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); + ifp = igmp->interface; + pim_ifp = ifp->info; + + /* + * RFC 3376: 4.1.6. QRV (Querier's Robustness Variable) + * + * Routers adopt the QRV value from the most recently received Query + * as their own [Robustness Variable] value, unless that most + * recently received QRV was zero, in which case the receivers use + * the default [Robustness Variable] value specified in section 8.1 + * or a statically configured value. + */ + resv_s_qrv = igmp_msg[8]; + qrv = 7 & resv_s_qrv; + igmp->querier_robustness_variable = qrv ? qrv : pim_ifp->igmp_default_robustness_variable; + + /* + * RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code) + * + * Multicast routers that are not the current querier adopt the QQI + * value from the most recently received Query as their own [Query + * Interval] value, unless that most recently received QQI was zero, + * in which case the receiving routers use the default. + */ + if (igmp->t_other_querier_timer) { + /* other querier present */ + uint8_t qqic; + uint16_t qqi; + qqic = igmp_msg[9]; + qqi = igmp_msg_decode8to16(qqic); + igmp->querier_query_interval = qqi ? qqi : pim_ifp->igmp_default_query_interval; + + if (PIM_DEBUG_IGMP_TRACE) { + char ifaddr_str[100]; + pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); + zlog_debug("Querier %s new query interval is %s QQI=%u sec (recv QQIC=%02x from %s)", + ifaddr_str, + qqi ? "recv-non-default" : "default", + igmp->querier_query_interval, + qqic, + from_str); + } + } + + /* + * RFC 3376: 6.6.1. Timer Updates + * + * When a router sends or receives a query with a clear Suppress + * Router-Side Processing flag, it must update its timers to reflect + * the correct timeout values for the group or sources being queried. + * + * General queries don't trigger timer update. + */ + s_flag = (1 << 3) & resv_s_qrv; + + if (!s_flag) { + /* s_flag is clear */ + + if (PIM_INADDR_IS_ANY(group_addr)) { + /* this is a general query */ + /* log that general query should have the s_flag set */ + zlog_warn("General IGMP query v3 from %s on %s: Suppress Router-Side Processing flag is clear", + from_str, ifp->name); + } else { + struct igmp_group *group; + + /* this is a non-general query: perform timer updates */ + + group = find_group_by_addr(igmp, group_addr); + if (group) { + int recv_num_sources = ntohs(*(uint16_t *)(igmp_msg + IGMP_V3_NUMSOURCES_OFFSET)); + + /* + * RFC 3376: 6.6.1. Timer Updates + * Query Q(G,A): Source Timer for sources in A are lowered to LMQT + * Query Q(G): Group Timer is lowered to LMQT + */ + if (recv_num_sources < 1) { + /* Query Q(G): Group Timer is lowered to LMQT */ + + igmp_group_timer_lower_to_lmqt(group); + } else { + /* Query Q(G,A): Source Timer for sources in A are lowered to LMQT */ + + /* Scan sources in query and lower their timers to LMQT */ + struct in_addr *sources = (struct in_addr *)(igmp_msg + IGMP_V3_SOURCES_OFFSET); + for (i = 0; i < recv_num_sources; ++i) { + struct in_addr src_addr; + struct igmp_source *src; + memcpy(&src_addr, sources + i, sizeof(struct in_addr)); + src = igmp_find_source_by_addr(group, src_addr); + if (src) { + igmp_source_timer_lower_to_lmqt(src); + } + } + } + } else { + char group_str[100]; + pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); + zlog_warn("IGMP query v3 from %s on %s: could not find group %s for timer update", + from_str, ifp->name, group_str); + } + } + } /* s_flag is clear: timer updates */ +} + +int +igmp_v3_recv_report (struct igmp_sock *igmp, + struct in_addr from, const char *from_str, + char *igmp_msg, int igmp_msg_len) +{ + uint16_t recv_checksum; + uint16_t checksum; + int num_groups; + uint8_t *group_record; + uint8_t *report_pastend = (uint8_t *) igmp_msg + igmp_msg_len; + struct interface *ifp = igmp->interface; + int i; + int local_ncb = 0; + + if (igmp_msg_len < IGMP_V3_MSG_MIN_SIZE) { + zlog_warn("Recv IGMP report v3 from %s on %s: size=%d shorter than minimum=%d", + from_str, ifp->name, igmp_msg_len, IGMP_V3_MSG_MIN_SIZE); + return -1; + } + + recv_checksum = *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET); + + /* for computing checksum */ + *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET) = 0; + + checksum = in_cksum(igmp_msg, igmp_msg_len); + if (checksum != recv_checksum) { + zlog_warn("Recv IGMP report v3 from %s on %s: checksum mismatch: received=%x computed=%x", + from_str, ifp->name, recv_checksum, checksum); + return -1; + } + + num_groups = ntohs(*(uint16_t *) (igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET)); + if (num_groups < 1) { + zlog_warn("Recv IGMP report v3 from %s on %s: missing group records", + from_str, ifp->name); + return -1; + } + + if (PIM_DEBUG_IGMP_PACKETS) { + zlog_debug("Recv IGMP report v3 from %s on %s: size=%d checksum=%x groups=%d", + from_str, ifp->name, igmp_msg_len, checksum, num_groups); + } + + group_record = (uint8_t *) igmp_msg + IGMP_V3_REPORT_GROUPPRECORD_OFFSET; + + /* Scan groups */ + for (i = 0; i < num_groups; ++i) { + struct in_addr rec_group; + uint8_t *sources; + uint8_t *src; + int rec_type; + int rec_auxdatalen; + int rec_num_sources; + int j; + struct prefix lncb; + struct prefix g; + + if ((group_record + IGMP_V3_GROUP_RECORD_MIN_SIZE) > report_pastend) { + zlog_warn("Recv IGMP report v3 from %s on %s: group record beyond report end", + from_str, ifp->name); + return -1; + } + + rec_type = group_record[IGMP_V3_GROUP_RECORD_TYPE_OFFSET]; + rec_auxdatalen = group_record[IGMP_V3_GROUP_RECORD_AUXDATALEN_OFFSET]; + rec_num_sources = ntohs(* (uint16_t *) (group_record + IGMP_V3_GROUP_RECORD_NUMSOURCES_OFFSET)); + + memcpy(&rec_group, group_record + IGMP_V3_GROUP_RECORD_GROUP_OFFSET, sizeof(struct in_addr)); + + if (PIM_DEBUG_IGMP_PACKETS) { + zlog_debug("Recv IGMP report v3 from %s on %s: record=%d type=%d auxdatalen=%d sources=%d group=%s", + from_str, ifp->name, i, rec_type, rec_auxdatalen, rec_num_sources, inet_ntoa(rec_group)); + } + + /* Scan sources */ + + sources = group_record + IGMP_V3_GROUP_RECORD_SOURCE_OFFSET; + + for (j = 0, src = sources; j < rec_num_sources; ++j, src += 4) { + + if ((src + 4) > report_pastend) { + zlog_warn("Recv IGMP report v3 from %s on %s: group source beyond report end", + from_str, ifp->name); + return -1; + } + + if (PIM_DEBUG_IGMP_PACKETS) { + char src_str[200]; + + if (!inet_ntop(AF_INET, src, src_str , sizeof(src_str))) + sprintf(src_str, ""); + + zlog_debug("Recv IGMP report v3 from %s on %s: record=%d group=%s source=%s", + from_str, ifp->name, i, inet_ntoa(rec_group), src_str); + } + } /* for (sources) */ + + + lncb.family = AF_INET; + lncb.u.prefix4.s_addr = 0x000000E0; + lncb.prefixlen = 24; + + g.family = AF_INET; + g.u.prefix4 = rec_group; + g.prefixlen = 32; + /* + * If we receive a igmp report with the group in 224.0.0.0/24 + * then we should ignore it + */ + if (prefix_match(&lncb, &g)) + local_ncb = 1; + + if (!local_ncb) + switch (rec_type) { + case IGMP_GRP_REC_TYPE_MODE_IS_INCLUDE: + igmpv3_report_isin(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); + break; + case IGMP_GRP_REC_TYPE_MODE_IS_EXCLUDE: + igmpv3_report_isex(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources, 0); + break; + case IGMP_GRP_REC_TYPE_CHANGE_TO_INCLUDE_MODE: + igmpv3_report_toin(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); + break; + case IGMP_GRP_REC_TYPE_CHANGE_TO_EXCLUDE_MODE: + igmpv3_report_toex(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); + break; + case IGMP_GRP_REC_TYPE_ALLOW_NEW_SOURCES: + igmpv3_report_allow(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); + break; + case IGMP_GRP_REC_TYPE_BLOCK_OLD_SOURCES: + igmpv3_report_block(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); + break; + default: + zlog_warn("Recv IGMP report v3 from %s on %s: unknown record type: type=%d", + from_str, ifp->name, rec_type); + } + + group_record += 8 + (rec_num_sources << 2) + (rec_auxdatalen << 2); + local_ncb = 0; + + } /* for (group records) */ + + return 0; } diff --git a/pimd/pim_igmpv3.h b/pimd/pim_igmpv3.h index 37baca5c8d..33a918bad1 100644 --- a/pimd/pim_igmpv3.h +++ b/pimd/pim_igmpv3.h @@ -31,6 +31,13 @@ #define IGMP_V3_NUMSOURCES_OFFSET (10) #define IGMP_V3_SOURCES_OFFSET (12) +#define IGMP_GRP_REC_TYPE_MODE_IS_INCLUDE (1) +#define IGMP_GRP_REC_TYPE_MODE_IS_EXCLUDE (2) +#define IGMP_GRP_REC_TYPE_CHANGE_TO_INCLUDE_MODE (3) +#define IGMP_GRP_REC_TYPE_CHANGE_TO_EXCLUDE_MODE (4) +#define IGMP_GRP_REC_TYPE_ALLOW_NEW_SOURCES (5) +#define IGMP_GRP_REC_TYPE_BLOCK_OLD_SOURCES (6) + /* GMI: Group Membership Interval */ #define PIM_IGMP_GMI_MSEC(qrv,qqi,qri_dsec) ((qrv) * (1000 * (qqi)) + 100 * (qri_dsec)) @@ -55,15 +62,13 @@ void igmp_source_free(struct igmp_source *source); void igmp_source_delete(struct igmp_source *source); void igmp_source_delete_expired(struct list *source_list); -int igmp_group_compat_mode(const struct igmp_sock *igmp, - const struct igmp_group *group); - void igmpv3_report_isin(struct igmp_sock *igmp, struct in_addr from, struct in_addr group_addr, int num_sources, struct in_addr *sources); void igmpv3_report_isex(struct igmp_sock *igmp, struct in_addr from, struct in_addr group_addr, - int num_sources, struct in_addr *sources); + int num_sources, struct in_addr *sources, + int from_igmp_v2_report); void igmpv3_report_toin(struct igmp_sock *igmp, struct in_addr from, struct in_addr group_addr, int num_sources, struct in_addr *sources); @@ -83,17 +88,24 @@ void igmp_source_timer_lower_to_lmqt(struct igmp_source *source); struct igmp_source *igmp_find_source_by_addr(struct igmp_group *group, struct in_addr src_addr); -void pim_igmp_send_membership_query(struct igmp_group *group, - int fd, - const char *ifname, - char *query_buf, - int query_buf_size, - int num_sources, - struct in_addr dst_addr, - struct in_addr group_addr, - int query_max_response_time_dsec, - uint8_t s_flag, - uint8_t querier_robustness_variable, - uint16_t querier_query_interval); +void igmp_v3_send_query (struct igmp_group *group, + int fd, + const char *ifname, + char *query_buf, + int query_buf_size, + int num_sources, + struct in_addr dst_addr, + struct in_addr group_addr, + int query_max_response_time_dsec, + uint8_t s_flag, + uint8_t querier_robustness_variable, + uint16_t querier_query_interval); + +void igmp_v3_recv_query (struct igmp_sock *igmp, const char *from_str, + char *igmp_msg); + +int igmp_v3_recv_report (struct igmp_sock *igmp, + struct in_addr from, const char *from_str, + char *igmp_msg, int igmp_msg_len); #endif /* PIM_IGMPV3_H */ diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index b9c97557c5..341d733361 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -399,59 +399,97 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) int pim_mroute_msg(int fd, const char *buf, int buf_size) { struct interface *ifp; + struct pim_interface *pim_ifp; const struct ip *ip_hdr; const struct igmpmsg *msg; + char ip_src_str[100] = ""; + char ip_dst_str[100] = ""; char src_str[100] = ""; char grp_str[100] = ""; + struct in_addr ifaddr; + struct igmp_sock *igmp; ip_hdr = (const struct ip *) buf; - /* kernel upcall must have protocol=0 */ - if (ip_hdr->ip_p) { - /* this is not a kernel upcall */ + if (ip_hdr->ip_p == IPPROTO_IGMP) { + + /* We have the IP packet but we do not know which interface this packet was + * received on. Find the interface that is on the same subnet as the source + * of the IP packet. + */ + ifp = if_lookup_address_vrf((void *) &ip_hdr->ip_src, AF_INET, VRF_DEFAULT); + + if (!ifp) { + if (PIM_DEBUG_MROUTE_DETAIL) { + pim_inet4_dump("", ip_hdr->ip_src, ip_src_str, sizeof(ip_src_str)); + pim_inet4_dump("", ip_hdr->ip_dst, ip_dst_str, sizeof(ip_dst_str)); + + zlog_warn("%s: igmp kernel upcall could not find interface for %s -> %s", + __PRETTY_FUNCTION__, + ip_src_str, + ip_dst_str); + } + return 0; + } + + pim_ifp = ifp->info; + ifaddr = pim_find_primary_addr(ifp); + igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr); + + if (PIM_DEBUG_MROUTE_DETAIL) { + pim_inet4_dump("", ip_hdr->ip_src, ip_src_str, sizeof(ip_src_str)); + pim_inet4_dump("", ip_hdr->ip_dst, ip_dst_str, sizeof(ip_dst_str)); + + zlog_warn("%s: igmp kernel upcall on %s for %s -> %s", + __PRETTY_FUNCTION__, ifp->name, ip_src_str, ip_dst_str); + } + + pim_igmp_packet(igmp, (char *)buf, buf_size); + + } else if (ip_hdr->ip_p) { if (PIM_DEBUG_MROUTE_DETAIL) { pim_inet4_dump("", ip_hdr->ip_src, src_str, sizeof(src_str)); pim_inet4_dump("", ip_hdr->ip_dst, grp_str, sizeof(grp_str)); - zlog_debug("%s: not a kernel upcall proto=%d src: %s dst: %s msg_size=%d", - __PRETTY_FUNCTION__, ip_hdr->ip_p, src_str, grp_str, buf_size); + zlog_debug("%s: no kernel upcall proto=%d src: %s dst: %s msg_size=%d", + __PRETTY_FUNCTION__, ip_hdr->ip_p, src_str, grp_str, buf_size); } - return 0; - } - msg = (const struct igmpmsg *) buf; + } else { + msg = (const struct igmpmsg *) buf; - ifp = pim_if_find_by_vif_index(msg->im_vif); + ifp = pim_if_find_by_vif_index(msg->im_vif); - if (PIM_DEBUG_MROUTE) { - 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 size=%d", - __PRETTY_FUNCTION__, - igmpmsgtype2str[msg->im_msgtype], - msg->im_msgtype, - ip_hdr->ip_p, - fd, - src_str, - grp_str, - ifp->name, - msg->im_vif, buf_size); - } + if (PIM_DEBUG_MROUTE) { + 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: pim kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%s,%s) on %s vifi=%d size=%d", + __PRETTY_FUNCTION__, + igmpmsgtype2str[msg->im_msgtype], + msg->im_msgtype, + ip_hdr->ip_p, + fd, + src_str, + grp_str, + ifp->name, + msg->im_vif, buf_size); + } - switch (msg->im_msgtype) { - case IGMPMSG_WRONGVIF: - return pim_mroute_msg_wrongvif(fd, ifp, msg); - break; - case IGMPMSG_NOCACHE: - return pim_mroute_msg_nocache(fd, ifp, msg); - break; - case IGMPMSG_WHOLEPKT: - return pim_mroute_msg_wholepkt(fd, ifp, (const char *)msg); - break; - case IGMPMSG_WRVIFWHOLE: - return pim_mroute_msg_wrvifwhole (fd, ifp, (const char *)msg); - break; - default: - break; + switch (msg->im_msgtype) { + case IGMPMSG_WRONGVIF: + return pim_mroute_msg_wrongvif(fd, ifp, msg); + break; + case IGMPMSG_NOCACHE: + return pim_mroute_msg_nocache(fd, ifp, msg); + break; + case IGMPMSG_WHOLEPKT: + return pim_mroute_msg_wholepkt(fd, ifp, (const char *)msg); + break; + case IGMPMSG_WRVIFWHOLE: + return pim_mroute_msg_wrvifwhole (fd, ifp, (const char *)msg); + break; + default: + break; + } } return 0; diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 3eb04d347e..644fb8e691 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -215,6 +215,15 @@ int pim_interface_config_write(struct vty *vty) ++writes; } + /* ip igmp version */ + if (pim_ifp->igmp_version != IGMP_DEFAULT_VERSION) + { + vty_out(vty, " ip igmp version %d%s", + pim_ifp->igmp_version, + VTY_NEWLINE); + ++writes; + } + /* IF ip igmp query-interval */ if (pim_ifp->igmp_default_query_interval != IGMP_GENERAL_QUERY_INTERVAL) { From eaa54bdb6729bbe97d938e70ee5580dcad666f0f Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Thu, 20 Oct 2016 14:09:30 +0000 Subject: [PATCH 213/386] pimd: replace grp_str[100] with grp_str[INET_ADDRSTRLEN] Signed-off-by: Daniel Walton --- pimd/pim_assert.c | 22 +++---- pimd/pim_cmd.c | 140 +++++++++++++++++++++---------------------- pimd/pim_hello.c | 32 +++++----- pimd/pim_iface.c | 34 +++++------ pimd/pim_ifchannel.c | 24 ++++---- pimd/pim_igmp.c | 36 +++++------ pimd/pim_igmpv2.c | 14 ++--- pimd/pim_igmpv3.c | 68 ++++++++++----------- pimd/pim_join.c | 32 +++++----- pimd/pim_mroute.c | 10 ++-- pimd/pim_msg.c | 6 +- pimd/pim_neighbor.c | 20 +++---- pimd/pim_oil.c | 44 +++++++------- pimd/pim_pim.c | 18 +++--- pimd/pim_register.c | 6 +- pimd/pim_rp.c | 6 +- pimd/pim_rpf.c | 12 ++-- pimd/pim_sock.c | 16 ++--- pimd/pim_ssmpingd.c | 32 +++++----- pimd/pim_static.c | 28 ++++----- pimd/pim_str.c | 4 +- pimd/pim_tlv.c | 18 +++--- pimd/pim_upstream.c | 10 ++-- pimd/pim_vty.c | 6 +- pimd/pim_zebra.c | 66 ++++++++++---------- pimd/pim_zlookup.c | 22 +++---- 26 files changed, 363 insertions(+), 363 deletions(-) diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index 481a2851d5..fced5dcd47 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -64,8 +64,8 @@ void pim_ifassert_winner_set(struct pim_ifchannel *ch, } if (winner_changed) { - char was_str[100]; - char winner_str[100]; + char was_str[INET_ADDRSTRLEN]; + char winner_str[INET_ADDRSTRLEN]; pim_inet4_dump("", ch->ifassert_winner, was_str, sizeof(was_str)); pim_inet4_dump("", winner, winner_str, sizeof(winner_str)); zlog_debug("%s: (S,G)=%s assert winner changed from %s to %s on interface %s", @@ -91,7 +91,7 @@ static void on_trace(const char *label, struct interface *ifp, struct in_addr src) { if (PIM_DEBUG_PIM_TRACE) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src, src_str, sizeof(src_str)); zlog_debug("%s: from %s on %s", label, src_str, ifp->name); @@ -243,7 +243,7 @@ int pim_assert_recv(struct interface *ifp, */ offset = pim_parse_addr_group (&msg_group_addr, curr, curr_size); if (offset < 1) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: pim_parse_addr_group() failure: from %s on %s", __PRETTY_FUNCTION__, @@ -258,7 +258,7 @@ int pim_assert_recv(struct interface *ifp, */ offset = pim_parse_addr_ucast (&msg_source_addr, curr, curr_size); if (offset < 1) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s", __PRETTY_FUNCTION__, @@ -269,7 +269,7 @@ int pim_assert_recv(struct interface *ifp, curr_size -= offset; if (curr_size != 8) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: preference/metric size is not 8: size=%d from %s on interface %s", __PRETTY_FUNCTION__, @@ -296,9 +296,9 @@ int pim_assert_recv(struct interface *ifp, msg_metric.route_metric = pim_read_uint32_host(curr); if (PIM_DEBUG_PIM_TRACE) { - char neigh_str[100]; - char source_str[100]; - char group_str[100]; + char neigh_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, neigh_str, sizeof(neigh_str)); pim_inet4_dump("", msg_source_addr.u.prefix4, source_str, sizeof(source_str)); pim_inet4_dump("", msg_group_addr.u.prefix4, group_str, sizeof(group_str)); @@ -384,7 +384,7 @@ int pim_assert_build_msg(uint8_t *pim_msg, int buf_size, remain, group_addr); if (!pim_msg_curr) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); zlog_warn("%s: failure encoding group address %s: space left=%d", __PRETTY_FUNCTION__, group_str, remain); @@ -397,7 +397,7 @@ int pim_assert_build_msg(uint8_t *pim_msg, int buf_size, remain, source_addr); if (!pim_msg_curr) { - char source_str[100]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); zlog_warn("%s: failure encoding source address %s: space left=%d", __PRETTY_FUNCTION__, source_str, remain); diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index c6390271f1..dbe8c3ef42 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -184,9 +184,9 @@ static void pim_show_assert(struct vty *vty) ifaddr = pim_ifp->primary_address; for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - char ch_src_str[100]; - char ch_grp_str[100]; - char winner_str[100]; + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + char winner_str[INET_ADDRSTRLEN]; char uptime[10]; char timer[10]; @@ -245,8 +245,8 @@ static void pim_show_assert_internal(struct vty *vty) ifaddr = pim_ifp->primary_address; for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - char ch_src_str[100]; - char ch_grp_str[100]; + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; pim_inet4_dump("", ch->sg.src, ch_src_str, sizeof(ch_src_str)); @@ -289,9 +289,9 @@ static void pim_show_assert_metric(struct vty *vty) ifaddr = pim_ifp->primary_address; for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - char ch_src_str[100]; - char ch_grp_str[100]; - char addr_str[100]; + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + char addr_str[INET_ADDRSTRLEN]; struct pim_assert_metric am; am = pim_macro_spt_assert_metric(&ch->upstream->rpf, pim_ifp->primary_address); @@ -340,9 +340,9 @@ static void pim_show_assert_winner_metric(struct vty *vty) ifaddr = pim_ifp->primary_address; for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - char ch_src_str[100]; - char ch_grp_str[100]; - char addr_str[100]; + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + char addr_str[INET_ADDRSTRLEN]; struct pim_assert_metric *am; char pref_str[5]; char metr_str[7]; @@ -438,8 +438,8 @@ static void pim_show_membership(struct vty *vty, u_char uj) ifaddr = pim_ifp->primary_address; for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - char ch_src_str[100]; - char ch_grp_str[100]; + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; pim_inet4_dump("", ch->sg.src, ch_src_str, sizeof(ch_src_str)); @@ -708,7 +708,7 @@ static void igmp_show_interface_join(struct vty *vty) struct listnode *join_node; struct igmp_join *ij; struct in_addr pri_addr; - char pri_addr_str[100]; + char pri_addr_str[INET_ADDRSTRLEN]; pim_ifp = ifp->info; @@ -722,8 +722,8 @@ static void igmp_show_interface_join(struct vty *vty) pim_inet4_dump("", pri_addr, pri_addr_str, sizeof(pri_addr_str)); for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_join_list, join_node, ij)) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; char uptime[10]; pim_time_uptime(uptime, sizeof(uptime), now - ij->sock_creation); @@ -755,14 +755,14 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch struct pim_neighbor *neigh; struct pim_upstream *up; time_t now; - char dr_str[100]; + char dr_str[INET_ADDRSTRLEN]; char dr_uptime[10]; char expire[10]; - char grp_str[100]; + char grp_str[INET_ADDRSTRLEN]; char hello_period[10]; char hello_timer[10]; - char neigh_src_str[100]; - char src_str[100]; + char neigh_src_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; char stat_uptime[10]; char uptime[10]; int mloop; @@ -1096,8 +1096,8 @@ static void pim_show_join(struct vty *vty, u_char uj) ifaddr = pim_ifp->primary_address; for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - char ch_src_str[100]; - char ch_grp_str[100]; + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; char uptime[10]; char expire[10]; char prune[10]; @@ -1169,7 +1169,7 @@ static void pim_show_neighbors_single(struct vty *vty, const char *neighbor, u_c int option_t_bit; char uptime[10]; char expire[10]; - char neigh_src_str[100]; + char neigh_src_str[INET_ADDRSTRLEN]; json_object *json = NULL; json_object *json_ifp = NULL; @@ -1322,8 +1322,8 @@ pim_show_state(struct vty *vty, const char *src_or_group, const char *group, u_c } for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { - char grp_str[100]; - char src_str[100]; + char grp_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; char in_ifname[16]; char out_ifname[16]; int oif_vif_index; @@ -1442,7 +1442,7 @@ static void pim_show_neighbors(struct vty *vty, u_char uj) time_t now; char uptime[10]; char expire[10]; - char neigh_src_str[100]; + char neigh_src_str[INET_ADDRSTRLEN]; json_object *json = NULL; json_object *json_ifp_rows = NULL; json_object *json_row = NULL; @@ -1530,7 +1530,7 @@ static void pim_show_neighbors_secondary(struct vty *vty) ifaddr = pim_ifp->primary_address; for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - char neigh_src_str[100]; + char neigh_src_str[INET_ADDRSTRLEN]; struct listnode *prefix_node; struct prefix *p; @@ -1541,7 +1541,7 @@ static void pim_show_neighbors_secondary(struct vty *vty) neigh_src_str, sizeof(neigh_src_str)); for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, prefix_node, p)) { - char neigh_sec_str[100]; + char neigh_sec_str[INET_ADDRSTRLEN]; if (p->family != AF_INET) continue; @@ -1599,8 +1599,8 @@ static void pim_show_upstream(struct vty *vty, u_char uj) vty_out(vty, "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt%s", VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { - char src_str[100]; - char grp_str[100]; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; char uptime[10]; char join_timer[10]; char rs_timer[10]; @@ -1661,8 +1661,8 @@ static void pim_show_join_desired(struct vty *vty, u_char uj) struct interface *ifp; struct pim_interface *pim_ifp; struct pim_ifchannel *ch; - char src_str[100]; - char grp_str[100]; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; json_object *json = NULL; json_object *json_group = NULL; json_object *json_row = NULL; @@ -1752,10 +1752,10 @@ static void pim_show_upstream_rpf(struct vty *vty, u_char uj) VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { - char src_str[100]; - char grp_str[100]; - char rpf_nexthop_str[100]; - char rpf_addr_str[100]; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + char rpf_nexthop_str[PREFIX_STRLEN]; + char rpf_addr_str[PREFIX_STRLEN]; struct pim_rpf *rpf; const char *rpf_ifname; @@ -1871,10 +1871,10 @@ static void pim_show_rpf(struct vty *vty, u_char uj) } for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) { - char src_str[100]; - char grp_str[100]; - char rpf_addr_str[100]; - char rib_nexthop_str[100]; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + char rpf_addr_str[PREFIX_STRLEN]; + char rib_nexthop_str[PREFIX_STRLEN]; const char *rpf_ifname; struct pim_rpf *rpf = &up->rpf; @@ -1949,7 +1949,7 @@ static void igmp_show_groups(struct vty *vty, u_char uj) /* scan igmp sockets */ for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - char ifaddr_str[100]; + char ifaddr_str[INET_ADDRSTRLEN]; struct listnode *grpnode; struct igmp_group *grp; @@ -1957,7 +1957,7 @@ static void igmp_show_groups(struct vty *vty, u_char uj) /* scan igmp groups */ for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; char hhmmss[10]; char uptime[10]; @@ -2027,7 +2027,7 @@ static void igmp_show_group_retransmission(struct vty *vty) /* scan igmp sockets */ for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - char ifaddr_str[100]; + char ifaddr_str[INET_ADDRSTRLEN]; struct listnode *grpnode; struct igmp_group *grp; @@ -2035,7 +2035,7 @@ static void igmp_show_group_retransmission(struct vty *vty) /* scan igmp groups */ for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; char grp_retr_mmss[10]; struct listnode *src_node; struct igmp_source *src; @@ -2087,7 +2087,7 @@ static void igmp_show_sources(struct vty *vty) /* scan igmp sockets */ for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - char ifaddr_str[100]; + char ifaddr_str[INET_ADDRSTRLEN]; struct listnode *grpnode; struct igmp_group *grp; @@ -2095,7 +2095,7 @@ static void igmp_show_sources(struct vty *vty) /* scan igmp groups */ for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; struct listnode *srcnode; struct igmp_source *src; @@ -2103,7 +2103,7 @@ static void igmp_show_sources(struct vty *vty) /* scan group sources */ for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) { - char source_str[100]; + char source_str[INET_ADDRSTRLEN]; char mmss[10]; char uptime[10]; @@ -2147,7 +2147,7 @@ static void igmp_show_source_retransmission(struct vty *vty) /* scan igmp sockets */ for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - char ifaddr_str[100]; + char ifaddr_str[INET_ADDRSTRLEN]; struct listnode *grpnode; struct igmp_group *grp; @@ -2155,7 +2155,7 @@ static void igmp_show_source_retransmission(struct vty *vty) /* scan igmp groups */ for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; struct listnode *srcnode; struct igmp_source *src; @@ -2163,7 +2163,7 @@ static void igmp_show_source_retransmission(struct vty *vty) /* scan group sources */ for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) { - char source_str[100]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src->source_addr, source_str, sizeof(source_str)); @@ -2248,8 +2248,8 @@ static void mroute_add_all() for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { if (pim_mroute_add(c_oil)) { /* just log warning */ - char source_str[100]; - char group_str[100]; + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC", @@ -2267,8 +2267,8 @@ static void mroute_del_all() for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { if (pim_mroute_del(c_oil)) { /* just log warning */ - char source_str[100]; - char group_str[100]; + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC", @@ -2286,8 +2286,8 @@ static void static_mroute_add_all() for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { if (pim_mroute_add(&s_route->c_oil)) { /* just log warning */ - char source_str[100]; - char group_str[100]; + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str)); pim_inet4_dump("", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str)); zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC", @@ -2305,8 +2305,8 @@ static void static_mroute_del_all() for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { if (pim_mroute_del(&s_route->c_oil)) { /* just log warning */ - char source_str[100]; - char group_str[100]; + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str)); pim_inet4_dump("", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str)); zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC", @@ -2843,8 +2843,8 @@ static void show_mroute(struct vty *vty, u_char uj) /* print list of PIM and IGMP routes */ for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { - char grp_str[100]; - char src_str[100]; + char grp_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; char in_ifname[16]; char out_ifname[16]; int oif_vif_index; @@ -2978,8 +2978,8 @@ static void show_mroute(struct vty *vty, u_char uj) /* Print list of static routes */ for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { - char grp_str[100]; - char src_str[100]; + char grp_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; char in_ifname[16]; char out_ifname[16]; int oif_vif_index; @@ -3124,8 +3124,8 @@ static void show_mroute_count(struct vty *vty) /* Print PIM and IGMP route counts */ for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; if (!c_oil->installed) continue; @@ -3147,8 +3147,8 @@ static void show_mroute_count(struct vty *vty) /* Print static route counts */ for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; if (!s_route->c_oil.installed) continue; @@ -3193,7 +3193,7 @@ DEFUN (show_ip_rib, struct in_addr addr; const char *addr_str; struct pim_nexthop nexthop; - char nexthop_addr_str[100]; + char nexthop_addr_str[PREFIX_STRLEN]; int result; addr_str = argv[idx_ipv4]->arg; @@ -3242,11 +3242,11 @@ static void show_ssmpingd(struct vty *vty) now = pim_time_monotonic_sec(); for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) { - char source_str[100]; + char source_str[INET_ADDRSTRLEN]; char ss_uptime[10]; struct sockaddr_in bind_addr; socklen_t len = sizeof(bind_addr); - char bind_addr_str[100]; + char bind_addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", ss->source_addr, source_str, sizeof(source_str)); @@ -3725,7 +3725,7 @@ static void igmp_sock_query_interval_reconfig(struct igmp_sock *igmp) pim_ifp = ifp->info; if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[100]; + char ifaddr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); zlog_debug("%s: Querier %s on %s reconfig query_interval=%d", __PRETTY_FUNCTION__, diff --git a/pimd/pim_hello.c b/pimd/pim_hello.c index 434a0e66c4..dd827c43b7 100644 --- a/pimd/pim_hello.c +++ b/pimd/pim_hello.c @@ -38,7 +38,7 @@ static void on_trace(const char *label, struct interface *ifp, struct in_addr src) { if (PIM_DEBUG_PIM_TRACE) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src, src_str, sizeof(src_str)); zlog_debug("%s: from %s on %s", label, src_str, ifp->name); @@ -50,7 +50,7 @@ static void tlv_trace_bool(const char *label, const char *tlv_name, int isset, int value) { if (isset) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_debug("%s: PIM hello option from %s on interface %s: %s=%d", label, @@ -64,7 +64,7 @@ static void tlv_trace_uint16(const char *label, const char *tlv_name, int isset, uint16_t value) { if (isset) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_debug("%s: PIM hello option from %s on interface %s: %s=%u", label, @@ -78,7 +78,7 @@ static void tlv_trace_uint32(const char *label, const char *tlv_name, int isset, uint32_t value) { if (isset) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_debug("%s: PIM hello option from %s on interface %s: %s=%u", label, @@ -92,7 +92,7 @@ static void tlv_trace_uint32_hex(const char *label, const char *tlv_name, int isset, uint32_t value) { if (isset) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_debug("%s: PIM hello option from %s on interface %s: %s=%08x", label, @@ -107,7 +107,7 @@ static void tlv_trace(const char *label, const char *tlv_name, int isset) { if (isset) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_debug("%s: PIM hello option from %s on interface %s: %s", label, @@ -122,7 +122,7 @@ static void tlv_trace_list(const char *label, const char *tlv_name, int isset, struct list *addr_list) { if (isset) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_debug("%s: PIM hello option from %s on interface %s: %s size=%d list=%p", label, @@ -182,7 +182,7 @@ int pim_hello_recv(struct interface *ifp, if (remain < PIM_TLV_MIN_SIZE) { if (PIM_DEBUG_PIM_HELLO) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_debug("%s: short PIM hello TLV size=%d < min=%d from %s on interface %s", __PRETTY_FUNCTION__, @@ -199,7 +199,7 @@ int pim_hello_recv(struct interface *ifp, if ((tlv_curr + option_len) > tlv_pastend) { if (PIM_DEBUG_PIM_HELLO) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_debug("%s: long PIM hello TLV type=%d length=%d > left=%td from %s on interface %s", __PRETTY_FUNCTION__, @@ -210,7 +210,7 @@ int pim_hello_recv(struct interface *ifp, } if (PIM_DEBUG_PIM_HELLO) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_debug("%s: parse left_size=%d: PIM hello TLV type=%d length=%d from %s on %s", __PRETTY_FUNCTION__, @@ -268,7 +268,7 @@ int pim_hello_recv(struct interface *ifp, break; case PIM_MSG_OPTION_TYPE_DM_STATE_REFRESH: if (PIM_DEBUG_PIM_HELLO) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_debug("%s: ignoring PIM hello dense-mode state refresh TLV option type=%d length=%d from %s on interface %s", __PRETTY_FUNCTION__, @@ -278,7 +278,7 @@ int pim_hello_recv(struct interface *ifp, break; default: if (PIM_DEBUG_PIM_HELLO) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_debug("%s: ignoring unknown PIM hello TLV type=%d length=%d from %s on interface %s", __PRETTY_FUNCTION__, @@ -327,7 +327,7 @@ int pim_hello_recv(struct interface *ifp, if (!PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) { if (PIM_DEBUG_PIM_HELLO) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_debug("%s: PIM hello missing holdtime from %s on interface %s", __PRETTY_FUNCTION__, @@ -354,7 +354,7 @@ int pim_hello_recv(struct interface *ifp, PIM_NEIGHBOR_SEND_DELAY); if (!neigh) { if (PIM_DEBUG_PIM_HELLO) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: failure creating PIM neighbor %s on interface %s", __PRETTY_FUNCTION__, @@ -378,7 +378,7 @@ int pim_hello_recv(struct interface *ifp, /* GenID mismatch, then replace neighbor */ if (PIM_DEBUG_PIM_HELLO) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_debug("%s: GenId mismatch new=%08x old=%08x: replacing neighbor %s on %s", __PRETTY_FUNCTION__, @@ -401,7 +401,7 @@ int pim_hello_recv(struct interface *ifp, PIM_NEIGHBOR_SEND_NOW); if (!neigh) { if (PIM_DEBUG_PIM_HELLO) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_debug("%s: failure re-creating PIM neighbor %s on interface %s", __PRETTY_FUNCTION__, diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index ceab93edff..3f3629395c 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -295,8 +295,8 @@ static int detect_primary_address_change(struct interface *ifp, changed = new_prim_addr.s_addr != pim_ifp->primary_address.s_addr; if (PIM_DEBUG_ZEBRA) { - char new_prim_str[100]; - char old_prim_str[100]; + char new_prim_str[INET_ADDRSTRLEN]; + char old_prim_str[INET_ADDRSTRLEN]; pim_inet4_dump("", new_prim_addr, new_prim_str, sizeof(new_prim_str)); pim_inet4_dump("", pim_ifp->primary_address, old_prim_str, sizeof(old_prim_str)); zlog_debug("%s: old=%s new=%s on interface %s: %s", @@ -965,7 +965,7 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp, } if (PIM_DEBUG_PIM_TRACE) { - char addr_str[100]; + char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_debug("%s: neighbor not found for address %s on interface %s", __PRETTY_FUNCTION__, @@ -1051,8 +1051,8 @@ static struct igmp_join *igmp_join_new(struct interface *ifp, join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr, source_addr); if (join_fd < 0) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); zlog_warn("%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", @@ -1063,8 +1063,8 @@ static struct igmp_join *igmp_join_new(struct interface *ifp, ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij)); if (!ij) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); zlog_err("%s: XCALLOC(%zu) failure for IGMP group %s source %s on interface %s", @@ -1111,8 +1111,8 @@ int pim_if_igmp_join_add(struct interface *ifp, ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr); if (ij) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); zlog_warn("%s: can't re-join existing IGMP group %s source %s on interface %s", @@ -1123,8 +1123,8 @@ int pim_if_igmp_join_add(struct interface *ifp, ij = igmp_join_new(ifp, group_addr, source_addr); if (!ij) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); zlog_warn("%s: igmp_join_new() failure for IGMP group %s source %s on interface %s", @@ -1134,8 +1134,8 @@ int pim_if_igmp_join_add(struct interface *ifp, } if (PIM_DEBUG_IGMP_EVENTS) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); zlog_debug("%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s", @@ -1172,8 +1172,8 @@ int pim_if_igmp_join_del(struct interface *ifp, ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr); if (!ij) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); zlog_warn("%s: could not find IGMP group %s source %s on interface %s", @@ -1183,8 +1183,8 @@ int pim_if_igmp_join_del(struct interface *ifp, } if (close(ij->sock_fd)) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); zlog_warn("%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s", diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 2f9e9b5981..93a6cad649 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -524,8 +524,8 @@ static void check_recv_upstream(int is_join, /* upstream directed to RPF'(S,G) ? */ if (upstream.s_addr != up->rpf.rpf_addr.u.prefix4.s_addr) { - char up_str[100]; - char rpf_str[100]; + char up_str[INET_ADDRSTRLEN]; + char rpf_str[PREFIX_STRLEN]; pim_inet4_dump("", upstream, up_str, sizeof(up_str)); pim_addr_dump("", &up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); zlog_warn("%s %s: (S,G)=%s upstream=%s not directed to RPF'(S,G)=%s on interface %s", @@ -579,7 +579,7 @@ static int nonlocal_upstream(int is_join, is_local = (upstream.s_addr == recv_pim_ifp->primary_address.s_addr); if (PIM_DEBUG_PIM_TRACE) { - char up_str[100]; + char up_str[INET_ADDRSTRLEN]; pim_inet4_dump("", upstream, up_str, sizeof(up_str)); zlog_warn("%s: recv %s (S,G)=%s to %s upstream=%s on %s", __PRETTY_FUNCTION__, @@ -638,7 +638,7 @@ void pim_ifchannel_join_add(struct interface *ifp, address of the join message is our primary address. */ if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { - char neigh_str[100]; + char neigh_str[INET_ADDRSTRLEN]; pim_inet4_dump("", neigh_addr, neigh_str, sizeof(neigh_str)); zlog_warn("%s: Assert Loser recv Join%s from %s on %s", __PRETTY_FUNCTION__, @@ -881,8 +881,8 @@ void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch) return; if (PIM_DEBUG_PIM_EVENTS) { - char src_str[100]; - char grp_str[100]; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; pim_inet4_dump("", ch->sg.src, src_str, sizeof(src_str)); pim_inet4_dump("", ch->sg.grp, grp_str, sizeof(grp_str)); zlog_debug("%s: CouldAssert(%s,%s,%s) changed from %d to %d", @@ -923,10 +923,10 @@ void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch) return; if (PIM_DEBUG_PIM_EVENTS) { - char src_str[100]; - char grp_str[100]; - char old_addr_str[100]; - char new_addr_str[100]; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + char old_addr_str[INET_ADDRSTRLEN]; + char new_addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", ch->sg.src, src_str, sizeof(src_str)); pim_inet4_dump("", ch->sg.grp, grp_str, sizeof(grp_str)); pim_inet4_dump("", ch->ifassert_my_metric.ip_address, old_addr_str, sizeof(old_addr_str)); @@ -961,8 +961,8 @@ void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch) return; if (PIM_DEBUG_PIM_EVENTS) { - char src_str[100]; - char grp_str[100]; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; pim_inet4_dump("", ch->sg.src, src_str, sizeof(src_str)); pim_inet4_dump("", ch->sg.grp, grp_str, sizeof(grp_str)); zlog_debug("%s: AssertTrackingDesired(%s,%s,%s) changed from %d to %d", diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 56f2457f97..5532dc1dd0 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -161,7 +161,7 @@ static int pim_igmp_other_querier_expire(struct thread *t) zassert(!igmp->t_igmp_query_timer); if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[100]; + char ifaddr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); zlog_debug("%s: Querier %s resuming", __PRETTY_FUNCTION__, @@ -197,7 +197,7 @@ void pim_igmp_other_querier_timer_on(struct igmp_sock *igmp) */ if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[100]; + char ifaddr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); zlog_debug("Querier %s resetting TIMER event for Other-Querier-Present", ifaddr_str); @@ -240,7 +240,7 @@ void pim_igmp_other_querier_timer_on(struct igmp_sock *igmp) pim_ifp->igmp_query_max_response_time_dsec); if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[100]; + char ifaddr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); zlog_debug("Querier %s scheduling %ld.%03ld sec TIMER event for Other-Querier-Present", ifaddr_str, @@ -259,7 +259,7 @@ void pim_igmp_other_querier_timer_off(struct igmp_sock *igmp) if (PIM_DEBUG_IGMP_TRACE) { if (igmp->t_other_querier_timer) { - char ifaddr_str[100]; + char ifaddr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); zlog_debug("IGMP querier %s fd=%d cancelling other-querier-present TIMER event on %s", ifaddr_str, igmp->fd, igmp->interface->name); @@ -321,7 +321,7 @@ igmp_recv_query(struct igmp_sock *igmp, int query_version, } if (PIM_DEBUG_IGMP_PACKETS) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); zlog_debug("Recv IGMP query v%d from %s on %s for group %s", query_version, from_str, ifp->name, group_str); @@ -338,7 +338,7 @@ igmp_recv_query(struct igmp_sock *igmp, int query_version, if (ntohl(from.s_addr) < ntohl(igmp->ifaddr.s_addr)) { if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[100]; + char ifaddr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); zlog_debug("%s: local address %s (%u) lost querier election to %s (%u)", ifp->name, @@ -361,7 +361,7 @@ static void on_trace(const char *label, struct interface *ifp, struct in_addr from) { if (PIM_DEBUG_IGMP_TRACE) { - char from_str[100]; + char from_str[INET_ADDRSTRLEN]; pim_inet4_dump("", from, from_str, sizeof(from_str)); zlog_debug("%s: from %s on %s", label, from_str, ifp->name); @@ -410,8 +410,8 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len) char *igmp_msg; int igmp_msg_len; int msg_type; - char from_str[100]; - char to_str[100]; + char from_str[INET_ADDRSTRLEN]; + char to_str[INET_ADDRSTRLEN]; if (len < sizeof(*ip_hdr)) { zlog_warn("IGMP packet size=%zu shorter than minimum=%zu", @@ -560,7 +560,7 @@ void pim_igmp_general_query_on(struct igmp_sock *igmp) } if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[100]; + char ifaddr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); zlog_debug("Querier %s scheduling %d-second (%s) TIMER event for IGMP query on fd=%d", ifaddr_str, @@ -580,7 +580,7 @@ void pim_igmp_general_query_off(struct igmp_sock *igmp) if (PIM_DEBUG_IGMP_TRACE) { if (igmp->t_igmp_query_timer) { - char ifaddr_str[100]; + char ifaddr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); zlog_debug("IGMP querier %s fd=%d cancelling query TIMER event on %s", ifaddr_str, igmp->fd, igmp->interface->name); @@ -629,8 +629,8 @@ static int pim_igmp_general_query(struct thread *t) group_addr.s_addr = PIM_NET_INADDR_ANY; if (PIM_DEBUG_IGMP_TRACE) { - char querier_str[100]; - char dst_str[100]; + char querier_str[INET_ADDRSTRLEN]; + char dst_str[INET_ADDRSTRLEN]; pim_inet4_dump("", igmp->ifaddr, querier_str, sizeof(querier_str)); pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); @@ -719,7 +719,7 @@ static void igmp_group_delete(struct igmp_group *group) struct igmp_source *src; if (PIM_DEBUG_IGMP_TRACE) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); zlog_debug("Deleting IGMP group %s from socket %d interface %s", group_str, @@ -887,7 +887,7 @@ static int igmp_group_timer(struct thread *t) zassert(group); if (PIM_DEBUG_IGMP_TRACE) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); zlog_debug("%s: Timer for group %s on interface %s", __PRETTY_FUNCTION__, @@ -926,7 +926,7 @@ static void group_timer_off(struct igmp_group *group) return; if (PIM_DEBUG_IGMP_TRACE) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); zlog_debug("Cancelling TIMER event for group %s on %s", group_str, group->group_igmp_sock->interface->name); @@ -942,7 +942,7 @@ void igmp_group_timer_on(struct igmp_group *group, group_timer_off(group); if (PIM_DEBUG_IGMP_EVENTS) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); zlog_debug("Scheduling %ld.%03ld sec TIMER event for group %s on %s", interval_msec / 1000, @@ -1033,7 +1033,7 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, listnode_add(igmp->igmp_group_list, group); if (PIM_DEBUG_IGMP_TRACE) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); zlog_debug("Creating new IGMP group %s on socket %d interface %s", group_str, igmp->fd, igmp->interface->name); diff --git a/pimd/pim_igmpv2.c b/pimd/pim_igmpv2.c index cc78f18d7c..4f005f0195 100644 --- a/pimd/pim_igmpv2.c +++ b/pimd/pim_igmpv2.c @@ -33,7 +33,7 @@ on_trace (const char *label, struct interface *ifp, struct in_addr from) { if (PIM_DEBUG_IGMP_TRACE) { - char from_str[100]; + char from_str[INET_ADDRSTRLEN]; pim_inet4_dump("", from, from_str, sizeof(from_str)); zlog_debug("%s: from %s on %s", label, from_str, ifp->name); @@ -69,8 +69,8 @@ igmp_v2_send_query (struct igmp_group *group, *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum; if (PIM_DEBUG_IGMP_PACKETS) { - char dst_str[100]; - char group_str[100]; + char dst_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); zlog_debug("Send IGMPv2 QUERY to %s on %s for group %s", @@ -85,8 +85,8 @@ igmp_v2_send_query (struct igmp_group *group, sent = sendto(fd, query_buf, msg_size, MSG_DONTWAIT, (struct sockaddr *)&to, tolen); if (sent != (ssize_t) msg_size) { - char dst_str[100]; - char group_str[100]; + char dst_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); if (sent < 0) { @@ -108,7 +108,7 @@ igmp_v2_recv_report (struct igmp_sock *igmp, { struct interface *ifp = igmp->interface; struct in_addr group_addr; - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; on_trace(__PRETTY_FUNCTION__, igmp->interface, from); @@ -151,7 +151,7 @@ igmp_v2_recv_leave (struct igmp_sock *igmp, { struct interface *ifp = igmp->interface; struct in_addr group_addr; - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; on_trace(__PRETTY_FUNCTION__, igmp->interface, from); diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index 21a5176a9d..706f708dd1 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -47,8 +47,8 @@ static void on_trace(const char *label, int num_sources, struct in_addr *sources) { if (PIM_DEBUG_IGMP_TRACE) { - char from_str[100]; - char group_str[100]; + char from_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", from, from_str, sizeof(from_str)); pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); @@ -89,7 +89,7 @@ void igmp_group_reset_gmi(struct igmp_group *group) pim_ifp->igmp_query_max_response_time_dsec); if (PIM_DEBUG_IGMP_TRACE) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); zlog_debug("Resetting group %s timer to GMI=%ld.%03ld sec on %s", group_str, @@ -122,8 +122,8 @@ static int igmp_source_timer(struct thread *t) group = source->source_group; if (PIM_DEBUG_IGMP_TRACE) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); zlog_debug("%s: Source timer expired for group %s source %s on %s", @@ -187,8 +187,8 @@ static void source_timer_off(struct igmp_group *group, return; if (PIM_DEBUG_IGMP_TRACE) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); zlog_debug("Cancelling TIMER event for group %s source %s on %s", @@ -207,8 +207,8 @@ static void igmp_source_timer_on(struct igmp_group *group, source_timer_off(group, source); if (PIM_DEBUG_IGMP_EVENTS) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); zlog_debug("Scheduling %ld.%03ld sec TIMER event for group %s source %s on %s", @@ -248,8 +248,8 @@ void igmp_source_reset_gmi(struct igmp_sock *igmp, pim_ifp->igmp_query_max_response_time_dsec); if (PIM_DEBUG_IGMP_TRACE) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); @@ -355,8 +355,8 @@ void igmp_source_delete(struct igmp_source *source) group = source->source_group; if (PIM_DEBUG_IGMP_TRACE) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); zlog_debug("Deleting IGMP source %s for group %s from socket %d interface %s", @@ -370,8 +370,8 @@ void igmp_source_delete(struct igmp_source *source) /* sanity check that forwarding has been disabled */ if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); zlog_warn("%s: forwarding=ON(!) IGMP source %s for group %s from socket %d interface %s", @@ -440,8 +440,8 @@ source_new (struct igmp_group *group, struct igmp_source *src; if (PIM_DEBUG_IGMP_TRACE) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", src_addr, source_str, sizeof(source_str)); zlog_debug("Creating new IGMP source %s for group %s on socket %d interface %s", @@ -1044,7 +1044,7 @@ static void group_retransmit_group(struct igmp_group *group) s_flag = igmp_group_timer_remain_msec(group) > lmqt_msec; if (PIM_DEBUG_IGMP_TRACE) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); zlog_debug("retransmit_group_specific_query: group %s on %s: s_flag=%d count=%d", group_str, igmp->interface->name, s_flag, @@ -1143,7 +1143,7 @@ static int group_retransmit_sources(struct igmp_group *group, num_sources_tosend2 = source_addr2 - (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET); if (PIM_DEBUG_IGMP_TRACE) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); zlog_debug("retransmit_grp&src_specific_query: group %s on %s: srcs_with_sflag=%d srcs_wo_sflag=%d will_send_sflag=%d retransmit_src_left=%d", group_str, igmp->interface->name, @@ -1163,7 +1163,7 @@ static int group_retransmit_sources(struct igmp_group *group, query_buf1_max_sources = (sizeof(query_buf1) - IGMP_V3_SOURCES_OFFSET) >> 2; if (num_sources_tosend1 > query_buf1_max_sources) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); zlog_warn("%s: group %s on %s: s_flag=1 unable to fit %d sources into buf_size=%zu (max_sources=%d)", __PRETTY_FUNCTION__, group_str, igmp->interface->name, @@ -1205,7 +1205,7 @@ static int group_retransmit_sources(struct igmp_group *group, query_buf2_max_sources = (sizeof(query_buf2) - IGMP_V3_SOURCES_OFFSET) >> 2; if (num_sources_tosend2 > query_buf2_max_sources) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); zlog_warn("%s: group %s on %s: s_flag=0 unable to fit %d sources into buf_size=%zu (max_sources=%d)", __PRETTY_FUNCTION__, group_str, igmp->interface->name, @@ -1250,7 +1250,7 @@ static int igmp_group_retransmit(struct thread *t) zassert(group); if (PIM_DEBUG_IGMP_TRACE) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); zlog_debug("group_retransmit_timer: group %s on %s", group_str, group->group_igmp_sock->interface->name); @@ -1316,7 +1316,7 @@ static void group_retransmit_timer_on(struct igmp_group *group) lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; if (PIM_DEBUG_IGMP_TRACE) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); zlog_debug("Scheduling %ld.%03ld sec retransmit timer for group %s on %s", lmqi_msec / 1000, @@ -1545,7 +1545,7 @@ void igmp_group_timer_lower_to_lmqt(struct igmp_group *group) lmqt_msec = PIM_IGMP_LMQT_MSEC(lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */ if (PIM_DEBUG_IGMP_TRACE) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); zlog_debug("%s: group %s on %s: LMQC=%d LMQI=%d dsec LMQT=%d msec", __PRETTY_FUNCTION__, @@ -1580,8 +1580,8 @@ void igmp_source_timer_lower_to_lmqt(struct igmp_source *source) lmqt_msec = PIM_IGMP_LMQT_MSEC(lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */ if (PIM_DEBUG_IGMP_TRACE) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); zlog_debug("%s: group %s source %s on %s: LMQC=%d LMQI=%d dsec LMQT=%d msec", @@ -1656,8 +1656,8 @@ igmp_v3_send_query (struct igmp_group *group, *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum; if (PIM_DEBUG_IGMP_PACKETS) { - char dst_str[100]; - char group_str[100]; + char dst_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); zlog_debug("Send IGMPv3 query to %s on %s for group %s, sources=%d msg_size=%zd s_flag=%x QRV=%u QQI=%u QQIC=%02x", @@ -1674,8 +1674,8 @@ igmp_v3_send_query (struct igmp_group *group, sent = sendto(fd, query_buf, msg_size, MSG_DONTWAIT, (struct sockaddr *)&to, tolen); if (sent != (ssize_t) msg_size) { - char dst_str[100]; - char group_str[100]; + char dst_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); if (sent < 0) { @@ -1703,8 +1703,8 @@ igmp_v3_send_query (struct igmp_group *group, if (!s_flag) { /* general query? */ if (PIM_INADDR_IS_ANY(group_addr)) { - char dst_str[100]; - char group_str[100]; + char dst_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); zlog_warn("%s: to %s on %s: group=%s sources=%d: s_flag is clear for general query!", @@ -1759,7 +1759,7 @@ igmp_v3_recv_query (struct igmp_sock *igmp, const char *from_str, char *igmp_msg igmp->querier_query_interval = qqi ? qqi : pim_ifp->igmp_default_query_interval; if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[100]; + char ifaddr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); zlog_debug("Querier %s new query interval is %s QQI=%u sec (recv QQIC=%02x from %s)", ifaddr_str, @@ -1823,7 +1823,7 @@ igmp_v3_recv_query (struct igmp_sock *igmp, const char *from_str, char *igmp_msg } } } else { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); zlog_warn("IGMP query v3 from %s on %s: could not find group %s for timer update", from_str, ifp->name, group_str); diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 0a00be9e60..0490efda9e 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -45,7 +45,7 @@ on_trace (const char *label, struct interface *ifp, struct in_addr src) { if (PIM_DEBUG_PIM_TRACE) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src, src_str, sizeof(src_str)); zlog_debug("%s: from %s on %s", label, src_str, ifp->name); @@ -67,8 +67,8 @@ static void recv_join(struct interface *ifp, sg.grp = group; if (PIM_DEBUG_PIM_TRACE) { - char up_str[100]; - char neigh_str[100]; + char up_str[INET_ADDRSTRLEN]; + char neigh_str[INET_ADDRSTRLEN]; pim_inet4_dump("", upstream, up_str, sizeof(up_str)); pim_inet4_dump("", neigh->source_addr, neigh_str, sizeof(neigh_str)); zlog_warn("%s: join (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", @@ -155,8 +155,8 @@ static void recv_prune(struct interface *ifp, sg.grp = group; if (PIM_DEBUG_PIM_TRACE) { - char up_str[100]; - char neigh_str[100]; + char up_str[INET_ADDRSTRLEN]; + char neigh_str[INET_ADDRSTRLEN]; pim_inet4_dump("", upstream, up_str, sizeof(up_str)); pim_inet4_dump("", neigh->source_addr, neigh_str, sizeof(neigh_str)); zlog_warn("%s: prune (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", @@ -253,7 +253,7 @@ int pim_joinprune_recv(struct interface *ifp, addr_offset = pim_parse_addr_ucast (&msg_upstream_addr, buf, pastend - buf); if (addr_offset < 1) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s", __PRETTY_FUNCTION__, @@ -267,7 +267,7 @@ int pim_joinprune_recv(struct interface *ifp, */ if (msg_upstream_addr.family != AF_INET) { if (PIM_DEBUG_PIM_J_P) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: ignoring join/prune directed to unexpected addr family=%d from %s on %s", __PRETTY_FUNCTION__, @@ -278,7 +278,7 @@ int pim_joinprune_recv(struct interface *ifp, remain = pastend - buf; if (remain < 4) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: short join/prune message buffer for group list: size=%d minimum=%d from %s on %s", __PRETTY_FUNCTION__, @@ -294,8 +294,8 @@ int pim_joinprune_recv(struct interface *ifp, ++buf; if (PIM_DEBUG_PIM_J_P) { - char src_str[100]; - char upstream_str[100]; + char src_str[INET_ADDRSTRLEN]; + char upstream_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); pim_inet4_dump("", msg_upstream_addr.u.prefix4, upstream_str, sizeof(upstream_str)); @@ -323,7 +323,7 @@ int pim_joinprune_recv(struct interface *ifp, remain = pastend - buf; if (remain < 4) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: short join/prune buffer for source list: size=%d minimum=%d from %s on %s", __PRETTY_FUNCTION__, @@ -337,9 +337,9 @@ int pim_joinprune_recv(struct interface *ifp, buf += 2; if (PIM_DEBUG_PIM_J_P) { - char src_str[100]; - char upstream_str[100]; - char group_str[100]; + char src_str[INET_ADDRSTRLEN]; + char upstream_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); pim_inet4_dump("", msg_upstream_addr.u.prefix4, upstream_str, sizeof(upstream_str)); @@ -416,7 +416,7 @@ int pim_joinprune_send(struct interface *ifp, } if (PIM_DEBUG_PIM_J_P) { - char dst_str[100]; + char dst_str[INET_ADDRSTRLEN]; pim_inet4_dump("", upstream_addr, dst_str, sizeof(dst_str)); zlog_debug("%s: sending %s(S,G)=%s to upstream=%s on interface %s", __PRETTY_FUNCTION__, @@ -426,7 +426,7 @@ int pim_joinprune_send(struct interface *ifp, if (PIM_INADDR_IS_ANY(upstream_addr)) { if (PIM_DEBUG_PIM_J_P) { - char dst_str[100]; + char dst_str[INET_ADDRSTRLEN]; pim_inet4_dump("", upstream_addr, dst_str, sizeof(dst_str)); zlog_debug("%s: %s(S,G)=%s: upstream=%s is myself on interface %s", __PRETTY_FUNCTION__, diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 341d733361..982aa9477a 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -402,10 +402,10 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size) struct pim_interface *pim_ifp; const struct ip *ip_hdr; const struct igmpmsg *msg; - char ip_src_str[100] = ""; - char ip_dst_str[100] = ""; - char src_str[100] = ""; - char grp_str[100] = ""; + char ip_src_str[INET_ADDRSTRLEN] = ""; + char ip_dst_str[INET_ADDRSTRLEN] = ""; + char src_str[INET_ADDRSTRLEN] = ""; + char grp_str[INET_ADDRSTRLEN] = ""; struct in_addr ifaddr; struct igmp_sock *igmp; @@ -646,7 +646,7 @@ int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, unsigned ch err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_VIF, (void*) &vc, sizeof(vc)); if (err) { - char ifaddr_str[100]; + char ifaddr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", ifaddr, ifaddr_str, sizeof(ifaddr_str)); diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index 0eadb5eb38..edc7f0ee42 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -128,7 +128,7 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, remain = end - pim_msg_curr; pim_msg_curr = pim_msg_addr_encode_ipv4_ucast (pim_msg_curr, buf_size - PIM_MSG_HEADER_LEN, upstream); if (!pim_msg_curr) { - char dst_str[100]; + char dst_str[INET_ADDRSTRLEN]; pim_inet4_dump("", upstream, dst_str, sizeof(dst_str)); zlog_warn("%s: failure encoding destination address %s: space left=%d", __PRETTY_FUNCTION__, dst_str, remain); @@ -155,7 +155,7 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, pim_msg_curr = pim_msg_addr_encode_ipv4_group (pim_msg_curr, remain, group); if (!pim_msg_curr) { - char group_str[100]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group, group_str, sizeof(group_str)); zlog_warn("%s: failure encoding group address %s: space left=%d", __PRETTY_FUNCTION__, group_str, remain); @@ -193,7 +193,7 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, } pim_msg_curr = pim_msg_addr_encode_ipv4_source (pim_msg_curr, remain, stosend, bits); if (!pim_msg_curr) { - char source_str[100]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", source, source_str, sizeof(source_str)); zlog_warn("%s: failure encoding source address %s: space left=%d", __PRETTY_FUNCTION__, source_str, remain); diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index 3696d2d47e..abca609421 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -129,8 +129,8 @@ int pim_if_dr_election(struct interface *ifp) if (old_dr_addr.s_addr != pim_ifp->pim_dr_addr.s_addr) { if (PIM_DEBUG_PIM_EVENTS) { - char dr_old_str[100]; - char dr_new_str[100]; + char dr_old_str[INET_ADDRSTRLEN]; + char dr_new_str[INET_ADDRSTRLEN]; pim_inet4_dump("", old_dr_addr, dr_old_str, sizeof(dr_old_str)); pim_inet4_dump("", pim_ifp->pim_dr_addr, dr_new_str, sizeof(dr_new_str)); zlog_debug("%s: DR was %s now is %s on interface %s", @@ -218,7 +218,7 @@ static int on_neighbor_timer(struct thread *t) ifp = neigh->interface; if (PIM_DEBUG_PIM_TRACE) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", neigh->source_addr, src_str, sizeof(src_str)); zlog_debug("Expired %d sec holdtime for neighbor %s on interface %s", neigh->holdtime, src_str, ifp->name); @@ -245,7 +245,7 @@ static void neighbor_timer_off(struct pim_neighbor *neigh) { if (PIM_DEBUG_PIM_TRACE_DETAIL) { if (neigh->t_expire_timer) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", neigh->source_addr, src_str, sizeof(src_str)); zlog_debug("%s: cancelling timer for neighbor %s on %s", __PRETTY_FUNCTION__, @@ -270,7 +270,7 @@ void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime) } if (PIM_DEBUG_PIM_TRACE_DETAIL) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", neigh->source_addr, src_str, sizeof(src_str)); zlog_debug("%s: starting %u sec timer for neighbor %s on %s", __PRETTY_FUNCTION__, @@ -294,7 +294,7 @@ static struct pim_neighbor *pim_neighbor_new(struct interface *ifp, { struct pim_interface *pim_ifp; struct pim_neighbor *neigh; - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; zassert(ifp); pim_ifp = ifp->info; @@ -541,7 +541,7 @@ void pim_neighbor_delete(struct interface *ifp, const char *delete_message) { struct pim_interface *pim_ifp; - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_ifp = ifp->info; zassert(pim_ifp); @@ -679,9 +679,9 @@ static void delete_from_neigh_addr(struct interface *ifp, { struct prefix *p = pim_neighbor_find_secondary(neigh, addr->u.prefix4); if (p) { - char addr_str[100]; - char this_neigh_str[100]; - char other_neigh_str[100]; + char addr_str[INET_ADDRSTRLEN]; + char this_neigh_str[INET_ADDRSTRLEN]; + char other_neigh_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr->u.prefix4, addr_str, sizeof(addr_str)); pim_inet4_dump("", neigh_addr, this_neigh_str, sizeof(this_neigh_str)); diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 7fe4d8af32..9416503204 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -206,8 +206,8 @@ pim_channel_del_oif (struct channel_oil *channel_oil, if (PIM_DEBUG_MROUTE) { - char group_str[100]; - char source_str[100]; + 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: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d", @@ -224,8 +224,8 @@ pim_channel_del_oif (struct channel_oil *channel_oil, { if (PIM_DEBUG_MROUTE) { - char group_str[100]; - char source_str[100]; + 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: no existing protocol mask %u(%u) for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", @@ -244,8 +244,8 @@ pim_channel_del_oif (struct channel_oil *channel_oil, { if (PIM_DEBUG_MROUTE) { - char group_str[100]; - char source_str[100]; + 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: other protocol masks remain for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", @@ -262,8 +262,8 @@ pim_channel_del_oif (struct channel_oil *channel_oil, if (pim_mroute_add (channel_oil)) { if (PIM_DEBUG_MROUTE) { - char group_str[100]; - char source_str[100]; + 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: could not remove output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)", @@ -298,8 +298,8 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, pim_ifp = oif->info; if (PIM_DEBUG_MROUTE) { - char group_str[100]; - char source_str[100]; + 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: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d", @@ -323,8 +323,8 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, if (pim_ifp->mroute_vif_index == channel_oil->oil.mfcc_parent) { if (PIM_DEBUG_MROUTE) { - char group_str[100]; - char source_str[100]; + 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: refusing protocol mask %u request for IIF=OIF=%s (vif_index=%d) for channel (S,G)=(%s,%s)", @@ -341,8 +341,8 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask) { if (PIM_DEBUG_MROUTE) { - char group_str[100]; - char source_str[100]; + 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: existing protocol mask %u requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", @@ -364,8 +364,8 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) { if (PIM_DEBUG_MROUTE) { - char group_str[100]; - char source_str[100]; + 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)", @@ -384,8 +384,8 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, if (old_ttl > 0) { if (PIM_DEBUG_MROUTE) { - char group_str[100]; - char source_str[100]; + 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: interface %s (vif_index=%d) is existing output for channel (S,G)=(%s,%s)", @@ -401,8 +401,8 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, if (pim_mroute_add(channel_oil)) { if (PIM_DEBUG_MROUTE) { - char group_str[100]; - char source_str[100]; + 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: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)", @@ -420,8 +420,8 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask; if (PIM_DEBUG_MROUTE) { - char group_str[100]; - char source_str[100]; + 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: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE", diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index b10528536e..1e71b0ad78 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -132,8 +132,8 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) { struct ip *ip_hdr; size_t ip_hlen; /* ip header length in bytes */ - char src_str[100]; - char dst_str[100]; + char src_str[INET_ADDRSTRLEN]; + char dst_str[INET_ADDRSTRLEN]; uint8_t *pim_msg; int pim_msg_len; uint8_t pim_version; @@ -318,8 +318,8 @@ static int pim_sock_read(struct thread *t) } if (PIM_DEBUG_PIM_PACKETS) { - char from_str[100]; - char to_str[100]; + char from_str[INET_ADDRSTRLEN]; + char to_str[INET_ADDRSTRLEN]; if (!inet_ntop(AF_INET, &from.sin_addr, from_str, sizeof(from_str))) sprintf(from_str, ""); @@ -337,8 +337,8 @@ static int pim_sock_read(struct thread *t) #ifdef PIM_CHECK_RECV_IFINDEX_SANITY /* ifindex sanity check */ if (ifindex != (int) ifp->ifindex) { - char from_str[100]; - char to_str[100]; + char from_str[INET_ADDRSTRLEN]; + char to_str[INET_ADDRSTRLEN]; struct interface *recv_ifp; if (!inet_ntop(AF_INET, &from.sin_addr, from_str , sizeof(from_str))) @@ -489,7 +489,7 @@ pim_msg_send_frame (int fd, char *buf, size_t len, while (sendto (fd, buf, len, MSG_DONTWAIT, dst, salen) < 0) { - char dst_str[100]; + char dst_str[INET_ADDRSTRLEN]; switch (errno) { @@ -559,7 +559,7 @@ pim_msg_send(int fd, struct in_addr src, ip->ip_len = htons (sendlen); if (PIM_DEBUG_PIM_PACKETS) { - char dst_str[100]; + char dst_str[INET_ADDRSTRLEN]; pim_inet4_dump("", dst, dst_str, sizeof(dst_str)); zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x", __PRETTY_FUNCTION__, @@ -592,7 +592,7 @@ static int hello_send(struct interface *ifp, pim_ifp = ifp->info; if (PIM_DEBUG_PIM_HELLO) { - char dst_str[100]; + char dst_str[INET_ADDRSTRLEN]; pim_inet4_dump("", qpim_all_pim_routers_addr, dst_str, sizeof(dst_str)); zlog_debug("%s: to %s on %s: holdt=%u prop_d=%u overr_i=%u dis_join_supp=%d dr_prio=%u gen_id=%08x addrs=%d", __PRETTY_FUNCTION__, diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 216e3390a6..62973bc9c1 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -156,7 +156,7 @@ pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct if (PIM_DEBUG_PIM_REG) { - char rp_str[100]; + char rp_str[INET_ADDRSTRLEN]; strcpy (rp_str, inet_ntoa (rpg->rpf_addr.u.prefix4)); zlog_debug ("Sending %sRegister Packet to %s", null_register ? "NULL " : "", rp_str); } @@ -259,7 +259,7 @@ pim_register_recv (struct interface *ifp, if (!pim_rp_check_is_my_ip_address (ip_hdr->ip_dst, dest_addr)) { if (PIM_DEBUG_PIM_REG) { - char dest[100]; + char dest[INET_ADDRSTRLEN]; pim_inet4_dump ("", dest_addr, dest, sizeof(dest)); zlog_debug ("%s: Received Register message for %s that I do not own", __func__, @@ -270,7 +270,7 @@ pim_register_recv (struct interface *ifp, if (PIM_DEBUG_PIM_REG) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump ("", src_addr, src_str, sizeof (src_str)); zlog_debug ("Received Register message from %s on %s", src_str, ifp->name); diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 98fc2eaabd..817837afbf 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -516,9 +516,9 @@ pim_rp_check_rp (struct in_addr old, struct in_addr new) for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { if (PIM_DEBUG_ZEBRA) { - char sold[100]; - char snew[100]; - char rp[100]; + char sold[INET_ADDRSTRLEN]; + char snew[INET_ADDRSTRLEN]; + char rp[PREFIX_STRLEN]; pim_addr_dump("", &rp_info->rp.rpf_addr, rp, sizeof(rp)); pim_inet4_dump("", old, sold, sizeof(sold)); pim_inet4_dump("", new, snew, sizeof(snew)); diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 46a6ef1ca4..ffedd84103 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -51,7 +51,7 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei MULTIPATH_NUM, addr, PIM_NEXTHOP_LOOKUP_MAX); if (num_ifindex < 1) { - char addr_str[100]; + char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_warn("%s %s: could not find nexthop ifindex for address %s", __FILE__, __PRETTY_FUNCTION__, @@ -68,7 +68,7 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei { if (PIM_DEBUG_ZEBRA) { - char addr_str[100]; + char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_debug("%s %s: could not find interface for ifindex %d (address %s)", __FILE__, __PRETTY_FUNCTION__, @@ -79,7 +79,7 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei if (!ifp->info && PIM_DEBUG_ZEBRA) { - char addr_str[100]; + char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_debug("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", __PRETTY_FUNCTION__, @@ -105,8 +105,8 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei if (found) { if (PIM_DEBUG_ZEBRA) { - char nexthop_str[100]; - char addr_str[100]; + char nexthop_str[PREFIX_STRLEN]; + char addr_str[INET_ADDRSTRLEN]; pim_addr_dump("", &nexthop_tab[0].nexthop_addr, nexthop_str, sizeof(nexthop_str)); pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_debug("%s %s: found nexthop %s for address %s: interface %s ifindex=%d metric=%d pref=%d", @@ -167,7 +167,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_ if (nexthop_mismatch(&rpf->source_nexthop, &save_nexthop)) { if (PIM_DEBUG_ZEBRA) { - char nhaddr_str[100]; + char nhaddr_str[PREFIX_STRLEN]; pim_addr_dump("", &rpf->source_nexthop.mrib_nexthop_addr, nhaddr_str, sizeof(nhaddr_str)); zlog_debug("%s %s: (S,G)=%s source nexthop now is: interface=%s address=%s pref=%d metric=%d", __FILE__, __PRETTY_FUNCTION__, diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index 8ba514a219..681b5fe5c1 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -269,8 +269,8 @@ int pim_socket_join(int fd, struct in_addr group, ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &opt, sizeof(opt)); if (ret) { - char group_str[100]; - char ifaddr_str[100]; + char group_str[INET_ADDRSTRLEN]; + char ifaddr_str[INET_ADDRSTRLEN]; if (!inet_ntop(AF_INET, &group, group_str , sizeof(group_str))) sprintf(group_str, ""); if (!inet_ntop(AF_INET, &ifaddr, ifaddr_str , sizeof(ifaddr_str))) @@ -282,8 +282,8 @@ int pim_socket_join(int fd, struct in_addr group, } if (PIM_DEBUG_TRACE) { - char group_str[100]; - char ifaddr_str[100]; + char group_str[INET_ADDRSTRLEN]; + char ifaddr_str[INET_ADDRSTRLEN]; if (!inet_ntop(AF_INET, &group, group_str , sizeof(group_str))) sprintf(group_str, ""); if (!inet_ntop(AF_INET, &ifaddr, ifaddr_str , sizeof(ifaddr_str))) @@ -302,8 +302,8 @@ int pim_socket_join_source(int fd, ifindex_t ifindex, const char *ifname) { if (pim_igmp_join_source(fd, ifindex, group_addr, source_addr)) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); zlog_warn("%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s", @@ -380,7 +380,7 @@ int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len, *ifindex = i->ipi_ifindex; if (to && PIM_DEBUG_PACKETS) { - char to_str[100]; + char to_str[INET_ADDRSTRLEN]; pim_inet4_dump("", to->sin_addr, to_str, sizeof(to_str)); zlog_debug("%s: HAVE_IP_PKTINFO to=%s,%d", __PRETTY_FUNCTION__, @@ -400,7 +400,7 @@ int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len, *tolen = sizeof(struct sockaddr_in); if (to && PIM_DEBUG_PACKETS) { - char to_str[100]; + char to_str[INET_ADDRSTRLEN]; pim_inet4_dump("", to->sin_addr, to_str, sizeof(to_str)); zlog_debug("%s: HAVE_IP_RECVDSTADDR to=%s,%d", __PRETTY_FUNCTION__, diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c index 40873ca69f..3d08552de8 100644 --- a/pimd/pim_ssmpingd.c +++ b/pimd/pim_ssmpingd.c @@ -97,7 +97,7 @@ static int ssmpingd_socket(struct in_addr addr, int port, int mttl) sockaddr.sin_port = htons(port); if (bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) { - char addr_str[100]; + char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_warn("%s: bind(fd=%d,addr=%s,port=%d,len=%zu) failure: errno=%d: %s", __PRETTY_FUNCTION__, @@ -196,7 +196,7 @@ static void ssmpingd_delete(struct ssmpingd_sock *ss) THREAD_OFF(ss->t_sock_read); if (close(ss->sock_fd)) { - char source_str[100]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", ss->source_addr, source_str, sizeof(source_str)); zlog_warn("%s: failure closing ssmpingd sock_fd=%d for source %s: errno=%d: %s", __PRETTY_FUNCTION__, @@ -219,7 +219,7 @@ static void ssmpingd_sendto(struct ssmpingd_sock *ss, sent = sendto(ss->sock_fd, buf, len, MSG_DONTWAIT, (struct sockaddr *)&to, tolen); if (sent != len) { - char to_str[100]; + char to_str[INET_ADDRSTRLEN]; pim_inet4_dump("", to.sin_addr, to_str, sizeof(to_str)); if (sent < 0) { zlog_warn("%s: sendto() failure to %s,%d: fd=%d len=%d: errno=%d: %s", @@ -254,7 +254,7 @@ static int ssmpingd_read_msg(struct ssmpingd_sock *ss) &to, &tolen, &ifindex); if (len < 0) { - char source_str[100]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", ss->source_addr, source_str, sizeof(source_str)); zlog_warn("%s: failure receiving ssmping for source %s on fd=%d: errno=%d: %s", __PRETTY_FUNCTION__, source_str, ss->sock_fd, errno, safe_strerror(errno)); @@ -264,9 +264,9 @@ static int ssmpingd_read_msg(struct ssmpingd_sock *ss) ifp = if_lookup_by_index(ifindex); if (buf[0] != PIM_SSMPINGD_REQUEST) { - char source_str[100]; - char from_str[100]; - char to_str[100]; + char source_str[INET_ADDRSTRLEN]; + char from_str[INET_ADDRSTRLEN]; + char to_str[INET_ADDRSTRLEN]; pim_inet4_dump("", ss->source_addr, source_str, sizeof(source_str)); pim_inet4_dump("", from.sin_addr, from_str, sizeof(from_str)); pim_inet4_dump("", to.sin_addr, to_str, sizeof(to_str)); @@ -282,9 +282,9 @@ static int ssmpingd_read_msg(struct ssmpingd_sock *ss) } if (PIM_DEBUG_SSMPINGD) { - char source_str[100]; - char from_str[100]; - char to_str[100]; + char source_str[INET_ADDRSTRLEN]; + char from_str[INET_ADDRSTRLEN]; + char to_str[INET_ADDRSTRLEN]; pim_inet4_dump("", ss->source_addr, source_str, sizeof(source_str)); pim_inet4_dump("", from.sin_addr, from_str, sizeof(from_str)); pim_inet4_dump("", to.sin_addr, to_str, sizeof(to_str)); @@ -356,7 +356,7 @@ static struct ssmpingd_sock *ssmpingd_new(struct in_addr source_addr) sock_fd = ssmpingd_socket(source_addr, /* port: */ 4321, /* mTTL: */ 64); if (sock_fd < 0) { - char source_str[100]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); zlog_warn("%s: ssmpingd_socket() failure for source %s", __PRETTY_FUNCTION__, source_str); @@ -365,7 +365,7 @@ static struct ssmpingd_sock *ssmpingd_new(struct in_addr source_addr) ss = XCALLOC(MTYPE_PIM_SSMPINGD, sizeof(*ss)); if (!ss) { - char source_str[100]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); zlog_err("%s: XCALLOC(%zu) failure for ssmpingd source %s", __PRETTY_FUNCTION__, @@ -398,7 +398,7 @@ int pim_ssmpingd_start(struct in_addr source_addr) } { - char source_str[100]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); zlog_info("%s: starting ssmpingd for source %s", __PRETTY_FUNCTION__, source_str); @@ -406,7 +406,7 @@ int pim_ssmpingd_start(struct in_addr source_addr) ss = ssmpingd_new(source_addr); if (!ss) { - char source_str[100]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); zlog_warn("%s: ssmpingd_new() failure for source %s", __PRETTY_FUNCTION__, source_str); @@ -422,7 +422,7 @@ int pim_ssmpingd_stop(struct in_addr source_addr) ss = ssmpingd_find(source_addr); if (!ss) { - char source_str[100]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); zlog_warn("%s: could not find ssmpingd for source %s", __PRETTY_FUNCTION__, source_str); @@ -430,7 +430,7 @@ int pim_ssmpingd_stop(struct in_addr source_addr) } { - char source_str[100]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); zlog_info("%s: stopping ssmpingd for source %s", __PRETTY_FUNCTION__, source_str); diff --git a/pimd/pim_static.c b/pimd/pim_static.c index a24a3f92a8..443e7cacaa 100644 --- a/pimd/pim_static.c +++ b/pimd/pim_static.c @@ -111,8 +111,8 @@ int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr s_route->source.s_addr == source.s_addr) { if (s_route->iif == iif_index && s_route->oif_ttls[oif_index]) { - char gifaddr_str[100]; - char sifaddr_str[100]; + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group, gifaddr_str, sizeof(gifaddr_str)); pim_inet4_dump("", source, sifaddr_str, sizeof(sifaddr_str)); zlog_warn("%s %s: Unable to add static route: Route already exists (iif=%d,oif=%d,group=%s,source=%s)", @@ -177,8 +177,8 @@ int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr if (pim_mroute_add(&s_route->c_oil)) { - char gifaddr_str[100]; - char sifaddr_str[100]; + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group, gifaddr_str, sizeof(gifaddr_str)); pim_inet4_dump("", source, sifaddr_str, sizeof(sifaddr_str)); zlog_warn("%s %s: Unable to add static route(iif=%d,oif=%d,group=%s,source=%s)", @@ -210,8 +210,8 @@ int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr } if (PIM_DEBUG_STATIC) { - char gifaddr_str[100]; - char sifaddr_str[100]; + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group, gifaddr_str, sizeof(gifaddr_str)); pim_inet4_dump("", source, sifaddr_str, sizeof(sifaddr_str)); zlog_debug("%s: Static route added(iif=%d,oif=%d,group=%s,source=%s)", @@ -255,8 +255,8 @@ int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr /* If there are no more outputs then delete the whole route, otherwise set the route with the new outputs */ if (s_route->c_oil.oil_ref_count <= 0 ? pim_mroute_del(&s_route->c_oil) : pim_mroute_add(&s_route->c_oil)) { - char gifaddr_str[100]; - char sifaddr_str[100]; + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group, gifaddr_str, sizeof(gifaddr_str)); pim_inet4_dump("", source, sifaddr_str, sizeof(sifaddr_str)); zlog_warn("%s %s: Unable to remove static route(iif=%d,oif=%d,group=%s,source=%s)", @@ -281,8 +281,8 @@ int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr } if (PIM_DEBUG_STATIC) { - char gifaddr_str[100]; - char sifaddr_str[100]; + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group, gifaddr_str, sizeof(gifaddr_str)); pim_inet4_dump("", source, sifaddr_str, sizeof(sifaddr_str)); zlog_debug("%s: Static route removed(iif=%d,oif=%d,group=%s,source=%s)", @@ -298,8 +298,8 @@ int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr } if (!node) { - char gifaddr_str[100]; - char sifaddr_str[100]; + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", group, gifaddr_str, sizeof(gifaddr_str)); pim_inet4_dump("", source, sifaddr_str, sizeof(sifaddr_str)); zlog_warn("%s %s: Unable to remove static route: Route does not exist(iif=%d,oif=%d,group=%s,source=%s)", @@ -320,8 +320,8 @@ pim_static_write_mroute (struct vty *vty, struct interface *ifp) struct listnode *node; struct static_route *sroute; int count = 0; - char sbuf[100]; - char gbuf[100]; + char sbuf[INET_ADDRSTRLEN]; + char gbuf[INET_ADDRSTRLEN]; for (ALL_LIST_ELEMENTS_RO (qpim_static_route_list, node, sroute)) { diff --git a/pimd/pim_str.c b/pimd/pim_str.c index 2dffe8c2b8..4c25c00294 100644 --- a/pimd/pim_str.c +++ b/pimd/pim_str.c @@ -65,8 +65,8 @@ void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, int buf_ char * pim_str_sg_dump (const struct prefix_sg *sg) { - char src_str[100]; - char grp_str[100]; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; static char sg_str[200]; pim_inet4_dump ("", sg->src, src_str, sizeof(src_str)); diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index 93227d6339..d083cd8f40 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -274,7 +274,7 @@ static int check_tlv_length(const char *label, const char *tlv_name, int correct_len, int option_len) { if (option_len != correct_len) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: PIM hello %s TLV with incorrect value size=%d correct=%d from %s on interface %s", label, tlv_name, @@ -293,7 +293,7 @@ static void check_tlv_redefinition_uint16(const char *label, const char *tlv_nam uint16_t new, uint16_t old) { if (PIM_OPTION_IS_SET(options, opt_mask)) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s", label, tlv_name, @@ -309,7 +309,7 @@ static void check_tlv_redefinition_uint32(const char *label, const char *tlv_nam uint32_t new, uint32_t old) { if (PIM_OPTION_IS_SET(options, opt_mask)) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s", label, tlv_name, @@ -325,7 +325,7 @@ static void check_tlv_redefinition_uint32_hex(const char *label, const char *tlv uint32_t new, uint32_t old) { if (PIM_OPTION_IS_SET(options, opt_mask)) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: PIM hello TLV redefined %s=%08x old=%08x from %s on interface %s", label, tlv_name, @@ -683,7 +683,7 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, */ addr_offset = pim_parse_addr_ucast(&tmp, addr, pastend - addr); if (addr_offset < 1) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s", __PRETTY_FUNCTION__, @@ -700,8 +700,8 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, switch (tmp.family) { case AF_INET: { - char addr_str[100]; - char src_str[100]; + char addr_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", tmp.u.prefix4, addr_str, sizeof(addr_str)); pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_debug("%s: PIM hello TLV option: list_old_size=%d IPv4 address %s from %s on %s", @@ -713,7 +713,7 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, break; default: { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_debug("%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %s on %s", __PRETTY_FUNCTION__, @@ -730,7 +730,7 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, */ if (tmp.family == AF_INET) { if (tmp.u.prefix4.s_addr == src_addr.s_addr) { - char src_str[100]; + char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); zlog_warn("%s: ignoring primary address in secondary list from %s on %s", __PRETTY_FUNCTION__, diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index a7e40da948..192b6609ed 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -181,7 +181,7 @@ void pim_upstream_send_join (struct pim_upstream *up) { if (PIM_DEBUG_PIM_TRACE) { - char rpf_str[100]; + char rpf_str[PREFIX_STRLEN]; pim_addr_dump("", &up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); zlog_debug ("%s: RPF'%s=%s(%s) for Interface %s", __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg), rpf_str, pim_upstream_state2str (up->join_state), @@ -279,7 +279,7 @@ void pim_upstream_join_suppress(struct pim_upstream *up, join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer); if (PIM_DEBUG_PIM_TRACE) { - char rpf_str[100]; + char rpf_str[INET_ADDRSTRLEN]; pim_inet4_dump("", rpf_addr, rpf_str, sizeof(rpf_str)); zlog_debug("%s %s: detected Join%s to RPF'(S,G)=%s: join_timer=%ld msec t_joinsuppress=%ld msec", __FILE__, __PRETTY_FUNCTION__, @@ -310,7 +310,7 @@ void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label, t_override_msec = pim_if_t_override_msec(up->rpf.source_nexthop.interface); if (PIM_DEBUG_PIM_TRACE) { - char rpf_str[100]; + char rpf_str[INET_ADDRSTRLEN]; pim_inet4_dump("", rpf_addr, rpf_str, sizeof(rpf_str)); zlog_debug("%s: to RPF'%s=%s: join_timer=%ld msec t_override=%d msec", debug_label, @@ -692,8 +692,8 @@ void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr) for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { if (PIM_DEBUG_PIM_TRACE) { - char neigh_str[100]; - char rpf_addr_str[100]; + char neigh_str[INET_ADDRSTRLEN]; + char rpf_addr_str[PREFIX_STRLEN]; pim_inet4_dump("", neigh_addr, neigh_str, sizeof(neigh_str)); pim_addr_dump("", &up->rpf.rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); zlog_debug("%s: matching neigh=%s against upstream (S,G)=%s joined=%d rpf_addr=%s", diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 644fb8e691..f5cdc2bd2c 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -160,7 +160,7 @@ int pim_global_config_write(struct vty *vty) vty_out(vty, "!%s", VTY_NEWLINE); ++writes; for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) { - char source_str[100]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", ss->source_addr, source_str, sizeof(source_str)); vty_out(vty, "ip ssmpingd %s%s", source_str, VTY_NEWLINE); ++writes; @@ -247,8 +247,8 @@ int pim_interface_config_write(struct vty *vty) struct listnode *node; struct igmp_join *ij; for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_join_list, node, ij)) { - char group_str[100]; - char source_str[100]; + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", ij->group_addr, group_str, sizeof(group_str)); pim_inet4_dump("", ij->source_addr, source_str, sizeof(source_str)); vty_out(vty, " ip igmp join %s %s%s", diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index e8460044e1..eac618b438 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -284,7 +284,7 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient, /* but we had a primary address already */ char buf[BUFSIZ]; - char old[100]; + char old[INET_ADDRSTRLEN]; prefix2str(p, buf, BUFSIZ); pim_inet4_dump("", primary_addr, old, sizeof(old)); @@ -436,8 +436,8 @@ pim_scan_individual_oil (struct channel_oil *c_oil) { if (PIM_DEBUG_ZEBRA) { - char source_str[100]; - char group_str[100]; + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); zlog_debug("%s %s: could not find input interface(%d) for (S,G)=(%s,%s)", @@ -461,8 +461,8 @@ pim_scan_individual_oil (struct channel_oil *c_oil) { struct interface *old_iif = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index); - char source_str[100]; - char group_str[100]; + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); zlog_debug("%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d", @@ -478,8 +478,8 @@ pim_scan_individual_oil (struct channel_oil *c_oil) struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index); if (PIM_DEBUG_ZEBRA) { - char source_str[100]; - char group_str[100]; + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); zlog_debug("%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d", @@ -501,8 +501,8 @@ pim_scan_individual_oil (struct channel_oil *c_oil) /* just log warning */ struct interface *old_iif = pim_if_find_by_vif_index(old_vif_index); struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index); - char source_str[100]; - char group_str[100]; + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); zlog_warn("%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d", @@ -804,7 +804,7 @@ static int fib_lookup_if_vif_index(struct in_addr addr) MULTIPATH_NUM, addr, PIM_NEXTHOP_LOOKUP_MAX); if (num_ifindex < 1) { - char addr_str[100]; + char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_warn("%s %s: could not find nexthop ifindex for address %s", __FILE__, __PRETTY_FUNCTION__, @@ -815,7 +815,7 @@ static int fib_lookup_if_vif_index(struct in_addr addr) first_ifindex = nexthop_tab[0].ifindex; if (num_ifindex > 1) { - char addr_str[100]; + char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_info("%s %s: FIXME ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)", __FILE__, __PRETTY_FUNCTION__, @@ -824,7 +824,7 @@ static int fib_lookup_if_vif_index(struct in_addr addr) } if (PIM_DEBUG_ZEBRA) { - char addr_str[100]; + char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_debug("%s %s: found nexthop ifindex=%d (interface %s) for address %s", __FILE__, __PRETTY_FUNCTION__, @@ -834,7 +834,7 @@ static int fib_lookup_if_vif_index(struct in_addr addr) vif_index = pim_if_find_vifindex_by_ifindex(first_ifindex); if (vif_index < 0) { - char addr_str[100]; + char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_warn("%s %s: low vif_index=%d < 1 nexthop for address %s", __FILE__, __PRETTY_FUNCTION__, @@ -845,7 +845,7 @@ static int fib_lookup_if_vif_index(struct in_addr addr) zassert(qpim_mroute_oif_highest_vif_index < MAXVIFS); if (vif_index > qpim_mroute_oif_highest_vif_index) { - char addr_str[100]; + char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_warn("%s %s: high vif_index=%d > highest_vif_index=%d nexthop for address %s", __FILE__, __PRETTY_FUNCTION__, @@ -878,8 +878,8 @@ static int del_oif(struct channel_oil *channel_oil, zassert(pim_ifp->mroute_vif_index <= qpim_mroute_oif_highest_vif_index); if (PIM_DEBUG_MROUTE) { - char group_str[100]; - char source_str[100]; + 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: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d", @@ -893,8 +893,8 @@ static int del_oif(struct channel_oil *channel_oil, if (!(channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask)) { if (PIM_DEBUG_MROUTE) { - char group_str[100]; - char source_str[100]; + 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: nonexistent protocol mask %u removed OIF %s (vif_index=%d, min_ttl=%d) from channel (S,G)=(%s,%s)", @@ -917,8 +917,8 @@ static int del_oif(struct channel_oil *channel_oil, /* Check the OIF keeps existing before returning, and only log warning otherwise */ if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) { - char group_str[100]; - char source_str[100]; + 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: protocol mask %u removing nonexistent OIF %s (vif_index=%d, min_ttl=%d) from channel (S,G)=(%s,%s)", @@ -934,8 +934,8 @@ static int del_oif(struct channel_oil *channel_oil, old_ttl = channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]; if (old_ttl < 1) { - char group_str[100]; - char source_str[100]; + 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: interface %s (vif_index=%d) is not output for channel (S,G)=(%s,%s)", @@ -948,8 +948,8 @@ static int del_oif(struct channel_oil *channel_oil, channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0; if (pim_mroute_add(channel_oil)) { - char group_str[100]; - char source_str[100]; + 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: could not remove output interface %s (vif_index=%d) from channel (S,G)=(%s,%s)", @@ -966,8 +966,8 @@ static int del_oif(struct channel_oil *channel_oil, if (channel_oil->oil_size < 1) { if (pim_mroute_del(channel_oil)) { /* just log a warning in case of failure */ - char group_str[100]; - char source_str[100]; + 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: failure removing OIL for channel (S,G)=(%s,%s)", @@ -977,8 +977,8 @@ static int del_oif(struct channel_oil *channel_oil, } if (PIM_DEBUG_MROUTE) { - char group_str[100]; - char source_str[100]; + 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: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE", @@ -1026,7 +1026,7 @@ void igmp_source_forward_start(struct igmp_source *source) int input_iface_vif_index = fib_lookup_if_vif_index(vif_source); if (input_iface_vif_index < 1) { - char source_str[100]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); zlog_warn("%s %s: could not find input interface for source %s", __FILE__, __PRETTY_FUNCTION__, @@ -1160,9 +1160,9 @@ void pim_forward_start(struct pim_ifchannel *ch) struct pim_upstream *up = ch->upstream; if (PIM_DEBUG_PIM_TRACE) { - char source_str[100]; - char group_str[100]; - char upstream_str[100]; + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + char upstream_str[INET_ADDRSTRLEN]; pim_inet4_dump("", ch->sg.src, source_str, sizeof(source_str)); pim_inet4_dump("", ch->sg.grp, group_str, sizeof(group_str)); @@ -1175,7 +1175,7 @@ void pim_forward_start(struct pim_ifchannel *ch) if (!up->channel_oil) { int input_iface_vif_index = fib_lookup_if_vif_index(up->upstream_addr); if (input_iface_vif_index < 1) { - char source_str[100]; + char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", up->sg.src, source_str, sizeof(source_str)); zlog_warn("%s %s: could not find input interface for source %s", __FILE__, __PRETTY_FUNCTION__, diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 4e6c76f0b0..cdaf04566d 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -165,7 +165,7 @@ static int zclient_read_nexthop(struct zclient *zlookup, int i, err; if (PIM_DEBUG_ZEBRA) { - char addr_str[100]; + char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_debug("%s: addr=%s", __PRETTY_FUNCTION__, @@ -197,8 +197,8 @@ static int zclient_read_nexthop(struct zclient *zlookup, raddr.s_addr = stream_get_ipv4(s); if (raddr.s_addr != addr.s_addr) { - char addr_str[100]; - char raddr_str[100]; + char addr_str[INET_ADDRSTRLEN]; + char raddr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); pim_inet4_dump("", raddr, raddr_str, sizeof(raddr_str)); zlog_warn("%s: address mismatch: addr=%s raddr=%s", @@ -223,7 +223,7 @@ static int zclient_read_nexthop(struct zclient *zlookup, nexthop_type = stream_getc(s); if (num_ifindex >= tab_size) { - char addr_str[100]; + char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_warn("%s %s: found too many nexthop ifindexes (%d > %d) for address %s", __FILE__, __PRETTY_FUNCTION__, @@ -262,7 +262,7 @@ static int zclient_read_nexthop(struct zclient *zlookup, default: /* do nothing */ { - char addr_str[100]; + char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_warn("%s %s: found non-ifindex nexthop type=%d for address %s", __FILE__, __PRETTY_FUNCTION__, @@ -284,7 +284,7 @@ zclient_lookup_nexthop_once (struct pim_zlookup_nexthop nexthop_tab[], int ret; if (PIM_DEBUG_ZEBRA) { - char addr_str[100]; + char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_debug("%s: addr=%s", __PRETTY_FUNCTION__, @@ -344,7 +344,7 @@ zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], tab_size, addr); if (num_ifindex < 1) { if (PIM_DEBUG_ZEBRA) { - char addr_str[100]; + char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_debug("%s %s: lookup=%d/%d: could not find nexthop ifindex for address %s", __FILE__, __PRETTY_FUNCTION__, @@ -376,7 +376,7 @@ zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], if (lookup > 0) { /* Report non-recursive success after first lookup */ if (PIM_DEBUG_ZEBRA) { - char addr_str[100]; + char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_debug("%s %s: lookup=%d/%d: found non-recursive ifindex=%d for address %s dist=%d met=%d", __FILE__, __PRETTY_FUNCTION__, @@ -397,8 +397,8 @@ zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], } if (PIM_DEBUG_ZEBRA) { - char addr_str[100]; - char nexthop_str[100]; + char addr_str[INET_ADDRSTRLEN]; + char nexthop_str[PREFIX_STRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); pim_addr_dump("", &nexthop_addr, nexthop_str, sizeof(nexthop_str)); zlog_debug("%s %s: lookup=%d/%d: zebra returned recursive nexthop %s for address %s dist=%d met=%d", @@ -413,7 +413,7 @@ zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], } /* for (max_lookup) */ if (PIM_DEBUG_ZEBRA) { - char addr_str[100]; + char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_warn("%s %s: lookup=%d/%d: failure searching recursive nexthop ifindex for address %s", __FILE__, __PRETTY_FUNCTION__, From 0da1854cee9fadfe9025afa5fe00c24afc4fdbea Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 22 Oct 2016 20:23:08 -0400 Subject: [PATCH 214/386] pimd: Fix show of 'ip pim rp keep-alive-timer When displaying this changed value, we were using an incorrect data value. Signed-off-by: Donald Sharpd --- pimd/pim_vty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index f5cdc2bd2c..5e13b60873 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -150,7 +150,7 @@ int pim_global_config_write(struct vty *vty) if (qpim_rp_keep_alive_time != PIM_RP_KEEPALIVE_PERIOD) { vty_out (vty, "ip pim rp keep-alive-timer %d%s", - qpim_keep_alive_time, VTY_NEWLINE); + qpim_rp_keep_alive_time, VTY_NEWLINE); ++writes; } From 1be8f9d323c53c98205bf3800edb81a399f3ec37 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 14 Oct 2016 11:22:12 -0400 Subject: [PATCH 215/386] pimd: Fix ifchannel being left around In some situations, the deletion of the ifchannel would not ocurr if the last flag cleared was the assert flag. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 93a6cad649..1be7ebb4a9 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -143,27 +143,13 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) pim_ifchannel_free(ch); } - -#define IFCHANNEL_NOINFO(ch) \ - ( \ - ((ch)->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO) \ - && \ - ((ch)->ifjoin_state == PIM_IFJOIN_NOINFO) \ - && \ - ((ch)->ifassert_state == PIM_IFASSERT_NOINFO) \ - ) static void delete_on_noinfo(struct pim_ifchannel *ch) { - if (IFCHANNEL_NOINFO(ch)) { - - /* In NOINFO state, timers should have been cleared */ - zassert(!ch->t_ifjoin_expiry_timer); - zassert(!ch->t_ifjoin_prune_pending_timer); - zassert(!ch->t_ifassert_timer); - + if (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO && + ch->ifjoin_state == PIM_IFJOIN_NOINFO) pim_ifchannel_delete(ch); - } + } void pim_ifchannel_ifjoin_switch(const char *caller, @@ -191,11 +177,8 @@ void pim_ifchannel_ifjoin_switch(const char *caller, ch->ifjoin_state = new_state; /* Transition to/from NOINFO ? */ - if ( - (old_state == PIM_IFJOIN_NOINFO) - || - (new_state == PIM_IFJOIN_NOINFO) - ) { + if ((old_state == PIM_IFJOIN_NOINFO) || + (new_state == PIM_IFJOIN_NOINFO)) { if (PIM_DEBUG_PIM_EVENTS) { zlog_debug("PIM_IFCHANNEL_%s: (S,G)=%s on interface %s", @@ -432,8 +415,6 @@ pim_ifchannel_add(struct interface *ifp, /* Attach to list */ listnode_add_sort(pim_ifp->pim_ifchannel_list, ch); - zassert(IFCHANNEL_NOINFO(ch)); - return ch; } @@ -695,8 +676,6 @@ void pim_ifchannel_join_add(struct interface *ifp, break; } - zassert(!IFCHANNEL_NOINFO(ch)); - if (holdtime != 0xFFFF) { THREAD_TIMER_ON(master, ch->t_ifjoin_expiry_timer, on_ifjoin_expiry_timer, @@ -782,8 +761,6 @@ void pim_ifchannel_local_membership_add(struct interface *ifp, ifmembership_set(ch, PIM_IFMEMBERSHIP_INCLUDE); - zassert(!IFCHANNEL_NOINFO(ch)); - if (sg->src.s_addr == INADDR_ANY) { struct pim_upstream *up = pim_upstream_find (sg); From bebc7290cd2cec4222beba831949d73161dfe318 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 14 Oct 2016 13:15:30 -0400 Subject: [PATCH 216/386] pimd: Add debug for packet stats Allow us to figure out what is going wrong in some situations, so add some debugs. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 192b6609ed..7f98f043da 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -863,6 +863,13 @@ pim_upstream_keep_alive_timer (struct thread *t) pim_mroute_update_counters (up->channel_oil); + if (PIM_DEBUG_MROUTE) + { + zlog_debug ("New: %llu %lu %lu %lu", up->channel_oil->cc.lastused, up->channel_oil->cc.pktcnt, + up->channel_oil->cc.bytecnt, up->channel_oil->cc.wrong_if); + zlog_debug ("old: %llu %lu %lu %lu", up->channel_oil->cc.lastused, up->channel_oil->cc.oldpktcnt, + up->channel_oil->cc.oldbytecnt, up->channel_oil->cc.oldwrong_if); + } if ((up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt) && (up->channel_oil->cc.lastused/100 >= qpim_keep_alive_time)) { From 594a78cc8a9f1c4524e3a16fed0e14288e511027 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 17 Oct 2016 08:33:13 -0400 Subject: [PATCH 217/386] pimd: Add interface to ifchannel debugs When outputting data about ifchannels due to debug include the interface this is happening on. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 11 ++++++----- pimd/pim_upstream.c | 6 +++++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 1be7ebb4a9..0f7413c500 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -159,7 +159,8 @@ void pim_ifchannel_ifjoin_switch(const char *caller, enum pim_ifjoin_state old_state = ch->ifjoin_state; if (PIM_DEBUG_PIM_EVENTS) - zlog_debug ("PIM_IFCHANNEL: %s is switching from %s to %s", + zlog_debug ("PIM_IFCHANNEL(%s): %s is switching from %s to %s", + ch->interface->name, pim_str_sg_dump (&ch->sg), pim_ifchannel_ifjoin_name (ch->ifjoin_state), pim_ifchannel_ifjoin_name (new_state)); @@ -776,9 +777,9 @@ void pim_ifchannel_local_membership_add(struct interface *ifp, char buff[100]; strcpy (buff, pim_str_sg_dump (&up->sg)); - zlog_debug("%s %s: IGMP (S,G)=%s from %s", + zlog_debug("%s %s: IGMP (S,G)=%s(%s) from %s", __FILE__, __PRETTY_FUNCTION__, - buff, pim_str_sg_dump (sg)); + buff, ifp->name, pim_str_sg_dump (sg)); } if (pim_upstream_evaluate_join_desired (child)) @@ -828,9 +829,9 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, { char buff[100]; strcpy (buff, pim_str_sg_dump (&up->sg)); - zlog_debug("%s %s: Prune(S,G)=%s from %s", + zlog_debug("%s %s: Prune(S,G)=%s(%s) from %s", __FILE__, __PRETTY_FUNCTION__, - buff, pim_str_sg_dump (&child->sg)); + buff, ifp->name, pim_str_sg_dump (&child->sg)); } if (!pim_upstream_evaluate_join_desired (child)) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 7f98f043da..b103a4fc66 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -158,6 +158,10 @@ static void upstream_channel_oil_detach(struct pim_upstream *up) void pim_upstream_delete(struct pim_upstream *up) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug ("%s: %s is being deleted", + __PRETTY_FUNCTION__, + pim_str_sg_dump (&up->sg)); THREAD_OFF(up->t_join_timer); THREAD_OFF(up->t_ka_timer); THREAD_OFF(up->t_rs_timer); @@ -546,7 +550,7 @@ struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, struct interface *incoming, int flags) { - struct pim_upstream *up; + struct pim_upstream *up = NULL; up = pim_upstream_find(sg); if (up) { From a447fa96494b785ae5e9587e292c8888a4b9cb8b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 25 Oct 2016 08:16:09 -0400 Subject: [PATCH 218/386] pimd: Fix uninitialized value When handling a igmp request, fill in group address before we attempt to output debug information on it. Signed-off-by: Donald Sharp --- pimd/pim_igmpv2.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/pimd/pim_igmpv2.c b/pimd/pim_igmpv2.c index 4f005f0195..975ff9faa1 100644 --- a/pimd/pim_igmpv2.c +++ b/pimd/pim_igmpv2.c @@ -169,8 +169,6 @@ igmp_v2_recv_leave (struct igmp_sock *igmp, from_str, ifp->name, group_str); } - memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); - /* * RFC 3376 * 7.3.2. In the Presence of Older Version Group Members From 518e5727b40b97827b92555bf8d867d642c91bc4 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 25 Oct 2016 10:40:04 -0400 Subject: [PATCH 219/386] pimd: Fix pim_nexthop_lookup There are situations where we may never look at a better route for nexthop_lookup. Signed-off-by: Donald Sharp --- pimd/pim_rpf.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index ffedd84103..d32d65fd4c 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -59,7 +59,7 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei return -1; } - while (!found) + while (!found && (i < num_ifindex)) { first_ifindex = nexthop_tab[i].ifindex; @@ -77,16 +77,19 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei return -2; } - if (!ifp->info && PIM_DEBUG_ZEBRA) + if (!ifp->info) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", - __PRETTY_FUNCTION__, - ifp->name, first_ifindex, addr_str); + if (PIM_DEBUG_ZEBRA) + { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_debug("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", + __PRETTY_FUNCTION__, + ifp->name, first_ifindex, addr_str); + } + i++; } - - if (neighbor_needed && !pim_if_connected_to_source (ifp, addr)) + else if (neighbor_needed && !pim_if_connected_to_source (ifp, addr)) { struct pim_neighbor *nbr; From 7e14782362f94fbde2b9a4febbc4a1ed45fb6292 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 26 Oct 2016 14:03:29 +0000 Subject: [PATCH 220/386] pimd: always build json for show commands Signed-off-by: Daniel Walton This cleans up the following so that they always collect the data to display in json structures and then either dumps the json output or traverses it to produce the non-json output. show ip pim local-membership show ip pim interface --- pimd/pim_cmd.c | 177 ++++++++++++++++++++++++++++++------------------- 1 file changed, 108 insertions(+), 69 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index dbe8c3ef42..54750d475c 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -413,30 +413,24 @@ static void pim_show_membership(struct vty *vty, u_char uj) { struct listnode *ifnode; struct interface *ifp; + enum json_type type; json_object *json = NULL; json_object *json_iface = NULL; json_object *json_row = NULL; + json_object *json_tmp = NULL; - if (uj) - json = json_object_new_object(); - else - vty_out(vty, - "Interface Address Source Group Membership%s", - VTY_NEWLINE); + json = json_object_new_object(); for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { struct pim_interface *pim_ifp; - struct in_addr ifaddr; struct listnode *ch_node; struct pim_ifchannel *ch; pim_ifp = ifp->info; - + if (!pim_ifp) continue; - ifaddr = pim_ifp->primary_address; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { char ch_src_str[INET_ADDRSTRLEN]; char ch_grp_str[INET_ADDRSTRLEN]; @@ -446,39 +440,80 @@ static void pim_show_membership(struct vty *vty, u_char uj) pim_inet4_dump("", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str)); - if (uj) { - json_object_object_get_ex(json, ifp->name, &json_iface); + json_object_object_get_ex(json, ifp->name, &json_iface); - if (!json_iface) { - json_iface = json_object_new_object(); - json_object_pim_ifp_add(json_iface, ifp); - json_object_object_add(json, ifp->name, json_iface); - } - - json_row = json_object_new_object(); - json_object_string_add(json_row, "source", ch_src_str); - json_object_string_add(json_row, "group", ch_grp_str); - json_object_string_add(json_row, "localMembership", - ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO ? "NOINFO" : "INCLUDE"); - json_object_object_add(json_iface, ch_grp_str, json_row); - - } else { - vty_out(vty, "%-9s %-15s %-15s %-15s %-10s%s", - ifp->name, - inet_ntoa(ifaddr), - ch_src_str, - ch_grp_str, - ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO ? - "NOINFO" : "INCLUDE", - VTY_NEWLINE); + if (!json_iface) { + json_iface = json_object_new_object(); + json_object_pim_ifp_add(json_iface, ifp); + json_object_object_add(json, ifp->name, json_iface); } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", ch_src_str); + json_object_string_add(json_row, "group", ch_grp_str); + json_object_string_add(json_row, "localMembership", + ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO ? "NOINFO" : "INCLUDE"); + json_object_object_add(json_iface, ch_grp_str, json_row); } /* scan interface channels */ } /* scan interfaces */ if (uj) { vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); - json_object_free(json); + } else { + vty_out(vty, + "Interface Address Source Group Membership%s", + VTY_NEWLINE); + + /* + * Example of the json data we are traversing + * + * { + * "swp3":{ + * "name":"swp3", + * "state":"up", + * "address":"10.1.20.1", + * "index":5, + * "flagMulticast":true, + * "flagBroadcast":true, + * "lanDelayEnabled":true, + * "226.10.10.10":{ + * "source":"*", + * "group":"226.10.10.10", + * "localMembership":"INCLUDE" + * } + * } + * } + */ + + /* foreach interface */ + json_object_object_foreach(json, key, val) { + + /* Find all of the keys where the val is an object. In the example + * above the only one is 226.10.10.10 + */ + json_object_object_foreach(val, if_field_key, if_field_val) { + type = json_object_get_type(if_field_val); + + if (type == json_type_object) { + vty_out(vty, "%-9s ", key); + + json_object_object_get_ex(val, "address", &json_tmp); + vty_out(vty, "%-15s ", json_object_get_string(json_tmp)); + + json_object_object_get_ex(if_field_val, "source", &json_tmp); + vty_out(vty, "%-15s ", json_object_get_string(json_tmp)); + + /* Group */ + vty_out(vty, "%-15s ", if_field_key); + + json_object_object_get_ex(if_field_val, "localMembership", &json_tmp); + vty_out(vty, "%-10s%s", json_object_get_string(json_tmp), VTY_NEWLINE); + } + } + } } + + json_object_free(json); } static void pim_print_ifp_flags(struct vty *vty, struct interface *ifp, int mloop) @@ -994,25 +1029,18 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch static void pim_show_interfaces(struct vty *vty, u_char uj) { - struct in_addr ifaddr; struct interface *ifp; struct listnode *node; struct listnode *upnode; struct pim_interface *pim_ifp; struct pim_upstream *up; int fhr = 0; - int pim_dr_local = 0; int pim_nbrs = 0; json_object *json = NULL; json_object *json_row = NULL; - char local_ip[INET_ADDRSTRLEN]; - char dr_ip[INET_ADDRSTRLEN]; + json_object *json_tmp; - if (uj) { - json = json_object_new_object(); - } else { - vty_out(vty, "Interface State Address PIM Nbrs PIM DR FHR%s", VTY_NEWLINE); - } + json = json_object_new_object(); for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { pim_ifp = ifp->info; @@ -1023,45 +1051,56 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) if (pim_ifp->pim_sock_fd < 0) continue; - ifaddr = pim_ifp->primary_address; pim_nbrs = pim_ifp->pim_neighbor_list->count; - pim_dr_local = 0; fhr = 0; - if (pim_ifp->pim_dr_addr.s_addr == pim_ifp->primary_address.s_addr) - pim_dr_local = 1; - for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) if (ifp == up->rpf.source_nexthop.interface) if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) fhr++; - if (uj) { - json_row = json_object_new_object(); - json_object_pim_ifp_add(json_row, ifp); - json_object_int_add(json_row, "pimNeighbors", pim_nbrs); - json_object_int_add(json_row, "firstHopRouter", fhr); - json_object_string_add(json_row, "pimDesignatedRouter", inet_ntoa(pim_ifp->pim_dr_addr)); - json_object_object_add(json, ifp->name, json_row); + json_row = json_object_new_object(); + json_object_pim_ifp_add(json_row, ifp); + json_object_int_add(json_row, "pimNeighbors", pim_nbrs); + json_object_int_add(json_row, "firstHopRouter", fhr); + json_object_string_add(json_row, "pimDesignatedRouter", inet_ntoa(pim_ifp->pim_dr_addr)); - } else { - strcpy(local_ip, inet_ntoa(ifaddr)); - strcpy(dr_ip, inet_ntoa(pim_ifp->pim_dr_addr)); - vty_out(vty, "%-9s %5s %15s %8d %15s %3d%s", - ifp->name, - if_is_up(ifp) ? "up" : "down", - local_ip, - pim_nbrs, - pim_dr_local ? "local" : dr_ip, - fhr, - VTY_NEWLINE); - } + if (pim_ifp->pim_dr_addr.s_addr == pim_ifp->primary_address.s_addr) + json_object_boolean_true_add(json_row, "pimDesignatedRouterLocal"); + + json_object_object_add(json, ifp->name, json_row); } if (uj) { vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); - json_object_free(json); + } else { + vty_out(vty, "Interface State Address PIM Nbrs PIM DR FHR%s", VTY_NEWLINE); + + json_object_object_foreach(json, key, val) { + vty_out(vty, "%-9s ", key); + + json_object_object_get_ex(val, "state", &json_tmp); + vty_out(vty, "%5s ", json_object_get_string(json_tmp)); + + json_object_object_get_ex(val, "address", &json_tmp); + vty_out(vty, "%15s ", json_object_get_string(json_tmp)); + + json_object_object_get_ex(val, "pimNeighbors", &json_tmp); + vty_out(vty, "%8d ", json_object_get_int(json_tmp)); + + if (json_object_object_get_ex(val, "pimDesignatedRouterLocal", &json_tmp)) { + vty_out(vty, "%15s ", "local"); + } else { + json_object_object_get_ex(val, "pimDesignatedRouter", &json_tmp); + vty_out(vty, "%15s ", json_object_get_string(json_tmp)); + } + + json_object_object_get_ex(val, "firstHopRouter", &json_tmp); + vty_out(vty, "%3d%s", json_object_get_int(json_tmp), VTY_NEWLINE); + } } + + json_object_free(json); } static void pim_show_join(struct vty *vty, u_char uj) From 7c4002dd3ecb0bd4afc0d5ae5b8f7f3e5d046731 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 23 Oct 2016 22:35:47 -0400 Subject: [PATCH 221/386] pimd: Fix child ifchannel overwrite parent ifchannel When we look for child channels, don't overwrite the parents ifchannel. Leave that one alone. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 0f7413c500..a811742e3e 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -822,7 +822,7 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, if (child->parent == up) { struct channel_oil *c_oil = child->channel_oil; - struct pim_ifchannel *ch = pim_ifchannel_find (ifp, &child->sg); + struct pim_ifchannel *chchannel = pim_ifchannel_find (ifp, &child->sg); struct pim_interface *pim_ifp = ifp->info; if (PIM_DEBUG_EVENTS) @@ -842,7 +842,7 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, * has output here then the *,G was supplying the implied * if channel. So remove it. */ - if (!ch && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) + if (!chchannel && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); } } From 3506072736df584a83af8d598e29f1aacf7ab1f9 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 26 Oct 2016 20:26:16 -0400 Subject: [PATCH 222/386] pimd: Fix crash when igmp message comes in on non-configured interface When we receive a igmp message through the kernel upcall, make sure that we are configured to work on that interface via pim/igmp before attempting to use that interface. Ticket: CM-13338 Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 982aa9477a..5f8d180742 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -433,6 +433,14 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size) } pim_ifp = ifp->info; + if (!pim_ifp) + { + if (PIM_DEBUG_MROUTE_DETAIL) + zlog_debug ("%s: igmp kernel upcall for interface:%s not configured for pim", + __PRETTY_FUNCTION__, ifp->name); + return 0; + } + ifaddr = pim_find_primary_addr(ifp); igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr); From e5905a3bc3b33940d01e1b4a62a4eee74f465698 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 27 Oct 2016 08:05:57 -0400 Subject: [PATCH 223/386] pimd: Fix possible double free of upstream Fix possible double free of upstream and in addition add some debug code to help find where the problem is coming from. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 4 ++-- pimd/pim_mroute.c | 4 ++-- pimd/pim_register.c | 4 +++- pimd/pim_upstream.c | 38 +++++++++++++++++++++++++------------- pimd/pim_upstream.h | 6 +++--- 5 files changed, 35 insertions(+), 21 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index a811742e3e..c2d27f1ec8 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -127,7 +127,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) pim_upstream_update_join_desired(ch->upstream); } - pim_upstream_del(ch->upstream); + pim_upstream_del(ch->upstream, __PRETTY_FUNCTION__); ch->upstream = NULL; THREAD_OFF(ch->t_ifjoin_expiry_timer); @@ -365,7 +365,7 @@ pim_ifchannel_add(struct interface *ifp, pim_ifp = ifp->info; zassert(pim_ifp); - up = pim_upstream_add(sg, NULL, flags); + up = pim_upstream_add(sg, NULL, flags, __PRETTY_FUNCTION__); if (!up) { zlog_err("%s: could not attach upstream (S,G)=%s on interface %s", __PRETTY_FUNCTION__, diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 5f8d180742..7935f7290e 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -136,7 +136,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg return 0; } - up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR); + up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, __PRETTY_FUNCTION__); if (!up) { if (PIM_DEBUG_MROUTE) { zlog_debug("%s: Failure to add upstream information for %s", @@ -371,7 +371,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) pim_mroute_add (oil); if (pim_if_connected_to_source (ifp, sg.src)) { - up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR); + up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, __PRETTY_FUNCTION__); if (!up) { if (PIM_DEBUG_MROUTE) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 62973bc9c1..c941388dc4 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -333,7 +333,9 @@ pim_register_recv (struct interface *ifp, */ if (!upstream) { - upstream = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM); + upstream = pim_upstream_add (&sg, ifp, + PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, + __PRETTY_FUNCTION__); if (!upstream) { zlog_warn ("Failure to create upstream state"); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index b103a4fc66..ee26683547 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -156,8 +156,19 @@ static void upstream_channel_oil_detach(struct pim_upstream *up) } } -void pim_upstream_delete(struct pim_upstream *up) +void +pim_upstream_del(struct pim_upstream *up, const char *name) { + if (PIM_DEBUG_PIM_TRACE) + { + zlog_debug ("%s: Delete (%s) ref count: %d", + name, pim_str_sg_dump (&up->sg), up->ref_count); + } + --up->ref_count; + + if (up->ref_count >= 1) + return; + if (PIM_DEBUG_PIM_TRACE) zlog_debug ("%s: %s is being deleted", __PRETTY_FUNCTION__, @@ -548,31 +559,29 @@ struct pim_upstream *pim_upstream_find(struct prefix_sg *sg) struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, struct interface *incoming, - int flags) + int flags, const char *name) { struct pim_upstream *up = NULL; - + int found = 0; up = pim_upstream_find(sg); if (up) { ++up->ref_count; up->flags |= flags; + found = 1; } else { up = pim_upstream_new(sg, incoming, flags); } + if (PIM_DEBUG_TRACE) + zlog_debug("%s(%s): (%s), found: %d: ref_count: %d", + __PRETTY_FUNCTION__, name, + pim_str_sg_dump (&up->sg), found, + up->ref_count); + return up; } -void pim_upstream_del(struct pim_upstream *up) -{ - --up->ref_count; - - if (up->ref_count < 1) { - pim_upstream_delete(up); - } -} - static int pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up, struct pim_ifchannel *ch) @@ -885,7 +894,10 @@ pim_upstream_keep_alive_timer (struct thread *t) &up->sg, 0); PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM (up->flags); if (PIM_UPSTREAM_FLAG_TEST_CREATED_BY_UPSTREAM(up->flags)) - pim_upstream_del (up); + { + PIM_UPSTREAM_FLAG_UNSET_CREATED_BY_UPSTREAM(up->flags); + pim_upstream_del (up, __PRETTY_FUNCTION__); + } } else { diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 70b5b01062..41fcd28679 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -116,11 +116,11 @@ struct list *pim_upstream_list; struct hash *pim_upstream_hash; void pim_upstream_free(struct pim_upstream *up); -void pim_upstream_delete(struct pim_upstream *up); struct pim_upstream *pim_upstream_find (struct prefix_sg *sg); struct pim_upstream *pim_upstream_add (struct prefix_sg *sg, - struct interface *ifp, int); -void pim_upstream_del(struct pim_upstream *up); + struct interface *ifp, int flags, + const char *name); +void pim_upstream_del(struct pim_upstream *up, const char *name); int pim_upstream_evaluate_join_desired(struct pim_upstream *up); void pim_upstream_update_join_desired(struct pim_upstream *up); From 8a9bd91cd9ebcecf3c9492ba1865d908448338da Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 27 Oct 2016 12:26:00 -0400 Subject: [PATCH 224/386] pimd: Add the ability to get time in usec Add ability to return a int64_t time in usec. Signed-off-by: Donald Sharp --- pimd/pim_time.c | 19 +++++++++++++++++++ pimd/pim_time.h | 1 + 2 files changed, 20 insertions(+) diff --git a/pimd/pim_time.c b/pimd/pim_time.c index ab3ac7340a..9bae661ba9 100644 --- a/pimd/pim_time.c +++ b/pimd/pim_time.c @@ -83,6 +83,25 @@ int64_t pim_time_monotonic_dsec() return now_dsec; } +int64_t +pim_time_monotonic_usec (void) +{ + struct timeval now_tv; + int64_t now_dsec; + + if (gettime_monotonic(&now_tv)) { + zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", + __PRETTY_FUNCTION__, + errno, safe_strerror(errno)); + return -1; + } + + now_dsec = ((int64_t) now_tv.tv_sec) * 1000000 + ((int64_t) now_tv.tv_usec); + + return now_dsec; + +} + int pim_time_mmss(char *buf, int buf_size, long sec) { long mm; diff --git a/pimd/pim_time.h b/pimd/pim_time.h index 0081b21bbb..9f811f1b94 100644 --- a/pimd/pim_time.h +++ b/pimd/pim_time.h @@ -29,6 +29,7 @@ int64_t pim_time_monotonic_sec(void); int64_t pim_time_monotonic_dsec(void); +int64_t pim_time_monotonic_usec(void); int pim_time_mmss(char *buf, int buf_size, long sec); void pim_time_timer_to_mmss(char *buf, int buf_size, struct thread *t); void pim_time_timer_to_hhmmss(char *buf, int buf_size, struct thread *t); From e71bf8f7bd5457e62fed234fcd9d908d4d614906 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 27 Oct 2016 11:54:55 -0400 Subject: [PATCH 225/386] pimd: Add basic nexthop lookup cached information. Cache the last time we looked up the nexthop for this particular address. Store time to usec accuracy. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 7 +++++-- pimd/pim_rpf.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++-- pimd/pim_rpf.h | 6 ++++++ pimd/pim_zebra.c | 2 ++ 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 54750d475c..d11c2f21f4 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1853,6 +1853,7 @@ static void show_rpf_refresh_stats(struct vty *vty, time_t now, json_object *jso json_object_int_add(json, "rpfCacheRefreshEvents", qpim_rpf_cache_refresh_events); json_object_string_add(json, "rpfCacheRefreshLast", refresh_uptime); json_object_int_add(json, "nexthopLookups", qpim_nexthop_lookups); + json_object_int_add(json, "nexthopLookupsAvoided", nexthop_lookups_avoided); } else { vty_out(vty, "RPF Cache Refresh Delay: %ld msecs%s" @@ -1860,13 +1861,15 @@ static void show_rpf_refresh_stats(struct vty *vty, time_t now, json_object *jso "RPF Cache Refresh Requests: %lld%s" "RPF Cache Refresh Events: %lld%s" "RPF Cache Refresh Last: %s%s" - "Nexthop Lookups: %lld%s", + "Nexthop Lookups: %lld%s" + "Nexthop Lookups Avoided: %lld%s", qpim_rpf_cache_refresh_delay_msec, VTY_NEWLINE, pim_time_timer_remain_msec(qpim_rpf_cache_refresher), VTY_NEWLINE, (long long)qpim_rpf_cache_refresh_requests, VTY_NEWLINE, (long long)qpim_rpf_cache_refresh_events, VTY_NEWLINE, refresh_uptime, VTY_NEWLINE, - (long long) qpim_nexthop_lookups, VTY_NEWLINE); + (long long) qpim_nexthop_lookups, VTY_NEWLINE, + (long long)nexthop_lookups_avoided, VTY_NEWLINE); } } diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index d32d65fd4c..2b16529627 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -34,9 +34,22 @@ #include "pim_iface.h" #include "pim_zlookup.h" #include "pim_ifchannel.h" +#include "pim_time.h" + +static long long last_route_change_time = -1; +long long nexthop_lookups_avoided = 0; static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up); +void +pim_rpf_set_refresh_time (void) +{ + last_route_change_time = pim_time_monotonic_usec(); + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: New last route change time: %lld", + __PRETTY_FUNCTION__, last_route_change_time); +} + int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int neighbor_needed) { struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; @@ -46,6 +59,36 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei int found = 0; int i = 0; + if ((nexthop->last_lookup.s_addr == addr.s_addr) && + (nexthop->last_lookup_time > last_route_change_time)) + { + if (PIM_DEBUG_TRACE) + { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_debug ("%s: Using last lookup for %s at %lld, %lld", + __PRETTY_FUNCTION__, + addr_str, + nexthop->last_lookup_time, + last_route_change_time); + } + nexthop_lookups_avoided++; + return 0; + } + else + { + if (PIM_DEBUG_TRACE) + { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_debug ("%s: Looking up: %s, last lookup time: %lld, %lld", + __PRETTY_FUNCTION__, + addr_str, + nexthop->last_lookup_time, + last_route_change_time); + } + } + memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM); num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, @@ -124,11 +167,16 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei nexthop->mrib_nexthop_addr = nexthop_tab[0].nexthop_addr; nexthop->mrib_metric_preference = nexthop_tab[0].protocol_distance; nexthop->mrib_route_metric = nexthop_tab[0].route_metric; - + nexthop->last_lookup = addr; + nexthop->last_lookup_time = pim_time_monotonic_usec(); return 0; } else - return -1; + { + nexthop->last_lookup = addr; + nexthop->last_lookup_time = pim_time_monotonic_usec(); + return -1; + } } static int nexthop_mismatch(const struct pim_nexthop *nh1, diff --git a/pimd/pim_rpf.h b/pimd/pim_rpf.h index b93c934116..b267a9b6fa 100644 --- a/pimd/pim_rpf.h +++ b/pimd/pim_rpf.h @@ -40,6 +40,8 @@ units applicable to the unicast routing protocol used. */ struct pim_nexthop { + struct in_addr last_lookup; + long long last_lookup_time; struct interface *interface; /* RPF_interface(S) */ struct prefix mrib_nexthop_addr; /* MRIB.next_hop(S) */ uint32_t mrib_metric_preference; /* MRIB.pref(S) */ @@ -59,9 +61,13 @@ enum pim_rpf_result { struct pim_upstream; +extern long long nexthop_lookups_avoided; + int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int neighbor_needed); enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_rpf_addr); int pim_rpf_addr_is_inaddr_none (struct pim_rpf *rpf); int pim_rpf_addr_is_inaddr_any (struct pim_rpf *rpf); + +void pim_rpf_set_refresh_time (void); #endif /* PIM_RPF_H */ diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index eac618b438..e2a71c6e7f 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -550,6 +550,8 @@ static void sched_rpf_cache_refresh() { ++qpim_rpf_cache_refresh_requests; + pim_rpf_set_refresh_time (); + if (qpim_rpf_cache_refresher) { /* Refresh timer is already running */ return; From 02e5bd7294fdcd328fbd24087cf40e6e029d40a3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 27 Oct 2016 18:09:09 -0400 Subject: [PATCH 226/386] pimd: Fix crash when cannot find igmp When we look up a igmp data structure, if we don't find it, safely do nothing. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 7935f7290e..8ece65d317 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -444,15 +444,15 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size) ifaddr = pim_find_primary_addr(ifp); igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr); - if (PIM_DEBUG_MROUTE_DETAIL) { + if (PIM_DEBUG_MROUTE) { pim_inet4_dump("", ip_hdr->ip_src, ip_src_str, sizeof(ip_src_str)); pim_inet4_dump("", ip_hdr->ip_dst, ip_dst_str, sizeof(ip_dst_str)); - zlog_warn("%s: igmp kernel upcall on %s for %s -> %s", - __PRETTY_FUNCTION__, ifp->name, ip_src_str, ip_dst_str); + zlog_warn("%s: igmp kernel upcall on %s(%p) for %s -> %s", + __PRETTY_FUNCTION__, ifp->name, igmp, ip_src_str, ip_dst_str); } - - pim_igmp_packet(igmp, (char *)buf, buf_size); + if (igmp) + pim_igmp_packet(igmp, (char *)buf, buf_size); } else if (ip_hdr->ip_p) { if (PIM_DEBUG_MROUTE_DETAIL) { From f89022af5302c2d2710e502cf7620c8275d6b333 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 27 Oct 2016 18:13:19 -0400 Subject: [PATCH 227/386] pimd: Ensure 'struct nexthop' has been zeroed When calling nexthop_lookup, the code assumes that the nexthop passed in has been 0'ed out. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 1 + 1 file changed, 1 insertion(+) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 8ece65d317..976fe74f08 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -345,6 +345,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) struct pim_rpf *rpf = RP (sg.grp); pim_ifp = rpf->source_nexthop.interface->info; + memset (&source, 0, sizeof (source)); //No if channel, but upstream we are at the RP. if (pim_nexthop_lookup (&source, up->upstream_register, 0) == 0) pim_register_stop_send(source.interface, &sg, pim_ifp->primary_address, up->upstream_register); From 580d76126660144a0ccf05b0b5cb3736b49aecce Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 27 Oct 2016 18:16:47 -0400 Subject: [PATCH 228/386] pimd: Fix possible crash using 'struct pim_nexthop' When passing in a nexthop data structure to nexthop_lookup ensure that it is zero'ed out. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index d11c2f21f4..36ec541cea 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3238,6 +3238,7 @@ DEFUN (show_ip_rib, char nexthop_addr_str[PREFIX_STRLEN]; int result; + memset (&nexthop, 0, sizeof (nexthop)); addr_str = argv[idx_ipv4]->arg; result = inet_pton(AF_INET, addr_str, &addr); if (result <= 0) { From f4075cb472efca96d20df6b9f7a1f563831a33ae Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 27 Oct 2016 18:27:28 -0400 Subject: [PATCH 229/386] pimd: Make sure we have valid pointer when printing debugs When we print a debug in the pim_upstream_add, there exists failure cases for pim_upstream_new where we cannot create a upstream data structure. Make sure the debug handles it right. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index ee26683547..7264c0de55 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -574,10 +574,17 @@ struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, } if (PIM_DEBUG_TRACE) - zlog_debug("%s(%s): (%s), found: %d: ref_count: %d", - __PRETTY_FUNCTION__, name, - pim_str_sg_dump (&up->sg), found, - up->ref_count); + { + if (up) + zlog_debug("%s(%s): (%s), found: %d: ref_count: %d", + __PRETTY_FUNCTION__, name, + pim_str_sg_dump (&up->sg), found, + up->ref_count); + else + zlog_debug("%s(%s): (%s) failure to create", + __PRETTY_FUNCTION__, name, + pim_str_sg_dump (sg)); + } return up; } From cb24fec45cb6f281263b0cc778e330a4eb710af1 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 27 Oct 2016 20:35:22 -0400 Subject: [PATCH 230/386] pimd: Clean up the interface deletion When cleaning up the interface, actually clean up data associated with that interface. Signed-off-by: Donald Sharp --- pimd/pim_iface.c | 11 +++-------- pimd/pim_ifchannel.c | 17 +++++++++++++++++ pimd/pim_ifchannel.h | 1 + pimd/pim_igmp.c | 16 ++++++++++++++++ pimd/pim_igmp.h | 2 +- 5 files changed, 38 insertions(+), 9 deletions(-) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 3f3629395c..50490fc9cb 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -185,16 +185,11 @@ void pim_if_delete(struct interface *ifp) if (pim_ifp->igmp_join_list) { pim_if_igmp_join_del_all(ifp); } - zassert(!pim_ifp->igmp_join_list); - zassert(pim_ifp->igmp_socket_list); - zassert(!listcount(pim_ifp->igmp_socket_list)); + pim_ifchannel_delete_all (ifp); + igmp_sock_delete_all (ifp); - zassert(pim_ifp->pim_neighbor_list); - zassert(!listcount(pim_ifp->pim_neighbor_list)); - - zassert(pim_ifp->pim_ifchannel_list); - zassert(!listcount(pim_ifp->pim_ifchannel_list)); + pim_neighbor_delete_all (ifp, "Interface removed from configuration"); if (PIM_MROUTE_IS_ENABLED) { pim_if_del_vif(ifp); diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index c2d27f1ec8..45d1d94344 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -143,6 +143,23 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) pim_ifchannel_free(ch); } + +void +pim_ifchannel_delete_all (struct interface *ifp) +{ + struct pim_interface *pim_ifp; + struct listnode *ifchannel_node; + struct listnode *ifchannel_nextnode; + struct pim_ifchannel *ifchannel; + + pim_ifp = ifp->info; + + for (ALL_LIST_ELEMENTS (pim_ifp->pim_ifchannel_list, ifchannel_node, + ifchannel_nextnode, ifchannel)) + { + pim_ifchannel_delete (ifchannel); + } +} static void delete_on_noinfo(struct pim_ifchannel *ch) { diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 8c542d17f2..107762c652 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -100,6 +100,7 @@ struct pim_ifchannel { void pim_ifchannel_free(struct pim_ifchannel *ch); void pim_ifchannel_delete(struct pim_ifchannel *ch); +void pim_ifchannel_delete_all (struct interface *ifp); void pim_ifchannel_membership_clear(struct interface *ifp); void pim_ifchannel_delete_on_noinfo(struct interface *ifp); struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 5532dc1dd0..04689a030f 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -781,6 +781,22 @@ void igmp_sock_delete(struct igmp_sock *igmp) igmp_sock_free(igmp); } +void +igmp_sock_delete_all (struct interface *ifp) +{ + struct pim_interface *pim_ifp; + struct listnode *igmp_node, *igmp_nextnode; + struct igmp_sock *igmp; + + pim_ifp = ifp->info; + + for (ALL_LIST_ELEMENTS (pim_ifp->igmp_socket_list, igmp_node, + igmp_nextnode, igmp)) + { + igmp_sock_delete(igmp); + } +} + static struct igmp_sock *igmp_sock_new(int fd, struct in_addr ifaddr, struct interface *ifp) diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h index fa2c255dd0..c9000e3fd9 100644 --- a/pimd/pim_igmp.h +++ b/pimd/pim_igmp.h @@ -101,7 +101,7 @@ struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, struct interface *ifp); void igmp_sock_delete(struct igmp_sock *igmp); void igmp_sock_free(struct igmp_sock *igmp); - +void igmp_sock_delete_all (struct interface *ifp); int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len); void pim_igmp_general_query_on(struct igmp_sock *igmp); From be4791f25754610727289d00b10a4871d512f160 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 28 Oct 2016 13:23:17 -0400 Subject: [PATCH 231/386] pimd: Start (S,G,rpt) coding Start putting some infrastructure for (S,G,rpt) handling Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 23 ++++++++++++++++++++--- pimd/pim_ifchannel.h | 3 +++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 45d1d94344..0c4be9a518 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -218,9 +218,12 @@ void pim_ifchannel_ifjoin_switch(const char *caller, const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state) { switch (ifjoin_state) { - case PIM_IFJOIN_NOINFO: return "NOINFO"; - case PIM_IFJOIN_JOIN: return "JOIN"; - case PIM_IFJOIN_PRUNE_PENDING: return "PRUNEP"; + case PIM_IFJOIN_NOINFO: return "NOINFO"; + case PIM_IFJOIN_JOIN: return "JOIN"; + case PIM_IFJOIN_PRUNE: return "PRUNE"; + case PIM_IFJOIN_PRUNE_PENDING: return "PRUNEP"; + case PIM_IFJOIN_PRUNE_TMP: return "PRUNET"; + case PIM_IFJOIN_PRUNE_PENDING_TMP: return "PRUNEPT"; } return "ifjoin_bad_state"; @@ -686,12 +689,21 @@ void pim_ifchannel_join_add(struct interface *ifp, } THREAD_OFF(ch->t_ifjoin_expiry_timer); break; + case PIM_IFJOIN_PRUNE: + zlog_debug ("PIM_IFJOIN_PRUNE: NOT PROGRAMMED YET"); + break; case PIM_IFJOIN_PRUNE_PENDING: zassert(!ch->t_ifjoin_expiry_timer); zassert(ch->t_ifjoin_prune_pending_timer); THREAD_OFF(ch->t_ifjoin_prune_pending_timer); pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN); break; + case PIM_IFJOIN_PRUNE_TMP: + zlog_debug ("PIM_IFJOIN_PRUNE_TMP: Not Programmed yet"); + break; + case PIM_IFJOIN_PRUNE_PENDING_TMP: + zlog_debug ("PIM_IFJOIN_PRUNE_PENDING_TMP: Not Programmed yet"); + break; } if (holdtime != 0xFFFF) { @@ -755,6 +767,11 @@ void pim_ifchannel_prune(struct interface *ifp, zassert(ch->t_ifjoin_prune_pending_timer); } break; + case PIM_IFJOIN_PRUNE: + case PIM_IFJOIN_PRUNE_TMP: + case PIM_IFJOIN_PRUNE_PENDING_TMP: + zlog_debug ("CASE NOT HANDLED"); + break; } } diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 107762c652..e98abfcf30 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -37,7 +37,10 @@ enum pim_ifmembership { enum pim_ifjoin_state { PIM_IFJOIN_NOINFO, PIM_IFJOIN_JOIN, + PIM_IFJOIN_PRUNE, PIM_IFJOIN_PRUNE_PENDING, + PIM_IFJOIN_PRUNE_TMP, + PIM_IFJOIN_PRUNE_PENDING_TMP, }; enum pim_ifassert_state { From 9f0edbc93c4f8145c667e3845d9c01c6c2aed910 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 28 Oct 2016 13:43:13 -0400 Subject: [PATCH 232/386] pimd: Find an interface that is both connected and setup for pim When we are looking up the incoming interface for the ipmr call back socket from the kernel, look to see if the src is connected as well as has a valid pim_ifp to use. This is to allow vrr configuration in a mlag env. Signed-off-by: Donald Sharp --- pimd/pim_iface.c | 15 +++++++++++++++ pimd/pim_iface.h | 2 ++ pimd/pim_mroute.c | 13 ++----------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 50490fc9cb..4d8850d638 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -26,6 +26,7 @@ #include "memory.h" #include "prefix.h" #include "vrf.h" +#include "linklist.h" #include "pimd.h" #include "pim_iface.h" @@ -1332,3 +1333,17 @@ pim_if_connected_to_source (struct interface *ifp, struct in_addr src) return 0; } + +struct interface * +pim_if_lookup_address_vrf (struct in_addr src, vrf_id_t vrf_id) +{ + struct listnode *ifnode; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS_RO (vrf_iflist(vrf_id), ifnode, ifp)) + { + if (pim_if_connected_to_source (ifp, src) && ifp->info) + return ifp; + } + return NULL; +} diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index 87530c6026..f671a7d54b 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -128,6 +128,8 @@ void pim_if_addr_del_all(struct interface *ifp); void pim_if_addr_del_all_igmp(struct interface *ifp); void pim_if_addr_del_all_pim(struct interface *ifp); +struct interface *pim_if_lookup_address_vrf (struct in_addr src, vrf_id_t vrf_id); + int pim_if_add_vif(struct interface *ifp); int pim_if_del_vif(struct interface *ifp); void pim_if_add_vif_all(void); diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 976fe74f08..a4ce4a5f33 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -418,30 +418,21 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size) * received on. Find the interface that is on the same subnet as the source * of the IP packet. */ - ifp = if_lookup_address_vrf((void *) &ip_hdr->ip_src, AF_INET, VRF_DEFAULT); + ifp = pim_if_lookup_address_vrf (ip_hdr->ip_src, VRF_DEFAULT); if (!ifp) { if (PIM_DEBUG_MROUTE_DETAIL) { pim_inet4_dump("", ip_hdr->ip_src, ip_src_str, sizeof(ip_src_str)); pim_inet4_dump("", ip_hdr->ip_dst, ip_dst_str, sizeof(ip_dst_str)); - zlog_warn("%s: igmp kernel upcall could not find interface for %s -> %s", + zlog_warn("%s: igmp kernel upcall could not find usable interface for %s -> %s", __PRETTY_FUNCTION__, ip_src_str, ip_dst_str); } return 0; } - pim_ifp = ifp->info; - if (!pim_ifp) - { - if (PIM_DEBUG_MROUTE_DETAIL) - zlog_debug ("%s: igmp kernel upcall for interface:%s not configured for pim", - __PRETTY_FUNCTION__, ifp->name); - return 0; - } - ifaddr = pim_find_primary_addr(ifp); igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr); From df90067aac1ec387fc073ba821ee89eee24cf267 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 28 Oct 2016 15:25:56 -0400 Subject: [PATCH 233/386] pimd: Ignore (S,G) Prunes with no current state If we get a (S,G) Prune with no current ifchannel state, ignore the neighbors request. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 0c4be9a518..ee09bf4fcb 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -727,6 +727,15 @@ void pim_ifchannel_prune(struct interface *ifp, return; } + ch = pim_ifchannel_find (ifp, sg); + if (!ch && !(source_flags & PIM_ENCODE_RPT_BIT)) + { + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: Received prune with no relevant ifchannel %s(%s) state: %d", + __PRETTY_FUNCTION__, ifp->name, pim_str_sg_dump (sg), source_flags); + return; + } + ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); if (!ch) return; From 7f748d958601a2270b321603a257e87aee5f34df Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 30 Oct 2016 19:34:26 -0400 Subject: [PATCH 234/386] pimd: When nexthop_lookup fails allow a retry. We are seeing situations where nexthop lookups are failing unexpectedly. Don't consider the lookup to have succeeded in this case to allow the next lookup to work? Signed-off-by: Donald Sharp --- pimd/pim_rpf.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 2b16529627..1724185e97 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -172,11 +172,7 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei return 0; } else - { - nexthop->last_lookup = addr; - nexthop->last_lookup_time = pim_time_monotonic_usec(); - return -1; - } + return -1; } static int nexthop_mismatch(const struct pim_nexthop *nh1, From 372eab92a2b286e03b57035dd66a3fce3f42e60a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 31 Oct 2016 08:44:01 -0400 Subject: [PATCH 235/386] pimd: Convert pim_joinprune_send to receive upstream When sending a join/prune send in the upstream pointer. this will allow us to implement some of the other state machines necessary. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 2 +- pimd/pim_join.c | 8 ++++---- pimd/pim_join.h | 2 +- pimd/pim_upstream.c | 6 +++--- pimd/pim_zebra.c | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index ee09bf4fcb..96546f1da8 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -493,7 +493,7 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) if (send_prune_echo) pim_joinprune_send (ifp, pim_ifp->primary_address, - &sg, 0); + ch->upstream, 0); return 0; } diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 0490efda9e..b4dd8e1466 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -395,7 +395,7 @@ int pim_joinprune_recv(struct interface *ifp, int pim_joinprune_send(struct interface *ifp, struct in_addr upstream_addr, - struct prefix_sg *sg, + struct pim_upstream *up, int send_join) { struct pim_interface *pim_ifp; @@ -421,7 +421,7 @@ int pim_joinprune_send(struct interface *ifp, zlog_debug("%s: sending %s(S,G)=%s to upstream=%s on interface %s", __PRETTY_FUNCTION__, send_join ? "Join" : "Prune", - pim_str_sg_dump (sg), dst_str, ifp->name); + pim_str_sg_dump (&up->sg), dst_str, ifp->name); } if (PIM_INADDR_IS_ANY(upstream_addr)) { @@ -431,7 +431,7 @@ int pim_joinprune_send(struct interface *ifp, zlog_debug("%s: %s(S,G)=%s: upstream=%s is myself on interface %s", __PRETTY_FUNCTION__, send_join ? "Join" : "Prune", - pim_str_sg_dump (sg), dst_str, ifp->name); + pim_str_sg_dump (&up->sg), dst_str, ifp->name); } return 0; } @@ -451,7 +451,7 @@ int pim_joinprune_send(struct interface *ifp, Build PIM message */ pim_msg_size = pim_msg_join_prune_encode (pim_msg, 1000, send_join, - sg->src, sg->grp, + up->sg.src, up->sg.grp, upstream_addr, PIM_JP_HOLDTIME); if (pim_msg_size < 0) diff --git a/pimd/pim_join.h b/pimd/pim_join.h index e6bddf31be..fadb613592 100644 --- a/pimd/pim_join.h +++ b/pimd/pim_join.h @@ -35,7 +35,7 @@ int pim_joinprune_recv(struct interface *ifp, int pim_joinprune_send(struct interface *ifp, struct in_addr upstream_addr, - struct prefix_sg *sg, + struct pim_upstream *up, int send_join); #endif /* PIM_JOIN_H */ diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 7264c0de55..cb5d9bcb28 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -212,7 +212,7 @@ pim_upstream_send_join (struct pim_upstream *up) /* send Join(S,G) to the current upstream neighbor */ pim_joinprune_send(up->rpf.source_nexthop.interface, up->rpf.rpf_addr.u.prefix4, - &up->sg, + up, 1 /* join */); } @@ -481,7 +481,7 @@ pim_upstream_switch(struct pim_upstream *up, forward_off(up); pim_joinprune_send(up->rpf.source_nexthop.interface, up->rpf.rpf_addr.u.prefix4, - &up->sg, + up, 0 /* prune */); if (up->t_join_timer) THREAD_OFF(up->t_join_timer); @@ -898,7 +898,7 @@ pim_upstream_keep_alive_timer (struct thread *t) 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->sg, 0); + 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_zebra.c b/pimd/pim_zebra.c index e2a71c6e7f..3189024f84 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -400,12 +400,12 @@ static void scan_upstream_rpf_cache() /* send Prune(S,G) to the old upstream neighbor */ pim_joinprune_send(old_interface, old_rpf_addr, - &up->sg, 0 /* prune */); + up, 0 /* prune */); /* send Join(S,G) to the current upstream neighbor */ pim_joinprune_send(up->rpf.source_nexthop.interface, up->rpf.rpf_addr.u.prefix4, - &up->sg, + up, 1 /* join */); pim_upstream_join_timer_restart(up); From 8b9c900bd1cc8e76d43b43bdc0c27dfbb5cb4b32 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 31 Oct 2016 08:54:35 -0400 Subject: [PATCH 236/386] pimd: Remove unused/unmaintained test commands The test commands are not being maintained and are not out of date with the rest of the system. There are better ways to test code and in addition these commands if entered by a user could seriously impact their running system. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 738 ------------------------------------------------- 1 file changed, 738 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 36ec541cea..35a991d8a7 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -5075,736 +5075,6 @@ DEFUN (show_debugging_pim, return CMD_SUCCESS; } -static struct igmp_sock *find_igmp_sock_by_fd(int fd) -{ - struct listnode *ifnode; - struct interface *ifp; - - /* scan all interfaces */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - struct pim_interface *pim_ifp; - struct igmp_sock *igmp; - - if (!ifp->info) - continue; - - pim_ifp = ifp->info; - - /* lookup igmp socket under current interface */ - igmp = igmp_sock_lookup_by_fd(pim_ifp->igmp_socket_list, fd); - if (igmp) - return igmp; - } - - return 0; -} - -DEFUN (test_igmp_receive_report, - test_igmp_receive_report_cmd, - "test igmp receive report (0-65535) A.B.C.D (1-6) LINE...", - "Test\n" - "Test IGMP protocol\n" - "Test IGMP message\n" - "Test IGMP report\n" - "Socket\n" - "IGMP group address\n" - "Record type\n" - "Sources\n") -{ - int idx_number = 4; - int idx_ipv4 = 5; - int idx_number_2 = 6; - int idx_line = 7; - char buf[1000]; - char *igmp_msg; - struct ip *ip_hdr; - size_t ip_hlen; /* ip header length in bytes */ - int ip_msg_len; - int igmp_msg_len; - const char *socket; - int socket_fd; - const char *grp_str; - struct in_addr grp_addr; - const char *record_type_str; - int record_type; - const char *src_str; - int result; - struct igmp_sock *igmp; - char *group_record; - int num_sources; - struct in_addr *sources; - struct in_addr *src_addr; - int argi; - - socket = argv[idx_number]->arg; - socket_fd = atoi(socket); - igmp = find_igmp_sock_by_fd(socket_fd); - if (!igmp) { - vty_out(vty, "Could not find IGMP socket %s: fd=%d%s", - socket, socket_fd, VTY_NEWLINE); - return CMD_WARNING; - } - - grp_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, grp_str, &grp_addr); - if (result <= 0) { - vty_out(vty, "Bad group address %s: errno=%d: %s%s", - grp_str, errno, safe_strerror(errno), VTY_NEWLINE); - return CMD_WARNING; - } - - record_type_str = argv[idx_number_2]->arg; - record_type = atoi(record_type_str); - - /* - Tweak IP header - */ - ip_hdr = (struct ip *) buf; - ip_hdr->ip_p = PIM_IP_PROTO_IGMP; - ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */ - ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */ - ip_hdr->ip_src = igmp->ifaddr; - ip_hdr->ip_dst = igmp->ifaddr; - - /* - Build IGMP v3 report message - */ - igmp_msg = buf + ip_hlen; - group_record = igmp_msg + IGMP_V3_REPORT_GROUPPRECORD_OFFSET; - *igmp_msg = PIM_IGMP_V3_MEMBERSHIP_REPORT; /* type */ - *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET) = 0; /* for computing checksum */ - *(uint16_t *) (igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET) = htons(1); /* one group record */ - *(uint8_t *) (group_record + IGMP_V3_GROUP_RECORD_TYPE_OFFSET) = record_type; - memcpy(group_record + IGMP_V3_GROUP_RECORD_GROUP_OFFSET, &grp_addr, sizeof(struct in_addr)); - - /* Scan LINE sources */ - sources = (struct in_addr *) (group_record + IGMP_V3_GROUP_RECORD_SOURCE_OFFSET); - src_addr = sources; - for (argi = idx_line; argi < argc; ++argi,++src_addr) { - src_str = argv[argi]->arg; - result = inet_pton(AF_INET, src_str, src_addr); - if (result <= 0) { - vty_out(vty, "Bad source address %s: errno=%d: %s%s", - src_str, errno, safe_strerror(errno), VTY_NEWLINE); - return CMD_WARNING; - } - } - num_sources = src_addr - sources; - - *(uint16_t *)(group_record + IGMP_V3_GROUP_RECORD_NUMSOURCES_OFFSET) = htons(num_sources); - - igmp_msg_len = IGMP_V3_MSG_MIN_SIZE + (num_sources << 4); /* v3 report for one single group record */ - - /* compute checksum */ - *(uint16_t *)(igmp_msg + IGMP_CHECKSUM_OFFSET) = in_cksum(igmp_msg, igmp_msg_len); - - /* "receive" message */ - - ip_msg_len = ip_hlen + igmp_msg_len; - result = pim_igmp_packet(igmp, buf, ip_msg_len); - if (result) { - vty_out(vty, "pim_igmp_packet(len=%d) returned: %d%s", - ip_msg_len, result, VTY_NEWLINE); - return CMD_WARNING; - } - - return CMD_SUCCESS; -} - -static int hexval(uint8_t ch) -{ - return isdigit(ch) ? (ch - '0') : (10 + tolower(ch) - 'a'); -} - -DEFUN (test_pim_receive_dump, - test_pim_receive_dump_cmd, - "test pim receive dump INTERFACE A.B.C.D LINE...", - "Test\n" - "Test PIM protocol\n" - "Test PIM message reception\n" - "Test PIM packet dump reception from neighbor\n" - "Interface\n" - "Neighbor address\n" - "Packet dump\n") -{ - int idx_interface = 4; - int idx_ipv4 = 5; - int idx_line = 6; - uint8_t buf[1000]; - uint8_t *pim_msg; - struct ip *ip_hdr; - size_t ip_hlen; /* ip header length in bytes */ - int ip_msg_len; - int pim_msg_size; - const char *neigh_str; - struct in_addr neigh_addr; - const char *ifname; - struct interface *ifp; - int argi; - int result; - - /* Find interface */ - ifname = argv[idx_interface]->arg; - ifp = if_lookup_by_name(ifname); - if (!ifp) { - vty_out(vty, "No such interface name %s%s", - ifname, VTY_NEWLINE); - return CMD_WARNING; - } - - /* Neighbor address */ - neigh_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, neigh_str, &neigh_addr); - if (result <= 0) { - vty_out(vty, "Bad neighbor address %s: errno=%d: %s%s", - neigh_str, errno, safe_strerror(errno), VTY_NEWLINE); - return CMD_WARNING; - } - - /* - Tweak IP header - */ - ip_hdr = (struct ip *) buf; - ip_hdr->ip_p = PIM_IP_PROTO_PIM; - ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */ - ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */ - ip_hdr->ip_src = neigh_addr; - ip_hdr->ip_dst = qpim_all_pim_routers_addr; - - /* - Build PIM hello message - */ - pim_msg = buf + ip_hlen; - pim_msg_size = 0; - - /* Scan LINE dump into buffer */ - for (argi = idx_line; argi < argc; ++argi) { - const char *str = argv[argi]->arg; - int str_len = strlen(str); - int str_last = str_len - 1; - int i; - - if (str_len % 2) { - vty_out(vty, "%% Uneven hex array arg %d=%s%s", - argi, str, VTY_NEWLINE); - return CMD_WARNING; - } - - for (i = 0; i < str_last; i += 2) { - uint8_t octet; - int left; - uint8_t h1 = str[i]; - uint8_t h2 = str[i + 1]; - - if (!isxdigit(h1) || !isxdigit(h2)) { - vty_out(vty, "%% Non-hex octet %c%c at hex array arg %d=%s%s", - h1, h2, argi, str, VTY_NEWLINE); - return CMD_WARNING; - } - octet = (hexval(h1) << 4) + hexval(h2); - - left = sizeof(buf) - ip_hlen - pim_msg_size; - if (left < 1) { - vty_out(vty, "%% Overflow buf_size=%zu buf_left=%d at hex array arg %d=%s octet %02x%s", - sizeof(buf), left, argi, str, octet, VTY_NEWLINE); - return CMD_WARNING; - } - - pim_msg[pim_msg_size++] = octet; - } - } - - ip_msg_len = ip_hlen + pim_msg_size; - - vty_out(vty, "Receiving: buf_size=%zu ip_msg_size=%d pim_msg_size=%d%s", - sizeof(buf), ip_msg_len, pim_msg_size, VTY_NEWLINE); - - /* "receive" message */ - - result = pim_pim_packet(ifp, buf, ip_msg_len); - if (result) { - vty_out(vty, "%% pim_pim_packet(len=%d) returned failure: %d%s", - ip_msg_len, result, VTY_NEWLINE); - return CMD_WARNING; - } - - return CMD_SUCCESS; -} - -DEFUN (test_pim_receive_hello, - test_pim_receive_hello_cmd, - "test pim receive hello INTERFACE A.B.C.D (0-65535) (0-65535) (0-65535) (0-32767) (0-65535) (0-1) [LINE]", - "Test\n" - "Test PIM protocol\n" - "Test PIM message reception\n" - "Test PIM hello reception from neighbor\n" - "Interface\n" - "Neighbor address\n" - "Neighbor holdtime\n" - "Neighbor DR priority\n" - "Neighbor generation ID\n" - "Neighbor propagation delay (msec)\n" - "Neighbor override interval (msec)\n" - "Neighbor LAN prune delay T-bit\n" - "Neighbor secondary addresses\n") -{ - int idx_interface = 4; - int idx_ipv4 = 5; - int idx_number = 6; - int idx_number_2 = 7; - int idx_number_3 = 8; - int idx_number_4 = 9; - int idx_number_5 = 10; - int idx_number_6 = 11; - int idx_line = 12; - uint8_t buf[1000]; - uint8_t *pim_msg; - struct ip *ip_hdr; - size_t ip_hlen; /* ip header length in bytes */ - int ip_msg_len; - int pim_tlv_size; - int pim_msg_size; - const char *neigh_str; - struct in_addr neigh_addr; - const char *ifname; - struct interface *ifp; - uint16_t neigh_holdtime; - uint16_t neigh_propagation_delay; - uint16_t neigh_override_interval; - int neigh_can_disable_join_suppression; - uint32_t neigh_dr_priority; - uint32_t neigh_generation_id; - int argi; - int result; - - /* Find interface */ - ifname = argv[idx_interface]->arg; - ifp = if_lookup_by_name(ifname); - if (!ifp) { - vty_out(vty, "No such interface name %s%s", - ifname, VTY_NEWLINE); - return CMD_WARNING; - } - - /* Neighbor address */ - neigh_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, neigh_str, &neigh_addr); - if (result <= 0) { - vty_out(vty, "Bad neighbor address %s: errno=%d: %s%s", - neigh_str, errno, safe_strerror(errno), VTY_NEWLINE); - return CMD_WARNING; - } - - neigh_holdtime = atoi(argv[idx_number]->arg); - neigh_dr_priority = atoi(argv[idx_number_2]->arg); - neigh_generation_id = atoi(argv[idx_number_3]->arg); - neigh_propagation_delay = atoi(argv[idx_number_4]->arg); - neigh_override_interval = atoi(argv[idx_number_5]->arg); - neigh_can_disable_join_suppression = atoi(argv[idx_number_6]->arg); - - /* - Tweak IP header - */ - ip_hdr = (struct ip *) buf; - ip_hdr->ip_p = PIM_IP_PROTO_PIM; - ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */ - ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */ - ip_hdr->ip_src = neigh_addr; - ip_hdr->ip_dst = qpim_all_pim_routers_addr; - - /* - Build PIM hello message - */ - pim_msg = buf + ip_hlen; - - /* Scan LINE addresses */ - for (argi = idx_line; argi < argc; ++argi) { - const char *sec_str = argv[argi]->arg; - struct in_addr sec_addr; - result = inet_pton(AF_INET, sec_str, &sec_addr); - if (result <= 0) { - vty_out(vty, "Bad neighbor secondary address %s: errno=%d: %s%s", - sec_str, errno, safe_strerror(errno), VTY_NEWLINE); - return CMD_WARNING; - } - - vty_out(vty, - "FIXME WRITEME consider neighbor secondary address %s%s", - sec_str, VTY_NEWLINE); - } - - pim_tlv_size = pim_hello_build_tlv(ifp->name, - pim_msg + PIM_PIM_MIN_LEN, - sizeof(buf) - ip_hlen - PIM_PIM_MIN_LEN, - neigh_holdtime, - neigh_dr_priority, - neigh_generation_id, - neigh_propagation_delay, - neigh_override_interval, - neigh_can_disable_join_suppression, - 0 /* FIXME secondary address list */); - if (pim_tlv_size < 0) { - vty_out(vty, "pim_hello_build_tlv() returned failure: %d%s", - pim_tlv_size, VTY_NEWLINE); - return CMD_WARNING; - } - - pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN; - - pim_msg_build_header(pim_msg, pim_msg_size, - PIM_MSG_TYPE_HELLO); - - /* "receive" message */ - - ip_msg_len = ip_hlen + pim_msg_size; - result = pim_pim_packet(ifp, buf, ip_msg_len); - if (result) { - vty_out(vty, "pim_pim_packet(len=%d) returned failure: %d%s", - ip_msg_len, result, VTY_NEWLINE); - return CMD_WARNING; - } - - return CMD_SUCCESS; -} - -DEFUN (test_pim_receive_assert, - test_pim_receive_assert_cmd, - "test pim receive assert INTERFACE A.B.C.D A.B.C.D A.B.C.D (0-65535) (0-65535) (0-1)", - "Test\n" - "Test PIM protocol\n" - "Test PIM message reception\n" - "Test reception of PIM assert\n" - "Interface\n" - "Neighbor address\n" - "Assert multicast group address\n" - "Assert unicast source address\n" - "Assert metric preference\n" - "Assert route metric\n" - "Assert RPT bit flag\n") -{ - int idx_interface = 4; - int idx_ipv4 = 5; - int idx_ipv4_2 = 6; - int idx_ipv4_3 = 7; - int idx_number = 8; - int idx_number_2 = 9; - int idx_number_3 = 10; - uint8_t buf[1000]; - uint8_t *buf_pastend = buf + sizeof(buf); - uint8_t *pim_msg; - struct ip *ip_hdr; - size_t ip_hlen; /* ip header length in bytes */ - int ip_msg_len; - int pim_msg_size; - const char *neigh_str; - struct in_addr neigh_addr; - const char *group_str; - struct in_addr group_addr; - const char *source_str; - struct in_addr source_addr; - const char *ifname; - struct interface *ifp; - uint32_t assert_metric_preference; - uint32_t assert_route_metric; - uint32_t assert_rpt_bit_flag; - int remain; - int result; - - /* Find interface */ - ifname = argv[idx_interface]->arg; - ifp = if_lookup_by_name(ifname); - if (!ifp) { - vty_out(vty, "No such interface name %s%s", - ifname, VTY_NEWLINE); - return CMD_WARNING; - } - - /* Neighbor address */ - neigh_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, neigh_str, &neigh_addr); - if (result <= 0) { - vty_out(vty, "Bad neighbor address %s: errno=%d: %s%s", - neigh_str, errno, safe_strerror(errno), VTY_NEWLINE); - return CMD_WARNING; - } - - /* Group address */ - group_str = argv[idx_ipv4_2]->arg; - result = inet_pton(AF_INET, group_str, &group_addr); - if (result <= 0) { - vty_out(vty, "Bad group address %s: errno=%d: %s%s", - group_str, errno, safe_strerror(errno), VTY_NEWLINE); - return CMD_WARNING; - } - - /* Source address */ - source_str = argv[idx_ipv4_3]->arg; - result = inet_pton(AF_INET, source_str, &source_addr); - if (result <= 0) { - vty_out(vty, "Bad source address %s: errno=%d: %s%s", - source_str, errno, safe_strerror(errno), VTY_NEWLINE); - return CMD_WARNING; - } - - assert_metric_preference = atoi(argv[idx_number]->arg); - assert_route_metric = atoi(argv[idx_number_2]->arg); - assert_rpt_bit_flag = atoi(argv[idx_number_3]->arg); - - remain = buf_pastend - buf; - if (remain < (int) sizeof(struct ip)) { - vty_out(vty, "No room for ip header: buf_size=%d < ip_header_size=%zu%s", - remain, sizeof(struct ip), VTY_NEWLINE); - return CMD_WARNING; - } - - /* - Tweak IP header - */ - ip_hdr = (struct ip *) buf; - ip_hdr->ip_p = PIM_IP_PROTO_PIM; - ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */ - ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */ - ip_hdr->ip_src = neigh_addr; - ip_hdr->ip_dst = qpim_all_pim_routers_addr; - - /* - Build PIM assert message - */ - pim_msg = buf + ip_hlen; /* skip ip header */ - - pim_msg_size = pim_assert_build_msg(pim_msg, buf_pastend - pim_msg, ifp, - group_addr, source_addr, - assert_metric_preference, - assert_route_metric, - assert_rpt_bit_flag); - if (pim_msg_size < 0) { - vty_out(vty, "Failure building PIM assert message: size=%d%s", - pim_msg_size, VTY_NEWLINE); - return CMD_WARNING; - } - - /* "receive" message */ - - ip_msg_len = ip_hlen + pim_msg_size; - result = pim_pim_packet(ifp, buf, ip_msg_len); - if (result) { - vty_out(vty, "pim_pim_packet(len=%d) returned failure: %d%s", - ip_msg_len, result, VTY_NEWLINE); - return CMD_WARNING; - } - - return CMD_SUCCESS; -} - -static int recv_joinprune(struct vty *vty, - struct cmd_token **argv, - int src_is_join) -{ - uint8_t buf[1000]; - const uint8_t *buf_pastend = buf + sizeof(buf); - uint8_t *pim_msg; - int pim_msg_size; - struct ip *ip_hdr; - size_t ip_hlen; /* ip header length in bytes */ - int ip_msg_len; - uint16_t neigh_holdtime; - const char *neigh_dst_str; - struct in_addr neigh_dst_addr; - const char *neigh_src_str; - struct in_addr neigh_src_addr; - const char *group_str; - struct in_addr group_addr; - const char *source_str; - struct in_addr source_addr; - const char *ifname; - struct interface *ifp; - int result; - - /* Find interface */ - ifname = argv[0]->arg; - ifp = if_lookup_by_name(ifname); - if (!ifp) { - vty_out(vty, "No such interface name %s%s", - ifname, VTY_NEWLINE); - return CMD_WARNING; - } - - neigh_holdtime = atoi(argv[1]->arg); - - /* Neighbor destination address */ - neigh_dst_str = argv[2]->arg; - result = inet_pton(AF_INET, neigh_dst_str, &neigh_dst_addr); - if (result <= 0) { - vty_out(vty, "Bad neighbor destination address %s: errno=%d: %s%s", - neigh_dst_str, errno, safe_strerror(errno), VTY_NEWLINE); - return CMD_WARNING; - } - - /* Neighbor source address */ - neigh_src_str = argv[3]->arg; - result = inet_pton(AF_INET, neigh_src_str, &neigh_src_addr); - if (result <= 0) { - vty_out(vty, "Bad neighbor source address %s: errno=%d: %s%s", - neigh_src_str, errno, safe_strerror(errno), VTY_NEWLINE); - return CMD_WARNING; - } - - /* Multicast group address */ - group_str = argv[4]->arg; - result = inet_pton(AF_INET, group_str, &group_addr); - if (result <= 0) { - vty_out(vty, "Bad group address %s: errno=%d: %s%s", - group_str, errno, safe_strerror(errno), VTY_NEWLINE); - return CMD_WARNING; - } - - /* Multicast source address */ - source_str = argv[5]->arg; - result = inet_pton(AF_INET, source_str, &source_addr); - if (result <= 0) { - vty_out(vty, "Bad source address %s: errno=%d: %s%s", - source_str, errno, safe_strerror(errno), VTY_NEWLINE); - return CMD_WARNING; - } - - /* - Tweak IP header - */ - ip_hdr = (struct ip *) buf; - ip_hdr->ip_p = PIM_IP_PROTO_PIM; - ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */ - ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */ - ip_hdr->ip_src = neigh_src_addr; - ip_hdr->ip_dst = qpim_all_pim_routers_addr; - - /* - Build PIM message - */ - pim_msg = buf + ip_hlen; - - pim_msg_size = pim_msg_join_prune_encode (pim_msg, buf_pastend - pim_msg, src_is_join, - source_addr, group_addr, neigh_dst_addr, - neigh_holdtime); - - /* - "Receive" message - */ - - ip_msg_len = ip_hlen + pim_msg_size; - result = pim_pim_packet(ifp, buf, ip_msg_len); - if (result) { - vty_out(vty, "pim_pim_packet(len=%d) returned failure: %d%s", - ip_msg_len, result, VTY_NEWLINE); - return CMD_WARNING; - } - - return CMD_SUCCESS; -} - -DEFUN (test_pim_receive_join, - test_pim_receive_join_cmd, - "test pim receive join INTERFACE (0-65535) A.B.C.D A.B.C.D A.B.C.D A.B.C.D", - "Test\n" - "Test PIM protocol\n" - "Test PIM message reception\n" - "Test PIM join reception from neighbor\n" - "Interface\n" - "Neighbor holdtime\n" - "Upstream neighbor unicast destination address\n" - "Downstream neighbor unicast source address\n" - "Multicast group address\n" - "Unicast source address\n") -{ - return recv_joinprune(vty, argv, 1 /* src_is_join=true */); -} - -DEFUN (test_pim_receive_prune, - test_pim_receive_prune_cmd, - "test pim receive prune INTERFACE (0-65535) A.B.C.D A.B.C.D A.B.C.D A.B.C.D", - "Test\n" - "Test PIM protocol\n" - "Test PIM message reception\n" - "Test PIM prune reception from neighbor\n" - "Interface\n" - "Neighbor holdtime\n" - "Upstream neighbor unicast destination address\n" - "Downstream neighbor unicast source address\n" - "Multicast group address\n" - "Unicast source address\n") -{ - return recv_joinprune(vty, argv, 0 /* src_is_join=false */); -} - -DEFUN (test_pim_receive_upcall, - test_pim_receive_upcall_cmd, - "test pim receive upcall (0-65535) A.B.C.D A.B.C.D", - "Test\n" - "Test PIM protocol\n" - "Test PIM message reception\n" - "Test reception of kernel upcall\n" - "NOCACHE kernel upcall\n" - "WRONGVIF kernel upcall\n" - "WHOLEPKT kernel upcall\n" - "Input interface vif index\n" - "Multicast group address\n" - "Multicast source address\n") -{ - int idx_type = 4; - int idx_number = 5; - int idx_ipv4 = 6; - int idx_ipv4_2 = 7; - struct igmpmsg msg; - const char *upcall_type; - const char *group_str; - const char *source_str; - int result; - - upcall_type = argv[idx_type]->arg; - - if (upcall_type[0] == 'n') - msg.im_msgtype = IGMPMSG_NOCACHE; - else if (upcall_type[1] == 'r') - msg.im_msgtype = IGMPMSG_WRONGVIF; - else if (upcall_type[1] == 'h') - msg.im_msgtype = IGMPMSG_WHOLEPKT; - else { - vty_out(vty, "Unknown kernel upcall type: %s%s", - upcall_type, VTY_NEWLINE); - return CMD_WARNING; - } - - msg.im_vif = atoi(argv[idx_number]->arg); - - /* Group address */ - group_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, group_str, &msg.im_dst); - if (result <= 0) { - vty_out(vty, "Bad group address %s: errno=%d: %s%s", - group_str, errno, safe_strerror(errno), VTY_NEWLINE); - return CMD_WARNING; - } - - /* Source address */ - source_str = argv[idx_ipv4_2]->arg; - result = inet_pton(AF_INET, source_str, &msg.im_src); - if (result <= 0) { - vty_out(vty, "Bad source address %s: errno=%d: %s%s", - source_str, errno, safe_strerror(errno), VTY_NEWLINE); - return CMD_WARNING; - } - - msg.im_mbz = 0; /* Must be zero */ - - result = pim_mroute_msg(-1, (char *) &msg, sizeof(msg)); - if (result) { - vty_out(vty, "pim_mroute_msg(len=%zu) returned failure: %d%s", - sizeof(msg), result, VTY_NEWLINE); - return CMD_WARNING; - } - - return CMD_SUCCESS; -} - void pim_cmd_init() { install_node (&pim_global_node, pim_global_config_write); /* PIM_NODE */ @@ -5887,14 +5157,6 @@ void pim_cmd_init() install_element (ENABLE_NODE, &clear_ip_pim_interfaces_cmd); install_element (ENABLE_NODE, &clear_ip_pim_oil_cmd); - install_element (ENABLE_NODE, &test_igmp_receive_report_cmd); - install_element (ENABLE_NODE, &test_pim_receive_assert_cmd); - install_element (ENABLE_NODE, &test_pim_receive_dump_cmd); - install_element (ENABLE_NODE, &test_pim_receive_hello_cmd); - install_element (ENABLE_NODE, &test_pim_receive_join_cmd); - install_element (ENABLE_NODE, &test_pim_receive_prune_cmd); - install_element (ENABLE_NODE, &test_pim_receive_upcall_cmd); - install_element (ENABLE_NODE, &debug_igmp_cmd); install_element (ENABLE_NODE, &no_debug_igmp_cmd); install_element (ENABLE_NODE, &debug_igmp_events_cmd); From f99df3e77acf482a1c53d11d7782a7aeaa74fedf Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 31 Oct 2016 09:03:57 -0400 Subject: [PATCH 237/386] pimd: Pass in upstream to pim_msg_join_prune_encode. Pass in the upstream data structure to pim_msg_join_prune_encode so it can decide to send (S,G,rpt) information if it wants to or not. Signed-off-by: Donald Sharp --- pimd/pim_join.c | 7 +++---- pimd/pim_msg.c | 14 +++++++------- pimd/pim_msg.h | 2 +- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/pimd/pim_join.c b/pimd/pim_join.c index b4dd8e1466..dcbd122151 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -399,7 +399,7 @@ int pim_joinprune_send(struct interface *ifp, int send_join) { struct pim_interface *pim_ifp; - uint8_t pim_msg[1000]; + uint8_t pim_msg[9000]; int pim_msg_size; on_trace (__PRETTY_FUNCTION__, ifp, upstream_addr); @@ -450,9 +450,8 @@ int pim_joinprune_send(struct interface *ifp, /* Build PIM message */ - pim_msg_size = pim_msg_join_prune_encode (pim_msg, 1000, send_join, - up->sg.src, up->sg.grp, - upstream_addr, PIM_JP_HOLDTIME); + pim_msg_size = pim_msg_join_prune_encode (pim_msg, 9000, send_join, + up, upstream_addr, PIM_JP_HOLDTIME); if (pim_msg_size < 0) return pim_msg_size; diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index edc7f0ee42..749cee96e9 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -115,7 +115,7 @@ pim_msg_addr_encode_ipv4_source(uint8_t *buf, int buf_size, int pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, - struct in_addr source, struct in_addr group, + struct pim_upstream *up, struct in_addr upstream, int holdtime) { uint8_t *pim_msg = buf; @@ -153,10 +153,10 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, remain = end - pim_msg_curr; pim_msg_curr = pim_msg_addr_encode_ipv4_group (pim_msg_curr, remain, - group); + up->sg.grp); if (!pim_msg_curr) { char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group, group_str, sizeof(group_str)); + pim_inet4_dump("", up->sg.grp, group_str, sizeof(group_str)); zlog_warn("%s: failure encoding group address %s: space left=%d", __PRETTY_FUNCTION__, group_str, remain); return -5; @@ -180,21 +180,21 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, ++pim_msg_curr; remain = end - pim_msg_curr; - if (source.s_addr == INADDR_ANY) + if (up->sg.src.s_addr == INADDR_ANY) { - struct pim_rpf *rpf = pim_rp_g (group); + struct pim_rpf *rpf = pim_rp_g (up->sg.grp); bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT | PIM_ENCODE_RPT_BIT; stosend = rpf->rpf_addr.u.prefix4; } else { bits = PIM_ENCODE_SPARSE_BIT; - stosend = source; + stosend = up->sg.src; } pim_msg_curr = pim_msg_addr_encode_ipv4_source (pim_msg_curr, remain, stosend, bits); if (!pim_msg_curr) { char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", source, source_str, sizeof(source_str)); + pim_inet4_dump("", up->sg.src, source_str, sizeof(source_str)); zlog_warn("%s: failure encoding source address %s: space left=%d", __PRETTY_FUNCTION__, source_str, remain); return -7; diff --git a/pimd/pim_msg.h b/pimd/pim_msg.h index 1bd8207cc1..78ff569b7c 100644 --- a/pimd/pim_msg.h +++ b/pimd/pim_msg.h @@ -55,6 +55,6 @@ uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, int pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, - struct in_addr source, struct in_addr group, + struct pim_upstream *up, struct in_addr upstream, int holdtime); #endif /* PIM_MSG_H */ From 06afa136e98ce4de5bd1161914a7418f5e19098d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 31 Oct 2016 09:20:01 -0400 Subject: [PATCH 238/386] pimd: Fix gcc compile issue. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 96546f1da8..f5b20ab485 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -470,7 +470,6 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) int send_prune_echo; /* boolean */ struct interface *ifp; struct pim_interface *pim_ifp; - struct prefix_sg sg; zassert(t); ch = THREAD_ARG(t); @@ -485,9 +484,6 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) pim_ifp = ifp->info; send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1); - /* Save (S,G) */ - sg = ch->sg; - ifjoin_to_noinfo(ch); /* from here ch may have been deleted */ From 2a333e0f220fb727406459d60815a1cc9000183a Mon Sep 17 00:00:00 2001 From: anuradhak Date: Tue, 25 Oct 2016 10:59:48 -0700 Subject: [PATCH 239/386] pim-msdp: part-1 - initial protocol infra. This commit includes the following changes - 1. Support for MSDP peer DB (hash and sorted list). 2. Support for the following timers - keepalive, connect-retry, hold. 3. TCP session management (lower-ip is active, higher-ip is passive). 4. MSDP KA packet rx/tx. 5. Limited temporary config (will be replaced with the more automation friendly RP-set). Testing done - Peer bringup/deletion (including interop with another vendor) Sample out - root@dell-s6000-04:~# sudo vtysh -c "show ip msdp peer" Peer Local Mesh-group State Uptime 100.1.1.1 100.1.2.1 default established 00:07:27 100.1.3.1 100.1.2.1 default established 00:31:50 root@dell-s6000-04:~# Coming soon - 1. part-2: SA cache management. 2. part-3: SPT setup using source in SA cache. 3. part-4: CLI cleanup. Ticket: CM-13306 Signed-off-by: Anuradha Karuppiah Acked-by: Donald Sharp --- pimd/Makefile.am | 4 +- pimd/pim_cmd.c | 251 +++++++++++++++++++ pimd/pim_cmd.h | 5 + pimd/pim_main.c | 3 +- pimd/pim_memory.c | 4 +- pimd/pim_memory.h | 2 + pimd/pim_msdp.c | 547 ++++++++++++++++++++++++++++++++++++++++- pimd/pim_msdp.h | 152 +++++++++--- pimd/pim_msdp_packet.c | 380 ++++++++++++++++++++++++++++ pimd/pim_msdp_packet.h | 34 +++ pimd/pim_msdp_socket.c | 228 +++++++++++++++++ pimd/pim_msdp_socket.h | 25 ++ pimd/pim_vty.c | 8 + pimd/pimd.h | 16 +- 14 files changed, 1613 insertions(+), 46 deletions(-) create mode 100644 pimd/pim_msdp_packet.c create mode 100644 pimd/pim_msdp_packet.h create mode 100644 pimd/pim_msdp_socket.c create mode 100644 pimd/pim_msdp_socket.h diff --git a/pimd/Makefile.am b/pimd/Makefile.am index bb3d1844c5..bab0d00ebc 100644 --- a/pimd/Makefile.am +++ b/pimd/Makefile.am @@ -55,7 +55,7 @@ libpim_a_SOURCES = \ pim_msg.c pim_upstream.c pim_rpf.c pim_macro.c \ pim_ssmpingd.c pim_int.c pim_rp.c \ pim_static.c pim_br.c pim_register.c pim_routemap.c \ - pim_msdp.c + pim_msdp.c pim_msdp_socket.c pim_msdp_packet.c noinst_HEADERS = \ pim_memory.h \ @@ -67,7 +67,7 @@ noinst_HEADERS = \ pim_msg.h pim_upstream.h pim_rpf.h pim_macro.h \ pim_igmp_join.h pim_ssmpingd.h pim_int.h pim_rp.h \ pim_static.h pim_br.h pim_register.h \ - pim_msdp.h + pim_msdp.h pim_msdp_socket.h pim_msdp_packet.h pimd_SOURCES = \ pim_main.c $(libpim_a_SOURCES) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 35a991d8a7..d0c05563c0 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -54,6 +54,7 @@ #include "pim_static.h" #include "pim_rp.h" #include "pim_zlookup.h" +#include "pim_msdp.h" static struct cmd_node pim_global_node = { PIM_NODE, @@ -5064,6 +5065,95 @@ DEFUN (no_debug_pim_zebra, } +DEFUN (debug_msdp, + debug_msdp_cmd, + "debug msdp", + DEBUG_STR + DEBUG_MSDP_STR) +{ + PIM_DO_DEBUG_MSDP_EVENTS; + PIM_DO_DEBUG_MSDP_PACKETS; + return CMD_SUCCESS; +} + +DEFUN (no_debug_msdp, + no_debug_msdp_cmd, + "no debug msdp", + NO_STR + DEBUG_STR + DEBUG_MSDP_STR) +{ + PIM_DONT_DEBUG_MSDP_EVENTS; + PIM_DONT_DEBUG_MSDP_PACKETS; + return CMD_SUCCESS; +} + +ALIAS (no_debug_msdp, + undebug_msdp_cmd, + "undebug msdp", + UNDEBUG_STR + DEBUG_MSDP_STR) + +DEFUN (debug_msdp_events, + debug_msdp_events_cmd, + "debug msdp events", + DEBUG_STR + DEBUG_MSDP_STR + DEBUG_MSDP_EVENTS_STR) +{ + PIM_DO_DEBUG_MSDP_EVENTS; + return CMD_SUCCESS; +} + +DEFUN (no_debug_msdp_events, + no_debug_msdp_events_cmd, + "no debug msdp events", + NO_STR + DEBUG_STR + DEBUG_MSDP_STR + DEBUG_MSDP_EVENTS_STR) +{ + PIM_DONT_DEBUG_MSDP_EVENTS; + return CMD_SUCCESS; +} + +ALIAS (no_debug_msdp_events, + undebug_msdp_events_cmd, + "undebug msdp events", + UNDEBUG_STR + DEBUG_MSDP_STR + DEBUG_MSDP_EVENTS_STR) + +DEFUN (debug_msdp_packets, + debug_msdp_packets_cmd, + "debug msdp packets", + DEBUG_STR + DEBUG_MSDP_STR + DEBUG_MSDP_PACKETS_STR) +{ + PIM_DO_DEBUG_MSDP_PACKETS; + return CMD_SUCCESS; +} + +DEFUN (no_debug_msdp_packets, + no_debug_msdp_packets_cmd, + "no debug msdp packets", + NO_STR + DEBUG_STR + DEBUG_MSDP_STR + DEBUG_MSDP_PACKETS_STR) +{ + PIM_DONT_DEBUG_MSDP_PACKETS; + return CMD_SUCCESS; +} + +ALIAS (no_debug_msdp_packets, + undebug_msdp_packets_cmd, + "undebug msdp packets", + UNDEBUG_STR + DEBUG_MSDP_STR + DEBUG_MSDP_PACKETS_STR) + DEFUN (show_debugging_pim, show_debugging_pim_cmd, "show debugging pim", @@ -5075,6 +5165,146 @@ DEFUN (show_debugging_pim, return CMD_SUCCESS; } +static int +ip_msdp_peer_cmd_worker (struct vty *vty, const char *peer, const char *local) +{ + enum pim_msdp_err result; + struct in_addr peer_addr; + struct in_addr local_addr; + + result = inet_pton(AF_INET, peer, &peer_addr); + if (result <= 0) { + vty_out(vty, "%% Bad peer address %s: errno=%d: %s%s", + peer, errno, safe_strerror(errno), VTY_NEWLINE); + return CMD_WARNING; + } + + result = inet_pton(AF_INET, local, &local_addr); + if (result <= 0) { + vty_out(vty, "%% Bad source address %s: errno=%d: %s%s", + local, errno, safe_strerror(errno), VTY_NEWLINE); + return CMD_WARNING; + } + + result = pim_msdp_peer_add(peer_addr, local_addr, "default"); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_OOM: + vty_out(vty, "%% Out of memory%s", VTY_NEWLINE); + break; + case PIM_MSDP_ERR_PEER_EXISTS: + vty_out(vty, "%% Peer exists%s", VTY_NEWLINE); + break; + case PIM_MSDP_ERR_MAX_MESH_GROUPS: + vty_out(vty, "%% Only one mesh-group allowed currently%s", VTY_NEWLINE); + break; + default: + vty_out(vty, "%% peer add failed%s", VTY_NEWLINE); + } + + return result?CMD_WARNING:CMD_SUCCESS; +} + +DEFUN (ip_msdp_peer, + ip_msdp_peer_cmd, + "ip msdp peer A.B.C.D source A.B.C.D", + IP_STR + CFG_MSDP_STR + "Configure MSDP peer\n" + "peer ip address\n" + "Source address for TCP connection\n" + "local ip address\n") +{ + return ip_msdp_peer_cmd_worker (vty, argv[3]->arg, argv[5]->arg); +} + +static int +ip_no_msdp_peer_cmd_worker (struct vty *vty, const char *peer) +{ + enum pim_msdp_err result; + struct in_addr peer_addr; + + result = inet_pton(AF_INET, peer, &peer_addr); + if (result <= 0) { + vty_out(vty, "%% Bad peer address %s: errno=%d: %s%s", + peer, errno, safe_strerror(errno), VTY_NEWLINE); + return CMD_WARNING; + } + + result = pim_msdp_peer_del(peer_addr); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_NO_PEER: + vty_out(vty, "%% Peer does not exist%s", VTY_NEWLINE); + break; + default: + vty_out(vty, "%% peer del failed%s", VTY_NEWLINE); + } + + return result?CMD_WARNING:CMD_SUCCESS; +} + +DEFUN (no_ip_msdp_peer, + no_ip_msdp_peer_cmd, + "no ip msdp peer A.B.C.D", + IP_STR + CFG_MSDP_STR + "Delete MSDP peer\n" + "peer ip address\n") +{ + return ip_no_msdp_peer_cmd_worker (vty, argv[4]->arg); +} + +static void +ip_msdp_show_peers(struct vty *vty, u_char uj) +{ + struct listnode *mpnode; + struct pim_msdp_peer *mp; + char peer_str[INET_ADDRSTRLEN]; + char local_str[INET_ADDRSTRLEN]; + char state_str[PIM_MSDP_STATE_STRLEN]; + char timebuf[PIM_MSDP_UPTIME_STRLEN]; + int64_t now; + + if (uj) { + // XXX: blah + return; + } else { + vty_out(vty, "Peer Local Mesh-group State Uptime%s", VTY_NEWLINE); + for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { + if (mp->state == PIM_MSDP_ESTABLISHED) { + now = pim_time_monotonic_sec(); + pim_time_uptime(timebuf, sizeof(timebuf), now - mp->uptime); + } else { + strcpy(timebuf, "-"); + } + pim_inet4_dump("", mp->peer, peer_str, sizeof(peer_str)); + pim_inet4_dump("", mp->local, local_str, sizeof(local_str)); + pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); + vty_out(vty, "%-15s %15s %16s %11s %8s%s", + peer_str, local_str, mp->mesh_group_name, state_str, + timebuf, VTY_NEWLINE); + } + } +} + +DEFUN (show_ip_msdp_peer, + show_ip_msdp_peer_cmd, + "show ip msdp peer [json]", + SHOW_STR + IP_STR + MSDP_STR + "MSDP peer information\n" + "JavaScript Object Notation\n") +{ + u_char uj = use_json(argc, argv); + ip_msdp_show_peers(vty, uj); + + return CMD_SUCCESS; +} + void pim_cmd_init() { install_node (&pim_global_node, pim_global_config_write); /* PIM_NODE */ @@ -5095,6 +5325,8 @@ void pim_cmd_init() install_element (CONFIG_NODE, &no_ip_pim_rp_keep_alive_cmd); install_element (CONFIG_NODE, &ip_ssmpingd_cmd); install_element (CONFIG_NODE, &no_ip_ssmpingd_cmd); + install_element (CONFIG_NODE, &ip_msdp_peer_cmd); + install_element (CONFIG_NODE, &no_ip_msdp_peer_cmd); install_element (INTERFACE_NODE, &interface_ip_igmp_cmd); install_element (INTERFACE_NODE, &interface_no_ip_igmp_cmd); @@ -5149,6 +5381,7 @@ void pim_cmd_init() install_element (VIEW_NODE, &show_ip_mroute_count_cmd); install_element (VIEW_NODE, &show_ip_rib_cmd); install_element (VIEW_NODE, &show_ip_ssmpingd_cmd); + install_element (VIEW_NODE, &show_ip_msdp_peer_cmd); install_element (VIEW_NODE, &show_debugging_pim_cmd); install_element (ENABLE_NODE, &clear_ip_interfaces_cmd); @@ -5189,6 +5422,15 @@ void pim_cmd_init() install_element (ENABLE_NODE, &no_debug_ssmpingd_cmd); install_element (ENABLE_NODE, &debug_pim_zebra_cmd); install_element (ENABLE_NODE, &no_debug_pim_zebra_cmd); + install_element (ENABLE_NODE, &debug_msdp_cmd); + install_element (ENABLE_NODE, &no_debug_msdp_cmd); + install_element (ENABLE_NODE, &undebug_msdp_cmd); + install_element (ENABLE_NODE, &debug_msdp_events_cmd); + install_element (ENABLE_NODE, &no_debug_msdp_events_cmd); + install_element (ENABLE_NODE, &undebug_msdp_events_cmd); + install_element (ENABLE_NODE, &debug_msdp_packets_cmd); + install_element (ENABLE_NODE, &no_debug_msdp_packets_cmd); + install_element (ENABLE_NODE, &undebug_msdp_packets_cmd); install_element (CONFIG_NODE, &debug_igmp_cmd); install_element (CONFIG_NODE, &no_debug_igmp_cmd); @@ -5218,4 +5460,13 @@ void pim_cmd_init() install_element (CONFIG_NODE, &no_debug_ssmpingd_cmd); install_element (CONFIG_NODE, &debug_pim_zebra_cmd); install_element (CONFIG_NODE, &no_debug_pim_zebra_cmd); + install_element (CONFIG_NODE, &debug_msdp_cmd); + install_element (CONFIG_NODE, &no_debug_msdp_cmd); + install_element (CONFIG_NODE, &undebug_msdp_cmd); + install_element (CONFIG_NODE, &debug_msdp_events_cmd); + install_element (CONFIG_NODE, &no_debug_msdp_events_cmd); + install_element (CONFIG_NODE, &undebug_msdp_events_cmd); + install_element (CONFIG_NODE, &debug_msdp_packets_cmd); + install_element (CONFIG_NODE, &no_debug_msdp_packets_cmd); + install_element (CONFIG_NODE, &undebug_msdp_packets_cmd); } diff --git a/pimd/pim_cmd.h b/pimd/pim_cmd.h index d5e5c6a304..dd9300df8e 100644 --- a/pimd/pim_cmd.h +++ b/pimd/pim_cmd.h @@ -59,6 +59,11 @@ #define CLEAR_IP_PIM_STR "PIM clear commands\n" #define MROUTE_STR "IP multicast routing table\n" #define RIB_STR "IP unicast routing table\n" +#define CFG_MSDP_STR "Configure multicast source discovery protocol\n" +#define MSDP_STR "MSDP information\n" +#define DEBUG_MSDP_STR "MSDP protocol activity\n" +#define DEBUG_MSDP_EVENTS_STR "MSDP protocol events\n" +#define DEBUG_MSDP_PACKETS_STR "MSDP protocol packets\n" void pim_cmd_init(void); diff --git a/pimd/pim_main.c b/pimd/pim_main.c index 1ddc1eac54..24163b0bd0 100644 --- a/pimd/pim_main.c +++ b/pimd/pim_main.c @@ -73,6 +73,7 @@ zebra_capabilities_t _caps_p [] = ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN, ZCAP_NET_RAW, + ZCAP_BIND, }; /* pimd privileges to run with */ @@ -214,7 +215,7 @@ int main(int argc, char** argv, char** envp) { pim_route_map_init (); pim_init(); - pim_msdp_init (); + pim_msdp_init (master); /* * Initialize zclient "update" and "lookup" sockets diff --git a/pimd/pim_memory.c b/pimd/pim_memory.c index 219dd96816..30a5446dd7 100644 --- a/pimd/pim_memory.c +++ b/pimd/pim_memory.c @@ -40,4 +40,6 @@ DEFINE_MTYPE(PIMD, PIM_SSMPINGD, "PIM sspimgd socket") DEFINE_MTYPE(PIMD, PIM_STATIC_ROUTE, "PIM Static Route") DEFINE_MTYPE(PIMD, PIM_BR, "PIM Bridge Router info") DEFINE_MTYPE(PIMD, PIM_RP, "PIM RP info") -DEFINE_MTYPE(PIMD, PIM_FILTER_NAME, "PIM Filter Name") +DEFINE_MTYPE(PIMD, PIM_FILTER_NAME, "PIM RP filter info") +DEFINE_MTYPE(PIMD, PIM_MSDP_PEER, "PIM MSDP peer") +DEFINE_MTYPE(PIMD, PIM_MSDP_PEER_MG_NAME, "PIM MSDP peer mesh-group") diff --git a/pimd/pim_memory.h b/pimd/pim_memory.h index fc0dd91f85..2b7e6ad375 100644 --- a/pimd/pim_memory.h +++ b/pimd/pim_memory.h @@ -40,5 +40,7 @@ DECLARE_MTYPE(PIM_STATIC_ROUTE) DECLARE_MTYPE(PIM_BR) DECLARE_MTYPE(PIM_RP) DECLARE_MTYPE(PIM_FILTER_NAME) +DECLARE_MTYPE(PIM_MSDP_PEER) +DECLARE_MTYPE(PIM_MSDP_PEER_MG_NAME) #endif /* _QUAGGA_PIM_MEMORY_H */ diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 8cfe7864a3..2805a06097 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -1,7 +1,6 @@ /* - * PIM for Quagga + * IP MSDP for Quagga * Copyright (C) 2016 Cumulus Networks, Inc. - * Donald Sharp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,12 +20,546 @@ #include -#include +#include +#include +#include +#include +#include +#include -#include +#include "pimd.h" +#include "pim_cmd.h" +#include "pim_memory.h" +#include "pim_str.h" +#include "pim_time.h" -void -pim_msdp_init (void) +#include "pim_msdp.h" +#include "pim_msdp_packet.h" +#include "pim_msdp_socket.h" + +struct pim_msdp pim_msdp, *msdp = &pim_msdp; + +static void pim_msdp_peer_listen(struct pim_msdp_peer *mp); +static void pim_msdp_peer_cr_timer_setup(struct pim_msdp_peer *mp, bool start); +static void pim_msdp_peer_ka_timer_setup(struct pim_msdp_peer *mp, bool start); +static void pim_msdp_peer_hold_timer_setup(struct pim_msdp_peer *mp, bool start); +static void pim_msdp_peer_free(struct pim_msdp_peer *mp); + +char * +pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf, int buf_size) { - return; + switch (state) { + case PIM_MSDP_DISABLED: + snprintf(buf, buf_size, "%s", "disabled"); + break; + case PIM_MSDP_INACTIVE: + snprintf(buf, buf_size, "%s", "inactive"); + break; + case PIM_MSDP_LISTEN: + snprintf(buf, buf_size, "%s", "listen"); + break; + case PIM_MSDP_CONNECTING: + snprintf(buf, buf_size, "%s", "connecting"); + break; + case PIM_MSDP_ESTABLISHED: + snprintf(buf, buf_size, "%s", "established"); + break; + default: + snprintf(buf, buf_size, "unk-%d", state); + } + return buf; +} + +char * +pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size, bool long_format) +{ + char peer_str[INET_ADDRSTRLEN]; + char local_str[INET_ADDRSTRLEN]; + + pim_inet4_dump("", mp->peer, peer_str, sizeof(peer_str)); + if (long_format) { + pim_inet4_dump("", mp->local, local_str, sizeof(local_str)); + snprintf(buf, buf_size, "MSDP peer %s local %s mg %s", + peer_str, local_str, mp->mesh_group_name); + } else { + snprintf(buf, buf_size, "MSDP peer %s", peer_str); + } + + return buf; +} + +static void +pim_msdp_peer_state_chg_log(struct pim_msdp_peer *mp) +{ + char state_str[PIM_MSDP_STATE_STRLEN]; + char key_str[PIM_MSDP_PEER_KEY_STRLEN]; + + pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); + pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), false); + zlog_debug("%s state chg to %s", key_str, state_str); +} + +/* MSDP Connection State Machine actions (defined in RFC-3618:Sec-11.2) */ +/* 11.2.A2: active peer - start connect retry timer; when the timer fires + * a tcp connection will be made */ +static void +pim_msdp_peer_connect(struct pim_msdp_peer *mp) +{ + mp->state = PIM_MSDP_CONNECTING; + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_state_chg_log(mp); + } + + pim_msdp_peer_cr_timer_setup(mp, true /* start */); +} + +/* 11.2.A3: passive peer - just listen for connections */ +static void +pim_msdp_peer_listen(struct pim_msdp_peer *mp) +{ + mp->state = PIM_MSDP_LISTEN; + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_state_chg_log(mp); + } + + /* this is interntionally asymmetric i.e. we set up listen-socket when the + * first listening peer is configured; but don't bother tearing it down when + * all the peers go down */ + pim_msdp_sock_listen(); +} + +/* 11.2.A4 and 11.2.A5: transition active or passive peer to + * established state */ +void +pim_msdp_peer_established(struct pim_msdp_peer *mp) +{ + mp->state = PIM_MSDP_ESTABLISHED; + mp->uptime = pim_time_monotonic_sec(); + + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_state_chg_log(mp); + } + + /* stop retry timer on active peers */ + pim_msdp_peer_cr_timer_setup(mp, false /* start */); + + /* send KA; start KA and hold timers */ + pim_msdp_pkt_ka_tx(mp); + pim_msdp_peer_ka_timer_setup(mp, true /* start */); + pim_msdp_peer_hold_timer_setup(mp, true /* start */); + + PIM_MSDP_PEER_WRITE_ON(mp); + PIM_MSDP_PEER_READ_ON(mp); +} + +/* 11.2.A6, 11.2.A7 and 11.2.A8: shutdown the peer tcp connection */ +void +pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state) +{ + if (chg_state) { + mp->state = PIM_MSDP_INACTIVE; + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_state_chg_log(mp); + } + } + + /* stop read and write threads */ + PIM_MSDP_PEER_READ_OFF(mp); + PIM_MSDP_PEER_WRITE_OFF(mp); + + /* reset buffers */ + if (mp->ibuf) + stream_reset(mp->ibuf); + if (mp->obuf) + stream_fifo_clean(mp->obuf); + + /* stop all peer timers */ + pim_msdp_peer_ka_timer_setup(mp, false /* start */); + pim_msdp_peer_cr_timer_setup(mp, false /* start */); + pim_msdp_peer_hold_timer_setup(mp, false /* start */); + + /* close connection */ + if (mp->fd >= 0) { + close(mp->fd); + mp->fd = -1; + } +} + +/* RFC-3618:Sec-5.6 - stop the peer tcp connection and startover */ +void +pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str) +{ + if (PIM_DEBUG_EVENTS) { + char key_str[PIM_MSDP_PEER_KEY_STRLEN]; + + pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), false); + zlog_debug("%s tcp reset %s", key_str, rc_str); + } + + /* close the connection and transition to listening or connecting */ + pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); + if (PIM_MSDP_PEER_IS_LISTENER(mp)) { + pim_msdp_peer_listen(mp); + } else { + pim_msdp_peer_connect(mp); + } +} + +static void +pim_msdp_peer_timer_expiry_log(struct pim_msdp_peer *mp, const char *timer_str) +{ + char key_str[PIM_MSDP_PEER_KEY_STRLEN]; + + pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), false); + zlog_debug("%s timer %s expired", key_str, timer_str); +} + +/* RFC-3618:Sec-5.4 - peer hold timer */ +static int +pim_msdp_peer_hold_timer_cb(struct thread *t) +{ + struct pim_msdp_peer *mp; + + zassert(t); + mp = THREAD_ARG(t); + zassert(mp); + + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_timer_expiry_log(mp, "hold"); + } + + if (mp->state != PIM_MSDP_ESTABLISHED) { + return 0; + } + + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_state_chg_log(mp); + } + pim_msdp_peer_reset_tcp_conn(mp, "ht-expired"); + return 0; +} +static void +pim_msdp_peer_hold_timer_setup(struct pim_msdp_peer *mp, bool start) +{ + THREAD_OFF(mp->hold_timer); + if (start) { + THREAD_TIMER_ON(msdp->master, mp->hold_timer, + pim_msdp_peer_hold_timer_cb, mp, PIM_MSDP_PEER_HOLD_TIME); + } +} + + +/* RFC-3618:Sec-5.5 - peer keepalive timer */ +static int +pim_msdp_peer_ka_timer_cb(struct thread *t) +{ + struct pim_msdp_peer *mp; + + zassert(t); + mp = THREAD_ARG(t); + zassert(mp); + + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_timer_expiry_log(mp, "ka"); + } + + if (mp->state != PIM_MSDP_ESTABLISHED) { + return 0; + } + + pim_msdp_pkt_ka_tx(mp); + 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) +{ + THREAD_OFF(mp->ka_timer); + if (start) { + THREAD_TIMER_ON(msdp->master, mp->ka_timer, + pim_msdp_peer_ka_timer_cb, mp, PIM_MSDP_PEER_KA_TIME); + } +} + +static void +pim_msdp_peer_active_connect(struct pim_msdp_peer *mp) +{ + int rc; + rc = pim_msdp_sock_connect(mp); + + 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_active_connect: %d", key_str, rc); + } + + switch (rc) { + case connect_error: + /* connect failed restart the connect-retry timer */ + pim_msdp_peer_cr_timer_setup(mp, true /* start */); + break; + + case connect_success: + /* connect was sucessful move to established */ + pim_msdp_peer_established(mp); + break; + + case connect_in_progress: + /* for NB content we need to wait till sock is readable or + * writeable */ + PIM_MSDP_PEER_WRITE_ON(mp); + PIM_MSDP_PEER_READ_ON(mp); + /* also restart connect-retry timer to reset the socket if connect is + * not sucessful */ + pim_msdp_peer_cr_timer_setup(mp, true /* start */); + break; + } +} + +/* RFC-3618:Sec-5.6 - connection retry on active peer */ +static int +pim_msdp_peer_cr_timer_cb(struct thread *t) +{ + struct pim_msdp_peer *mp; + + zassert(t); + mp = THREAD_ARG(t); + zassert(mp); + + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_timer_expiry_log(mp, "connect-retry"); + } + + if (mp->state != PIM_MSDP_CONNECTING || PIM_MSDP_PEER_IS_LISTENER(mp)) { + return 0; + } + + pim_msdp_peer_active_connect(mp); + return 0; +} +static void +pim_msdp_peer_cr_timer_setup(struct pim_msdp_peer *mp, bool start) +{ + THREAD_OFF(mp->cr_timer); + if (start) { + THREAD_TIMER_ON(msdp->master, mp->cr_timer, + pim_msdp_peer_cr_timer_cb, mp, PIM_MSDP_PEER_CONNECT_RETRY_TIME); + } +} + +/* if a valid packet is rxed from the peer we can restart hold timer */ +void +pim_msdp_peer_pkt_rxed(struct pim_msdp_peer *mp) +{ + if (mp->state == PIM_MSDP_ESTABLISHED) { + pim_msdp_peer_hold_timer_setup(mp, true /* start */); + } +} + +static void pim_msdp_addr2su(union sockunion *su, struct in_addr addr) +{ + sockunion_init(su); + su->sin.sin_addr = addr; + su->sin.sin_family = AF_INET; +#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN + su->sin.sin_len = sizeof(struct sockaddr_in); +#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ +} + +/* 11.2.A1: create a new peer and transition state to listen or connecting */ +static enum pim_msdp_err +pim_msdp_peer_new(struct in_addr peer_addr, struct in_addr local_addr, + const char *mesh_group_name) +{ + struct pim_msdp_peer *mp; + + mp = XCALLOC(MTYPE_PIM_MSDP_PEER, sizeof(*mp)); + if (!mp) { + zlog_err("%s: PIM XCALLOC(%zu) failure", + __PRETTY_FUNCTION__, sizeof(*mp)); + return PIM_MSDP_ERR_OOM; + } + + mp->peer = peer_addr; + pim_msdp_addr2su(&mp->su_peer, mp->peer); + mp->local = local_addr; + pim_msdp_addr2su(&mp->su_local, mp->local); + mp->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_PEER_MG_NAME, mesh_group_name); + mp->state = PIM_MSDP_INACTIVE; + mp->fd = -1; + /* higher IP address is listener */ + if (ntohl(mp->local.s_addr) > ntohl(mp->peer.s_addr)) { + mp->flags |= PIM_MSDP_PEERF_LISTENER; + } + + if (PIM_DEBUG_MSDP_EVENTS) { + char key_str[PIM_MSDP_PEER_KEY_STRLEN]; + + pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), true); + zlog_debug("%s created", key_str); + } + + /* setup packet buffers */ + mp->ibuf = stream_new(PIM_MSDP_MAX_PACKET_SIZE); + mp->obuf = stream_fifo_new(); + + /* insert into misc tables for easy access */ + mp = hash_get(msdp->peer_hash, mp, hash_alloc_intern); + if (!mp) { + zlog_err("%s: PIM hash get failure", __PRETTY_FUNCTION__); + pim_msdp_peer_free(mp); + return PIM_MSDP_ERR_OOM; + } + listnode_add_sort(msdp->peer_list, mp); + + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_state_chg_log(mp); + } + /* fireup the connect state machine */ + if (PIM_MSDP_PEER_IS_LISTENER(mp)) { + pim_msdp_peer_listen(mp); + } else { + pim_msdp_peer_connect(mp); + } + return PIM_MSDP_ERR_NONE; +} + +struct pim_msdp_peer * +pim_msdp_peer_find(struct in_addr peer_addr) +{ + struct pim_msdp_peer lookup; + + lookup.peer = peer_addr; + return hash_lookup(msdp->peer_hash, &lookup); +} + +/* add peer configuration if it doesn't already exist */ +enum pim_msdp_err +pim_msdp_peer_add(struct in_addr peer_addr, struct in_addr local_addr, + const char *mesh_group_name) +{ + struct pim_msdp_peer *mp; + + mp = pim_msdp_peer_find(peer_addr); + if (mp) { + return PIM_MSDP_ERR_PEER_EXISTS; + } + + return pim_msdp_peer_new(peer_addr, local_addr, mesh_group_name); +} + +/* release all mem associated with a peer */ +static void +pim_msdp_peer_free(struct pim_msdp_peer *mp) +{ + if (mp->ibuf) { + stream_free(mp->ibuf); + } + + if (mp->obuf) { + stream_fifo_free(mp->obuf); + } + + if (mp->mesh_group_name) { + XFREE(MTYPE_PIM_MSDP_PEER_MG_NAME, mp->mesh_group_name); + } + XFREE(MTYPE_PIM_MSDP_PEER, mp); +} + +/* delete the peer config */ +enum pim_msdp_err +pim_msdp_peer_del(struct in_addr peer_addr) +{ + struct pim_msdp_peer *mp; + + mp = pim_msdp_peer_find(peer_addr); + if (!mp) { + return PIM_MSDP_ERR_NO_PEER; + } + + /* stop the tcp connection and shutdown all timers */ + pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); + + /* remove the session from various tables */ + listnode_delete(msdp->peer_list, mp); + hash_release(msdp->peer_hash, mp); + + if (PIM_DEBUG_MSDP_EVENTS) { + char key_str[PIM_MSDP_PEER_KEY_STRLEN]; + + pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), true); + zlog_debug("%s deleted", key_str); + } + + /* free up any associated memory */ + pim_msdp_peer_free(mp); + + return PIM_MSDP_ERR_NONE; +} + +/* peer hash and peer list helpers */ +static unsigned int +pim_msdp_peer_hash_key_make(void *p) +{ + struct pim_msdp_peer *mp = p; + return (jhash_1word(mp->peer.s_addr, 0)); +} + +static int +pim_msdp_peer_hash_eq(const void *p1, const void *p2) +{ + const struct pim_msdp_peer *mp1 = p1; + const struct pim_msdp_peer *mp2 = p2; + + return (mp1->peer.s_addr == mp2->peer.s_addr); +} + +static int +pim_msdp_peer_comp(const void *p1, const void *p2) +{ + const struct pim_msdp_peer *mp1 = p1; + const struct pim_msdp_peer *mp2 = p2; + + if (ntohl(mp1->peer.s_addr) < ntohl(mp2->peer.s_addr)) + return -1; + + if (ntohl(mp1->peer.s_addr) > ntohl(mp2->peer.s_addr)) + return 1; + + return 0; +} + +/* MSDP init */ +void +pim_msdp_init(struct thread_master *master) +{ + /* XXX: temporarily enable noisy logs; will be disabled once dev is + * complete */ + PIM_DO_DEBUG_MSDP_INTERNAL; + + msdp->peer_hash = hash_create(pim_msdp_peer_hash_key_make, + pim_msdp_peer_hash_eq); + msdp->peer_list = list_new(); + msdp->peer_list->del = (void (*)(void *))pim_msdp_peer_free; + msdp->peer_list->cmp = (int (*)(void *, void *))pim_msdp_peer_comp; + msdp->master = master; +} + +/* counterpart to MSDP init; XXX: unused currently */ +void +pim_msdp_exit(void) +{ + /* XXX: stop listener and delete all peer sessions */ + + if (msdp->peer_hash) { + hash_free(msdp->peer_hash); + msdp->peer_hash = NULL; + } + + if (msdp->peer_list) { + list_free(msdp->peer_list); + msdp->peer_list = NULL; + } } diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h index c6c38be257..6f8561f3cc 100644 --- a/pimd/pim_msdp.h +++ b/pimd/pim_msdp.h @@ -1,7 +1,6 @@ /* - * PIM for Quagga + * IP MSDP for Quagga * Copyright (C) 2016 Cumulus Networks, Inc. - * Donald Sharp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,37 +20,124 @@ #ifndef PIM_MSDP_H #define PIM_MSDP_H -enum pim_msdp_states_t - { - PIM_MSDP_DISABLED, - PIM_MSDP_INACTIVE, - PIM_MSDP_LISTEN, - PIM_MSDP_CONNECTING, - PIM_MSDP_ESTABLISHED - }; - -enum pim_msdp_tlv_t - { - PIM_MSDP_V4_SOURCE_ACTIVE = 1, - PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST, - PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE, - PIM_MSDP_KEEPALIVE, - PIM_MSDP_RESERVED, - PIM_MSDP_TRACEROUTE_PROGRESS, - PIM_MSDP_TRACEROUTE_REPLY, - }; - -struct pim_msdp_t -{ - enum pim_msdp_states_t state; - - struct prefix peer; - - struct thread *cr_timer; // 5.6 - struct thread *h_timer; // 5.4 - struct thread *ka_timer; // 5.5 - +enum pim_msdp_peer_state { + PIM_MSDP_DISABLED, + PIM_MSDP_INACTIVE, + PIM_MSDP_LISTEN, + PIM_MSDP_CONNECTING, + PIM_MSDP_ESTABLISHED }; -void pim_msdp_init (void); +/* SA and KA TLVs are processed; rest ignored */ +enum pim_msdp_tlv { + PIM_MSDP_V4_SOURCE_ACTIVE = 1, + PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST, + PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE, + PIM_MSDP_KEEPALIVE, + PIM_MSDP_RESERVED, + PIM_MSDP_TRACEROUTE_PROGRESS, + PIM_MSDP_TRACEROUTE_REPLY, +}; + +/* MSDP error codes */ +enum pim_msdp_err { + PIM_MSDP_ERR_NONE = 0, + PIM_MSDP_ERR_OOM = -1, + PIM_MSDP_ERR_PEER_EXISTS = -2, + PIM_MSDP_ERR_MAX_MESH_GROUPS = -3, + PIM_MSDP_ERR_NO_PEER = -4, +}; + +#define PIM_MSDP_STATE_STRLEN 16 +#define PIM_MSDP_PEER_KEY_STRLEN 80 +#define PIM_MSDP_UPTIME_STRLEN 80 +#define PIM_MSDP_TCP_PORT 639 +#define PIM_MSDP_SOCKET_SNDBUF_SIZE 65536 + +#define PIM_MSDP_PEER_IS_LISTENER(mp) (mp->flags & PIM_MSDP_PEERF_LISTENER) +enum pim_msdp_peer_flags { + PIM_MSDP_PEERF_NONE = 0, + PIM_MSDP_PEERF_LISTENER = (1 << 0) +}; + +struct pim_msdp_peer { + /* configuration */ + struct in_addr local; + struct in_addr peer; + char *mesh_group_name; + + /* state */ + enum pim_msdp_peer_state state; + enum pim_msdp_peer_flags flags; + + /* TCP socket info */ + union sockunion su_local; + union sockunion su_peer; + int fd; + + /* protocol timers */ +#define PIM_MSDP_PEER_HOLD_TIME 75 + struct thread *hold_timer; // 5.4 +#define PIM_MSDP_PEER_KA_TIME 60 + struct thread *ka_timer; // 5.5 +#define PIM_MSDP_PEER_CONNECT_RETRY_TIME 30 + struct thread *cr_timer; // 5.6 + + /* packet thread and buffers */ + struct stream *ibuf; + struct stream_fifo *obuf; + struct thread *t_read; + struct thread *t_write; + + /* stats */ + uint32_t ka_tx_cnt; + uint32_t sa_tx_cnt; + uint32_t ka_rx_cnt; + uint32_t sa_rx_cnt; + uint32_t unk_rx_cnt; + + /* timestamps */ + int64_t uptime; +}; + +enum pim_msdp_flags { + PIM_MSDPF_NONE = 0, + PIM_MSDPF_LISTENER = (1 << 0) +}; + +struct pim_msdp_listener { + int fd; + union sockunion su; + struct thread *thread; +}; + +struct pim_msdp { + enum pim_msdp_flags flags; + struct hash *peer_hash; + struct list *peer_list; + struct pim_msdp_listener listener; + struct thread_master *master; + uint32_t rejected_accepts; +}; + +#define PIM_MSDP_PEER_READ_ON(mp) THREAD_READ_ON(msdp->master, mp->t_read, pim_msdp_read, mp, mp->fd); +#define PIM_MSDP_PEER_WRITE_ON(mp) THREAD_WRITE_ON(msdp->master, mp->t_write, pim_msdp_write, mp, mp->fd); + +#define PIM_MSDP_PEER_READ_OFF(mp) THREAD_READ_OFF(mp->t_read) +#define PIM_MSDP_PEER_WRITE_OFF(mp) THREAD_WRITE_OFF(mp->t_write) + +extern struct pim_msdp *msdp; +void pim_msdp_init(struct thread_master *master); +void pim_msdp_exit(void); +enum pim_msdp_err pim_msdp_peer_add(struct in_addr peer, struct in_addr local, const char *mesh_group_name); +enum pim_msdp_err pim_msdp_peer_del(struct in_addr peer_addr); +char *pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf, int buf_size); +struct pim_msdp_peer *pim_msdp_peer_find(struct in_addr peer_addr); +void pim_msdp_peer_established(struct pim_msdp_peer *mp); +void pim_msdp_peer_pkt_rxed(struct pim_msdp_peer *mp); +void pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state); +void pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str); +int pim_msdp_write(struct thread *thread); +char *pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size, bool long_format); + #endif diff --git a/pimd/pim_msdp_packet.c b/pimd/pim_msdp_packet.c new file mode 100644 index 0000000000..458d5e4621 --- /dev/null +++ b/pimd/pim_msdp_packet.c @@ -0,0 +1,380 @@ +/* + * IP MSDP packet helper + * Copyright (C) 2016 Cumulus Networks, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +#include + +#include +#include +#include +#include + +#include "pimd.h" +#include "pim_str.h" + +#include "pim_msdp.h" +#include "pim_msdp_packet.h" +#include "pim_msdp_socket.h" + +static char * +pim_msdp_pkt_type_dump(enum pim_msdp_tlv type, char *buf, int buf_size) +{ + switch (type) { + case PIM_MSDP_V4_SOURCE_ACTIVE: + snprintf(buf, buf_size, "%s", "SA"); + break; + case PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST: + snprintf(buf, buf_size, "%s", "SA_REQ"); + break; + case PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE: + snprintf(buf, buf_size, "%s", "SA_RESP"); + break; + case PIM_MSDP_KEEPALIVE: + snprintf(buf, buf_size, "%s", "KA"); + break; + case PIM_MSDP_RESERVED: + snprintf(buf, buf_size, "%s", "RSVD"); + break; + case PIM_MSDP_TRACEROUTE_PROGRESS: + snprintf(buf, buf_size, "%s", "TRACE_PROG"); + break; + case PIM_MSDP_TRACEROUTE_REPLY: + snprintf(buf, buf_size, "%s", "TRACE_REPLY"); + break; + default: + snprintf(buf, buf_size, "UNK-%d", type); + } + return buf; +} + +static void +pim_msdp_pkt_dump(struct pim_msdp_peer *mp, int type, int len, bool rx) +{ + char key_str[PIM_MSDP_PEER_KEY_STRLEN]; + char type_str[PIM_MSDP_PKT_TYPE_STRLEN]; + + pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), false); + pim_msdp_pkt_type_dump(type, type_str, sizeof(type_str)); + + zlog_debug("%s pkt %s type %s len %d", + key_str, rx?"rx":"tx", type_str, len); + /* XXX: dump actual data */ +} + +/* Check file descriptor whether connect is established. */ +static void +pim_msdp_connect_check(struct pim_msdp_peer *mp) +{ + int status; + socklen_t slen; + int ret; + + if (mp->state != PIM_MSDP_CONNECTING) { + /* if we are here it means we are not in a connecting or established state + * for now treat this as a fatal error */ + /* XXX:revisit; reset TCP connection */ + pim_msdp_peer_reset_tcp_conn(mp, "invalid-state"); + return; + } + + PIM_MSDP_PEER_READ_OFF(mp); + PIM_MSDP_PEER_WRITE_OFF(mp); + + /* Check file descriptor. */ + slen = sizeof(status); + ret = getsockopt(mp->fd, SOL_SOCKET, SO_ERROR, (void *)&status, &slen); + + /* If getsockopt is fail, this is fatal error. */ + if (ret < 0) { + zlog_err("can't get sockopt for nonblocking connect"); + /* XXX:revisit; reset TCP connection */ + pim_msdp_peer_reset_tcp_conn(mp, "connect-failed"); + return; + } + + /* When status is 0 then TCP connection is established. */ + 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_connect_check %s", key_str, status?"fail":"success"); + } + if (status == 0) { + pim_msdp_peer_established(mp); + } else { + /* XXX:revisit; reset TCP connection */ + pim_msdp_peer_reset_tcp_conn(mp, "connect-failed"); + } +} + +static void +pim_msdp_pkt_delete(struct pim_msdp_peer *mp) +{ + stream_free(stream_fifo_pop(mp->obuf)); +} + +static void +pim_msdp_write_proceed_actions(struct pim_msdp_peer *mp) +{ + if (stream_fifo_head(mp->obuf)) { + PIM_MSDP_PEER_WRITE_ON(mp); + } +} + +int +pim_msdp_write(struct thread *thread) +{ + struct pim_msdp_peer *mp; + struct stream *s; + int num; + enum pim_msdp_tlv type; + + 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); + zlog_debug("%s pim_msdp_write", key_str); + } + if (mp->fd < 0) { + return -1; + } + + /* check if TCP connection is established */ + if (mp->state != PIM_MSDP_ESTABLISHED) { + pim_msdp_connect_check(mp); + return 0; + } + + s = stream_fifo_head(mp->obuf); + if (!s) { + pim_msdp_write_proceed_actions(mp); + return 0; + } + + sockopt_cork (mp->fd, 1); + + /* Nonblocking write until TCP output buffer is full */ + do + { + int writenum; + + /* Number of bytes to be sent */ + writenum = stream_get_endp(s) - stream_get_getp(s); + + /* Call write() system call */ + num = write(mp->fd, STREAM_PNT(s), writenum); + if (num < 0) { + /* write failed either retry needed or error */ + if (ERRNO_IO_RETRY(errno)) + break; + + /* XXX:revisit; reset TCP connection */ + pim_msdp_peer_reset_tcp_conn(mp, "pkt-tx-failed"); + return 0; + } + + if (num != writenum) { + /* Partial write */ + stream_forward_getp(s, num); + break; + } + + /* Retrieve msdp packet type. */ + type = stream_getc(s); + switch (type) + { + case PIM_MSDP_KEEPALIVE: + mp->ka_tx_cnt++; + break; + case PIM_MSDP_V4_SOURCE_ACTIVE: + mp->sa_tx_cnt++; + break; + default:; + } + if (PIM_DEBUG_MSDP_PACKETS) { + pim_msdp_pkt_dump(mp, type, writenum, false /*rx*/); + } + + /* packet sent delete it. */ + pim_msdp_pkt_delete(mp); + + /* 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); + + return 0; +} + +static void +pim_msdp_pkt_send(struct pim_msdp_peer *mp, struct stream *s) +{ + /* Add packet to the end of list. */ + stream_fifo_push(mp->obuf, s); + + PIM_MSDP_PEER_WRITE_ON(mp); +} + +/* Make keepalive packet and send it to the peer + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| 4 | 3 | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ +void +pim_msdp_pkt_ka_tx(struct pim_msdp_peer *mp) +{ + struct stream *s; + + s = stream_new(PIM_MSDP_KA_TLV_MAX_SIZE); + stream_putc(s, PIM_MSDP_KEEPALIVE); + stream_putw(s, PIM_MSDP_KA_TLV_MAX_SIZE); + + pim_msdp_pkt_send(mp, s); +} + +static void +pim_msdp_pkt_rxed_with_fatal_error(struct pim_msdp_peer *mp) +{ + /* XXX:revisit; reset TCP connection */ + pim_msdp_peer_reset_tcp_conn(mp, "invalid-pkt-rx"); +} + +static void +pim_msdp_pkt_ka_rx(struct pim_msdp_peer *mp, int len) +{ + mp->ka_rx_cnt++; + if (len != PIM_MSDP_KA_TLV_MAX_SIZE) { + pim_msdp_pkt_rxed_with_fatal_error(mp); + return; + } + pim_msdp_peer_pkt_rxed(mp); +} + +static void +pim_msdp_pkt_sa_rx(struct pim_msdp_peer *mp, int len) +{ + mp->sa_rx_cnt++; + /* XXX: proc SA ... */ + pim_msdp_peer_pkt_rxed(mp); +} + +/* Theoretically you could have different tlv types in the same message. + * For the time being I am assuming one; will revisit before 3.2 - XXX */ +static void +pim_msdp_pkt_rx(struct pim_msdp_peer *mp, int nbytes) +{ + enum pim_msdp_tlv type; + int len; + + type = stream_getc(mp->ibuf); + len = stream_getw(mp->ibuf); + if (len < PIM_MSDP_HEADER_SIZE) { + pim_msdp_pkt_rxed_with_fatal_error(mp); + return; + } + + if (len > PIM_MSDP_SA_TLV_MAX_SIZE) { + /* if tlv size if greater than max just ignore the tlv */ + return; + } + + if (len > nbytes) { + /* we got a partial read or the packet is malformed */ + pim_msdp_pkt_rxed_with_fatal_error(mp); + return; + } + + if (PIM_DEBUG_MSDP_PACKETS) { + pim_msdp_pkt_dump(mp, type, len, true /*rx*/); + } + + switch(type) { + case PIM_MSDP_KEEPALIVE: + pim_msdp_pkt_ka_rx(mp, len); + break; + case PIM_MSDP_V4_SOURCE_ACTIVE: + mp->sa_rx_cnt++; + pim_msdp_pkt_sa_rx(mp, len); + break; + default: + mp->unk_rx_cnt++; + } + /* XXX: process next tlv*/ +} + +/* pim msdp read utility function. */ +static int +pim_msdp_read_packet(struct pim_msdp_peer *mp) +{ + int nbytes; + /* Read packet from fd. */ + nbytes = stream_read_try(mp->ibuf, mp->fd, PIM_MSDP_MAX_PACKET_SIZE); + if (nbytes < PIM_MSDP_HEADER_SIZE) { + if (nbytes == -2) { + /* transient error retry */ + return -1; + } + pim_msdp_pkt_rxed_with_fatal_error(mp); + return -1; + } + return nbytes; +} + +int +pim_msdp_read(struct thread *thread) +{ + struct pim_msdp_peer *mp; + int rc; + + mp = THREAD_ARG(thread); + mp->t_read = 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); + zlog_debug("%s pim_msdp_read", key_str); + } + + if (mp->fd < 0) { + return -1; + } + + /* check if TCP connection is established */ + if (mp->state != PIM_MSDP_ESTABLISHED) { + pim_msdp_connect_check(mp); + return 0; + } + + THREAD_READ_ON(msdp->master, mp->t_read, pim_msdp_read, mp, mp->fd); + + rc = pim_msdp_read_packet(mp); + if (rc > 0) { + pim_msdp_pkt_rx(mp, rc); + } + + stream_reset(mp->ibuf); + return 0; +} diff --git a/pimd/pim_msdp_packet.h b/pimd/pim_msdp_packet.h new file mode 100644 index 0000000000..7f9ed9f68f --- /dev/null +++ b/pimd/pim_msdp_packet.h @@ -0,0 +1,34 @@ +/* + * IP MSDP packet helpers + * Copyright (C) 2016 Cumulus Networks, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +#ifndef PIM_MSDP_PACKET_H +#define PIM_MSDP_PACKET_H + +/* type and length of a single tlv can be consider packet header */ +#define PIM_MSDP_HEADER_SIZE 3 +#define PIM_MSDP_SA_TLV_MAX_SIZE 9192 +#define PIM_MSDP_KA_TLV_MAX_SIZE PIM_MSDP_HEADER_SIZE +/* XXX: this is just a guesstimate - need to revist */ +#define PIM_MSDP_MAX_PACKET_SIZE (PIM_MSDP_SA_TLV_MAX_SIZE + PIM_MSDP_KA_TLV_MAX_SIZE) + +#define PIM_MSDP_PKT_TYPE_STRLEN 16 + +void pim_msdp_pkt_ka_tx(struct pim_msdp_peer *mp); +int pim_msdp_read(struct thread *thread); +#endif diff --git a/pimd/pim_msdp_socket.c b/pimd/pim_msdp_socket.c new file mode 100644 index 0000000000..fdb77c530b --- /dev/null +++ b/pimd/pim_msdp_socket.c @@ -0,0 +1,228 @@ +/* + * IP MSDP socket management + * Copyright (C) 2016 Cumulus Networks, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include + +#include +#include +#include +#include + +#include "pimd.h" + +#include "pim_msdp.h" +#include "pim_msdp_socket.h" + +extern struct zebra_privs_t pimd_privs; + +/* increase socket send buffer size */ +static void +pim_msdp_update_sock_send_buffer_size (int fd) +{ + int size = PIM_MSDP_SOCKET_SNDBUF_SIZE; + int optval; + socklen_t optlen = sizeof(optval); + + if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen) < 0) { + zlog_err("getsockopt of SO_SNDBUF failed %s\n", safe_strerror(errno)); + return; + } + + if (optval < size) { + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) < 0) { + zlog_err("Couldn't increase send buffer: %s\n", safe_strerror(errno)); + } + } +} + +/* passive peer socket accept */ +static int +pim_msdp_sock_accept(struct thread *thread) +{ + union sockunion su; + struct pim_msdp_listener *listener = THREAD_ARG(thread); + int accept_sock; + int msdp_sock; + struct pim_msdp_peer *mp; + char buf[SU_ADDRSTRLEN]; + + sockunion_init(&su); + + /* re-register accept thread */ + accept_sock = THREAD_FD(thread); + if (accept_sock < 0) { + zlog_err ("accept_sock is negative value %d", accept_sock); + return -1; + } + listener->thread = thread_add_read(master, pim_msdp_sock_accept, + listener, accept_sock); + + /* accept client connection. */ + msdp_sock = sockunion_accept(accept_sock, &su); + if (msdp_sock < 0) { + zlog_err ("pim_msdp_sock_accept failed (%s)", safe_strerror (errno)); + return -1; + } + + /* see if have peer config for this */ + mp = pim_msdp_peer_find(su.sin.sin_addr); + if (!mp || !PIM_MSDP_PEER_IS_LISTENER(mp)) { + ++msdp->rejected_accepts; + //XXX: make debug event + zlog_err("msdp peer connection refused from %s", + sockunion2str(&su, buf, SU_ADDRSTRLEN)); + close(msdp_sock); + return -1; + } + + 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 accept success%s", key_str, mp->fd>=0?"(dup)":""); + } + + /* if we have an existing connection we need to kill that one + * with this one */ + if (mp->fd >= 0) { + /* XXX: revisit */ + pim_msdp_peer_stop_tcp_conn(mp, false /* chg_state */); + } + mp->fd = msdp_sock; + set_nonblocking(mp->fd); + pim_msdp_update_sock_send_buffer_size(mp->fd); + pim_msdp_peer_established(mp); + return 0; +} + +/* global listener for the MSDP well know TCP port */ +int +pim_msdp_sock_listen(void) +{ + int sock; + int socklen; + struct sockaddr_in sin; + int rc; + struct pim_msdp_listener *listener = &msdp->listener; + + if (msdp->flags & PIM_MSDPF_LISTENER) { + /* listener already setup */ + return 0; + } + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + zlog_err ("socket: %s", safe_strerror (errno)); + return sock; + } + + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; + sin.sin_port = htons(PIM_MSDP_TCP_PORT); + socklen = sizeof(struct sockaddr_in); +#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN + sin.sin_len = socklen; +#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ + + sockopt_reuseaddr(sock); + sockopt_reuseport(sock); + + if (pimd_privs.change(ZPRIVS_RAISE)) { + zlog_err ("pim_msdp_socket: could not raise privs, %s", + safe_strerror (errno)); + } + + /* bond to well known TCP port */ + rc = bind(sock, (struct sockaddr *)&sin, socklen); + + if (pimd_privs.change(ZPRIVS_LOWER)) { + zlog_err ("pim_msdp_socket: could not raise privs, %s", + safe_strerror (errno)); + } + + if (rc < 0) { + zlog_err ("pim_msdp_socket bind to port %d: %s", ntohs(sin.sin_port), safe_strerror (errno)); + close(sock); + return rc; + } + + rc = listen(sock, 3 /* backlog */); + if (rc < 0) { + zlog_err ("pim_msdp_socket listen: %s", safe_strerror (errno)); + close(sock); + return rc; + } + + /* add accept thread */ + listener->fd = sock; + memcpy(&listener->su, &sin, socklen); + listener->thread = thread_add_read(msdp->master, pim_msdp_sock_accept, listener, sock); + + msdp->flags |= PIM_MSDPF_LISTENER; + return 0; +} + +/* active peer socket setup */ +int +pim_msdp_sock_connect(struct pim_msdp_peer *mp) +{ + int rc; + + 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 attempt connect%s", key_str, mp->fd<0?"":"(dup)"); + } + + /* if we have an existing connection we need to kill that one + * with this one */ + if (mp->fd >= 0) { + /* XXX: revisit */ + pim_msdp_peer_stop_tcp_conn(mp, false /* chg_state */); + } + + /* Make socket for the peer. */ + mp->fd = sockunion_socket(&mp->su_peer); + if (mp->fd < 0) { + zlog_err ("pim_msdp_socket socket failure: %s", safe_strerror (errno)); + return -1; + } + + set_nonblocking(mp->fd); + + /* Set socket send buffer size */ + pim_msdp_update_sock_send_buffer_size(mp->fd); + sockopt_reuseaddr(mp->fd); + sockopt_reuseport(mp->fd); + + /* source bind */ + rc = sockunion_bind(mp->fd, &mp->su_local, 0, &mp->su_local); + if (rc < 0) { + zlog_err ("pim_msdp_socket connect bind failure: %s", safe_strerror (errno)); + close(mp->fd); + mp->fd = -1; + return rc; + } + + /* Connect to the remote mp. */ + return (sockunion_connect(mp->fd, &mp->su_peer, htons(PIM_MSDP_TCP_PORT), 0)); +} + diff --git a/pimd/pim_msdp_socket.h b/pimd/pim_msdp_socket.h new file mode 100644 index 0000000000..bf3d12ad2c --- /dev/null +++ b/pimd/pim_msdp_socket.h @@ -0,0 +1,25 @@ +/* + * IP MSDP socket management for Quagga + * Copyright (C) 2016 Cumulus Networks, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +#ifndef PIM_MSDP_SOCKET_H +#define PIM_MSDP_SOCKET_H + +int pim_msdp_sock_listen(void); +int pim_msdp_sock_connect(struct pim_msdp_peer *mp); +#endif diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 5e13b60873..3a1a1c04a1 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -44,6 +44,14 @@ pim_debug_config_write (struct vty *vty) { int writes = 0; + if (PIM_DEBUG_MSDP_EVENTS) { + vty_out(vty, "debug msdp events%s", VTY_NEWLINE); + ++writes; + } + if (PIM_DEBUG_MSDP_PACKETS) { + vty_out(vty, "debug msdp packets%s", VTY_NEWLINE); + ++writes; + } if (PIM_DEBUG_IGMP_EVENTS) { vty_out(vty, "debug igmp events%s", VTY_NEWLINE); ++writes; diff --git a/pimd/pimd.h b/pimd/pimd.h index fb9cb14ca1..3f59b36df2 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -70,6 +70,9 @@ #define PIM_MASK_PIM_J_P (1 << 16) #define PIM_MASK_STATIC (1 << 17) #define PIM_MASK_PIM_REG (1 << 18) +#define PIM_MASK_MSDP_EVENTS (1 << 19) +#define PIM_MASK_MSDP_PACKETS (1 << 20) +#define PIM_MASK_MSDP_INTERNAL (1 << 21) /* PIM error codes */ @@ -150,9 +153,12 @@ extern int32_t qpim_register_probe_time; #define PIM_DEBUG_PIM_J_P (qpim_debugs & PIM_MASK_PIM_J_P) #define PIM_DEBUG_PIM_REG (qpim_debugs & PIM_MASK_PIM_REG) #define PIM_DEBUG_STATIC (qpim_debugs & PIM_MASK_STATIC) +#define PIM_DEBUG_MSDP_EVENTS (qpim_debugs & PIM_MASK_MSDP_EVENTS) +#define PIM_DEBUG_MSDP_PACKETS (qpim_debugs & PIM_MASK_MSDP_PACKETS) +#define PIM_DEBUG_MSDP_INTERNAL (qpim_debugs & PIM_MASK_MSDP_INTERNAL) -#define PIM_DEBUG_EVENTS (qpim_debugs & (PIM_MASK_PIM_EVENTS | PIM_MASK_IGMP_EVENTS)) -#define PIM_DEBUG_PACKETS (qpim_debugs & (PIM_MASK_PIM_PACKETS | PIM_MASK_IGMP_PACKETS)) +#define PIM_DEBUG_EVENTS (qpim_debugs & (PIM_MASK_PIM_EVENTS | PIM_MASK_IGMP_EVENTS | PIM_MASK_MSDP_EVENTS)) +#define PIM_DEBUG_PACKETS (qpim_debugs & (PIM_MASK_PIM_PACKETS | PIM_MASK_IGMP_PACKETS | PIM_MASK_MSDP_PACKETS)) #define PIM_DEBUG_TRACE (qpim_debugs & (PIM_MASK_PIM_TRACE | PIM_MASK_IGMP_TRACE)) #define PIM_DO_DEBUG_PIM_EVENTS (qpim_debugs |= PIM_MASK_PIM_EVENTS) @@ -172,6 +178,9 @@ extern int32_t qpim_register_probe_time; #define PIM_DO_DEBUG_PIM_J_P (qpim_debugs |= PIM_MASK_PIM_J_P) #define PIM_DO_DEBUG_PIM_REG (qpim_debugs |= PIM_MASK_PIM_REG) #define PIM_DO_DEBUG_STATIC (qpim_debugs |= PIM_MASK_STATIC) +#define PIM_DO_DEBUG_MSDP_EVENTS (qpim_debugs |= PIM_MASK_MSDP_EVENTS) +#define PIM_DO_DEBUG_MSDP_PACKETS (qpim_debugs |= PIM_MASK_MSDP_PACKETS) +#define PIM_DO_DEBUG_MSDP_INTERNAL (qpim_debugs |= PIM_MASK_MSDP_INTERNAL) #define PIM_DONT_DEBUG_PIM_EVENTS (qpim_debugs &= ~PIM_MASK_PIM_EVENTS) #define PIM_DONT_DEBUG_PIM_PACKETS (qpim_debugs &= ~PIM_MASK_PIM_PACKETS) @@ -190,6 +199,9 @@ extern int32_t qpim_register_probe_time; #define PIM_DONT_DEBUG_PIM_J_P (qpim_debugs &= ~PIM_MASK_PIM_J_P) #define PIM_DONT_DEBUG_PIM_REG (qpim_debugs &= ~PIM_MASK_PIM_REG) #define PIM_DONT_DEBUG_STATIC (qpim_debugs &= ~PIM_MASK_STATIC) +#define PIM_DONT_DEBUG_MSDP_EVENTS (qpim_debugs &= ~PIM_MASK_MSDP_EVENTS) +#define PIM_DONT_DEBUG_MSDP_PACKETS (qpim_debugs &= ~PIM_MASK_MSDP_PACKETS) +#define PIM_DONT_DEBUG_MSDP_INTERNAL (qpim_debugs &= ~PIM_MASK_MSDP_INTERNAL) void pim_init(void); void pim_terminate(void); From 03417ccd6d78c2a2a39032d51c228759e52c364f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 23 Oct 2016 22:47:25 -0400 Subject: [PATCH 240/386] pimd: pim upstream child list Add the ability to keep the list of S,G's associated with a *,G. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 78 ++++++++++++-------------- pimd/pim_join.c | 78 ++++++++++++-------------- pimd/pim_upstream.c | 127 ++++++++++++++++++++++++++----------------- pimd/pim_upstream.h | 1 + 4 files changed, 149 insertions(+), 135 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index f5b20ab485..b786ad09ae 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -807,26 +807,23 @@ void pim_ifchannel_local_membership_add(struct interface *ifp, struct pim_upstream *child; struct listnode *up_node; - for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, up_node, child)) + for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) { - if (child->parent == up) - { - if (PIM_DEBUG_EVENTS) - { - char buff[100]; + if (PIM_DEBUG_EVENTS) + { + char buff[100]; - strcpy (buff, pim_str_sg_dump (&up->sg)); - zlog_debug("%s %s: IGMP (S,G)=%s(%s) from %s", - __FILE__, __PRETTY_FUNCTION__, - buff, ifp->name, pim_str_sg_dump (sg)); - } + strcpy (buff, pim_str_sg_dump (&child->sg)); + zlog_debug("%s %s: IGMP (S,G)=%s(%s) from %s", + __FILE__, __PRETTY_FUNCTION__, + buff, ifp->name, pim_str_sg_dump (sg)); + } - if (pim_upstream_evaluate_join_desired (child)) - { - pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); - pim_upstream_switch (child, PIM_UPSTREAM_JOINED); - } - } + if (pim_upstream_evaluate_join_desired (child)) + { + pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + pim_upstream_switch (child, PIM_UPSTREAM_JOINED); + } } } } @@ -856,34 +853,31 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, struct pim_upstream *child; struct listnode *up_node; - for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, up_node, child)) + for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) { - if (child->parent == up) - { - struct channel_oil *c_oil = child->channel_oil; - struct pim_ifchannel *chchannel = pim_ifchannel_find (ifp, &child->sg); - struct pim_interface *pim_ifp = ifp->info; + struct channel_oil *c_oil = child->channel_oil; + struct pim_ifchannel *chchannel = pim_ifchannel_find (ifp, &child->sg); + struct pim_interface *pim_ifp = ifp->info; - if (PIM_DEBUG_EVENTS) - { - char buff[100]; - strcpy (buff, pim_str_sg_dump (&up->sg)); - zlog_debug("%s %s: Prune(S,G)=%s(%s) from %s", - __FILE__, __PRETTY_FUNCTION__, - buff, ifp->name, pim_str_sg_dump (&child->sg)); - } - - if (!pim_upstream_evaluate_join_desired (child)) - pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); - - /* - * If the S,G has no if channel and the c_oil still - * has output here then the *,G was supplying the implied - * if channel. So remove it. - */ - if (!chchannel && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) - pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + if (PIM_DEBUG_EVENTS) + { + char buff[100]; + strcpy (buff, pim_str_sg_dump (&child->sg)); + zlog_debug("%s %s: Prune(S,G)=%s(%s) from %s", + __FILE__, __PRETTY_FUNCTION__, + buff, ifp->name, pim_str_sg_dump (&child->sg)); } + + if (!pim_upstream_evaluate_join_desired (child)) + pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + + /* + * If the S,G has no if channel and the c_oil still + * has output here then the *,G was supplying the implied + * if channel. So remove it. + */ + if (!chchannel && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) + pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); } } delete_on_noinfo(ch); diff --git a/pimd/pim_join.c b/pimd/pim_join.c index dcbd122151..2dc9d91529 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -117,24 +117,21 @@ static void recv_join(struct interface *ifp, if (!up) return; - for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, up_node, child)) + for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) { - if (child->parent == up) - { - char buff[100]; + char buff[100]; - strcpy (buff, pim_str_sg_dump (&up->sg)); - if (PIM_DEBUG_PIM_TRACE) - zlog_debug("%s %s: Join(S,G)=%s from %s", - __FILE__, __PRETTY_FUNCTION__, - buff, pim_str_sg_dump (&sg)); + strcpy (buff, pim_str_sg_dump (&child->sg)); + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s %s: Join(S,G)=%s from %s", + __FILE__, __PRETTY_FUNCTION__, + buff, pim_str_sg_dump (&sg)); - if (pim_upstream_evaluate_join_desired (child)) - { - pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); - pim_upstream_switch (child, PIM_UPSTREAM_JOINED); - } - } + if (pim_upstream_evaluate_join_desired (child)) + { + pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + pim_upstream_switch (child, PIM_UPSTREAM_JOINED); + } } } @@ -194,36 +191,33 @@ static void recv_prune(struct interface *ifp, if (!up) return; - for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, up_node, child)) + for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) { - if (child->parent == up) - { - struct channel_oil *c_oil = child->channel_oil; - struct pim_ifchannel *ch = pim_ifchannel_find (ifp, &child->sg); - struct pim_interface *pim_ifp = ifp->info; + struct channel_oil *c_oil = child->channel_oil; + struct pim_ifchannel *ch = pim_ifchannel_find (ifp, &child->sg); + struct pim_interface *pim_ifp = ifp->info; - if (PIM_DEBUG_PIM_TRACE) - { - char buff[100]; - strcpy (buff, pim_str_sg_dump (&up->sg)); - zlog_debug("%s %s: Prune(S,G)=%s from %s", - __FILE__, __PRETTY_FUNCTION__, - buff, pim_str_sg_dump (&child->sg)); - } - if (!c_oil) - continue; - - if (!pim_upstream_evaluate_join_desired (child)) - pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); - - /* - * If the S,G has no if channel and the c_oil still - * has output here then the *,G was supplying the implied - * if channel. So remove it. - */ - if (!ch && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) - pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + if (PIM_DEBUG_PIM_TRACE) + { + char buff[100]; + strcpy (buff, pim_str_sg_dump (&child->sg)); + zlog_debug("%s %s: Prune(S,G)=%s from %s", + __FILE__, __PRETTY_FUNCTION__, + buff, pim_str_sg_dump (&sg)); } + if (!c_oil) + continue; + + if (!pim_upstream_evaluate_join_desired (child)) + pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); + + /* + * If the S,G has no if channel and the c_oil still + * has output here then the *,G was supplying the implied + * if channel. So remove it. + */ + if (!ch && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) + pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); } } } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index cb5d9bcb28..9d31245207 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -65,23 +65,16 @@ static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up) static void pim_upstream_remove_children (struct pim_upstream *up) { - struct listnode *ch_node; struct pim_upstream *child; - // Basic sanity, (*,*) not currently supported - if ((up->sg.src.s_addr == INADDR_ANY) && - (up->sg.grp.s_addr == INADDR_ANY)) + if (!up->sources) return; - // Basic sanity (S,G) have no children - if ((up->sg.src.s_addr != INADDR_ANY) && - (up->sg.grp.s_addr != INADDR_ANY)) - return; - - for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, ch_node, child)) + while (!list_isempty (up->sources)) { - if (child->parent == up) - child->parent = NULL; + child = listnode_head (up->sources); + child->parent = NULL; + listnode_delete (up->sources, child); } } @@ -109,7 +102,10 @@ pim_upstream_find_new_children (struct pim_upstream *up) if ((up->sg.grp.s_addr != INADDR_ANY) && (child->sg.grp.s_addr == up->sg.grp.s_addr) && (child != up)) - child->parent = up; + { + child->parent = up; + listnode_add_sort (up->sources, child); + } } } @@ -119,28 +115,25 @@ pim_upstream_find_new_children (struct pim_upstream *up) * If we have a (*,G), find the (*,*) */ static struct pim_upstream * -pim_upstream_find_parent (struct prefix_sg *sg) +pim_upstream_find_parent (struct pim_upstream *child) { - struct prefix_sg any = *sg; - - // (*,*) || (S,*) - if (((sg->src.s_addr == INADDR_ANY) && - (sg->grp.s_addr == INADDR_ANY)) || - ((sg->src.s_addr != INADDR_ANY) && - (sg->grp.s_addr == INADDR_ANY))) - return NULL; + struct prefix_sg any = child->sg; + struct pim_upstream *up = NULL; // (S,G) - if ((sg->src.s_addr != INADDR_ANY) && - (sg->grp.s_addr != INADDR_ANY)) + if ((child->sg.src.s_addr != INADDR_ANY) && + (child->sg.grp.s_addr != INADDR_ANY)) { any.src.s_addr = INADDR_ANY; - return pim_upstream_find (&any); + up = pim_upstream_find (&any); + + if (up) + listnode_add (up->sources, child); + + return up; } - // (*,G) - any.grp.s_addr = INADDR_ANY; - return pim_upstream_find (&any); + return NULL; } void pim_upstream_free(struct pim_upstream *up) @@ -181,11 +174,20 @@ pim_upstream_del(struct pim_upstream *up, const char *name) pim_mroute_del (up->channel_oil); upstream_channel_oil_detach(up); + if (up->sources) + list_delete (up->sources); + up->sources = NULL; + /* notice that listnode_delete() can't be moved into pim_upstream_free() because the later is called by list_delete_all_node() */ + if (up->parent) + { + listnode_delete (up->parent->sources, up); + up->parent = NULL; + } listnode_delete (pim_upstream_list, up); hash_release (pim_upstream_hash, up); @@ -488,6 +490,27 @@ pim_upstream_switch(struct pim_upstream *up, } } +static int +pim_upstream_compare (void *arg1, void *arg2) +{ + const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; + const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; + + if (ntohl(up1->sg.grp.s_addr) < ntohl(up2->sg.grp.s_addr)) + return -1; + + if (ntohl(up1->sg.grp.s_addr) > ntohl(up2->sg.grp.s_addr)) + return 1; + + if (ntohl(up1->sg.src.s_addr) < ntohl(up2->sg.src.s_addr)) + return -1; + + if (ntohl(up1->sg.src.s_addr) > ntohl(up2->sg.src.s_addr)) + return 1; + + return 0; +} + static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, struct interface *incoming, int flags) @@ -509,11 +532,20 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, if (PIM_DEBUG_PIM_TRACE) zlog_debug("%s: Received a (*,G) with no RP configured", __PRETTY_FUNCTION__); + hash_release (pim_upstream_hash, up); XFREE (MTYPE_PIM_UPSTREAM, up); return NULL; } - up->parent = pim_upstream_find_parent (sg); + up->parent = pim_upstream_find_parent (up); + if (up->sg.src.s_addr == INADDR_ANY) + { + up->sources = list_new (); + up->sources->cmp = pim_upstream_compare; + } + else + up->sources = NULL; + pim_upstream_find_new_children (up); up->flags = flags; up->ref_count = 1; @@ -538,12 +570,26 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, if (PIM_DEBUG_PIM_TRACE) zlog_debug ("%s: Attempting to create upstream(%s), Unable to RPF for source", __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg)); + + if (up->parent) + { + listnode_delete (up->parent->sources, up); + up->parent = NULL; + } + pim_upstream_remove_children (up); + if (up->sources) + list_delete (up->sources); + + hash_release (pim_upstream_hash, up); XFREE(MTYPE_PIM_UPSTREAM, up); return NULL; } listnode_add_sort(pim_upstream_list, up); + if (PIM_DEBUG_PIM_TRACE) + zlog_debug ("%s: Created Upstream %s", __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg)); + return up; } @@ -1162,27 +1208,6 @@ pim_upstream_find_new_rpf (void) } } -static int -pim_upstream_compare (const void *arg1, const void *arg2) -{ - const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; - const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; - - if (ntohl(up1->sg.grp.s_addr) < ntohl(up2->sg.grp.s_addr)) - return -1; - - if (ntohl(up1->sg.grp.s_addr) > ntohl(up2->sg.grp.s_addr)) - return 1; - - if (ntohl(up1->sg.src.s_addr) < ntohl(up2->sg.src.s_addr)) - return -1; - - if (ntohl(up1->sg.src.s_addr) > ntohl(up2->sg.src.s_addr)) - return 1; - - return 0; -} - static unsigned int pim_upstream_hash_key (void *arg) { @@ -1222,6 +1247,6 @@ pim_upstream_init (void) pim_upstream_list = list_new (); pim_upstream_list->del = (void (*)(void *)) pim_upstream_free; - pim_upstream_list->cmp = (int (*)(void *, void *)) pim_upstream_compare; + pim_upstream_list->cmp = pim_upstream_compare; } diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 41fcd28679..a2a912ff4f 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -85,6 +85,7 @@ struct pim_upstream { struct prefix_sg sg; /* (S,G) group key */ uint32_t flags; struct channel_oil *channel_oil; + struct list *sources; enum pim_upstream_state join_state; enum pim_upstream_sptbit sptbit; From d1b64e31aa615f9a4e06431fd78f4dfb7db7fb32 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 31 Oct 2016 16:33:38 -0400 Subject: [PATCH 241/386] pimd: Be more careful looking up mroute statistics When we get a request to look up the mroute statistics from the kernel, ensure that the interface returned is a valid usable interface. Signed-off-by: Donald Sharp --- pimd/pim_zlookup.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index cdaf04566d..53fd0ce071 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -456,6 +456,9 @@ pim_zlookup_sg_statistics (struct channel_oil *c_oil) zlog_debug ("Sending Request for New Channel Oil Information(%s)", pim_str_sg_dump (&more)); } + if (!ifp) + return -1; + stream_reset (s); zclient_create_header (s, ZEBRA_IPMR_ROUTE_STATS, VRF_DEFAULT); stream_put_in_addr (s, &c_oil->oil.mfcc_origin); From 5d84a3bc9a332d36e9ac0809170601abaf244bdf Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 31 Oct 2016 20:01:16 -0400 Subject: [PATCH 242/386] pimd: Modify Debug to be better Make debugs of some pim processes easier to interpret and understand. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 1 + pimd/pim_register.c | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index d0c05563c0..6eb14a140d 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1672,6 +1672,7 @@ static void pim_show_upstream(struct vty *vty, u_char uj) json_object_string_add(json_row, "resetTimer", rs_timer); json_object_string_add(json_row, "keepaliveTimer", ka_timer); json_object_int_add(json_row, "refCount", up->ref_count); + json_object_int_add(json_row, "sptBit", up->sptbit); json_object_object_add(json_group, src_str, json_row); } else { vty_out(vty, "%-10s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d%s", diff --git a/pimd/pim_register.c b/pimd/pim_register.c index c941388dc4..eab87fefb0 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -268,14 +268,6 @@ pim_register_recv (struct interface *ifp, return 0; } - if (PIM_DEBUG_PIM_REG) - { - char src_str[INET_ADDRSTRLEN]; - - pim_inet4_dump ("", src_addr, src_str, sizeof (src_str)); - zlog_debug ("Received Register message from %s on %s", src_str, ifp->name); - } - /* * Please note this is not drawn to get the correct bit/data size * @@ -307,6 +299,16 @@ pim_register_recv (struct interface *ifp, sg.grp = ip_hdr->ip_dst; i_am_rp = I_am_RP (sg.grp); + + if (PIM_DEBUG_PIM_REG) + { + char src_str[INET_ADDRSTRLEN]; + + pim_inet4_dump ("", src_addr, src_str, sizeof (src_str)); + zlog_debug ("Received Register message(%s) from %s on %s, rp: %d", + pim_str_sg_dump (&sg), src_str, ifp->name, i_am_rp); + } + if (i_am_rp && (dest_addr.s_addr == ((RP (sg.grp))->rpf_addr.u.prefix4.s_addr))) { sentRegisterStop = 0; @@ -360,8 +362,10 @@ pim_register_recv (struct interface *ifp, //pim_scan_individual_oil (upstream->channel_oil); pim_register_stop_send (ifp, &sg, dest_addr, src_addr); sentRegisterStop = 1; + } else { + if (PIM_DEBUG_PIM_REG) + zlog_debug ("(%s) sptbit: %d", pim_str_sg_dump (&upstream->sg), upstream->sptbit); } - if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || (SwitchToSptDesired(&sg))) { if (sentRegisterStop) { From 9244dd13db439e0177d66983c4ad720304feeb13 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 31 Oct 2016 20:49:18 -0400 Subject: [PATCH 243/386] pimd: Allow FHR/RP/LHR to be one and the same When we have a FHR/RP/LHR all on the same box, we were experiencing a situation where we were not sending a register stop nor where we setting the sptbit. Signed-off-by: Donald Sharp fd --- pimd/pim_mroute.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index a4ce4a5f33..d0afb124a3 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -335,17 +335,20 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) up = pim_upstream_find (&sg); if (up) { + struct pim_nexthop source; + struct pim_rpf *rpf = RP (sg.grp); + if (!rpf || !rpf->source_nexthop.interface) + return 0; + + pim_ifp = rpf->source_nexthop.interface->info; + + memset (&source, 0, sizeof (source)); /* * If we are the fhr that means we are getting a callback during * the pimreg period, so I believe we can ignore this packet */ if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) { - struct pim_nexthop source; - struct pim_rpf *rpf = RP (sg.grp); - pim_ifp = rpf->source_nexthop.interface->info; - - memset (&source, 0, sizeof (source)); //No if channel, but upstream we are at the RP. if (pim_nexthop_lookup (&source, up->upstream_register, 0) == 0) pim_register_stop_send(source.interface, &sg, pim_ifp->primary_address, up->upstream_register); @@ -359,6 +362,12 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) } else { + if (I_am_RP (up->sg.grp)) + { + if (pim_nexthop_lookup (&source, up->upstream_register, 0) == 0) + pim_register_stop_send(source.interface, &sg, pim_ifp->primary_address, up->upstream_register); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + } pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); pim_upstream_inherited_olist (up); pim_mroute_msg_wholepkt (fd, ifp, buf); From e5009aed2ff15d83094debe872fca2c3f10002bb Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 31 Oct 2016 23:17:53 -0400 Subject: [PATCH 244/386] pimd: When nexthop lookup fails, back out gracefully When the nexthop lookup fails when establishing the upstream state as part of a register receive, kill the upstream state. Signed-off-by: Donald Sharp --- pimd/pim_register.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index eab87fefb0..0c6a759dc3 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -347,8 +347,16 @@ pim_register_recv (struct interface *ifp, upstream->upstream_register = src_addr; pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.src, sg.grp); - pim_nexthop_lookup (&upstream->rpf.source_nexthop, - upstream->upstream_addr, 1); + if (pim_nexthop_lookup (&upstream->rpf.source_nexthop, + upstream->upstream_addr, 1) != 0) + { + if (PIM_DEBUG_PIM_REG) + { + zlog_debug ("Received Register(%s), for which I have no path back", pim_str_sg_dump (&upstream->sg)); + } + pim_upstream_del (upstream, __PRETTY_FUNCTION__); + return 1; + } upstream->sg.src = sg.src; upstream->rpf.rpf_addr = upstream->rpf.source_nexthop.mrib_nexthop_addr; From a277fb849563ee3e1428b117049ade4fc137be3b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 1 Nov 2016 10:16:03 -0400 Subject: [PATCH 245/386] pimd: Fix 'ip igmp join ..' When a static igmp join is issued, before routing has come up, the ability to recover was accidently removed from the code. Ticket: CM-13379 Signed-off-by: Donald Sharp --- pimd/pim_igmp.c | 2 +- pimd/pim_vty.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 04689a030f..0ce12f1ad7 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -48,7 +48,7 @@ static int igmp_sock_open(struct in_addr ifaddr, ifindex_t ifindex, uint32_t pim int join = 0; struct in_addr group; - fd = pim_socket_mcast(IPPROTO_IGMP, ifaddr, ifindex, 0 /* loop=false */); + fd = pim_socket_mcast(IPPROTO_IGMP, ifaddr, ifindex, 1); if (fd < 0) return -1; diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 3a1a1c04a1..c9dca53334 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -258,7 +258,7 @@ int pim_interface_config_write(struct vty *vty) char group_str[INET_ADDRSTRLEN]; char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", ij->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", ij->source_addr, source_str, sizeof(source_str)); + inet_ntop(AF_INET, &ij->source_addr, source_str, sizeof(source_str)); vty_out(vty, " ip igmp join %s %s%s", group_str, source_str, VTY_NEWLINE); From 7d1c3a085aeddef27b14cd8f756983dcce33af71 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 2 Nov 2016 09:35:31 -0400 Subject: [PATCH 246/386] pimd: Add ability to listen to igmp messages on 224.0.0.2 Some igmpv2 messages are sent to 224.0.0.2. We were not listening for these messages and as such we were ignoring some withdrawals. Signed-off-by: Donald Sharp --- pimd/pim_iface.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 4d8850d638..5e2fc19f2e 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -125,10 +125,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim) if (igmp) PIM_IF_DO_IGMP(pim_ifp->options); -#if 0 - /* FIXME: Should join? */ PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp->options); -#endif pim_ifp->igmp_join_list = NULL; pim_ifp->igmp_socket_list = NULL; From 0afd31c92bce7f342eb128909059dbe72b7de8dc Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 2 Nov 2016 18:03:00 +0000 Subject: [PATCH 247/386] PIM After LHR swp bounce toward rx host, igmp_source_forward_start failure message repeats in log Signed-off-by: Daniel Walton Ticket: CM-13340 --- pimd/pim_zebra.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 3189024f84..4936ca8ff6 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -1082,8 +1082,11 @@ void igmp_source_forward_start(struct igmp_source *source) group->group_igmp_sock->interface, PIM_OIF_FLAG_PROTO_IGMP); if (result) { - zlog_warn("%s: add_oif() failed with return=%d", - __func__, result); + if (PIM_DEBUG_MROUTE) + { + zlog_warn("%s: add_oif() failed with return=%d", + __func__, result); + } return; } From 66cc32fa0a057c3c036c876bd6326c7b27e9a585 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 2 Nov 2016 10:53:28 -0400 Subject: [PATCH 248/386] pimd: Add the ability to test if the RPF' is the same Test the ability to see if two RPF' are the same or not. Signed-off-by: Donald Sharp --- pimd/pim_rpf.c | 9 +++++++++ pimd/pim_rpf.h | 1 + 2 files changed, 10 insertions(+) diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 1724185e97..b71024711a 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -347,3 +347,12 @@ pim_rpf_addr_is_inaddr_any (struct pim_rpf *rpf) return 0; } + +int +pim_rpf_is_same (struct pim_rpf *rpf1, struct pim_rpf *rpf2) +{ + if (rpf1->source_nexthop.interface == rpf2->source_nexthop.interface) + return 1; + + return 0; +} diff --git a/pimd/pim_rpf.h b/pimd/pim_rpf.h index b267a9b6fa..e54aa51256 100644 --- a/pimd/pim_rpf.h +++ b/pimd/pim_rpf.h @@ -69,5 +69,6 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_ int pim_rpf_addr_is_inaddr_none (struct pim_rpf *rpf); int pim_rpf_addr_is_inaddr_any (struct pim_rpf *rpf); +int pim_rpf_is_same (struct pim_rpf *rpf1, struct pim_rpf *rpf2); void pim_rpf_set_refresh_time (void); #endif /* PIM_RPF_H */ From 80d9c3a014f4da2bafe52c5e7d98878aab984641 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 2 Nov 2016 11:20:27 -0400 Subject: [PATCH 249/386] pimd: Add some helper functions. Currently these are stubs to help debug logic. Will be filled in as we go. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 15 +++++++++++++++ pimd/pim_upstream.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 9d31245207..0ab21166da 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1009,6 +1009,14 @@ pim_upstream_switch_to_spt_desired (struct prefix_sg *sg) return 0; } +int +pim_upstream_is_sg_rpt (struct pim_upstream *up) +{ + // FIXME: When we implement the ability to + // receive a s,g,rpt prune this can be modified + return 0; +} + const char * pim_upstream_state2str (enum pim_upstream_state join_state) { @@ -1180,6 +1188,13 @@ pim_upstream_inherited_olist (struct pim_upstream *up) return output_intf; } +int +pim_upstream_empty_inherited_olist (struct pim_upstream *up) +{ + // FIXME: Currently this is not implemented + return 0; +} + /* * When we have a new neighbor, * find upstreams that don't have their rpf_addr diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index a2a912ff4f..46aaef39b7 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -144,6 +144,7 @@ void pim_upstream_keep_alive_timer_start (struct pim_upstream *up, uint32_t time int pim_upstream_switch_to_spt_desired (struct prefix_sg *sg); #define SwitchToSptDesired(sg) pim_upstream_switch_to_spt_desired (sg) +int pim_upstream_is_sg_rpt (struct pim_upstream *up); void pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_register); @@ -154,6 +155,7 @@ void pim_upstream_switch (struct pim_upstream *up, enum pim_upstream_state new_s const char *pim_upstream_state2str (enum pim_upstream_state join_state); int pim_upstream_inherited_olist (struct pim_upstream *up); +int pim_upstream_empty_inherited_olist (struct pim_upstream *up); void pim_upstream_find_new_rpf (void); From d67f268e94707d4e3e9d130a8fb90ae571dc2ea0 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 2 Nov 2016 11:21:49 -0400 Subject: [PATCH 250/386] pimd: Start coding of sending Prune (s,g,rpt) with *,g prune. Add logic to show that we are making decisions about the s,g,rpt prune send. We are not actually sending anything yet. Signed-off-by: Donald Sharp --- pimd/pim_msg.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index 749cee96e9..12a043b650 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -34,6 +34,7 @@ #include "pim_util.h" #include "pim_str.h" #include "pim_rp.h" +#include "pim_rpf.h" void pim_msg_build_header(uint8_t *pim_msg, int pim_msg_size, uint8_t pim_msg_type) @@ -121,6 +122,8 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, uint8_t *pim_msg = buf; uint8_t *pim_msg_curr = buf + PIM_MSG_HEADER_LEN; uint8_t *end = buf + buf_size; + uint16_t *prunes = NULL; + uint16_t *joins = NULL; struct in_addr stosend; uint8_t bits; int remain; @@ -170,12 +173,14 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, } /* number of joined sources */ - *((uint16_t *) pim_msg_curr) = htons(is_join ? 1 : 0); + joins = (uint16_t *)pim_msg_curr; + *joins = htons(is_join ? 1 : 0); ++pim_msg_curr; ++pim_msg_curr; /* number of pruned sources */ - *((uint16_t *) pim_msg_curr) = htons(is_join ? 0 : 1); + prunes = (uint16_t *)pim_msg_curr; + *prunes = htons(is_join ? 0 : 1); ++pim_msg_curr; ++pim_msg_curr; @@ -200,6 +205,50 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, return -7; } + if (up->sg.src.s_addr == INADDR_ANY) + { + struct pim_upstream *child; + struct listnode *up_node; + char star_g[100]; + + strcpy (star_g, pim_str_sg_dump (&up->sg)); + zlog_debug ("%s: Considering (%s) children for (S,G,rpt) prune", + __PRETTY_FUNCTION__, star_g); + for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) + { + if (child->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) + { + if (pim_rpf_is_same(&up->rpf, &child->rpf)) + { + zlog_debug ("%s: SPT Bit and RPF'(%s) != RPF'(S,G): Add Prune (%s,rpt) to compound message", + __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); + } + else + zlog_debug ("%s: SPT Bit and RPF'(%s) == RPF'(S,G): Not adding Prune for (%s,rpt)", + __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); + } + else if (pim_upstream_is_sg_rpt (child)) + { + if (pim_upstream_empty_inherited_olist (child)) + { + zlog_debug ("%s: inherited_olist(%s,rpt) is NULL, Add Prune to compound message", + __PRETTY_FUNCTION__, pim_str_sg_dump (&child->sg)); + } + else if (!pim_rpf_is_same (&up->rpf, &child->rpf)) + { + zlog_debug ("%s: RPF'(%s) != RPF'(%s,rpt), Add Prune to compound message", + __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); + } + else + zlog_debug ("%s: RPF'(%s) == RPF'(%s,rpt), Do not add Prune to compound message", + __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); + } + else + zlog_debug ("%s: SPT bit is not set for (%s)", + __PRETTY_FUNCTION__, pim_str_sg_dump (&child->sg)); + } + } + remain = pim_msg_curr - pim_msg; pim_msg_build_header (pim_msg, remain, PIM_MSG_TYPE_JOIN_PRUNE); From 1de1c5bed38caba3bf48a183eaec8dff1bd7c554 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 2 Nov 2016 19:03:29 -0400 Subject: [PATCH 251/386] lib: Add Timer Wheel functionality Signed-off-by: Donald Sharp --- lib/Makefile.am | 4 +- lib/wheel.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/wheel.h | 70 +++++++++++++++++++++ 3 files changed, 236 insertions(+), 2 deletions(-) create mode 100644 lib/wheel.c create mode 100644 lib/wheel.h diff --git a/lib/Makefile.am b/lib/Makefile.am index 1bb2d395c8..f2c076c475 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -24,7 +24,7 @@ libzebra_la_SOURCES = \ sigevent.c pqueue.c jhash.c workqueue.c nexthop.c json.c \ ptm_lib.c csv.c bfd.c vrf.c systemd.c ns.c memory.c memory_vty.c \ imsg-buffer.c imsg.c skiplist.c \ - qobj.c \ + qobj.c wheel.c \ event_counter.c \ strlcpy.c \ strlcat.c @@ -45,7 +45,7 @@ pkginclude_HEADERS = \ workqueue.h route_types.h libospf.h nexthop.h json.h \ ptm_lib.h csv.h bfd.h vrf.h ns.h systemd.h bitfield.h \ fifo.h memory_vty.h mpls.h imsg.h openbsd-queue.h openbsd-tree.h \ - skiplist.h qobj.h \ + skiplist.h qobj.h wheel.h \ event_counter.h noinst_HEADERS = \ diff --git a/lib/wheel.c b/lib/wheel.c new file mode 100644 index 0000000000..3cfd925ac7 --- /dev/null +++ b/lib/wheel.c @@ -0,0 +1,164 @@ +/* + * Timer Wheel + * Copyright (C) 2016 Cumulus Networks, Inc. + * Donald Sharp + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +#include "zebra.h" +#include "linklist.h" +#include "thread.h" +#include "memory.h" +#include "wheel.h" +#include "log.h" + +DEFINE_MTYPE_STATIC(LIB, TIMER_WHEEL, "Timer Wheel") +DEFINE_MTYPE_STATIC(LIB, TIMER_WHEEL_LIST, "Timer Wheel Slot List") + +static int debug_timer_wheel = 1; + +static int +wheel_timer_thread (struct thread *t) +{ + struct listnode *node, *nextnode; + unsigned long long curr_slot; + unsigned int slots_to_skip = 1; + struct timer_wheel *wheel; + void *data; + + wheel = THREAD_ARG(t); + THREAD_OFF(wheel->timer); + + wheel->curr_slot += wheel->slots_to_skip; + + curr_slot = wheel->curr_slot % wheel->slots; + + if (debug_timer_wheel) + zlog_debug ("%s: Wheel Slot: %lld(%lld) count: %d", + __PRETTY_FUNCTION__, + wheel->curr_slot, + curr_slot, listcount(wheel->wheel_slot_lists[curr_slot])); + + for (ALL_LIST_ELEMENTS (wheel->wheel_slot_lists[curr_slot], node, nextnode, data)) + (*wheel->slot_run)(data); + + while (list_isempty(wheel->wheel_slot_lists[(curr_slot + slots_to_skip) % wheel->slots]) && + (curr_slot + slots_to_skip ) % wheel->slots != curr_slot) + slots_to_skip++; + + wheel->slots_to_skip = slots_to_skip; + THREAD_TIMER_MSEC_ON (wheel->master, wheel->timer, + wheel_timer_thread, wheel, + wheel->nexttime * slots_to_skip); + + return 0; +} + +struct timer_wheel * +wheel_init (struct thread_master *master, int period, size_t slots, + unsigned int (*slot_key) (void *), + void (*slot_run) (void *)) +{ + struct timer_wheel *wheel; + size_t i; + + wheel = XCALLOC(MTYPE_TIMER_WHEEL, sizeof (struct timer_wheel)); + + wheel->slot_key = slot_key; + wheel->slot_run = slot_run; + + wheel->period = period; + wheel->slots = slots; + wheel->curr_slot = 0; + wheel->master = master; + wheel->nexttime = period / slots; + + wheel->wheel_slot_lists = XCALLOC(MTYPE_TIMER_WHEEL_LIST, + slots * sizeof (struct listnode *)); + for (i = 0; i < slots; i++) + wheel->wheel_slot_lists[i] = list_new (); + + THREAD_TIMER_MSEC_ON (wheel->master, wheel->timer, + wheel_timer_thread, wheel, + wheel->nexttime); + + return wheel; +} + +void +wheel_delete (struct timer_wheel *wheel) +{ + int i; + + for (i = 0; i < wheel->slots; i++) + { + list_delete(wheel->wheel_slot_lists[i]); + } + + THREAD_OFF(wheel->timer); + XFREE(MTYPE_TIMER_WHEEL_LIST, wheel->wheel_slot_lists); + XFREE(MTYPE_TIMER_WHEEL, wheel); +} + +int +wheel_stop (struct timer_wheel *wheel) +{ + THREAD_OFF(wheel->timer); + return 0; +} + +int +wheel_start (struct timer_wheel *wheel) +{ + if (!wheel->timer) + THREAD_TIMER_MSEC_ON (wheel->master, wheel->timer, + wheel_timer_thread, wheel, + wheel->nexttime); + + return 0; +} + +int +wheel_add_item (struct timer_wheel *wheel, void *item) +{ + long long slot; + + slot = (*wheel->slot_key)(item); + + if (debug_timer_wheel) + zlog_debug ("%s: Inserting %p: %lld %lld", + __PRETTY_FUNCTION__, item, + slot, slot % wheel->slots); + listnode_add (wheel->wheel_slot_lists[slot % wheel->slots], item); + + return 0; +} + +int +wheel_remove_item (struct timer_wheel *wheel, void *item) +{ + long long slot; + + slot = (*wheel->slot_key)(item); + + if (debug_timer_wheel) + zlog_debug ("%s: Removing %p: %lld %lld", + __PRETTY_FUNCTION__, item, + slot, slot % wheel->slots); + listnode_delete (wheel->wheel_slot_lists[slot % wheel->slots], item); + + return 0; +} diff --git a/lib/wheel.h b/lib/wheel.h new file mode 100644 index 0000000000..ddb79988b4 --- /dev/null +++ b/lib/wheel.h @@ -0,0 +1,70 @@ +/* + * Timer Wheel + * Copyright (C) 2016 Cumulus Networks, Inc. + * Donald Sharp + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +#ifndef __WHEEL_H__ +#define __WHEEL_H__ + +struct timer_wheel +{ + struct thread_master *master; + int slots; + long long curr_slot; + unsigned int period; + unsigned int nexttime; + unsigned int slots_to_skip; + + struct list **wheel_slot_lists; + struct thread *timer; + /* + * Key to determine what slot the item belongs in + */ + unsigned int (*slot_key) (void *); + + void (*slot_run) (void *); +}; + +struct timer_wheel *wheel_init (struct thread_master *master, int period, size_t slots, + unsigned int (*slot_key) (void *), + void (*slot_run) (void *)); +void wheel_delete (struct timer_wheel *); + +/* + * Pause the Wheel from running + */ +int wheel_stop (struct timer_wheel *wheel); + +/* + * Start the wheel from running again + */ +int wheel_start (struct timer_wheel *wheel); + +/* + * Add item to a slot setup by the slot_key, + * possibly change next time pop. + */ +int wheel_add_item (struct timer_wheel *wheel, void *item); + +/* + * Remove a item to a slot setup by the slot_key, + * possibly change next time pop. + */ +int wheel_remove_item (struct timer_wheel *wheel, void *item); + +#endif From 9c5e4d6275a571aad50f250008e310bde44a39d7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 2 Nov 2016 19:19:40 -0400 Subject: [PATCH 252/386] pimd: Start addition of timer wheel Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 0ab21166da..89fc6178fa 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -32,6 +32,7 @@ #include "plist.h" #include "hash.h" #include "jhash.h" +#include "wheel.h" #include "pimd.h" #include "pim_pim.h" @@ -53,6 +54,7 @@ struct hash *pim_upstream_hash = NULL; struct list *pim_upstream_list = NULL; +struct timer_wheel *pim_upstream_sg_wheel = NULL; static void join_timer_start(struct pim_upstream *up); static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up); @@ -170,6 +172,9 @@ pim_upstream_del(struct pim_upstream *up, const char *name) THREAD_OFF(up->t_ka_timer); THREAD_OFF(up->t_rs_timer); + if (up->sg.src.s_addr != INADDR_ANY) + wheel_remove_item (pim_upstream_sg_wheel, up); + pim_upstream_remove_children (up); pim_mroute_del (up->channel_oil); upstream_channel_oil_detach(up); @@ -565,6 +570,9 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, up->rpf.rpf_addr.family = AF_INET; up->rpf.rpf_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY; + if (up->sg.src.s_addr != INADDR_ANY) + wheel_add_item (pim_upstream_sg_wheel, up); + rpf_result = pim_rpf_update(up, NULL); if (rpf_result == PIM_RPF_FAILURE) { if (PIM_DEBUG_PIM_TRACE) @@ -576,6 +584,10 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, listnode_delete (up->parent->sources, up); up->parent = NULL; } + + if (up->sg.src.s_addr != INADDR_ANY) + wheel_remove_item (pim_upstream_sg_wheel, up); + pim_upstream_remove_children (up); if (up->sources) list_delete (up->sources); @@ -1254,9 +1266,25 @@ pim_upstream_equal (const void *arg1, const void *arg2) return 0; } +/* + * Code to check and see if we've received packets on a S,G mroute + * and if so to set the SPT bit appropriately + */ +static void +pim_upstream_sg_running (void *arg) +{ + struct pim_upstream *up = (struct pim_upstream *)arg; + + zlog_debug ("%s: %s work", __PRETTY_FUNCTION__, + pim_str_sg_dump (&up->sg)); +} + void pim_upstream_init (void) { + pim_upstream_sg_wheel = wheel_init (master, 31000, 100, + pim_upstream_hash_key, + pim_upstream_sg_running); pim_upstream_hash = hash_create_size (8192, pim_upstream_hash_key, pim_upstream_equal); From e43b86973cd20a3b64eec4b50258488025c9dfc8 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 3 Nov 2016 10:02:59 -0400 Subject: [PATCH 253/386] pimd: Add ability to set SPTBIT on a S,G stream Implement 4.2.2 for setting the SPT bit. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 86 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 4 deletions(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 89fc6178fa..fdfa283173 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1024,8 +1024,9 @@ pim_upstream_switch_to_spt_desired (struct prefix_sg *sg) int pim_upstream_is_sg_rpt (struct pim_upstream *up) { - // FIXME: When we implement the ability to - // receive a s,g,rpt prune this can be modified + if (up->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) + return 1; + return 0; } @@ -1274,9 +1275,86 @@ static void pim_upstream_sg_running (void *arg) { struct pim_upstream *up = (struct pim_upstream *)arg; + long long now; - zlog_debug ("%s: %s work", __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg)); + // If we are TRUE already no need to do more work + if (up->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) + { + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: %s sptbit is true", __PRETTY_FUNCTION__, + pim_str_sg_dump(&up->sg)); + return; + } + + // No packet can have arrived here if this is the case + if (!up->channel_oil || !up->channel_oil->installed) + { + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: %s is not installed in mroute", + __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg)); + return; + } + + // We need at least 30 seconds to see if we are getting packets + now = pim_time_monotonic_sec(); + if (now - up->state_transition <= 30) + { + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: %s uptime is %lld", + __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg), + now - up->state_transition); + return; + } + + pim_mroute_update_counters (up->channel_oil); + + // Have we seen packets? + if ((up->channel_oil->cc.oldpktcnt <= up->channel_oil->cc.pktcnt) && + (up->channel_oil->cc.lastused/100 > 30)) + { + if (PIM_DEBUG_TRACE) + { + zlog_debug ("%s: %s old packet count is equal or lastused is greater than 30", + __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg)); + zlog_debug ("%s: %ld %ld %lld", __PRETTY_FUNCTION__, up->channel_oil->cc.oldpktcnt, up->channel_oil->cc.pktcnt, up->channel_oil->cc.lastused/100); + } + return; + } + + // AND JoinDesired(S,G) == TRUE + // FIXME + + if (pim_if_connected_to_source (up->rpf.source_nexthop.interface, up->sg.src)) + { + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: %s is directly connected to the source", __PRETTY_FUNCTION__, + pim_str_sg_dump (&up->sg)); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + return; + } + + // OR inherited_olist(S,G,rpt) == NULL + if (pim_upstream_is_sg_rpt(up) && pim_upstream_empty_inherited_olist(up)) + { + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: %s OR inherited_olist(S,G,rpt) == NULL", __PRETTY_FUNCTION__, + pim_str_sg_dump (&up->sg)); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + return; + } + + // OR ( ( RPF'(S,G) == RPF'(*,G) ) AND + // ( RPF'(S,G) != NULL ) ) + if (up->parent && pim_rpf_is_same (&up->rpf, &up->parent->rpf)) + { + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: %s RPF'(S,G) is the same as RPF'(*,G)", __PRETTY_FUNCTION__, + pim_str_sg_dump (&up->sg)); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + return; + } + + return; } void From 3a66b17b6934cc733668e17498e0e88eb9f8f25c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 3 Nov 2016 10:56:39 -0400 Subject: [PATCH 254/386] pimd: Abstract setting of the spt bit a bit more Allow the spt bit to be set appropriately from multiple places. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 3 +- pimd/pim_upstream.c | 111 +++++++++++++++++++++++++++++++------------- pimd/pim_upstream.h | 2 + 3 files changed, 81 insertions(+), 35 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index d0afb124a3..467fc45b98 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -357,8 +357,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) pim_upstream_inherited_olist (up); if (!up->channel_oil->installed) pim_mroute_add (up->channel_oil); - //Send S bit down the join. - up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + pim_upstream_set_sptbit (up, ifp); } else { diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index fdfa283173..a070e92e45 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1029,6 +1029,83 @@ pim_upstream_is_sg_rpt (struct pim_upstream *up) return 0; } +/* + * After receiving a packet set SPTbit: + * void + * Update_SPTbit(S,G,iif) { + * if ( iif == RPF_interface(S) + * AND JoinDesired(S,G) == TRUE + * AND ( DirectlyConnected(S) == TRUE + * OR RPF_interface(S) != RPF_interface(RP(G)) + * OR inherited_olist(S,G,rpt) == NULL + * OR ( ( RPF'(S,G) == RPF'(*,G) ) AND + * ( RPF'(S,G) != NULL ) ) + * OR ( I_Am_Assert_Loser(S,G,iif) ) { + * Set SPTbit(S,G) to TRUE + * } + * } + */ +void +pim_upstream_set_sptbit (struct pim_upstream *up, struct interface *incoming) +{ + struct pim_rpf *grpf = NULL; + + // iif == RPF_interfvace(S) + if (up->rpf.source_nexthop.interface != incoming) + { + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: Incoming Interface: %s is different than RPF_interface(S) %s", + __PRETTY_FUNCTION__, incoming->name, up->rpf.source_nexthop.interface->name); + return; + } + + // AND JoinDesired(S,G) == TRUE + // FIXME + + // DirectlyConnected(S) == TRUE + if (pim_if_connected_to_source (up->rpf.source_nexthop.interface, up->sg.src)) + { + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: %s is directly connected to the source", __PRETTY_FUNCTION__, + pim_str_sg_dump (&up->sg)); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + return; + } + + // OR RPF_interface(S) != RPF_interface(RP(G)) + grpf = RP(up->sg.grp); + if (!grpf || up->rpf.source_nexthop.interface != grpf->source_nexthop.interface) + { + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: %s RPF_interface(S) != RPF_interface(RP(G))", + __PRETTY_FUNCTION__, pim_str_sg_dump(&up->sg)); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + return; + } + + // OR inherited_olist(S,G,rpt) == NULL + if (pim_upstream_is_sg_rpt(up) && pim_upstream_empty_inherited_olist(up)) + { + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: %s OR inherited_olist(S,G,rpt) == NULL", __PRETTY_FUNCTION__, + pim_str_sg_dump (&up->sg)); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + return; + } + + // OR ( ( RPF'(S,G) == RPF'(*,G) ) AND + // ( RPF'(S,G) != NULL ) ) + if (up->parent && pim_rpf_is_same (&up->rpf, &up->parent->rpf)) + { + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: %s RPF'(S,G) is the same as RPF'(*,G)", __PRETTY_FUNCTION__, + pim_str_sg_dump (&up->sg)); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + return; + } + + return; +} const char * pim_upstream_state2str (enum pim_upstream_state join_state) @@ -1321,39 +1398,7 @@ pim_upstream_sg_running (void *arg) return; } - // AND JoinDesired(S,G) == TRUE - // FIXME - - if (pim_if_connected_to_source (up->rpf.source_nexthop.interface, up->sg.src)) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: %s is directly connected to the source", __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg)); - up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - return; - } - - // OR inherited_olist(S,G,rpt) == NULL - if (pim_upstream_is_sg_rpt(up) && pim_upstream_empty_inherited_olist(up)) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: %s OR inherited_olist(S,G,rpt) == NULL", __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg)); - up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - return; - } - - // OR ( ( RPF'(S,G) == RPF'(*,G) ) AND - // ( RPF'(S,G) != NULL ) ) - if (up->parent && pim_rpf_is_same (&up->rpf, &up->parent->rpf)) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: %s RPF'(S,G) is the same as RPF'(*,G)", __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg)); - up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - return; - } - + pim_upstream_set_sptbit (up, up->rpf.source_nexthop.interface); return; } diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 46aaef39b7..a91a9ae378 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -146,6 +146,8 @@ int pim_upstream_switch_to_spt_desired (struct prefix_sg *sg); #define SwitchToSptDesired(sg) pim_upstream_switch_to_spt_desired (sg) int pim_upstream_is_sg_rpt (struct pim_upstream *up); +void pim_upstream_set_sptbit (struct pim_upstream *up, struct interface *incoming); + void pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_register); void pim_upstream_send_join (struct pim_upstream *up); From e5b6b229976e3ac9dc8f019337acf21391e7cf2f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 3 Nov 2016 13:51:18 -0400 Subject: [PATCH 255/386] pimd: No need to reset uptime if state is the same Do not reset the time the mroute has been in it's current state if we get a transition to the same state. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index a070e92e45..3d592460dc 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -452,7 +452,8 @@ pim_upstream_switch(struct pim_upstream *up, case PIM_UPSTREAM_NOTJOINED: case PIM_UPSTREAM_JOINED: up->join_state = new_state; - up->state_transition = pim_time_monotonic_sec(); + if (old_state != new_state) + up->state_transition = pim_time_monotonic_sec(); break; } From 07d6bab3f2ab8919202c63c87df52b864d7ff321 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 3 Nov 2016 15:44:24 -0400 Subject: [PATCH 256/386] pimd: Fix test for (S,G,rpt) prune inclusion. The (S,G,rpt) prune inclusion was incorrectly considering if the RPF' was the same for (S,G) and (*,G). Signed-off-by: Donald Sharp --- pimd/pim_msg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index 12a043b650..1ae039e1c2 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -218,7 +218,7 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, { if (child->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) { - if (pim_rpf_is_same(&up->rpf, &child->rpf)) + if (!pim_rpf_is_same(&up->rpf, &child->rpf)) { zlog_debug ("%s: SPT Bit and RPF'(%s) != RPF'(S,G): Add Prune (%s,rpt) to compound message", __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); From ffac1326b2f0d6a496e27c49f3a948b846fa16fc Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 3 Nov 2016 16:23:50 -0400 Subject: [PATCH 257/386] pimd: Add some explanatory debugging for a error condition. When we decide to ignore a incoming packet, allow detailed debugging to give a pointer to where to go to understand the issue. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 467fc45b98..48890d32fd 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -103,7 +103,12 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg (!pim_ifp) || (!(PIM_I_am_DR(pim_ifp))) || (pim_ifp->itype == PIM_INTERFACE_SSM)) - return 0; + { + if (PIM_DEBUG_MROUTE_DETAIL) + zlog_debug ("%s: Interface is not configured correctly to handle incoming packet: Could be !DR, !pim_ifp, !SM, !RP", + __PRETTY_FUNCTION__); + return 0; + } /* * If we've received a multicast packet that isn't connected to From 95f0715748201d7630f716abcc8a2765ee82c14e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 3 Nov 2016 16:25:12 -0400 Subject: [PATCH 258/386] lib: Turn off automatic debugging of Wheel code. Turn off the automatic debugging of Timer wheel code. Signed-off-by: Donald Sharp --- lib/wheel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/wheel.c b/lib/wheel.c index 3cfd925ac7..fe53dea299 100644 --- a/lib/wheel.c +++ b/lib/wheel.c @@ -28,7 +28,7 @@ DEFINE_MTYPE_STATIC(LIB, TIMER_WHEEL, "Timer Wheel") DEFINE_MTYPE_STATIC(LIB, TIMER_WHEEL_LIST, "Timer Wheel Slot List") -static int debug_timer_wheel = 1; +static int debug_timer_wheel = 0; static int wheel_timer_thread (struct thread *t) From fad009d2887f22c413320b6cf209a2689afc7ea0 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 3 Nov 2016 16:29:05 -0400 Subject: [PATCH 259/386] pimd: Protect debug messages. Protect some debug messages from being displayed always. Signed-off-by: Donald Sharp --- pimd/pim_msg.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index 1ae039e1c2..f58aec858e 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -220,32 +220,38 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, { if (!pim_rpf_is_same(&up->rpf, &child->rpf)) { - zlog_debug ("%s: SPT Bit and RPF'(%s) != RPF'(S,G): Add Prune (%s,rpt) to compound message", - __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug ("%s: SPT Bit and RPF'(%s) != RPF'(S,G): Add Prune (%s,rpt) to compound message", + __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); } else - zlog_debug ("%s: SPT Bit and RPF'(%s) == RPF'(S,G): Not adding Prune for (%s,rpt)", - __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug ("%s: SPT Bit and RPF'(%s) == RPF'(S,G): Not adding Prune for (%s,rpt)", + __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); } else if (pim_upstream_is_sg_rpt (child)) { if (pim_upstream_empty_inherited_olist (child)) { - zlog_debug ("%s: inherited_olist(%s,rpt) is NULL, Add Prune to compound message", - __PRETTY_FUNCTION__, pim_str_sg_dump (&child->sg)); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug ("%s: inherited_olist(%s,rpt) is NULL, Add Prune to compound message", + __PRETTY_FUNCTION__, pim_str_sg_dump (&child->sg)); } else if (!pim_rpf_is_same (&up->rpf, &child->rpf)) { - zlog_debug ("%s: RPF'(%s) != RPF'(%s,rpt), Add Prune to compound message", - __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug ("%s: RPF'(%s) != RPF'(%s,rpt), Add Prune to compound message", + __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); } else - zlog_debug ("%s: RPF'(%s) == RPF'(%s,rpt), Do not add Prune to compound message", - __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug ("%s: RPF'(%s) == RPF'(%s,rpt), Do not add Prune to compound message", + __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); } else - zlog_debug ("%s: SPT bit is not set for (%s)", - __PRETTY_FUNCTION__, pim_str_sg_dump (&child->sg)); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug ("%s: SPT bit is not set for (%s)", + __PRETTY_FUNCTION__, pim_str_sg_dump (&child->sg)); } } From 8711a53dbcb643caf2faf4c4691dd787470969d9 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 3 Nov 2016 18:55:35 -0400 Subject: [PATCH 260/386] pimd: Protect some zlog_debug messages Protect some zlog_debug messages with if(...) so we don't see them all the time. Signed-off-by: Donald Sharp --- pimd/pim_zebra.c | 243 +++++++++++++++++++++++------------------------ 1 file changed, 120 insertions(+), 123 deletions(-) diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 4936ca8ff6..a92d55b2af 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -498,18 +498,21 @@ pim_scan_individual_oil (struct channel_oil *c_oil) /* update kernel multicast forwarding cache (MFC) */ if (pim_mroute_add(c_oil)) { - /* just log warning */ - struct interface *old_iif = pim_if_find_by_vif_index(old_vif_index); - struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index); - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - zlog_warn("%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str, - old_iif ? old_iif->name : "", c_oil->oil.mfcc_parent, - new_iif ? new_iif->name : "", input_iface_vif_index); + if (PIM_DEBUG_MROUTE) + { + /* just log warning */ + struct interface *old_iif = pim_if_find_by_vif_index(old_vif_index); + struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index); + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); + pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); + zlog_debug("%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d", + __FILE__, __PRETTY_FUNCTION__, + source_str, group_str, + old_iif ? old_iif->name : "", c_oil->oil.mfcc_parent, + new_iif ? new_iif->name : "", input_iface_vif_index); + } } } @@ -619,17 +622,6 @@ static int redist_read_ipv4_route(int command, struct zclient *zclient, CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? " metr" : ""); } - if (length < min_len) { - zlog_warn("%s %s: short buffer: length=%d min_len=%d flags=%s%s%s%s", - __FILE__, __PRETTY_FUNCTION__, - length, min_len, - CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP) ? "nh" : "", - CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX) ? " ifi" : "", - CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? " dist" : "", - CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? " metr" : ""); - return -1; - } - /* IPv4 prefix. */ stream_get(&p.prefix, s, PSIZE(p.prefixlen)); @@ -707,6 +699,7 @@ pim_zebra_connected (struct zclient *zclient) { zclient_send_reg_requests (zclient, VRF_DEFAULT); } + void pim_zebra_init(char *zebra_sock_path) { int i; @@ -806,22 +799,28 @@ static int fib_lookup_if_vif_index(struct in_addr addr) MULTIPATH_NUM, addr, PIM_NEXTHOP_LOOKUP_MAX); if (num_ifindex < 1) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s %s: could not find nexthop ifindex for address %s", - __FILE__, __PRETTY_FUNCTION__, - addr_str); + if (PIM_DEBUG_ZEBRA) + { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_debug("%s %s: could not find nexthop ifindex for address %s", + __FILE__, __PRETTY_FUNCTION__, + addr_str); + } return -1; } first_ifindex = nexthop_tab[0].ifindex; if (num_ifindex > 1) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_info("%s %s: FIXME ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)", - __FILE__, __PRETTY_FUNCTION__, - num_ifindex, addr_str, first_ifindex); + if (PIM_DEBUG_ZEBRA) + { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_debug("%s %s: FIXME ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)", + __FILE__, __PRETTY_FUNCTION__, + num_ifindex, addr_str, first_ifindex); + } /* debug warning only, do not return */ } @@ -836,31 +835,17 @@ static int fib_lookup_if_vif_index(struct in_addr addr) vif_index = pim_if_find_vifindex_by_ifindex(first_ifindex); if (vif_index < 0) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s %s: low vif_index=%d < 1 nexthop for address %s", - __FILE__, __PRETTY_FUNCTION__, - vif_index, addr_str); + if (PIM_DEBUG_ZEBRA) + { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_debug("%s %s: low vif_index=%d < 1 nexthop for address %s", + __FILE__, __PRETTY_FUNCTION__, + vif_index, addr_str); + } return -2; } - zassert(qpim_mroute_oif_highest_vif_index < MAXVIFS); - - if (vif_index > qpim_mroute_oif_highest_vif_index) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s %s: high vif_index=%d > highest_vif_index=%d nexthop for address %s", - __FILE__, __PRETTY_FUNCTION__, - vif_index, qpim_mroute_oif_highest_vif_index, addr_str); - - zlog_warn("%s %s: pim disabled on interface %s vif_index=%d ?", - __FILE__, __PRETTY_FUNCTION__, - ifindex2ifname(vif_index), - vif_index); - - return -3; - } - return vif_index; } @@ -871,14 +856,8 @@ static int del_oif(struct channel_oil *channel_oil, struct pim_interface *pim_ifp; int old_ttl; - zassert(channel_oil); - pim_ifp = oif->info; - zassert(pim_ifp->mroute_vif_index >= 1); - zassert(qpim_mroute_oif_highest_vif_index < MAXVIFS); - zassert(pim_ifp->mroute_vif_index <= qpim_mroute_oif_highest_vif_index); - if (PIM_DEBUG_MROUTE) { char group_str[INET_ADDRSTRLEN]; char source_str[INET_ADDRSTRLEN]; @@ -899,11 +878,11 @@ static int del_oif(struct channel_oil *channel_oil, 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: nonexistent protocol mask %u removed OIF %s (vif_index=%d, min_ttl=%d) from 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); + zlog_debug("%s %s: nonexistent protocol mask %u removed OIF %s (vif_index=%d, min_ttl=%d) from 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 -2; } @@ -919,15 +898,18 @@ static int del_oif(struct channel_oil *channel_oil, /* Check the OIF keeps existing before returning, and only log warning otherwise */ if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) { - 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: protocol mask %u removing nonexistent OIF %s (vif_index=%d, min_ttl=%d) from 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); + 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: protocol mask %u removing nonexistent OIF %s (vif_index=%d, min_ttl=%d) from 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; @@ -936,21 +918,24 @@ static int del_oif(struct channel_oil *channel_oil, old_ttl = channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]; if (old_ttl < 1) { - 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: interface %s (vif_index=%d) is not output for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - oif->name, pim_ifp->mroute_vif_index, - source_str, group_str); + 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: interface %s (vif_index=%d) is not output for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, + oif->name, pim_ifp->mroute_vif_index, + source_str, group_str); + } return -3; } channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0; if (pim_mroute_add(channel_oil)) { - char group_str[INET_ADDRSTRLEN]; + 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)); @@ -967,14 +952,17 @@ static int del_oif(struct channel_oil *channel_oil, if (channel_oil->oil_size < 1) { if (pim_mroute_del(channel_oil)) { - /* just log a warning in case of failure */ - 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: failure removing OIL for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str); + if (PIM_DEBUG_MROUTE) + { + /* just log a warning in case of failure */ + 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: failure removing OIL for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, + source_str, group_str); + } } } @@ -1028,11 +1016,14 @@ void igmp_source_forward_start(struct igmp_source *source) int input_iface_vif_index = fib_lookup_if_vif_index(vif_source); if (input_iface_vif_index < 1) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); - zlog_warn("%s %s: could not find input interface for source %s", - __FILE__, __PRETTY_FUNCTION__, - source_str); + if (PIM_DEBUG_IGMP_TRACE) + { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); + zlog_debug("%s %s: could not find input interface for source %s", + __FILE__, __PRETTY_FUNCTION__, + source_str); + } return; } @@ -1043,18 +1034,15 @@ void igmp_source_forward_start(struct igmp_source *source) */ pim_oif = source->source_group->group_igmp_sock->interface->info; if (!pim_oif) { - zlog_warn("%s: multicast not enabled on oif=%s ?", - __PRETTY_FUNCTION__, - source->source_group->group_igmp_sock->interface->name); - return; - } - if (pim_oif->mroute_vif_index < 1) { - zlog_warn("%s %s: oif=%s vif_index=%d < 1", - __FILE__, __PRETTY_FUNCTION__, - source->source_group->group_igmp_sock->interface->name, - pim_oif->mroute_vif_index); + if (PIM_DEBUG_IGMP_TRACE) + { + zlog_debug("%s: multicast not enabled on oif=%s ?", + __PRETTY_FUNCTION__, + source->source_group->group_igmp_sock->interface->name); + } return; } + if (input_iface_vif_index == pim_oif->mroute_vif_index) { /* ignore request for looped MFC entry */ if (PIM_DEBUG_IGMP_TRACE) { @@ -1071,9 +1059,12 @@ void igmp_source_forward_start(struct igmp_source *source) source->source_channel_oil = pim_channel_oil_add(&sg, input_iface_vif_index); if (!source->source_channel_oil) { - zlog_warn("%s %s: could not create OIL for channel (S,G)=%s", - __FILE__, __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg)); + if (PIM_DEBUG_IGMP_TRACE) + { + zlog_debug("%s %s: could not create OIL for channel (S,G)=%s", + __FILE__, __PRETTY_FUNCTION__, + pim_str_sg_dump (&sg)); + } return; } } @@ -1145,8 +1136,9 @@ void igmp_source_forward_stop(struct igmp_source *source) group->group_igmp_sock->interface, PIM_OIF_FLAG_PROTO_IGMP); if (result) { - zlog_warn("%s: del_oif() failed with return=%d", - __func__, result); + if (PIM_DEBUG_IGMP_TRACE) + zlog_debug("%s: del_oif() failed with return=%d", + __func__, result); return; } @@ -1180,20 +1172,24 @@ void pim_forward_start(struct pim_ifchannel *ch) if (!up->channel_oil) { int input_iface_vif_index = fib_lookup_if_vif_index(up->upstream_addr); if (input_iface_vif_index < 1) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", up->sg.src, source_str, sizeof(source_str)); - zlog_warn("%s %s: could not find input interface for source %s", - __FILE__, __PRETTY_FUNCTION__, - source_str); + if (PIM_DEBUG_PIM_TRACE) + { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", up->sg.src, source_str, sizeof(source_str)); + zlog_debug("%s %s: could not find input interface for source %s", + __FILE__, __PRETTY_FUNCTION__, + source_str); + } return; } up->channel_oil = pim_channel_oil_add(&up->sg, input_iface_vif_index); if (!up->channel_oil) { - zlog_warn("%s %s: could not create OIL for channel (S,G)=%s", - __FILE__, __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg)); + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s %s: could not create OIL for channel (S,G)=%s", + __FILE__, __PRETTY_FUNCTION__, + pim_str_sg_dump (&up->sg)); return; } } @@ -1214,9 +1210,10 @@ void pim_forward_stop(struct pim_ifchannel *ch) } if (!up->channel_oil) { - zlog_warn("%s: (S,G)=%s oif=%s missing channel OIL", - __PRETTY_FUNCTION__, - pim_str_sg_dump(&ch->sg), ch->interface->name); + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: (S,G)=%s oif=%s missing channel OIL", + __PRETTY_FUNCTION__, + pim_str_sg_dump(&ch->sg), ch->interface->name); return; } From 340bce7d3574f2f892334b7beb10bb1c282c5ce6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 7 Nov 2016 10:01:50 -0500 Subject: [PATCH 261/386] pimd: Allow further refinement of pim join order When a 'show ip pim join' is issued and we have (S,G,rpt) being sent back up to us. We need to order correctly for this situation. Signed-off-by: Donald Sharp --- pimd/pim_iface.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 5e2fc19f2e..599b18ddce 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -76,17 +76,34 @@ static void *if_list_clean(struct pim_interface *pim_ifp) static int pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2) { - if (ntohl(ch1->sg.grp.s_addr) < ntohl(ch2->sg.grp.s_addr)) - return -1; + struct pim_interface *pim_ifp1; + struct pim_interface *pim_ifp2; - if (ntohl(ch1->sg.grp.s_addr) > ntohl(ch2->sg.grp.s_addr)) - return 1; + if (ntohl(ch1->sg.grp.s_addr) < ntohl(ch2->sg.grp.s_addr)) + return -1; - if (ntohl(ch1->sg.src.s_addr) < ntohl(ch2->sg.src.s_addr)) - return -1; + if (ntohl(ch1->sg.grp.s_addr) > ntohl(ch2->sg.grp.s_addr)) + return 1; - if (ntohl(ch1->sg.src.s_addr) > ntohl(ch2->sg.src.s_addr)) - return 1; + if (ntohl(ch1->sg.src.s_addr) < ntohl(ch2->sg.src.s_addr)) + return -1; + + if (ntohl(ch1->sg.src.s_addr) > ntohl(ch2->sg.src.s_addr)) + return 1; + + pim_ifp1 = ch1->interface->info; + pim_ifp2 = ch2->interface->info; + if (ntohl(pim_ifp1->primary_address.s_addr) < ntohl(pim_ifp2->primary_address.s_addr)) + return -1; + + if (ntohl(pim_ifp1->primary_address.s_addr) > ntohl(pim_ifp2->primary_address.s_addr)) + return 1; + + if (pim_ifp1->mroute_vif_index < pim_ifp2->mroute_vif_index) + return -1; + + if (pim_ifp1->mroute_vif_index > pim_ifp2->mroute_vif_index) + return 1; return 0; } From ea4a71fcf796b4f129970b97513a674ca198e0a8 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 7 Nov 2016 12:34:44 -0500 Subject: [PATCH 262/386] pimd: Store ifchannel information in a global list too. This fix handles two issues: 1) Searching entire vrf_iflist to get per interface pim_ifchannel_list 2) Display of ifchannel information in pim not being ordered correctly. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 508 ++++++++++++++++++++----------------------- pimd/pim_iface.c | 67 +++--- pimd/pim_iface.h | 2 + pimd/pim_ifchannel.c | 2 + pimd/pim_upstream.c | 194 ++++++----------- pimd/pimd.c | 1 + 6 files changed, 352 insertions(+), 422 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 6eb14a140d..52d1157f26 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -161,9 +161,11 @@ static void pim_if_membership_refresh(struct interface *ifp) static void pim_show_assert(struct vty *vty) { - struct listnode *ifnode; - struct interface *ifp; - time_t now; + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + struct listnode *ch_node; + struct in_addr ifaddr; + time_t now; now = pim_time_monotonic_sec(); @@ -171,55 +173,50 @@ static void pim_show_assert(struct vty *vty) "Interface Address Source Group State Winner Uptime Timer%s", VTY_NEWLINE); - for (ALL_LIST_ELEMENTS_RO(vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - struct pim_interface *pim_ifp; - struct in_addr ifaddr; - struct listnode *ch_node; - struct pim_ifchannel *ch; + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + char winner_str[INET_ADDRSTRLEN]; + char uptime[10]; + char timer[10]; - pim_ifp = ifp->info; + pim_ifp = ch->interface->info; if (!pim_ifp) continue; ifaddr = pim_ifp->primary_address; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; - char winner_str[INET_ADDRSTRLEN]; - char uptime[10]; - char timer[10]; + pim_inet4_dump("", ch->sg.src, + ch_src_str, sizeof(ch_src_str)); + pim_inet4_dump("", ch->sg.grp, + ch_grp_str, sizeof(ch_grp_str)); + pim_inet4_dump("", ch->ifassert_winner, + winner_str, sizeof(winner_str)); - pim_inet4_dump("", ch->sg.src, - ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->sg.grp, - ch_grp_str, sizeof(ch_grp_str)); - pim_inet4_dump("", ch->ifassert_winner, - winner_str, sizeof(winner_str)); + pim_time_uptime(uptime, sizeof(uptime), now - ch->ifassert_creation); + pim_time_timer_to_mmss(timer, sizeof(timer), + ch->t_ifassert_timer); - pim_time_uptime(uptime, sizeof(uptime), now - ch->ifassert_creation); - pim_time_timer_to_mmss(timer, sizeof(timer), - ch->t_ifassert_timer); - - vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %-15s %-8s %-5s%s", - ifp->name, - inet_ntoa(ifaddr), - ch_src_str, - ch_grp_str, - pim_ifchannel_ifassert_name(ch->ifassert_state), - winner_str, - uptime, - timer, - VTY_NEWLINE); - } /* scan interface channels */ - } /* scan interfaces */ + vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %-15s %-8s %-5s%s", + ch->interface->name, + inet_ntoa(ifaddr), + ch_src_str, + ch_grp_str, + pim_ifchannel_ifassert_name(ch->ifassert_state), + winner_str, + uptime, + timer, + VTY_NEWLINE); + } /* scan interface channels */ } static void pim_show_assert_internal(struct vty *vty) { - struct listnode *ifnode; - struct interface *ifp; + struct pim_interface *pim_ifp; + struct listnode *ch_node; + struct pim_ifchannel *ch; + struct in_addr ifaddr; vty_out(vty, "CA: CouldAssert%s" @@ -232,153 +229,136 @@ static void pim_show_assert_internal(struct vty *vty) "Interface Address Source Group CA eCA ATD eATD%s", VTY_NEWLINE); - for (ALL_LIST_ELEMENTS_RO(vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - struct pim_interface *pim_ifp; - struct in_addr ifaddr; - struct listnode *ch_node; - struct pim_ifchannel *ch; - - pim_ifp = ifp->info; + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { + pim_ifp = ch->interface->info; if (!pim_ifp) continue; ifaddr = pim_ifp->primary_address; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", ch->sg.src, - ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->sg.grp, - ch_grp_str, sizeof(ch_grp_str)); - vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s%s", - ifp->name, - inet_ntoa(ifaddr), - ch_src_str, - ch_grp_str, - PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no", - pim_macro_ch_could_assert_eval(ch) ? "yes" : "no", - PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags) ? "yes" : "no", - pim_macro_assert_tracking_desired_eval(ch) ? "yes" : "no", - VTY_NEWLINE); - } /* scan interface channels */ - } /* scan interfaces */ + pim_inet4_dump("", ch->sg.src, + ch_src_str, sizeof(ch_src_str)); + pim_inet4_dump("", ch->sg.grp, + ch_grp_str, sizeof(ch_grp_str)); + vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s%s", + ch->interface->name, + inet_ntoa(ifaddr), + ch_src_str, + ch_grp_str, + PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no", + pim_macro_ch_could_assert_eval(ch) ? "yes" : "no", + PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags) ? "yes" : "no", + pim_macro_assert_tracking_desired_eval(ch) ? "yes" : "no", + VTY_NEWLINE); + } /* scan interface channels */ } static void pim_show_assert_metric(struct vty *vty) { - struct listnode *ifnode; - struct interface *ifp; - + struct pim_interface *pim_ifp; + struct listnode *ch_node; + struct pim_ifchannel *ch; + struct in_addr ifaddr; + vty_out(vty, "Interface Address Source Group RPT Pref Metric Address %s", VTY_NEWLINE); - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - struct pim_interface *pim_ifp; - struct in_addr ifaddr; - struct listnode *ch_node; - struct pim_ifchannel *ch; + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { + pim_ifp = ch->interface->info; - pim_ifp = ifp->info; - if (!pim_ifp) continue; ifaddr = pim_ifp->primary_address; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; - char addr_str[INET_ADDRSTRLEN]; - struct pim_assert_metric am; + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + char addr_str[INET_ADDRSTRLEN]; + struct pim_assert_metric am; - am = pim_macro_spt_assert_metric(&ch->upstream->rpf, pim_ifp->primary_address); + am = pim_macro_spt_assert_metric(&ch->upstream->rpf, pim_ifp->primary_address); - pim_inet4_dump("", ch->sg.src, - ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->sg.grp, - ch_grp_str, sizeof(ch_grp_str)); - pim_inet4_dump("", am.ip_address, - addr_str, sizeof(addr_str)); + pim_inet4_dump("", ch->sg.src, + ch_src_str, sizeof(ch_src_str)); + pim_inet4_dump("", ch->sg.grp, + ch_grp_str, sizeof(ch_grp_str)); + pim_inet4_dump("", am.ip_address, + addr_str, sizeof(addr_str)); - vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %4u %6u %-15s%s", - ifp->name, - inet_ntoa(ifaddr), - ch_src_str, - ch_grp_str, - am.rpt_bit_flag ? "yes" : "no", - am.metric_preference, - am.route_metric, - addr_str, - VTY_NEWLINE); + vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %4u %6u %-15s%s", + ch->interface->name, + inet_ntoa(ifaddr), + ch_src_str, + ch_grp_str, + am.rpt_bit_flag ? "yes" : "no", + am.metric_preference, + am.route_metric, + addr_str, + VTY_NEWLINE); } /* scan interface channels */ - } /* scan interfaces */ } static void pim_show_assert_winner_metric(struct vty *vty) { - struct listnode *ifnode; - struct interface *ifp; + struct pim_interface *pim_ifp; + struct listnode *ch_node; + struct pim_ifchannel *ch; + struct in_addr ifaddr; vty_out(vty, "Interface Address Source Group RPT Pref Metric Address %s", VTY_NEWLINE); - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - struct pim_interface *pim_ifp; - struct in_addr ifaddr; - struct listnode *ch_node; - struct pim_ifchannel *ch; - - pim_ifp = ifp->info; + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { + pim_ifp = ch->interface->info; if (!pim_ifp) continue; ifaddr = pim_ifp->primary_address; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; - char addr_str[INET_ADDRSTRLEN]; - struct pim_assert_metric *am; - char pref_str[5]; - char metr_str[7]; + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + char addr_str[INET_ADDRSTRLEN]; + struct pim_assert_metric *am; + char pref_str[5]; + char metr_str[7]; - am = &ch->ifassert_winner_metric; + am = &ch->ifassert_winner_metric; - pim_inet4_dump("", ch->sg.src, - ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->sg.grp, - ch_grp_str, sizeof(ch_grp_str)); - pim_inet4_dump("", am->ip_address, - addr_str, sizeof(addr_str)); + pim_inet4_dump("", ch->sg.src, + ch_src_str, sizeof(ch_src_str)); + pim_inet4_dump("", ch->sg.grp, + ch_grp_str, sizeof(ch_grp_str)); + pim_inet4_dump("", am->ip_address, + addr_str, sizeof(addr_str)); - if (am->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX) - snprintf(pref_str, sizeof(pref_str), "INFI"); - else - snprintf(pref_str, sizeof(pref_str), "%4u", am->metric_preference); + if (am->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX) + snprintf(pref_str, sizeof(pref_str), "INFI"); + else + snprintf(pref_str, sizeof(pref_str), "%4u", am->metric_preference); - if (am->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX) - snprintf(metr_str, sizeof(metr_str), "INFI"); - else - snprintf(metr_str, sizeof(metr_str), "%6u", am->route_metric); + if (am->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX) + snprintf(metr_str, sizeof(metr_str), "INFI"); + else + snprintf(metr_str, sizeof(metr_str), "%6u", am->route_metric); - vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-4s %-6s %-15s%s", - ifp->name, - inet_ntoa(ifaddr), - ch_src_str, - ch_grp_str, - am->rpt_bit_flag ? "yes" : "no", - pref_str, - metr_str, - addr_str, - VTY_NEWLINE); - } /* scan interface channels */ - } /* scan interfaces */ + vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-4s %-6s %-15s%s", + ch->interface->name, + inet_ntoa(ifaddr), + ch_src_str, + ch_grp_str, + am->rpt_bit_flag ? "yes" : "no", + pref_str, + metr_str, + addr_str, + VTY_NEWLINE); + } /* scan interface channels */ } static void json_object_pim_ifp_add(struct json_object *json, struct interface *ifp) @@ -412,8 +392,9 @@ static void json_object_pim_ifp_add(struct json_object *json, struct interface * static void pim_show_membership(struct vty *vty, u_char uj) { - struct listnode *ifnode; - struct interface *ifp; + struct pim_interface *pim_ifp; + struct listnode *ch_node; + struct pim_ifchannel *ch; enum json_type type; json_object *json = NULL; json_object *json_iface = NULL; @@ -422,41 +403,36 @@ static void pim_show_membership(struct vty *vty, u_char uj) json = json_object_new_object(); - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - struct pim_interface *pim_ifp; - struct listnode *ch_node; - struct pim_ifchannel *ch; + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { - pim_ifp = ifp->info; + pim_ifp = ch->interface->info; if (!pim_ifp) continue; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", ch->sg.src, - ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->sg.grp, - ch_grp_str, sizeof(ch_grp_str)); + pim_inet4_dump("", ch->sg.src, + ch_src_str, sizeof(ch_src_str)); + pim_inet4_dump("", ch->sg.grp, + ch_grp_str, sizeof(ch_grp_str)); - json_object_object_get_ex(json, ifp->name, &json_iface); + json_object_object_get_ex(json, ch->interface->name, &json_iface); - if (!json_iface) { - json_iface = json_object_new_object(); - json_object_pim_ifp_add(json_iface, ifp); - json_object_object_add(json, ifp->name, json_iface); - } + if (!json_iface) { + json_iface = json_object_new_object(); + json_object_pim_ifp_add(json_iface, ch->interface); + json_object_object_add(json, ch->interface->name, json_iface); + } - json_row = json_object_new_object(); - json_object_string_add(json_row, "source", ch_src_str); - json_object_string_add(json_row, "group", ch_grp_str); - json_object_string_add(json_row, "localMembership", - ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO ? "NOINFO" : "INCLUDE"); - json_object_object_add(json_iface, ch_grp_str, json_row); - } /* scan interface channels */ - } /* scan interfaces */ + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", ch_src_str); + json_object_string_add(json_row, "group", ch_grp_str); + json_object_string_add(json_row, "localMembership", + ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO ? "NOINFO" : "INCLUDE"); + json_object_object_add(json_iface, ch_grp_str, json_row); + } /* scan interface channels */ if (uj) { vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); @@ -1106,8 +1082,10 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) static void pim_show_join(struct vty *vty, u_char uj) { - struct listnode *ifnode; - struct interface *ifp; + struct pim_interface *pim_ifp; + struct in_addr ifaddr; + struct listnode *ch_node; + struct pim_ifchannel *ch; time_t now; json_object *json = NULL; json_object *json_iface = NULL; @@ -1122,69 +1100,63 @@ static void pim_show_join(struct vty *vty, u_char uj) "Interface Address Source Group State Uptime Expire Prune%s", VTY_NEWLINE); - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - struct pim_interface *pim_ifp; - struct in_addr ifaddr; - struct listnode *ch_node; - struct pim_ifchannel *ch; + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { - pim_ifp = ifp->info; + pim_ifp = ch->interface->info; if (!pim_ifp) continue; ifaddr = pim_ifp->primary_address; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; - char uptime[10]; - char expire[10]; - char prune[10]; + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + char uptime[10]; + char expire[10]; + char prune[10]; - pim_inet4_dump("", ch->sg.src, - ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->sg.grp, - ch_grp_str, sizeof(ch_grp_str)); + pim_inet4_dump("", ch->sg.src, + ch_src_str, sizeof(ch_src_str)); + pim_inet4_dump("", ch->sg.grp, + ch_grp_str, sizeof(ch_grp_str)); - pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation); - pim_time_timer_to_mmss(expire, sizeof(expire), - ch->t_ifjoin_expiry_timer); - pim_time_timer_to_mmss(prune, sizeof(prune), - ch->t_ifjoin_prune_pending_timer); + pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation); + pim_time_timer_to_mmss(expire, sizeof(expire), + ch->t_ifjoin_expiry_timer); + pim_time_timer_to_mmss(prune, sizeof(prune), + ch->t_ifjoin_prune_pending_timer); - if (uj) { - json_object_object_get_ex(json, ifp->name, &json_iface); + if (uj) { + json_object_object_get_ex(json, ch->interface->name, &json_iface); - if (!json_iface) { - json_iface = json_object_new_object(); - json_object_pim_ifp_add(json_iface, ifp); - json_object_object_add(json, ifp->name, json_iface); - } - - json_row = json_object_new_object(); - json_object_string_add(json_row, "source", ch_src_str); - json_object_string_add(json_row, "group", ch_grp_str); - json_object_string_add(json_row, "upTime", uptime); - json_object_string_add(json_row, "expire", expire); - json_object_string_add(json_row, "prune", prune); - json_object_string_add(json_row, "channelJoinName", pim_ifchannel_ifjoin_name(ch->ifjoin_state)); - json_object_object_add(json_iface, ch_grp_str, json_row); - - } else { - vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s%s", - ifp->name, - inet_ntoa(ifaddr), - ch_src_str, - ch_grp_str, - pim_ifchannel_ifjoin_name(ch->ifjoin_state), - uptime, - expire, - prune, - VTY_NEWLINE); + if (!json_iface) { + json_iface = json_object_new_object(); + json_object_pim_ifp_add(json_iface, ch->interface); + json_object_object_add(json, ch->interface->name, json_iface); } - } /* scan interface channels */ - } /* scan interfaces */ + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", ch_src_str); + json_object_string_add(json_row, "group", ch_grp_str); + json_object_string_add(json_row, "upTime", uptime); + json_object_string_add(json_row, "expire", expire); + json_object_string_add(json_row, "prune", prune); + json_object_string_add(json_row, "channelJoinName", pim_ifchannel_ifjoin_name(ch->ifjoin_state)); + json_object_object_add(json_iface, ch_grp_str, json_row); + + } else { + vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s%s", + ch->interface->name, + inet_ntoa(ifaddr), + ch_src_str, + ch_grp_str, + pim_ifchannel_ifjoin_name(ch->ifjoin_state), + uptime, + expire, + prune, + VTY_NEWLINE); + } + } /* scan interface channels */ if (uj) { vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); @@ -1697,9 +1669,7 @@ static void pim_show_upstream(struct vty *vty, u_char uj) static void pim_show_join_desired(struct vty *vty, u_char uj) { - struct listnode *ifnode; struct listnode *chnode; - struct interface *ifp; struct pim_interface *pim_ifp; struct pim_ifchannel *ch; char src_str[INET_ADDRSTRLEN]; @@ -1715,59 +1685,57 @@ static void pim_show_join_desired(struct vty *vty, u_char uj) "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD%s", VTY_NEWLINE); - /* scan all interfaces */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - pim_ifp = ifp->info; + /* scan per-interface (S,G) state */ + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, chnode, ch)) { + /* scan all interfaces */ + pim_ifp = ch->interface->info; if (!pim_ifp) continue; - /* scan per-interface (S,G) state */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, chnode, ch)) { - struct pim_upstream *up = ch->upstream; + struct pim_upstream *up = ch->upstream; - pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); + pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); - if (uj) { - json_object_object_get_ex(json, grp_str, &json_group); + if (uj) { + json_object_object_get_ex(json, grp_str, &json_group); - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - json_row = json_object_new_object(); - json_object_pim_upstream_add(json_row, up); - json_object_string_add(json_row, "interface", ifp->name); - json_object_string_add(json_row, "source", src_str); - json_object_string_add(json_row, "group", grp_str); - - if (pim_macro_ch_lost_assert(ch)) - json_object_boolean_true_add(json_row, "lostAssert"); - - if (pim_macro_chisin_joins(ch)) - json_object_boolean_true_add(json_row, "joins"); - - if (pim_macro_chisin_pim_include(ch)) - json_object_boolean_true_add(json_row, "pimInclude"); - - if (pim_upstream_evaluate_join_desired(up)) - json_object_boolean_true_add(json_row, "evaluateJoinDesired"); - - json_object_object_add(json_group, src_str, json_row); - - } else { - vty_out(vty, "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s%s", - ifp->name, - src_str, - grp_str, - pim_macro_ch_lost_assert(ch) ? "yes" : "no", - pim_macro_chisin_joins(ch) ? "yes" : "no", - pim_macro_chisin_pim_include(ch) ? "yes" : "no", - PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags) ? "yes" : "no", - pim_upstream_evaluate_join_desired(up) ? "yes" : "no", - VTY_NEWLINE); + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, json_group); } + + json_row = json_object_new_object(); + json_object_pim_upstream_add(json_row, up); + json_object_string_add(json_row, "interface", ch->interface->name); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + + if (pim_macro_ch_lost_assert(ch)) + json_object_boolean_true_add(json_row, "lostAssert"); + + if (pim_macro_chisin_joins(ch)) + json_object_boolean_true_add(json_row, "joins"); + + if (pim_macro_chisin_pim_include(ch)) + json_object_boolean_true_add(json_row, "pimInclude"); + + if (pim_upstream_evaluate_join_desired(up)) + json_object_boolean_true_add(json_row, "evaluateJoinDesired"); + + json_object_object_add(json_group, src_str, json_row); + + } else { + vty_out(vty, "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s%s", + ch->interface->name, + src_str, + grp_str, + pim_macro_ch_lost_assert(ch) ? "yes" : "no", + pim_macro_chisin_joins(ch) ? "yes" : "no", + pim_macro_chisin_pim_include(ch) ? "yes" : "no", + PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags) ? "yes" : "no", + pim_upstream_evaluate_join_desired(up) ? "yes" : "no", + VTY_NEWLINE); } } diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 599b18ddce..ecba4dd1b2 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -42,37 +42,10 @@ #include "pim_ssmpingd.h" struct interface *pim_regiface = NULL; +struct list *pim_ifchannel_list = NULL; static void pim_if_igmp_join_del_all(struct interface *ifp); -void pim_if_init() -{ - vrf_iflist_create(VRF_DEFAULT); -} - -static void *if_list_clean(struct pim_interface *pim_ifp) -{ - if (pim_ifp->igmp_join_list) { - list_delete(pim_ifp->igmp_join_list); - } - - if (pim_ifp->igmp_socket_list) { - list_delete(pim_ifp->igmp_socket_list); - } - - if (pim_ifp->pim_neighbor_list) { - list_delete(pim_ifp->pim_neighbor_list); - } - - if (pim_ifp->pim_ifchannel_list) { - list_delete(pim_ifp->pim_ifchannel_list); - } - - XFREE(MTYPE_PIM_INTERFACE, pim_ifp); - - return 0; -} - static int pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2) { @@ -108,6 +81,44 @@ pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2) return 0; } +void +pim_if_init (void) +{ + vrf_iflist_create(VRF_DEFAULT); + pim_ifchannel_list = list_new(); + pim_ifchannel_list->cmp = (int (*)(void *, void *))pim_ifchannel_compare; +} + +void +pim_if_terminate (void) +{ + if (pim_ifchannel_list) + list_free (pim_ifchannel_list); +} + +static void *if_list_clean(struct pim_interface *pim_ifp) +{ + if (pim_ifp->igmp_join_list) { + list_delete(pim_ifp->igmp_join_list); + } + + if (pim_ifp->igmp_socket_list) { + list_delete(pim_ifp->igmp_socket_list); + } + + if (pim_ifp->pim_neighbor_list) { + list_delete(pim_ifp->pim_neighbor_list); + } + + if (pim_ifp->pim_ifchannel_list) { + list_delete(pim_ifp->pim_ifchannel_list); + } + + XFREE(MTYPE_PIM_INTERFACE, pim_ifp); + + return 0; +} + struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim) { struct pim_interface *pim_ifp; diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index f671a7d54b..9e8b177947 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -108,6 +108,7 @@ struct pim_interface { }; extern struct interface *pim_regiface; +extern struct list *pim_ifchannel_list; /* if default_holdtime is set (>= 0), use it; otherwise default_holdtime is 3.5 * hello_period @@ -118,6 +119,7 @@ extern struct interface *pim_regiface; ((pim_ifp)->pim_default_holdtime)) void pim_if_init(void); +void pim_if_terminate (void); struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim); void pim_if_delete(struct interface *ifp); diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index b786ad09ae..32e0798310 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -140,6 +140,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) called by list_delete_all_node() */ listnode_delete(pim_ifp->pim_ifchannel_list, ch); + listnode_delete(pim_ifchannel_list, ch); pim_ifchannel_free(ch); } @@ -435,6 +436,7 @@ pim_ifchannel_add(struct interface *ifp, /* Attach to list */ listnode_add_sort(pim_ifp->pim_ifchannel_list, ch); + listnode_add_sort(pim_ifchannel_list, ch); return ch; } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 3d592460dc..84503eb3e9 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -354,59 +354,45 @@ void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label, static void forward_on(struct pim_upstream *up) { - struct listnode *ifnode; - struct listnode *ifnextnode; struct listnode *chnode; struct listnode *chnextnode; - struct interface *ifp; struct pim_interface *pim_ifp; struct pim_ifchannel *ch; - /* scan all interfaces */ - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - pim_ifp = ifp->info; + /* scan (S,G) state */ + for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) { + pim_ifp = ch->interface->info; if (!pim_ifp) continue; - /* scan per-interface (S,G) state */ - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) { + if (ch->upstream != up) + continue; - if (ch->upstream != up) - continue; + if (pim_macro_chisin_oiflist(ch)) + pim_forward_start(ch); - if (pim_macro_chisin_oiflist(ch)) - pim_forward_start(ch); - - } /* scan iface channel list */ - } /* scan iflist */ + } /* scan iface channel list */ } static void forward_off(struct pim_upstream *up) { - struct listnode *ifnode; - struct listnode *ifnextnode; struct listnode *chnode; struct listnode *chnextnode; - struct interface *ifp; struct pim_interface *pim_ifp; struct pim_ifchannel *ch; - /* scan all interfaces */ - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - pim_ifp = ifp->info; + /* scan per-interface (S,G) state */ + for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) { + pim_ifp = ch->interface->info; if (!pim_ifp) continue; - /* scan per-interface (S,G) state */ - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) { + if (ch->upstream != up) + continue; - if (ch->upstream != up) - continue; + pim_forward_stop(ch); - pim_forward_stop(ch); - - } /* scan iface channel list */ - } /* scan iflist */ + } /* scan iface channel list */ } static int @@ -696,27 +682,21 @@ pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up, */ int pim_upstream_evaluate_join_desired(struct pim_upstream *up) { - struct listnode *ifnode; - struct listnode *ifnextnode; struct listnode *chnode; struct listnode *chnextnode; - struct interface *ifp; struct pim_interface *pim_ifp; struct pim_ifchannel *ch; int ret = 0; - /* scan all interfaces */ - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - pim_ifp = ifp->info; - if (!pim_ifp) - continue; + /* scan per-interface (S,G) state */ + for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) + { + pim_ifp = ch->interface->info; + if (!pim_ifp) + continue; - /* scan per-interface (S,G) state */ - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) - { - ret += pim_upstream_evaluate_join_desired_interface (up, ch); - } /* scan iface channel list */ - } /* scan iflist */ + ret += pim_upstream_evaluate_join_desired_interface (up, ch); + } /* scan iface channel list */ return ret; /* false */ } @@ -799,125 +779,97 @@ void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr) void pim_upstream_rpf_interface_changed(struct pim_upstream *up, struct interface *old_rpf_ifp) { - struct listnode *ifnode; - struct listnode *ifnextnode; - struct interface *ifp; + struct listnode *chnode; + struct listnode *chnextnode; + struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; - /* scan all interfaces */ - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - struct listnode *chnode; - struct listnode *chnextnode; - struct pim_ifchannel *ch; - struct pim_interface *pim_ifp; + /* search all ifchannels */ + for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) { - pim_ifp = ifp->info; + pim_ifp = ch->interface->info; if (!pim_ifp) continue; - /* search all ifchannels */ - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) { - if (ch->upstream != up) - continue; + if (ch->upstream != up) + continue; - if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { - if ( - /* RPF_interface(S) was NOT I */ - (old_rpf_ifp == ch->interface) - && - /* RPF_interface(S) stopped being I */ - (ch->upstream->rpf.source_nexthop.interface != ch->interface) - ) { - assert_action_a5(ch); - } - } /* PIM_IFASSERT_I_AM_LOSER */ + if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { + if ( + /* RPF_interface(S) was NOT I */ + (old_rpf_ifp == ch->interface) + && + /* RPF_interface(S) stopped being I */ + (ch->upstream->rpf.source_nexthop.interface != ch->interface) + ) { + assert_action_a5(ch); + } + } /* PIM_IFASSERT_I_AM_LOSER */ - pim_ifchannel_update_assert_tracking_desired(ch); - } + pim_ifchannel_update_assert_tracking_desired(ch); } } void pim_upstream_update_could_assert(struct pim_upstream *up) { - struct listnode *ifnode; - struct listnode *ifnextnode; struct listnode *chnode; struct listnode *chnextnode; - struct interface *ifp; struct pim_interface *pim_ifp; struct pim_ifchannel *ch; - /* scan all interfaces */ - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - pim_ifp = ifp->info; + /* scan per-interface (S,G) state */ + for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) { + pim_ifp = ch->interface->info; if (!pim_ifp) continue; - /* scan per-interface (S,G) state */ - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) { + if (ch->upstream != up) + continue; - if (ch->upstream != up) - continue; - - pim_ifchannel_update_could_assert(ch); - - } /* scan iface channel list */ - } /* scan iflist */ + pim_ifchannel_update_could_assert(ch); + } /* scan iface channel list */ } void pim_upstream_update_my_assert_metric(struct pim_upstream *up) { - struct listnode *ifnode; - struct listnode *ifnextnode; struct listnode *chnode; struct listnode *chnextnode; - struct interface *ifp; struct pim_interface *pim_ifp; struct pim_ifchannel *ch; - /* scan all interfaces */ - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - pim_ifp = ifp->info; + /* scan per-interface (S,G) state */ + for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) { + pim_ifp = ch->interface->info; if (!pim_ifp) continue; - /* scan per-interface (S,G) state */ - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) { + if (ch->upstream != up) + continue; - if (ch->upstream != up) - continue; + pim_ifchannel_update_my_assert_metric(ch); - pim_ifchannel_update_my_assert_metric(ch); - - } /* scan iface channel list */ - } /* scan iflist */ + } /* scan iface channel list */ } static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up) { - struct listnode *ifnode; - struct listnode *ifnextnode; struct listnode *chnode; struct listnode *chnextnode; - struct interface *ifp; struct pim_interface *pim_ifp; struct pim_ifchannel *ch; - /* scan all interfaces */ - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - pim_ifp = ifp->info; + /* scan per-interface (S,G) state */ + for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) { + pim_ifp = ch->interface->info; if (!pim_ifp) continue; - /* scan per-interface (S,G) state */ - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) { + if (ch->upstream != up) + continue; - if (ch->upstream != up) - continue; + pim_ifchannel_update_assert_tracking_desired(ch); - pim_ifchannel_update_assert_tracking_desired(ch); - - } /* scan iface channel list */ - } /* scan iflist */ + } /* scan iface channel list */ } /* @@ -1237,31 +1189,25 @@ int pim_upstream_inherited_olist (struct pim_upstream *up) { struct pim_interface *pim_ifp; - struct listnode *ifnextnode; struct listnode *chnextnode; struct pim_ifchannel *ch; struct listnode *chnode; - struct listnode *ifnode; - struct interface *ifp; int output_intf = 0; pim_ifp = up->rpf.source_nexthop.interface->info; if (pim_ifp && !up->channel_oil) up->channel_oil = pim_channel_oil_add (&up->sg, pim_ifp->mroute_vif_index); - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) + for (ALL_LIST_ELEMENTS (pim_ifchannel_list, chnode, chnextnode, ch)) { - pim_ifp = ifp->info; + pim_ifp = ch->interface->info; if (!pim_ifp) continue; - for (ALL_LIST_ELEMENTS (pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) + if (pim_upstream_evaluate_join_desired_interface (up, ch)) { - if (pim_upstream_evaluate_join_desired_interface (up, ch)) - { - pim_channel_add_oif (up->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); - output_intf++; - } + pim_channel_add_oif (up->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_PIM); + output_intf++; } } diff --git a/pimd/pimd.c b/pimd/pimd.c index 1608f2d07e..bd8ee755c3 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -90,6 +90,7 @@ static void pim_free() pim_route_map_terminate(); + pim_if_terminate (); pim_rp_free (); pim_route_map_terminate(); } From 3c72d6549515c6b4603a9458ff2af76ed85fe70b Mon Sep 17 00:00:00 2001 From: anuradhak Date: Mon, 31 Oct 2016 12:29:17 -0700 Subject: [PATCH 263/386] pim-msdp: part-2: SA cache support This commit includes - 1. Maintaining SA cache with local and remote entries. 2. Local SA entries - there are two cases where we pick up these - - We are RP and got a source-register from the FHR. - We are RP and FHR and learnt a new directly connected source on a DR interface. 3. Local entries are pushed to peers immediately on addition and periodically. An immediate push is also done when peer session is established. 4. Remote SA entries - from other peers in the mesh group and passed peer-RPF checks. 5. Remote entries are aged out. No other way to del them currently. In the future we may add a knob to flush entries on peer-down. Testing done - Misc topologies with CL routers plus basic interop with another vendor ( we can process their SA updates and they ours). Sample output - root@rp:~# vtysh -c "show ip msdp sa" Source Group RP Uptime 33.1.1.1 239.1.1.2 local 00:02:34 33.1.1.1 239.1.1.3 local 00:02:19 44.1.1.1 239.1.1.4 100.1.3.1 00:01:12 44.1.1.1 239.1.1.5 100.1.3.1 00:00:55 root@rp:~# Ticket: CM-13306 Signed-off-by: Anuradha Karuppiah Acked-by: Donald Sharp --- pimd/pim_cmd.c | 48 +++++ pimd/pim_memory.c | 1 + pimd/pim_memory.h | 1 + pimd/pim_mroute.c | 4 +- pimd/pim_msdp.c | 453 +++++++++++++++++++++++++++++++++++++++-- pimd/pim_msdp.h | 67 +++++- pimd/pim_msdp_packet.c | 312 +++++++++++++++++++++++++--- pimd/pim_msdp_packet.h | 39 +++- pimd/pim_msdp_socket.c | 7 +- pimd/pim_register.c | 2 +- pimd/pim_upstream.c | 18 +- pimd/pim_upstream.h | 1 + pimd/pim_vty.c | 3 + 13 files changed, 896 insertions(+), 60 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 52d1157f26..23e8ebd77c 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -5274,6 +5274,53 @@ DEFUN (show_ip_msdp_peer, return CMD_SUCCESS; } +static void +ip_msdp_show_sa(struct vty *vty, u_char uj) +{ + struct listnode *sanode; + struct pim_msdp_sa *sa; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + char rp_str[INET_ADDRSTRLEN]; + char timebuf[PIM_MSDP_UPTIME_STRLEN]; + int64_t now; + + if (uj) { + // XXX: blah + return; + } else { + vty_out(vty, "Source Group RP 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); + pim_inet4_dump("", sa->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", sa->sg.grp, grp_str, sizeof(grp_str)); + if (sa->flags & PIM_MSDP_SAF_LOCAL) { + strcpy(rp_str, "local"); + } else { + pim_inet4_dump("", sa->rp, rp_str, sizeof(rp_str)); + } + vty_out(vty, "%-15s %15s %15s %8s%s", + src_str, grp_str, rp_str, timebuf, VTY_NEWLINE); + } + } +} + +DEFUN (show_ip_msdp_sa, + show_ip_msdp_sa_cmd, + "show ip msdp sa [json]", + SHOW_STR + IP_STR + MSDP_STR + "MSDP active-source information\n" + "JavaScript Object Notation\n") +{ + u_char uj = use_json(argc, argv); + ip_msdp_show_sa(vty, uj); + + return CMD_SUCCESS; +} + void pim_cmd_init() { install_node (&pim_global_node, pim_global_config_write); /* PIM_NODE */ @@ -5351,6 +5398,7 @@ void pim_cmd_init() install_element (VIEW_NODE, &show_ip_rib_cmd); install_element (VIEW_NODE, &show_ip_ssmpingd_cmd); install_element (VIEW_NODE, &show_ip_msdp_peer_cmd); + install_element (VIEW_NODE, &show_ip_msdp_sa_cmd); install_element (VIEW_NODE, &show_debugging_pim_cmd); install_element (ENABLE_NODE, &clear_ip_interfaces_cmd); diff --git a/pimd/pim_memory.c b/pimd/pim_memory.c index 30a5446dd7..da37da6997 100644 --- a/pimd/pim_memory.c +++ b/pimd/pim_memory.c @@ -43,3 +43,4 @@ DEFINE_MTYPE(PIMD, PIM_RP, "PIM RP info") DEFINE_MTYPE(PIMD, PIM_FILTER_NAME, "PIM RP filter info") DEFINE_MTYPE(PIMD, PIM_MSDP_PEER, "PIM MSDP peer") DEFINE_MTYPE(PIMD, PIM_MSDP_PEER_MG_NAME, "PIM MSDP peer mesh-group") +DEFINE_MTYPE(PIMD, PIM_MSDP_SA, "PIM MSDP source-active cache") diff --git a/pimd/pim_memory.h b/pimd/pim_memory.h index 2b7e6ad375..434de0b194 100644 --- a/pimd/pim_memory.h +++ b/pimd/pim_memory.h @@ -42,5 +42,6 @@ DECLARE_MTYPE(PIM_RP) DECLARE_MTYPE(PIM_FILTER_NAME) DECLARE_MTYPE(PIM_MSDP_PEER) DECLARE_MTYPE(PIM_MSDP_PEER_MG_NAME) +DECLARE_MTYPE(PIM_MSDP_SA) #endif /* _QUAGGA_PIM_MEMORY_H */ diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 48890d32fd..9cd323a2d0 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -151,7 +151,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg return 0; } PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); - PIM_UPSTREAM_FLAG_SET_CREATED_BY_UPSTREAM(up->flags); + pim_upstream_set_created_by_upstream(up); pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); @@ -394,7 +394,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) return -2; } PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); - PIM_UPSTREAM_FLAG_SET_CREATED_BY_UPSTREAM(up->flags); + pim_upstream_set_created_by_upstream(up); pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); up->channel_oil = oil; diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 2805a06097..9ca9244823 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -23,13 +23,17 @@ #include #include #include +#include #include #include #include +#include +#include #include "pimd.h" #include "pim_cmd.h" #include "pim_memory.h" +#include "pim_rp.h" #include "pim_str.h" #include "pim_time.h" @@ -44,7 +48,376 @@ static void pim_msdp_peer_cr_timer_setup(struct pim_msdp_peer *mp, bool start); static void pim_msdp_peer_ka_timer_setup(struct pim_msdp_peer *mp, bool start); static void pim_msdp_peer_hold_timer_setup(struct pim_msdp_peer *mp, bool start); static void pim_msdp_peer_free(struct pim_msdp_peer *mp); +static void pim_msdp_enable(void); +static void pim_msdp_sa_adv_timer_setup(bool start); +static void pim_msdp_sa_deref(struct pim_msdp_sa *sa, enum pim_msdp_sa_flags flags); +/************************ SA cache management ******************************/ +char * +pim_msdp_sa_key_dump(struct pim_msdp_sa *sa, char *buf, int buf_size, bool long_format) +{ + char rp_str[INET_ADDRSTRLEN]; + + if (long_format && (sa->flags & PIM_MSDP_SAF_PEER)) { + pim_inet4_dump("", sa->rp, rp_str, sizeof(rp_str)); + snprintf(buf, buf_size, "MSDP SA %s rp %s", + pim_str_sg_dump(&sa->sg), rp_str); + } else { + snprintf(buf, buf_size, "MSDP SA %s", pim_str_sg_dump(&sa->sg)); + } + + return buf; +} + +static void +pim_msdp_sa_timer_expiry_log(struct pim_msdp_sa *sa, const char *timer_str) +{ + char key_str[PIM_MSDP_SA_KEY_STRLEN]; + + pim_msdp_sa_key_dump(sa, key_str, sizeof(key_str), false); + zlog_debug("%s %s timer expired", key_str, timer_str); +} + +/* RFC-3618:Sec-5.1 - global active source advertisement timer */ +static int +pim_msdp_sa_adv_timer_cb(struct thread *t) +{ + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP SA advertisment timer expired"); + } + + pim_msdp_pkt_sa_tx(); + pim_msdp_sa_adv_timer_setup(true /* start */); + return 0; +} +static void +pim_msdp_sa_adv_timer_setup(bool start) +{ + THREAD_OFF(msdp->sa_adv_timer); + if (start) { + THREAD_TIMER_ON(msdp->master, msdp->sa_adv_timer, + pim_msdp_sa_adv_timer_cb, NULL, PIM_MSDP_SA_ADVERTISMENT_TIME); + } +} + +/* RFC-3618:Sec-5.3 - SA cache state timer */ +static int +pim_msdp_sa_state_timer_cb(struct thread *t) +{ + struct pim_msdp_sa *sa; + + zassert(t); + sa = THREAD_ARG(t); + zassert(sa); + + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_sa_timer_expiry_log(sa, "state"); + } + + pim_msdp_sa_deref(sa, PIM_MSDP_SAF_PEER); + return 0; +} +static void +pim_msdp_sa_state_timer_setup(struct pim_msdp_sa *sa, bool start) +{ + THREAD_OFF(sa->sa_state_timer); + if (start) { + THREAD_TIMER_ON(msdp->master, sa->sa_state_timer, + pim_msdp_sa_state_timer_cb, sa, PIM_MSDP_SA_HOLD_TIME); + } +} + +/* release all mem associated with a sa */ +static void +pim_msdp_sa_free(struct pim_msdp_sa *sa) +{ + XFREE(MTYPE_PIM_MSDP_SA, sa); +} + +static struct pim_msdp_sa * +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", + __PRETTY_FUNCTION__, sizeof(*sa)); + return NULL; + } + + sa->sg = *sg; + sa->rp = rp; + sa->uptime = pim_time_monotonic_sec(); + + /* insert into misc tables for easy access */ + sa = hash_get(msdp->sa_hash, sa, hash_alloc_intern); + if (!sa) { + zlog_err("%s: PIM hash get failure", __PRETTY_FUNCTION__); + pim_msdp_sa_free(sa); + return NULL; + } + listnode_add_sort(msdp->sa_list, sa); + + 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 created", key_str); + } + + return sa; +} + +static struct pim_msdp_sa * +pim_msdp_sa_find(struct prefix_sg *sg) +{ + struct pim_msdp_sa lookup; + + lookup.sg = *sg; + return hash_lookup(msdp->sa_hash, &lookup); +} + +static struct pim_msdp_sa * +pim_msdp_sa_add(struct prefix_sg *sg, struct in_addr rp) +{ + struct pim_msdp_sa *sa; + + sa = pim_msdp_sa_find(sg); + if (sa) { + return sa; + } + + return pim_msdp_sa_new(sg, rp); +} + +static void +pim_msdp_sa_del(struct pim_msdp_sa * sa) +{ + /* stop timers */ + pim_msdp_sa_state_timer_setup(sa, false /* start */); + + /* remove the entry from various tables */ + listnode_delete(msdp->sa_list, sa); + hash_release(msdp->sa_hash, sa); + + 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 /* long */); + zlog_debug("%s deleted", key_str); + } + + /* free up any associated memory */ + pim_msdp_sa_free(sa); +} + +/* When a local active-source is removed there is no way to withdraw the + * source from peers. We will simply remove it from the SA cache so it will + * not be sent in supsequent SA updates. Peers will consequently timeout the + * SA. + * Similarly a "peer-added" SA is never explicitly deleted. It is simply + * aged out overtime if not seen in the SA updates from the peers. + * XXX: should we provide a knob to drop entries learnt from a peer when the + * peer goes down? */ +static void +pim_msdp_sa_deref(struct pim_msdp_sa *sa, enum pim_msdp_sa_flags flags) +{ + char key_str[PIM_MSDP_SA_KEY_STRLEN]; + + pim_msdp_sa_key_dump(sa, key_str, sizeof(key_str), true); + + if ((sa->flags &PIM_MSDP_SAF_LOCAL)) { + if (flags & PIM_MSDP_SAF_LOCAL) { + zlog_debug("%s local reference removed", key_str); + if (msdp->local_cnt) + --msdp->local_cnt; + } + } + + if ((sa->flags &PIM_MSDP_SAF_PEER)) { + if (flags & PIM_MSDP_SAF_PEER) { + zlog_debug("%s peer reference removed", key_str); + pim_msdp_sa_state_timer_setup(sa, false /* start */); + } + } + + sa->flags &= ~flags; + if (!(sa->flags & PIM_MSDP_SAF_REF)) { + pim_msdp_sa_del(sa); + } +} + +void +pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, + struct in_addr rp) +{ + struct pim_msdp_sa *sa; + char key_str[PIM_MSDP_SA_KEY_STRLEN]; + + sa = pim_msdp_sa_add(sg, rp); + if (!sa) { + return; + } + + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_sa_key_dump(sa, key_str, sizeof(key_str), true); + } + + /* reference it */ + if (mp) { + if (!(sa->flags & PIM_MSDP_SAF_PEER)) { + sa->flags |= PIM_MSDP_SAF_PEER; + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("%s added by peer", key_str); + } + } + sa->peer = mp->peer; + /* start/re-start the state timer to prevent cache expiry */ + pim_msdp_sa_state_timer_setup(sa, true /* start */); + } else { + if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { + sa->flags |= PIM_MSDP_SAF_LOCAL; + ++msdp->local_cnt; + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("%s added locally", key_str); + } + /* send an immeidate SA update to peers */ + pim_msdp_pkt_sa_tx_one(sa); + } + sa->flags &= ~PIM_MSDP_SAF_STALE; + } +} + +void +pim_msdp_sa_local_add(struct prefix_sg *sg) +{ + struct in_addr rp; + + if (!(msdp->flags & PIM_MSDPF_ENABLE)) { + /* if the feature is not enabled do nothing; we will collect all local + * sources whenever it is */ + return; + } + + /* check if I am RP for this group. XXX: is this check really needed? */ + if (!I_am_RP(sg->grp)) { + return; + } + rp.s_addr = 0; + pim_msdp_sa_ref(NULL /* mp */, sg, rp); +} + +void +pim_msdp_sa_local_del(struct prefix_sg *sg) +{ + struct pim_msdp_sa *sa; + + if (!(msdp->flags & PIM_MSDPF_ENABLE)) { + /* if the feature is not enabled do nothing; we will collect all local + * sources whenever it is */ + return; + } + + sa = pim_msdp_sa_find(sg); + if (sa) { + pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); + } +} + +static void +pim_msdp_sa_local_setup(void) +{ + struct pim_upstream *up; + struct listnode *up_node; + + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) { + if (PIM_UPSTREAM_FLAG_TEST_CREATED_BY_UPSTREAM(up->flags)) { + pim_msdp_sa_local_add(&up->sg); + } + } +} + +/* 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 */ +void +pim_msdp_i_am_rp_changed(void) +{ + struct listnode *sanode; + struct pim_msdp_sa *sa; + + /* mark all local entries as stale */ + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + 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)) { + if (sa->flags & PIM_MSDP_SAF_STALE) { + pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); + } + } +} + +/* sa hash and peer list helpers */ +static unsigned int +pim_msdp_sa_hash_key_make(void *p) +{ + struct pim_msdp_sa *sa = p; + + return (jhash_2words(sa->sg.src.s_addr, sa->sg.grp.s_addr, 0)); +} + +static int +pim_msdp_sa_hash_eq(const void *p1, const void *p2) +{ + const struct pim_msdp_sa *sa1 = p1; + const struct pim_msdp_sa *sa2 = p2; + + return ((sa1->sg.src.s_addr == sa2->sg.src.s_addr) && + (sa1->sg.grp.s_addr == sa2->sg.grp.s_addr)); +} + +static int +pim_msdp_sa_comp(const void *p1, const void *p2) +{ + const struct pim_msdp_sa *sa1 = p1; + const struct pim_msdp_sa *sa2 = p2; + + if (ntohl(sa1->sg.grp.s_addr) < ntohl(sa2->sg.grp.s_addr)) + return -1; + + if (ntohl(sa1->sg.grp.s_addr) > ntohl(sa2->sg.grp.s_addr)) + return 1; + + if (ntohl(sa1->sg.src.s_addr) < ntohl(sa2->sg.src.s_addr)) + return -1; + + if (ntohl(sa1->sg.src.s_addr) > ntohl(sa2->sg.src.s_addr)) + return 1; + + return 0; +} + +/* RFC-3618:Sec-10.1.3 - Peer-RPF forwarding */ +/* XXX: this can use a bit of refining and extensions */ +bool +pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp) +{ + if (mp->peer.s_addr == rp.s_addr) { + return true; + } + + return false; +} + +/************************ Peer session management **************************/ char * pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf, int buf_size) { @@ -148,6 +521,8 @@ pim_msdp_peer_established(struct pim_msdp_peer *mp) pim_msdp_peer_ka_timer_setup(mp, true /* start */); pim_msdp_peer_hold_timer_setup(mp, true /* start */); + pim_msdp_pkt_sa_tx_to_one_peer(mp); + PIM_MSDP_PEER_WRITE_ON(mp); PIM_MSDP_PEER_READ_ON(mp); } @@ -211,7 +586,7 @@ pim_msdp_peer_timer_expiry_log(struct pim_msdp_peer *mp, const char *timer_str) char key_str[PIM_MSDP_PEER_KEY_STRLEN]; pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), false); - zlog_debug("%s timer %s expired", key_str, timer_str); + zlog_debug("%s %s timer expired", key_str, timer_str); } /* RFC-3618:Sec-5.4 - peer hold timer */ @@ -263,10 +638,6 @@ pim_msdp_peer_ka_timer_cb(struct thread *t) pim_msdp_peer_timer_expiry_log(mp, "ka"); } - if (mp->state != PIM_MSDP_ESTABLISHED) { - return 0; - } - pim_msdp_pkt_ka_tx(mp); pim_msdp_peer_ka_timer_setup(mp, true /* start */); return 0; @@ -358,6 +729,16 @@ pim_msdp_peer_pkt_rxed(struct pim_msdp_peer *mp) } } +/* if a valid packet is txed to the peer we can restart ka timer and avoid + * unnecessary ka noise in the network */ +void +pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp) +{ + if (mp->state == PIM_MSDP_ESTABLISHED) { + pim_msdp_peer_ka_timer_setup(mp, true /* start */); + } +} + static void pim_msdp_addr2su(union sockunion *su, struct in_addr addr) { sockunion_init(su); @@ -375,6 +756,8 @@ pim_msdp_peer_new(struct in_addr peer_addr, struct in_addr local_addr, { struct pim_msdp_peer *mp; + pim_msdp_enable(); + mp = XCALLOC(MTYPE_PIM_MSDP_PEER, sizeof(*mp)); if (!mp) { zlog_err("%s: PIM XCALLOC(%zu) failure", @@ -385,6 +768,8 @@ pim_msdp_peer_new(struct in_addr peer_addr, struct in_addr local_addr, mp->peer = peer_addr; pim_msdp_addr2su(&mp->su_peer, mp->peer); mp->local = local_addr; + /* XXX: originator_id setting needs to move to the mesh group */ + msdp->originator_id = local_addr; pim_msdp_addr2su(&mp->su_local, mp->local); mp->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_PEER_MG_NAME, mesh_group_name); mp->state = PIM_MSDP_INACTIVE; @@ -394,13 +779,6 @@ pim_msdp_peer_new(struct in_addr peer_addr, struct in_addr local_addr, mp->flags |= PIM_MSDP_PEERF_LISTENER; } - if (PIM_DEBUG_MSDP_EVENTS) { - char key_str[PIM_MSDP_PEER_KEY_STRLEN]; - - pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), true); - zlog_debug("%s created", key_str); - } - /* setup packet buffers */ mp->ibuf = stream_new(PIM_MSDP_MAX_PACKET_SIZE); mp->obuf = stream_fifo_new(); @@ -415,8 +793,14 @@ pim_msdp_peer_new(struct in_addr peer_addr, struct in_addr local_addr, listnode_add_sort(msdp->peer_list, mp); if (PIM_DEBUG_MSDP_EVENTS) { + char key_str[PIM_MSDP_PEER_KEY_STRLEN]; + + pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), true); + zlog_debug("%s created", key_str); + pim_msdp_peer_state_chg_log(mp); } + /* fireup the connect state machine */ if (PIM_MSDP_PEER_IS_LISTENER(mp)) { pim_msdp_peer_listen(mp); @@ -531,6 +915,42 @@ pim_msdp_peer_comp(const void *p1, const void *p2) return 0; } +/*********************** MSDP feature APIs *********************************/ +int +pim_msdp_config_write(struct vty *vty) +{ + struct listnode *mpnode; + struct pim_msdp_peer *mp; + char peer_str[INET_ADDRSTRLEN]; + char local_str[INET_ADDRSTRLEN]; + int count = 0; + + for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { + pim_inet4_dump("", mp->peer, peer_str, sizeof(peer_str)); + pim_inet4_dump("", mp->local, local_str, sizeof(local_str)); + vty_out(vty, "ip msdp peer %s source %s%s", + peer_str, local_str, VTY_NEWLINE); + ++count; + } + return count; +} + +/* Enable feature including active/periodic timers etc. on the first peer + * config. Till then MSDP should just stay quiet. */ +static void +pim_msdp_enable(void) +{ + if (msdp->flags & PIM_MSDPF_ENABLE) { + /* feature is already enabled */ + return; + } + msdp->flags |= PIM_MSDPF_ENABLE; + msdp->work_obuf = stream_new(PIM_MSDP_MAX_PACKET_SIZE); + pim_msdp_sa_adv_timer_setup(true /* start */); + /* setup sa cache based on local sources */ + pim_msdp_sa_local_setup(); +} + /* MSDP init */ void pim_msdp_init(struct thread_master *master) @@ -539,12 +959,19 @@ pim_msdp_init(struct thread_master *master) * complete */ PIM_DO_DEBUG_MSDP_INTERNAL; + msdp->master = master; + msdp->peer_hash = hash_create(pim_msdp_peer_hash_key_make, pim_msdp_peer_hash_eq); msdp->peer_list = list_new(); msdp->peer_list->del = (void (*)(void *))pim_msdp_peer_free; msdp->peer_list->cmp = (int (*)(void *, void *))pim_msdp_peer_comp; - msdp->master = master; + + msdp->sa_hash = hash_create(pim_msdp_sa_hash_key_make, + pim_msdp_sa_hash_eq); + msdp->sa_list = list_new(); + msdp->sa_list->del = (void (*)(void *))pim_msdp_sa_free; + msdp->sa_list->cmp = (int (*)(void *, void *))pim_msdp_sa_comp; } /* counterpart to MSDP init; XXX: unused currently */ diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h index 6f8561f3cc..2af453f689 100644 --- a/pimd/pim_msdp.h +++ b/pimd/pim_msdp.h @@ -50,14 +50,44 @@ enum pim_msdp_err { #define PIM_MSDP_STATE_STRLEN 16 #define PIM_MSDP_PEER_KEY_STRLEN 80 +#define PIM_MSDP_SA_KEY_STRLEN 80 #define PIM_MSDP_UPTIME_STRLEN 80 #define PIM_MSDP_TCP_PORT 639 #define PIM_MSDP_SOCKET_SNDBUF_SIZE 65536 -#define PIM_MSDP_PEER_IS_LISTENER(mp) (mp->flags & PIM_MSDP_PEERF_LISTENER) +enum pim_msdp_sa_flags { + PIM_MSDP_SAF_NONE = 0, + /* There are two cases where we can pickup an active source locally - + * 1. We are RP and got a source-register from the FHR + * 2. We are RP and FHR and learnt a new directly connected source on a + * DR interface */ + PIM_MSDP_SAF_LOCAL = (1 << 0), + /* We got this in the MSDP SA TLV from a peer (and this passed peer-RPF + * checks) */ + PIM_MSDP_SAF_PEER = (1 << 1), + PIM_MSDP_SAF_REF = (PIM_MSDP_SAF_LOCAL | PIM_MSDP_SAF_PEER), + PIM_MSDP_SAF_STALE = (1 << 2) /* local entries can get kicked out on + * misc pim events such as RP change */ +}; + +struct pim_msdp_sa { + struct prefix_sg sg; + struct in_addr rp; /* Last RP address associated with this SA */ + struct in_addr peer; /* last peer from who we heard this SA */ + enum pim_msdp_sa_flags flags; + + /* rfc-3618 is missing default value for SA-hold-down-Period. pulled + * this number from industry-standards */ +#define PIM_MSDP_SA_HOLD_TIME ((3*60)+30) + struct thread *sa_state_timer; // 5.6 + int64_t uptime; +}; + enum pim_msdp_peer_flags { PIM_MSDP_PEERF_NONE = 0, - PIM_MSDP_PEERF_LISTENER = (1 << 0) + PIM_MSDP_PEERF_LISTENER = (1 << 0), +#define PIM_MSDP_PEER_IS_LISTENER(mp) (mp->flags & PIM_MSDP_PEERF_LISTENER) + PIM_MSDP_PEERF_SA_JUST_SENT = (1 << 1) }; struct pim_msdp_peer { @@ -84,6 +114,7 @@ struct pim_msdp_peer { struct thread *cr_timer; // 5.6 /* packet thread and buffers */ + uint32_t packet_size; struct stream *ibuf; struct stream_fifo *obuf; struct thread *t_read; @@ -102,7 +133,8 @@ struct pim_msdp_peer { enum pim_msdp_flags { PIM_MSDPF_NONE = 0, - PIM_MSDPF_LISTENER = (1 << 0) + PIM_MSDPF_ENABLE = (1 << 0), + PIM_MSDPF_LISTENER = (1 << 1) }; struct pim_msdp_listener { @@ -113,11 +145,25 @@ struct pim_msdp_listener { struct pim_msdp { enum pim_msdp_flags flags; + struct thread_master *master; + struct pim_msdp_listener listener; + uint32_t rejected_accepts; + + /* MSDP peer info */ struct hash *peer_hash; struct list *peer_list; - struct pim_msdp_listener listener; - struct thread_master *master; - uint32_t rejected_accepts; + + /* MSDP active-source info */ +#define PIM_MSDP_SA_ADVERTISMENT_TIME 60 + struct thread *sa_adv_timer; // 5.6 + struct hash *sa_hash; + struct list *sa_list; + uint32_t local_cnt; + + /* keep a scratch pad for building SA TLVs */ + struct stream *work_obuf; + + struct in_addr originator_id; }; #define PIM_MSDP_PEER_READ_ON(mp) THREAD_READ_ON(msdp->master, mp->t_read, pim_msdp_read, mp, mp->fd); @@ -139,5 +185,12 @@ void pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state); void pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str); int pim_msdp_write(struct thread *thread); char *pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size, bool long_format); - +int pim_msdp_config_write(struct vty *vty); +void pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp); +char *pim_msdp_sa_key_dump(struct pim_msdp_sa *sa, char *buf, int buf_size, bool long_format); +void pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, struct in_addr rp); +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); #endif diff --git a/pimd/pim_msdp_packet.c b/pimd/pim_msdp_packet.c index 458d5e4621..d6b4765714 100644 --- a/pimd/pim_msdp_packet.c +++ b/pimd/pim_msdp_packet.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "pimd.h" #include "pim_str.h" @@ -128,6 +129,12 @@ pim_msdp_pkt_delete(struct pim_msdp_peer *mp) stream_free(stream_fifo_pop(mp->obuf)); } +static void +pim_msdp_pkt_add(struct pim_msdp_peer *mp, struct stream *s) +{ + stream_fifo_push(mp->obuf, s); +} + static void pim_msdp_write_proceed_actions(struct pim_msdp_peer *mp) { @@ -194,10 +201,17 @@ pim_msdp_write(struct thread *thread) if (num != writenum) { /* 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; } /* Retrieve msdp packet type. */ + stream_set_getp(s,0); type = stream_getc(s); switch (type) { @@ -230,23 +244,20 @@ static void pim_msdp_pkt_send(struct pim_msdp_peer *mp, struct stream *s) { /* Add packet to the end of list. */ - stream_fifo_push(mp->obuf, s); + pim_msdp_pkt_add(mp, s); PIM_MSDP_PEER_WRITE_ON(mp); } -/* Make keepalive packet and send it to the peer - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| 4 | 3 | -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ void pim_msdp_pkt_ka_tx(struct pim_msdp_peer *mp) { struct stream *s; + if (mp->state != PIM_MSDP_ESTABLISHED) { + /* don't tx anything unless a session is established */ + return; + } s = stream_new(PIM_MSDP_KA_TLV_MAX_SIZE); stream_putc(s, PIM_MSDP_KEEPALIVE); stream_putw(s, PIM_MSDP_KA_TLV_MAX_SIZE); @@ -254,6 +265,142 @@ pim_msdp_pkt_ka_tx(struct pim_msdp_peer *mp) pim_msdp_pkt_send(mp, s); } +static void +pim_msdp_pkt_sa_push_to_one_peer(struct pim_msdp_peer *mp) +{ + struct stream *s; + + if (mp->state != PIM_MSDP_ESTABLISHED) { + /* don't tx anything unless a session is established */ + return; + } + s = stream_dup(msdp->work_obuf); + if (s) { + pim_msdp_pkt_send(mp, s); + mp->flags |= PIM_MSDP_PEERF_SA_JUST_SENT; + } +} + +/* push the stream into the obuf fifo of all the peers */ +static void +pim_msdp_pkt_sa_push(struct pim_msdp_peer *mp) +{ + struct listnode *mpnode; + + if (mp) { + pim_msdp_pkt_sa_push_to_one_peer(mp); + } else { + for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { + 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_pkt_sa_push", key_str); + } + pim_msdp_pkt_sa_push_to_one_peer(mp); + } + } +} + +static int +pim_msdp_pkt_sa_fill_hdr(int local_cnt) +{ + int curr_tlv_ecnt; + + stream_reset(msdp->work_obuf); + curr_tlv_ecnt = local_cnt>PIM_MSDP_SA_MAX_ENTRY_CNT?PIM_MSDP_SA_MAX_ENTRY_CNT:local_cnt; + local_cnt -= curr_tlv_ecnt; + stream_putc(msdp->work_obuf, PIM_MSDP_V4_SOURCE_ACTIVE); + stream_putw(msdp->work_obuf, PIM_MSDP_SA_ENTRY_CNT2SIZE(curr_tlv_ecnt)); + stream_putc(msdp->work_obuf, curr_tlv_ecnt); + stream_put_ipv4(msdp->work_obuf, msdp->originator_id.s_addr); + + return local_cnt; +} + +static void +pim_msdp_pkt_sa_fill_one(struct pim_msdp_sa *sa) +{ + stream_put3(msdp->work_obuf, 0 /* reserved */); + stream_putc(msdp->work_obuf, 32 /* sprefix len */); + stream_put_ipv4(msdp->work_obuf, sa->sg.grp.s_addr); + stream_put_ipv4(msdp->work_obuf, sa->sg.src.s_addr); +} + +static void +pim_msdp_pkt_sa_gen(struct pim_msdp_peer *mp) +{ + struct listnode *sanode; + struct pim_msdp_sa *sa; + int sa_count; + int local_cnt = msdp->local_cnt; + + sa_count = 0; + local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt); + + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { + /* current implementation of MSDP is for anycast i.e. full mesh. so + * no re-forwarding of SAs that we learnt from other peers */ + continue; + } + /* add sa into scratch pad */ + pim_msdp_pkt_sa_fill_one(sa); + ++sa_count; + if (sa_count >= PIM_MSDP_SA_MAX_ENTRY_CNT) { + pim_msdp_pkt_sa_push(mp); + /* reset headers */ + sa_count = 0; + local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt); + } + } + + if (sa_count) { + pim_msdp_pkt_sa_push(mp); + } + return; +} + +static void +pim_msdp_pkt_sa_tx_done(void) +{ + struct listnode *mpnode; + struct pim_msdp_peer *mp; + + /* if SA were sent to the peers we restart ka timer and avoid + * unnecessary ka noise */ + for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { + if (mp->flags & PIM_MSDP_PEERF_SA_JUST_SENT) { + mp->flags &= ~PIM_MSDP_PEERF_SA_JUST_SENT; + pim_msdp_peer_pkt_txed(mp); + } + } +} + +void +pim_msdp_pkt_sa_tx(void) +{ + pim_msdp_pkt_sa_gen(NULL /* mp */); + pim_msdp_pkt_sa_tx_done(); +} + +void +pim_msdp_pkt_sa_tx_one(struct pim_msdp_sa *sa) +{ + pim_msdp_pkt_sa_fill_hdr(1 /* cnt */); + pim_msdp_pkt_sa_fill_one(sa); + pim_msdp_pkt_sa_push(NULL); + pim_msdp_pkt_sa_tx_done(); +} + +/* when a connection is first established we push all SAs immediately */ +void +pim_msdp_pkt_sa_tx_to_one_peer(struct pim_msdp_peer *mp) +{ + pim_msdp_pkt_sa_gen(mp); + pim_msdp_pkt_sa_tx_done(); +} + static void pim_msdp_pkt_rxed_with_fatal_error(struct pim_msdp_peer *mp) { @@ -273,23 +420,85 @@ pim_msdp_pkt_ka_rx(struct pim_msdp_peer *mp, int len) } static void -pim_msdp_pkt_sa_rx(struct pim_msdp_peer *mp, int len) +pim_msdp_pkt_sa_rx_one(struct pim_msdp_peer *mp, struct in_addr rp) { - mp->sa_rx_cnt++; - /* XXX: proc SA ... */ - pim_msdp_peer_pkt_rxed(mp); + int prefix_len; + struct prefix_sg sg; + + /* just throw away the three reserved bytes */ + stream_get3(mp->ibuf); + prefix_len = stream_getc(mp->ibuf); + + memset(&sg, 0, sizeof (struct prefix_sg)); + sg.grp.s_addr = stream_get_ipv4(mp->ibuf); + sg.src.s_addr = stream_get_ipv4(mp->ibuf); + + if (prefix_len != 32) { + /* ignore SA update if the prefix length is not 32 */ + zlog_err("rxed sa update with invalid prefix length %d", prefix_len); + return; + } + if (PIM_DEBUG_MSDP_PACKETS) { + zlog_debug(" sg %s", pim_str_sg_dump(&sg)); + } + pim_msdp_sa_ref(mp, &sg, rp); } -/* Theoretically you could have different tlv types in the same message. - * For the time being I am assuming one; will revisit before 3.2 - XXX */ static void -pim_msdp_pkt_rx(struct pim_msdp_peer *mp, int nbytes) +pim_msdp_pkt_sa_rx(struct pim_msdp_peer *mp, int len) +{ + int entry_cnt; + int i; + struct in_addr rp; /* Last RP address associated with this SA */ + + mp->sa_rx_cnt++; + + if (len < PIM_MSDP_SA_TLV_MIN_SIZE) { + pim_msdp_pkt_rxed_with_fatal_error(mp); + return; + } + + entry_cnt = stream_getc(mp->ibuf); + /* some vendors include the actual multicast data in the tlv (at the end). + * we will ignore such data. in the future we may consider pushing it down + * the RPT */ + if (len < PIM_MSDP_SA_ENTRY_CNT2SIZE(entry_cnt)) { + pim_msdp_pkt_rxed_with_fatal_error(mp); + return; + } + rp.s_addr = stream_get_ipv4(mp->ibuf); + + if (PIM_DEBUG_MSDP_PACKETS) { + char rp_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", rp, rp_str, sizeof(rp_str)); + zlog_debug(" entry_cnt %d rp %s", entry_cnt, rp_str); + } + + if (!pim_msdp_peer_rpf_check(mp, rp)) { + /* if peer-RPF check fails don't process the packet any further */ + if (PIM_DEBUG_MSDP_PACKETS) { + zlog_debug(" peer RPF check failed"); + } + return; + } + + pim_msdp_peer_pkt_rxed(mp); + + /* update SA cache */ + for (i = 0; i < entry_cnt; ++i) { + pim_msdp_pkt_sa_rx_one(mp, rp); + } +} + +static void +pim_msdp_pkt_rx(struct pim_msdp_peer *mp) { enum pim_msdp_tlv type; int len; - type = stream_getc(mp->ibuf); - len = stream_getw(mp->ibuf); + /* re-read type and len */ + type = stream_getc_from(mp->ibuf, 0); + len = stream_getw_from(mp->ibuf, 1); if (len < PIM_MSDP_HEADER_SIZE) { pim_msdp_pkt_rxed_with_fatal_error(mp); return; @@ -300,12 +509,6 @@ pim_msdp_pkt_rx(struct pim_msdp_peer *mp, int nbytes) return; } - if (len > nbytes) { - /* we got a partial read or the packet is malformed */ - pim_msdp_pkt_rxed_with_fatal_error(mp); - return; - } - if (PIM_DEBUG_MSDP_PACKETS) { pim_msdp_pkt_dump(mp, type, len, true /*rx*/); } @@ -321,7 +524,6 @@ pim_msdp_pkt_rx(struct pim_msdp_peer *mp, int nbytes) default: mp->unk_rx_cnt++; } - /* XXX: process next tlv*/ } /* pim msdp read utility function. */ @@ -329,9 +531,16 @@ static int pim_msdp_read_packet(struct pim_msdp_peer *mp) { int nbytes; - /* Read packet from fd. */ - nbytes = stream_read_try(mp->ibuf, mp->fd, PIM_MSDP_MAX_PACKET_SIZE); - if (nbytes < PIM_MSDP_HEADER_SIZE) { + int readsize; + + readsize = mp->packet_size - stream_get_endp(mp->ibuf); + if (!readsize) { + return 0; + } + + /* Read packet from fd */ + nbytes = stream_read_try(mp->ibuf, mp->fd, readsize); + if (nbytes < 0) { if (nbytes == -2) { /* transient error retry */ return -1; @@ -339,7 +548,17 @@ pim_msdp_read_packet(struct pim_msdp_peer *mp) pim_msdp_pkt_rxed_with_fatal_error(mp); return -1; } - return nbytes; + + if (!nbytes) { + pim_msdp_peer_reset_tcp_conn(mp, "peer-down"); + return -1; + } + + /* We read partial packet. */ + if (stream_get_endp(mp->ibuf) != mp->packet_size) + return -1; + + return 0; } int @@ -347,6 +566,7 @@ pim_msdp_read(struct thread *thread) { struct pim_msdp_peer *mp; int rc; + uint32_t len; mp = THREAD_ARG(thread); mp->t_read = NULL; @@ -368,13 +588,41 @@ pim_msdp_read(struct thread *thread) return 0; } - THREAD_READ_ON(msdp->master, mp->t_read, pim_msdp_read, mp, mp->fd); + PIM_MSDP_PEER_READ_ON(mp); - rc = pim_msdp_read_packet(mp); - if (rc > 0) { - pim_msdp_pkt_rx(mp, rc); + if (!mp->packet_size) { + mp->packet_size = PIM_MSDP_HEADER_SIZE; } + if (stream_get_endp(mp->ibuf) < PIM_MSDP_HEADER_SIZE) { + /* start by reading the TLV header */ + rc = pim_msdp_read_packet(mp); + if (rc < 0) { + goto pim_msdp_read_end; + } + + /* Find TLV type and len */ + stream_getc(mp->ibuf); + len = stream_getw(mp->ibuf); + if (len < PIM_MSDP_HEADER_SIZE) { + pim_msdp_pkt_rxed_with_fatal_error(mp); + goto pim_msdp_read_end; + } + /* read complete TLV */ + mp->packet_size = len; + } + + rc = pim_msdp_read_packet(mp); + if (rc < 0) { + goto pim_msdp_read_end; + } + + pim_msdp_pkt_rx(mp); + + /* reset input buffers and get ready for the next packet */ + mp->packet_size = 0; stream_reset(mp->ibuf); + +pim_msdp_read_end: return 0; } diff --git a/pimd/pim_msdp_packet.h b/pimd/pim_msdp_packet.h index 7f9ed9f68f..30221a399a 100644 --- a/pimd/pim_msdp_packet.h +++ b/pimd/pim_msdp_packet.h @@ -22,8 +22,41 @@ /* type and length of a single tlv can be consider packet header */ #define PIM_MSDP_HEADER_SIZE 3 -#define PIM_MSDP_SA_TLV_MAX_SIZE 9192 + +/* Keepalive TLV + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| 4 | 3 | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ #define PIM_MSDP_KA_TLV_MAX_SIZE PIM_MSDP_HEADER_SIZE + +/* Source-Active TLV (x=8, y=12xEntryCount) + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| 1 | x + y | Entry Count | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| RP Address | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Reserved | Sprefix Len | \ ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ \ +| Group Address | ) z ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / +| Source Address | / ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ +#define PIM_MSDP_SA_TLV_MAX_SIZE 9192 +#define PIM_MSDP_SA_X_SIZE 8 +#define PIM_MSDP_SA_ONE_ENTRY_SIZE 12 +#define PIM_MSDP_SA_Y_SIZE(entry_cnt) (PIM_MSDP_SA_ONE_ENTRY_SIZE * entry_cnt) +#define PIM_MSDP_SA_ENTRY_CNT2SIZE(entry_cnt) (PIM_MSDP_SA_X_SIZE +\ + PIM_MSDP_SA_Y_SIZE(entry_cnt)) +/* SA TLV has to have atleast only one entry in it so x=8 + y=12 */ +#define PIM_MSDP_SA_TLV_MIN_SIZE PIM_MSDP_SA_ENTRY_CNT2SIZE(1) +#define PIM_MSDP_SA_MAX_ENTRY_CNT ((PIM_MSDP_SA_TLV_MAX_SIZE - PIM_MSDP_SA_X_SIZE)/PIM_MSDP_SA_ONE_ENTRY_SIZE) + /* XXX: this is just a guesstimate - need to revist */ #define PIM_MSDP_MAX_PACKET_SIZE (PIM_MSDP_SA_TLV_MAX_SIZE + PIM_MSDP_KA_TLV_MAX_SIZE) @@ -31,4 +64,8 @@ void pim_msdp_pkt_ka_tx(struct pim_msdp_peer *mp); int pim_msdp_read(struct thread *thread); +void pim_msdp_pkt_sa_tx(void); +void pim_msdp_pkt_sa_tx_one(struct pim_msdp_sa *sa); +void pim_msdp_pkt_sa_tx_to_one_peer(struct pim_msdp_peer *mp); + #endif diff --git a/pimd/pim_msdp_socket.c b/pimd/pim_msdp_socket.c index fdb77c530b..f71d23e4a1 100644 --- a/pimd/pim_msdp_socket.c +++ b/pimd/pim_msdp_socket.c @@ -22,8 +22,9 @@ #include #include -#include #include +#include +#include #include "pimd.h" @@ -149,11 +150,11 @@ pim_msdp_sock_listen(void) safe_strerror (errno)); } - /* bond to well known TCP port */ + /* bind to well known TCP port */ rc = bind(sock, (struct sockaddr *)&sin, socklen); if (pimd_privs.change(ZPRIVS_LOWER)) { - zlog_err ("pim_msdp_socket: could not raise privs, %s", + zlog_err ("pim_msdp_socket: could not lower privs, %s", safe_strerror (errno)); } diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 0c6a759dc3..017d21b1b7 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -343,7 +343,7 @@ pim_register_recv (struct interface *ifp, zlog_warn ("Failure to create upstream state"); return 1; } - PIM_UPSTREAM_FLAG_SET_CREATED_BY_UPSTREAM(upstream->flags); + pim_upstream_set_created_by_upstream(upstream); upstream->upstream_register = src_addr; pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.src, sg.grp); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 84503eb3e9..3cfe0887ef 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -51,6 +51,7 @@ #include "pim_rp.h" #include "pim_br.h" #include "pim_register.h" +#include "pim_msdp.h" struct hash *pim_upstream_hash = NULL; struct list *pim_upstream_list = NULL; @@ -111,6 +112,20 @@ pim_upstream_find_new_children (struct pim_upstream *up) } } +void +pim_upstream_set_created_by_upstream(struct pim_upstream *up) +{ + PIM_UPSTREAM_FLAG_SET_CREATED_BY_UPSTREAM(up->flags); + pim_msdp_sa_local_add(&up->sg); +} + +static void +pim_upstream_unset_created_by_upstream(struct pim_upstream *up) +{ + PIM_UPSTREAM_FLAG_UNSET_CREATED_BY_UPSTREAM(up->flags); + pim_msdp_sa_local_del(&up->sg); +} + /* * If we have a (*,*) || (S,*) there is no parent * If we have a (S,G), find the (*,G) @@ -175,6 +190,7 @@ pim_upstream_del(struct pim_upstream *up, const char *name) 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); @@ -913,7 +929,7 @@ pim_upstream_keep_alive_timer (struct thread *t) PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM (up->flags); if (PIM_UPSTREAM_FLAG_TEST_CREATED_BY_UPSTREAM(up->flags)) { - PIM_UPSTREAM_FLAG_UNSET_CREATED_BY_UPSTREAM(up->flags); + pim_upstream_unset_created_by_upstream(up); pim_upstream_del (up, __PRETTY_FUNCTION__); } } diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index a91a9ae378..7f8c0c99cb 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -163,4 +163,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); #endif /* PIM_UPSTREAM_H */ diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index c9dca53334..d336051f2b 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -38,6 +38,7 @@ #include "pim_oil.h" #include "pim_static.h" #include "pim_rp.h" +#include "pim_msdp.h" int pim_debug_config_write (struct vty *vty) @@ -142,6 +143,8 @@ int pim_global_config_write(struct vty *vty) { int writes = 0; + writes += pim_msdp_config_write (vty); + if (PIM_MROUTE_IS_ENABLED) { vty_out(vty, "ip multicast-routing%s", VTY_NEWLINE); ++writes; From 1c01dbd8f8bc8adbcf61f3894ca0efec49656a40 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 7 Nov 2016 10:40:26 -0500 Subject: [PATCH 264/386] pimd: Send prune(S,G,RPT) with (*,G) join Signed-off-by: Donald Sharp --- pimd/pim_msg.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index f58aec858e..c22011b576 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -204,11 +204,13 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, __PRETTY_FUNCTION__, source_str, remain); return -7; } + remain = pim_msg_curr - pim_msg; if (up->sg.src.s_addr == INADDR_ANY) { struct pim_upstream *child; struct listnode *up_node; + int send_prune = 0; char star_g[100]; strcpy (star_g, pim_str_sg_dump (&up->sg)); @@ -220,6 +222,7 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, { if (!pim_rpf_is_same(&up->rpf, &child->rpf)) { + send_prune = 1; if (PIM_DEBUG_PIM_PACKETS) zlog_debug ("%s: SPT Bit and RPF'(%s) != RPF'(S,G): Add Prune (%s,rpt) to compound message", __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); @@ -233,12 +236,14 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, { if (pim_upstream_empty_inherited_olist (child)) { + send_prune = 1; if (PIM_DEBUG_PIM_PACKETS) zlog_debug ("%s: inherited_olist(%s,rpt) is NULL, Add Prune to compound message", __PRETTY_FUNCTION__, pim_str_sg_dump (&child->sg)); } else if (!pim_rpf_is_same (&up->rpf, &child->rpf)) { + send_prune = 1; if (PIM_DEBUG_PIM_PACKETS) zlog_debug ("%s: RPF'(%s) != RPF'(%s,rpt), Add Prune to compound message", __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); @@ -252,10 +257,18 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, if (PIM_DEBUG_PIM_PACKETS) zlog_debug ("%s: SPT bit is not set for (%s)", __PRETTY_FUNCTION__, pim_str_sg_dump (&child->sg)); + if (send_prune) + { + pim_msg_curr = pim_msg_addr_encode_ipv4_source (pim_msg_curr, remain, + child->sg.src, + PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_RPT_BIT); + remain = pim_msg_curr - pim_msg; + *prunes = htons(ntohs(*prunes) + 1); + send_prune = 0; + } } } - remain = pim_msg_curr - pim_msg; pim_msg_build_header (pim_msg, remain, PIM_MSG_TYPE_JOIN_PRUNE); return remain; From 3fdfd9433ec8c6162043ffd6fe82085cf0fc1d8f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 7 Nov 2016 14:33:54 -0500 Subject: [PATCH 265/386] pimd: Add ability for ifchannel *,G to know their S,G's Add the ability for pim ifchannels *,G's to know their corresponding S,G's. This will facilitate handling S,G,rpt state information better. Signed-off-by: Donald Sharp --- pimd/pim_iface.c | 35 -------------- pimd/pim_iface.h | 1 + pimd/pim_ifchannel.c | 112 ++++++++++++++++++++++++++++--------------- pimd/pim_ifchannel.h | 3 ++ 4 files changed, 78 insertions(+), 73 deletions(-) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index ecba4dd1b2..b83e8c1785 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -46,41 +46,6 @@ struct list *pim_ifchannel_list = NULL; static void pim_if_igmp_join_del_all(struct interface *ifp); -static int -pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2) -{ - struct pim_interface *pim_ifp1; - struct pim_interface *pim_ifp2; - - if (ntohl(ch1->sg.grp.s_addr) < ntohl(ch2->sg.grp.s_addr)) - return -1; - - if (ntohl(ch1->sg.grp.s_addr) > ntohl(ch2->sg.grp.s_addr)) - return 1; - - if (ntohl(ch1->sg.src.s_addr) < ntohl(ch2->sg.src.s_addr)) - return -1; - - if (ntohl(ch1->sg.src.s_addr) > ntohl(ch2->sg.src.s_addr)) - return 1; - - pim_ifp1 = ch1->interface->info; - pim_ifp2 = ch2->interface->info; - if (ntohl(pim_ifp1->primary_address.s_addr) < ntohl(pim_ifp2->primary_address.s_addr)) - return -1; - - if (ntohl(pim_ifp1->primary_address.s_addr) > ntohl(pim_ifp2->primary_address.s_addr)) - return 1; - - if (pim_ifp1->mroute_vif_index < pim_ifp2->mroute_vif_index) - return -1; - - if (pim_ifp1->mroute_vif_index > pim_ifp2->mroute_vif_index) - return 1; - - return 0; -} - void pim_if_init (void) { diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index 9e8b177947..b1759c0da9 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -174,4 +174,5 @@ void pim_if_update_assert_tracking_desired(struct interface *ifp); void pim_if_create_pimreg(void); int pim_if_connected_to_source (struct interface *ifp, struct in_addr src); + #endif /* PIM_IFACE_H */ diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 32e0798310..835ea424c5 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -41,6 +41,41 @@ #include "pim_oil.h" #include "pim_upstream.h" +int +pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2) +{ + struct pim_interface *pim_ifp1; + struct pim_interface *pim_ifp2; + + if (ntohl(ch1->sg.grp.s_addr) < ntohl(ch2->sg.grp.s_addr)) + return -1; + + if (ntohl(ch1->sg.grp.s_addr) > ntohl(ch2->sg.grp.s_addr)) + return 1; + + if (ntohl(ch1->sg.src.s_addr) < ntohl(ch2->sg.src.s_addr)) + return -1; + + if (ntohl(ch1->sg.src.s_addr) > ntohl(ch2->sg.src.s_addr)) + return 1; + + pim_ifp1 = ch1->interface->info; + pim_ifp2 = ch2->interface->info; + if (ntohl(pim_ifp1->primary_address.s_addr) < ntohl(pim_ifp2->primary_address.s_addr)) + return -1; + + if (ntohl(pim_ifp1->primary_address.s_addr) > ntohl(pim_ifp2->primary_address.s_addr)) + return 1; + + if (pim_ifp1->mroute_vif_index < pim_ifp2->mroute_vif_index) + return -1; + + if (pim_ifp1->mroute_vif_index > pim_ifp2->mroute_vif_index) + return 1; + + return 0; +} + /* * A (*,G) or a (*,*) is going away * remove the parent pointer from @@ -49,24 +84,16 @@ static void pim_ifchannel_remove_children (struct pim_ifchannel *ch) { - struct pim_interface *pim_ifp = ch->interface->info; - struct listnode *ch_node; struct pim_ifchannel *child; - // Basic sanity, (*,*) not currently supported - if ((ch->sg.src.s_addr == INADDR_ANY) && - (ch->sg.grp.s_addr == INADDR_ANY)) + if (!ch->sources) return; - // Basic sanity (S,G) have no children - if ((ch->sg.src.s_addr != INADDR_ANY) && - (ch->sg.grp.s_addr != INADDR_ANY)) - return; - - for (ALL_LIST_ELEMENTS_RO (pim_ifp->pim_ifchannel_list, ch_node, child)) + while (!list_isempty (ch->sources)) { - if (child->parent == ch) - child->parent = NULL; + child = listnode_head (ch->sources); + child->parent = NULL; + listnode_delete (ch->sources, child); } } @@ -96,16 +123,15 @@ pim_ifchannel_find_new_children (struct pim_ifchannel *ch) if ((ch->sg.grp.s_addr != INADDR_ANY) && (child->sg.grp.s_addr == ch->sg.grp.s_addr) && (child != ch)) - child->parent = ch; + { + child->parent = ch; + listnode_add_sort (ch->sources, child); + } } } void pim_ifchannel_free(struct pim_ifchannel *ch) { - zassert(!ch->t_ifjoin_expiry_timer); - zassert(!ch->t_ifjoin_prune_pending_timer); - zassert(!ch->t_ifassert_timer); - XFREE(MTYPE_PIM_IFCHANNEL, ch); } @@ -114,7 +140,6 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) struct pim_interface *pim_ifp; pim_ifp = ch->interface->info; - zassert(pim_ifp); /* * When this channel is removed @@ -123,6 +148,9 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) */ pim_ifchannel_remove_children (ch); + if (ch->sources) + list_delete (ch->sources); + if (ch->ifjoin_state != PIM_IFJOIN_NOINFO) { pim_upstream_update_join_desired(ch->upstream); } @@ -134,6 +162,11 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) THREAD_OFF(ch->t_ifjoin_prune_pending_timer); THREAD_OFF(ch->t_ifassert_timer); + if (ch->parent) + { + listnode_delete (ch->parent->sources, ch); + ch->parent = NULL; + } /* notice that listnode_delete() can't be moved into pim_ifchannel_free() because the later is @@ -346,29 +379,24 @@ void pim_ifchannel_delete_on_noinfo(struct interface *ifp) * if we have it. */ static struct pim_ifchannel * -pim_ifchannel_find_parent (struct interface *ifp, - struct prefix_sg *sg) +pim_ifchannel_find_parent (struct pim_ifchannel *ch) { - struct prefix_sg parent_sg = *sg; - - // (*,*) || (S,*) - if (((sg->src.s_addr == INADDR_ANY) && - (sg->grp.s_addr == INADDR_ANY)) || - ((sg->src.s_addr != INADDR_ANY) && - (sg->grp.s_addr == INADDR_ANY))) - return NULL; + struct prefix_sg parent_sg = ch->sg; + struct pim_ifchannel *parent = NULL; // (S,G) - if ((sg->src.s_addr != INADDR_ANY) && - (sg->grp.s_addr != INADDR_ANY)) + if ((parent_sg.src.s_addr != INADDR_ANY) && + (parent_sg.grp.s_addr != INADDR_ANY)) { parent_sg.src.s_addr = INADDR_ANY; - return pim_ifchannel_find (ifp, &parent_sg); + parent = pim_ifchannel_find (ch->interface, &parent_sg); + + if (parent) + listnode_add (parent->sources, ch); + return parent; } - // (*,G) -- Not going to find anything currently - parent_sg.grp.s_addr = INADDR_ANY; - return pim_ifchannel_find (ifp, &parent_sg); + return NULL; } struct pim_ifchannel * @@ -384,7 +412,6 @@ pim_ifchannel_add(struct interface *ifp, return ch; pim_ifp = ifp->info; - zassert(pim_ifp); up = pim_upstream_add(sg, NULL, flags, __PRETTY_FUNCTION__); if (!up) { @@ -399,7 +426,8 @@ pim_ifchannel_add(struct interface *ifp, zlog_warn("%s: pim_ifchannel_new() failure for (S,G)=%s on interface %s", __PRETTY_FUNCTION__, pim_str_sg_dump (sg), ifp->name); - + + pim_upstream_del (up, __PRETTY_FUNCTION__); return NULL; } @@ -407,7 +435,15 @@ pim_ifchannel_add(struct interface *ifp, ch->upstream = up; ch->interface = ifp; ch->sg = *sg; - ch->parent = pim_ifchannel_find_parent (ifp, sg); + ch->parent = pim_ifchannel_find_parent (ch); + if (ch->sg.src.s_addr == INADDR_ANY) + { + ch->sources = list_new (); + ch->sources->cmp = (int (*)(void *, void *))pim_ifchannel_compare; + } + else + ch->sources = NULL; + pim_ifchannel_find_new_children (ch); ch->local_ifmembership = PIM_IFMEMBERSHIP_NOINFO; diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index e98abfcf30..7791e6d950 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -76,6 +76,7 @@ struct pim_assert_metric { */ struct pim_ifchannel { struct pim_ifchannel *parent; + struct list *sources; struct prefix_sg sg; struct interface *interface; /* backpointer to interface */ uint32_t flags; @@ -141,4 +142,6 @@ void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch); void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch); void pim_ifchannel_scan_forward_start (struct interface *new_ifp); + +int pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2); #endif /* PIM_IFCHANNEL_H */ From bce0e645214306808047f3ffd321abaa844c3e97 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 7 Nov 2016 15:40:08 -0500 Subject: [PATCH 266/386] pimd: Modify pim_parse_addr_group to use 'struct prefix_sg' Modify the pim_parse_addr_group to use 'struct prefix_sg sg'. This is the first of 2 commits to clean up this parsing to be a bit better. Signed-off-by: Donald Sharp --- pimd/pim_assert.c | 8 ++++---- pimd/pim_join.c | 14 +++++++------- pimd/pim_neighbor.h | 1 + pimd/pim_register.c | 4 +--- pimd/pim_tlv.c | 10 ++++------ pimd/pim_tlv.h | 2 +- 6 files changed, 18 insertions(+), 21 deletions(-) diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index fced5dcd47..ca21786aea 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -226,7 +226,7 @@ int pim_assert_recv(struct interface *ifp, struct in_addr src_addr, uint8_t *buf, int buf_size) { - struct prefix msg_group_addr; + struct prefix_sg sg; struct prefix msg_source_addr; struct pim_assert_metric msg_metric; int offset; @@ -241,7 +241,7 @@ int pim_assert_recv(struct interface *ifp, /* Parse assert group addr */ - offset = pim_parse_addr_group (&msg_group_addr, curr, curr_size); + offset = pim_parse_addr_group (&sg, curr, curr_size); if (offset < 1) { char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); @@ -301,7 +301,7 @@ int pim_assert_recv(struct interface *ifp, char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", src_addr, neigh_str, sizeof(neigh_str)); pim_inet4_dump("", msg_source_addr.u.prefix4, source_str, sizeof(source_str)); - pim_inet4_dump("", msg_group_addr.u.prefix4, group_str, sizeof(group_str)); + pim_inet4_dump("", sg.grp, group_str, sizeof(group_str)); zlog_debug("%s: from %s on %s: (S,G)=(%s,%s) pref=%u metric=%u rpt_bit=%u", __PRETTY_FUNCTION__, neigh_str, ifp->name, source_str, group_str, @@ -314,7 +314,7 @@ int pim_assert_recv(struct interface *ifp, return dispatch_assert(ifp, msg_source_addr.u.prefix4, - msg_group_addr.u.prefix4, + sg.grp, msg_metric); } diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 2dc9d91529..15d73fd1bd 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -301,14 +301,14 @@ int pim_joinprune_recv(struct interface *ifp, /* Scan groups */ for (group = 0; group < msg_num_groups; ++group) { - struct prefix msg_group_addr; + struct prefix_sg sg; struct prefix msg_source_addr; uint8_t msg_source_flags; uint16_t msg_num_joined_sources; uint16_t msg_num_pruned_sources; int source; - addr_offset = pim_parse_addr_group (&msg_group_addr, + addr_offset = pim_parse_addr_group (&sg, buf, pastend - buf); if (addr_offset < 1) { return -5; @@ -337,11 +337,11 @@ int pim_joinprune_recv(struct interface *ifp, pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); pim_inet4_dump("", msg_upstream_addr.u.prefix4, upstream_str, sizeof(upstream_str)); - pim_inet4_dump("", msg_group_addr.u.prefix4, + pim_inet4_dump("", sg.grp, group_str, sizeof(group_str)); - zlog_warn("%s: join/prune upstream=%s group=%s/%d join_src=%d prune_src=%d from %s on %s", + zlog_warn("%s: join/prune upstream=%s group=%s/32 join_src=%d prune_src=%d from %s on %s", __PRETTY_FUNCTION__, - upstream_str, group_str, msg_group_addr.prefixlen, + upstream_str, group_str, msg_num_joined_sources, msg_num_pruned_sources, src_str, ifp->name); } @@ -359,7 +359,7 @@ int pim_joinprune_recv(struct interface *ifp, recv_join(ifp, neigh, msg_holdtime, msg_upstream_addr.u.prefix4, - msg_group_addr.u.prefix4, + sg.grp, msg_source_addr.u.prefix4, msg_source_flags); } @@ -377,7 +377,7 @@ int pim_joinprune_recv(struct interface *ifp, recv_prune(ifp, neigh, msg_holdtime, msg_upstream_addr.u.prefix4, - msg_group_addr.u.prefix4, + sg.grp, msg_source_addr.u.prefix4, msg_source_flags); } diff --git a/pimd/pim_neighbor.h b/pimd/pim_neighbor.h index 3f5a121d4c..b5bd5f6244 100644 --- a/pimd/pim_neighbor.h +++ b/pimd/pim_neighbor.h @@ -26,6 +26,7 @@ #include "if.h" #include "linklist.h" +#include "prefix.h" #include "pim_tlv.h" diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 017d21b1b7..229232fde4 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -102,17 +102,15 @@ pim_register_stop_recv (uint8_t *buf, int buf_size) { struct pim_upstream *upstream = NULL; struct prefix source; - struct prefix group; struct prefix_sg sg; int l; - l = pim_parse_addr_group (&group, buf, buf_size); + l = pim_parse_addr_group (&sg, buf, buf_size); buf += l; buf_size -= l; pim_parse_addr_ucast (&source, buf, buf_size); memset (&sg, 0, sizeof (struct prefix_sg)); sg.src = source.u.prefix4; - sg.grp = group.u.prefix4; if (PIM_DEBUG_PIM_REG) { diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index d083cd8f40..3d48c05afc 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -509,7 +509,7 @@ pim_parse_addr_ucast (struct prefix *p, } int -pim_parse_addr_group (struct prefix *p, +pim_parse_addr_group (struct prefix_sg *sg, const uint8_t *buf, int buf_size) { @@ -551,17 +551,15 @@ pim_parse_addr_group (struct prefix *p, return -3; } - p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */ - memcpy(&p->u.prefix4, addr, sizeof(struct in_addr)); - p->prefixlen = mask_len; + memcpy(&sg->grp.s_addr, addr, sizeof(struct in_addr)); addr += sizeof(struct in_addr); break; default: { - zlog_warn("%s: unknown group address encoding family=%d from", - __PRETTY_FUNCTION__, family); + zlog_warn("%s: unknown group address encoding family=%d mask_len=%d from", + __PRETTY_FUNCTION__, family, mask_len); return -4; } } diff --git a/pimd/pim_tlv.h b/pimd/pim_tlv.h index 3f1b7a34e7..ee890d2895 100644 --- a/pimd/pim_tlv.h +++ b/pimd/pim_tlv.h @@ -116,7 +116,7 @@ int pim_encode_addr_group (uint8_t *buf, afi_t afi, int bidir, int scope, struct int pim_parse_addr_ucast (struct prefix *p, const uint8_t *buf, int buf_size); -int pim_parse_addr_group (struct prefix *p, +int pim_parse_addr_group (struct prefix_sg *sg, const uint8_t *buf, int buf_size); int pim_parse_addr_source(struct prefix *p, From a7762e076597867bb75c8a60fb184f924035ed2e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 7 Nov 2016 15:45:40 -0500 Subject: [PATCH 267/386] pimd: Modify pim_parse_addr_source to use 'struct prefix_sg' Modify the pim_parse_addr_source function to take a 'struct prefix_sg' and to fill in the src data. Signed-off-by: Donald Sharp --- pimd/pim_join.c | 9 ++++----- pimd/pim_tlv.c | 10 ++++------ pimd/pim_tlv.h | 2 +- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 15d73fd1bd..3185b60108 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -302,7 +302,6 @@ int pim_joinprune_recv(struct interface *ifp, /* Scan groups */ for (group = 0; group < msg_num_groups; ++group) { struct prefix_sg sg; - struct prefix msg_source_addr; uint8_t msg_source_flags; uint16_t msg_num_joined_sources; uint16_t msg_num_pruned_sources; @@ -348,7 +347,7 @@ int pim_joinprune_recv(struct interface *ifp, /* Scan joined sources */ for (source = 0; source < msg_num_joined_sources; ++source) { - addr_offset = pim_parse_addr_source (&msg_source_addr, + addr_offset = pim_parse_addr_source (&sg, &msg_source_flags, buf, pastend - buf); if (addr_offset < 1) { @@ -360,13 +359,13 @@ int pim_joinprune_recv(struct interface *ifp, recv_join(ifp, neigh, msg_holdtime, msg_upstream_addr.u.prefix4, sg.grp, - msg_source_addr.u.prefix4, + sg.src, msg_source_flags); } /* Scan pruned sources */ for (source = 0; source < msg_num_pruned_sources; ++source) { - addr_offset = pim_parse_addr_source (&msg_source_addr, + addr_offset = pim_parse_addr_source (&sg, &msg_source_flags, buf, pastend - buf); if (addr_offset < 1) { @@ -378,7 +377,7 @@ int pim_joinprune_recv(struct interface *ifp, recv_prune(ifp, neigh, msg_holdtime, msg_upstream_addr.u.prefix4, sg.grp, - msg_source_addr.u.prefix4, + sg.src, msg_source_flags); } diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index 3d48c05afc..dcded95035 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -568,7 +568,7 @@ pim_parse_addr_group (struct prefix_sg *sg, } int -pim_parse_addr_source(struct prefix *p, +pim_parse_addr_source(struct prefix_sg *sg, uint8_t *flags, const uint8_t *buf, int buf_size) @@ -612,9 +612,7 @@ pim_parse_addr_source(struct prefix *p, return -3; } - p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */ - memcpy(&p->u.prefix4, addr, sizeof(struct in_addr)); - p->prefixlen = mask_len; + memcpy(&sg->src, addr, sizeof(struct in_addr)); /* RFC 4601: 4.9.1 Encoded Source and Group Address Formats @@ -626,9 +624,9 @@ pim_parse_addr_source(struct prefix *p, and 128 for IPv6 native). A router SHOULD ignore any messages received with any other mask length. */ - if (p->prefixlen != 32) { + if (mask_len != 32) { zlog_warn("%s: IPv4 bad source address mask: %d", - __PRETTY_FUNCTION__, p->prefixlen); + __PRETTY_FUNCTION__, mask_len); return -4; } diff --git a/pimd/pim_tlv.h b/pimd/pim_tlv.h index ee890d2895..ee7692ab80 100644 --- a/pimd/pim_tlv.h +++ b/pimd/pim_tlv.h @@ -119,7 +119,7 @@ int pim_parse_addr_ucast (struct prefix *p, int pim_parse_addr_group (struct prefix_sg *sg, const uint8_t *buf, int buf_size); -int pim_parse_addr_source(struct prefix *p, +int pim_parse_addr_source(struct prefix_sg *sg, uint8_t *flags, const uint8_t *buf, int buf_size); From cf4ea1c4e5170023f5323b0d90d312eb2fe3aed5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 7 Nov 2016 15:51:18 -0500 Subject: [PATCH 268/386] pimd: use 'struct prefix_sg' for recv_join and _prune When we read in the S,G from the join/prune message, convert it into a 'struct prefix_sg' at an earlier point in time. Signed-off-by: Donald Sharp --- pimd/pim_join.c | 56 ++++++++++++++++++------------------------------- 1 file changed, 20 insertions(+), 36 deletions(-) diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 3185b60108..8ef2cada87 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -56,16 +56,9 @@ static void recv_join(struct interface *ifp, struct pim_neighbor *neigh, uint16_t holdtime, struct in_addr upstream, - struct in_addr group, - struct in_addr source, + struct prefix_sg *sg, uint8_t source_flags) { - struct prefix_sg sg; - - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = source; - sg.grp = group; - if (PIM_DEBUG_PIM_TRACE) { char up_str[INET_ADDRSTRLEN]; char neigh_str[INET_ADDRSTRLEN]; @@ -73,7 +66,7 @@ static void recv_join(struct interface *ifp, pim_inet4_dump("", neigh->source_addr, neigh_str, sizeof(neigh_str)); zlog_warn("%s: join (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), + pim_str_sg_dump (sg), source_flags & PIM_RPT_BIT_MASK, source_flags & PIM_WILDCARD_BIT_MASK, up_str, holdtime, neigh_str, ifp->name); @@ -86,25 +79,25 @@ static void recv_join(struct interface *ifp, if ((source_flags & PIM_RPT_BIT_MASK) && (source_flags & PIM_WILDCARD_BIT_MASK)) { - struct pim_rpf *rp = RP (sg.grp); + struct pim_rpf *rp = RP (sg->grp); /* * If the RP sent in the message is not * our RP for the group, drop the message */ - if (sg.src.s_addr != rp->rpf_addr.u.prefix4.s_addr) + if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr) return; - sg.src.s_addr = INADDR_ANY; + sg->src.s_addr = INADDR_ANY; } /* Restart join expiry timer */ pim_ifchannel_join_add(ifp, neigh->source_addr, upstream, - &sg, source_flags, holdtime); + sg, source_flags, holdtime); - if (sg.src.s_addr == INADDR_ANY) + if (sg->src.s_addr == INADDR_ANY) { - struct pim_upstream *up = pim_upstream_find (&sg); + struct pim_upstream *up = pim_upstream_find (sg); struct pim_upstream *child; struct listnode *up_node; @@ -125,7 +118,7 @@ static void recv_join(struct interface *ifp, if (PIM_DEBUG_PIM_TRACE) zlog_debug("%s %s: Join(S,G)=%s from %s", __FILE__, __PRETTY_FUNCTION__, - buff, pim_str_sg_dump (&sg)); + buff, pim_str_sg_dump (sg)); if (pim_upstream_evaluate_join_desired (child)) { @@ -141,16 +134,9 @@ static void recv_prune(struct interface *ifp, struct pim_neighbor *neigh, uint16_t holdtime, struct in_addr upstream, - struct in_addr group, - struct in_addr source, + struct prefix_sg *sg, uint8_t source_flags) { - struct prefix_sg sg; - - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = source; - sg.grp = group; - if (PIM_DEBUG_PIM_TRACE) { char up_str[INET_ADDRSTRLEN]; char neigh_str[INET_ADDRSTRLEN]; @@ -158,7 +144,7 @@ static void recv_prune(struct interface *ifp, pim_inet4_dump("", neigh->source_addr, neigh_str, sizeof(neigh_str)); zlog_warn("%s: prune (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), + pim_str_sg_dump (sg), source_flags & PIM_RPT_BIT_MASK, source_flags & PIM_WILDCARD_BIT_MASK, up_str, holdtime, neigh_str, ifp->name); @@ -167,20 +153,20 @@ static void recv_prune(struct interface *ifp, if ((source_flags & PIM_RPT_BIT_MASK) && (source_flags & PIM_WILDCARD_BIT_MASK)) { - struct pim_rpf *rp = RP (sg.grp); + struct pim_rpf *rp = RP (sg->grp); // Ignoring Prune *,G's at the moment. - if (sg.src.s_addr != rp->rpf_addr.u.prefix4.s_addr) + if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr) return; - sg.src.s_addr = INADDR_ANY; + sg->src.s_addr = INADDR_ANY; } - pim_ifchannel_prune(ifp, upstream, &sg, source_flags, holdtime); + pim_ifchannel_prune(ifp, upstream, sg, source_flags, holdtime); - if (sg.src.s_addr == INADDR_ANY) + if (sg->src.s_addr == INADDR_ANY) { - struct pim_upstream *up = pim_upstream_find (&sg); + struct pim_upstream *up = pim_upstream_find (sg); struct pim_upstream *child; struct listnode *up_node; @@ -203,7 +189,7 @@ static void recv_prune(struct interface *ifp, strcpy (buff, pim_str_sg_dump (&child->sg)); zlog_debug("%s %s: Prune(S,G)=%s from %s", __FILE__, __PRETTY_FUNCTION__, - buff, pim_str_sg_dump (&sg)); + buff, pim_str_sg_dump (sg)); } if (!c_oil) continue; @@ -358,8 +344,7 @@ int pim_joinprune_recv(struct interface *ifp, recv_join(ifp, neigh, msg_holdtime, msg_upstream_addr.u.prefix4, - sg.grp, - sg.src, + &sg, msg_source_flags); } @@ -376,8 +361,7 @@ int pim_joinprune_recv(struct interface *ifp, recv_prune(ifp, neigh, msg_holdtime, msg_upstream_addr.u.prefix4, - sg.grp, - sg.src, + &sg, msg_source_flags); } From 45b0c8f3cfb4981a2b32d5115ca68ecac1184e93 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 7 Nov 2016 19:43:13 -0500 Subject: [PATCH 269/386] pimd: Don't delete ifchannel if expiry timer is still running. Don't delete the ifchannel if the expiry timer is still running. We might need to add the prune pending timer as well? Not sure Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 835ea424c5..5838bfa63e 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -198,7 +198,8 @@ pim_ifchannel_delete_all (struct interface *ifp) static void delete_on_noinfo(struct pim_ifchannel *ch) { if (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO && - ch->ifjoin_state == PIM_IFJOIN_NOINFO) + ch->ifjoin_state == PIM_IFJOIN_NOINFO && + ch->t_ifjoin_expiry_timer == NULL) pim_ifchannel_delete(ch); } From 11757d7b98876be9c3a21e04dcecd93113081ffa Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 8 Nov 2016 07:55:51 -0500 Subject: [PATCH 270/386] pimd: 'show ip pim join json' add by src not grp If you add to the json by grp, if you have multiple ifchannels for that group, on the the first one will be displayed. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 23e8ebd77c..8120d32132 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1142,7 +1142,7 @@ static void pim_show_join(struct vty *vty, u_char uj) json_object_string_add(json_row, "expire", expire); json_object_string_add(json_row, "prune", prune); json_object_string_add(json_row, "channelJoinName", pim_ifchannel_ifjoin_name(ch->ifjoin_state)); - json_object_object_add(json_iface, ch_grp_str, json_row); + json_object_object_add(json_iface, ch_src_str, json_row); } else { vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s%s", From 637a61fa2b556f38f861e2d3fd2ba4110ddaef99 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 8 Nov 2016 08:00:02 -0500 Subject: [PATCH 271/386] pimd: Add ability to know if ifchannel is (S,G,rpt) Add ability to track (S,G,rpt) ifchannel prunes. Add ability to display this data in json. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 2 ++ pimd/pim_ifchannel.h | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 8120d32132..fe8a113b4f 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1142,6 +1142,8 @@ static void pim_show_join(struct vty *vty, u_char uj) json_object_string_add(json_row, "expire", expire); json_object_string_add(json_row, "prune", prune); json_object_string_add(json_row, "channelJoinName", pim_ifchannel_ifjoin_name(ch->ifjoin_state)); + if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) + json_object_int_add(json_row, "SGRpt", 1); json_object_object_add(json_iface, ch_src_str, json_row); } else { diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 7791e6d950..908d27fd68 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -71,6 +71,14 @@ struct pim_assert_metric { #define PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(flags) ((flags) |= PIM_IF_FLAG_MASK_ASSERT_TRACKING_DESIRED) #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) + */ +#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) +#define PIM_IF_FLAG_SET_S_G_RPT(flags) ((flags) |= PIM_IF_FLAG_MASK_S_G_RPT) +#define PIM_IF_FLAG_UNSET_S_G_RPT(flags) ((flags) &= ~PIM_IF_FLAG_MASK_S_G_RPT) + /* Per-interface (S,G) state */ From 5349cf9a09288e90cc30c43c0ff448a053dd2fe9 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 8 Nov 2016 12:53:28 -0500 Subject: [PATCH 272/386] pimd: Fix 'show ip pim join json' output When we have multiple incoming joins for a single group on a interface, we need to allow proper output. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index fe8a113b4f..5b5bf8235d 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1090,6 +1090,7 @@ static void pim_show_join(struct vty *vty, u_char uj) json_object *json = NULL; json_object *json_iface = NULL; json_object *json_row = NULL; + json_object *json_grp = NULL; now = pim_time_monotonic_sec(); @@ -1144,8 +1145,16 @@ static void pim_show_join(struct vty *vty, u_char uj) json_object_string_add(json_row, "channelJoinName", pim_ifchannel_ifjoin_name(ch->ifjoin_state)); if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) json_object_int_add(json_row, "SGRpt", 1); - json_object_object_add(json_iface, ch_src_str, json_row); + json_object_object_get_ex(json_iface, ch_grp_str, &json_grp); + if (!json_grp) + { + json_grp = json_object_new_object(); + json_object_object_add(json_grp, ch_src_str, json_row); + json_object_object_add(json_iface, ch_grp_str, json_grp); + } + else + json_object_object_add(json_grp, ch_src_str, json_row); } else { vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s%s", ch->interface->name, From 53e39e140d288e429f3c2c73db056a5bc4ac4659 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 8 Nov 2016 19:40:08 -0500 Subject: [PATCH 273/386] pimd: Ensure 'struct prefix sg' is inited in right order When we called pim_parse_addr_group, don't reinitialize the 'struct prefix_sg' *after* we've parsed the group. Ensure in other places that we do this work, we initialize prior as well. Ticket: CM-13510 Signed-off-by: Donald Sharp --- pimd/pim_assert.c | 1 + pimd/pim_join.c | 1 + pimd/pim_register.c | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index ca21786aea..29a241b277 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -241,6 +241,7 @@ int pim_assert_recv(struct interface *ifp, /* Parse assert group addr */ + memset (&sg, 0, sizeof (struct prefix_sg)); offset = pim_parse_addr_group (&sg, curr, curr_size); if (offset < 1) { char src_str[INET_ADDRSTRLEN]; diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 8ef2cada87..53c91ab4af 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -293,6 +293,7 @@ int pim_joinprune_recv(struct interface *ifp, uint16_t msg_num_pruned_sources; int source; + memset (&sg, 0, sizeof (struct prefix_sg)); addr_offset = pim_parse_addr_group (&sg, buf, pastend - buf); if (addr_offset < 1) { diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 229232fde4..e012115e37 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -105,11 +105,11 @@ pim_register_stop_recv (uint8_t *buf, int buf_size) struct prefix_sg sg; int l; + memset (&sg, 0, sizeof (struct prefix_sg)); l = pim_parse_addr_group (&sg, buf, buf_size); buf += l; buf_size -= l; pim_parse_addr_ucast (&source, buf, buf_size); - memset (&sg, 0, sizeof (struct prefix_sg)); sg.src = source.u.prefix4; if (PIM_DEBUG_PIM_REG) From 220d8a49e6fcadae3dbb7f60cf88edca819b8d65 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 8 Nov 2016 15:26:48 -0500 Subject: [PATCH 274/386] pimd: Add Handler for Receive (*,G) join for (S,G,rpt) According to Figure 5( Downstream per-interface (S,G,rpt) state when we receive a (*,G) we need to move (S,G,rpt) children of the (*,G) into different states. This implements that. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 64 +++++++++++++++++++++++++++++++++++++++----- pimd/pim_ifchannel.h | 1 + pimd/pim_join.c | 12 ++++++++- 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 5838bfa63e..3be88553d0 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -725,19 +725,21 @@ void pim_ifchannel_join_add(struct interface *ifp, THREAD_OFF(ch->t_ifjoin_expiry_timer); break; case PIM_IFJOIN_PRUNE: - zlog_debug ("PIM_IFJOIN_PRUNE: NOT PROGRAMMED YET"); + if (source_flags & PIM_ENCODE_RPT_BIT) + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); break; case PIM_IFJOIN_PRUNE_PENDING: - zassert(!ch->t_ifjoin_expiry_timer); - zassert(ch->t_ifjoin_prune_pending_timer); - THREAD_OFF(ch->t_ifjoin_prune_pending_timer); - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN); + if (source_flags & PIM_ENCODE_RPT_BIT) + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); + else + { + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN); + } break; case PIM_IFJOIN_PRUNE_TMP: - zlog_debug ("PIM_IFJOIN_PRUNE_TMP: Not Programmed yet"); break; case PIM_IFJOIN_PRUNE_PENDING_TMP: - zlog_debug ("PIM_IFJOIN_PRUNE_PENDING_TMP: Not Programmed yet"); break; } @@ -1072,3 +1074,51 @@ pim_ifchannel_scan_forward_start (struct interface *new_ifp) } } } + +/* + * Downstream per-interface (S,G,rpt) state machine + * states that we need to move (S,G,rpt) items + * into different states at the start of the + * reception of a *,G join as well, when + * we get End of Message + */ +void +pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom) +{ + struct pim_ifchannel *child; + struct listnode *ch_node; + + if (PIM_DEBUG_PIM_TRACE) + zlog_debug ("%s: %s %s eom: %d", __PRETTY_FUNCTION__, + pim_ifchannel_ifjoin_name(ch->ifjoin_state), + pim_str_sg_dump(&ch->sg), eom); + if (!ch->sources) + return; + + for (ALL_LIST_ELEMENTS_RO (ch->sources, ch_node, child)) + { + if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) + continue; + + switch (child->ifjoin_state) + { + case PIM_IFJOIN_NOINFO: + case PIM_IFJOIN_JOIN: + break; + case PIM_IFJOIN_PRUNE: + if (!eom) + child->ifjoin_state = PIM_IFJOIN_PRUNE_TMP; + break; + case PIM_IFJOIN_PRUNE_PENDING: + if (!eom) + child->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING_TMP; + break; + case PIM_IFJOIN_PRUNE_TMP: + case PIM_IFJOIN_PRUNE_PENDING_TMP: + if (eom) + child->ifjoin_state = PIM_IFJOIN_NOINFO; + break; + + } + } +} diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 908d27fd68..b640cfd4df 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -150,6 +150,7 @@ void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch); void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch); void pim_ifchannel_scan_forward_start (struct interface *new_ifp); +void pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom); int pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2); #endif /* PIM_IFCHANNEL_H */ diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 53c91ab4af..7f5c46004a 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -292,6 +292,7 @@ int pim_joinprune_recv(struct interface *ifp, uint16_t msg_num_joined_sources; uint16_t msg_num_pruned_sources; int source; + struct pim_ifchannel *ch = NULL; memset (&sg, 0, sizeof (struct prefix_sg)); addr_offset = pim_parse_addr_group (&sg, @@ -347,6 +348,13 @@ int pim_joinprune_recv(struct interface *ifp, msg_upstream_addr.u.prefix4, &sg, msg_source_flags); + + if (sg.src.s_addr == INADDR_ANY) + { + ch = pim_ifchannel_find (ifp, &sg); + if (ch) + pim_ifchannel_set_star_g_join_state (ch, 0); + } } /* Scan pruned sources */ @@ -365,7 +373,9 @@ int pim_joinprune_recv(struct interface *ifp, &sg, msg_source_flags); } - + if (ch) + pim_ifchannel_set_star_g_join_state (ch, 1); + ch = NULL; } /* scan groups */ return 0; From 7f8b8a9af65212217646e3b98cd627fbac10830f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 8 Nov 2016 15:49:28 -0500 Subject: [PATCH 275/386] pimd: Remove unnecessary asserts When we handle the thread arguments, there is no need to assert. As that if they are wrong, we are going down shortly anyways. Signed-off-by: Donald Sharp --- pimd/pim_assert.c | 3 --- pimd/pim_ifchannel.c | 4 ---- pimd/pim_igmp.c | 7 ------- pimd/pim_igmpv3.c | 4 ---- pimd/pim_mroute.c | 3 --- pimd/pim_msdp.c | 8 -------- pimd/pim_neighbor.c | 2 -- pimd/pim_pim.c | 6 ------ pimd/pim_ssmpingd.c | 3 --- pimd/pim_upstream.c | 2 -- pimd/pim_zebra.c | 1 - 11 files changed, 43 deletions(-) diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index 29a241b277..505d1f1ec1 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -516,12 +516,9 @@ static int on_assert_timer(struct thread *t) struct pim_ifchannel *ch; struct interface *ifp; - zassert(t); ch = THREAD_ARG(t); - zassert(ch); ifp = ch->interface; - zassert(ifp); if (PIM_DEBUG_PIM_TRACE) { zlog_debug("%s: (S,G)=%s timer expired on interface %s", diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 3be88553d0..ca1f2f6b42 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -489,9 +489,7 @@ static int on_ifjoin_expiry_timer(struct thread *t) { struct pim_ifchannel *ch; - zassert(t); ch = THREAD_ARG(t); - zassert(ch); ch->t_ifjoin_expiry_timer = NULL; @@ -510,9 +508,7 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) struct interface *ifp; struct pim_interface *pim_ifp; - zassert(t); ch = THREAD_ARG(t); - zassert(ch); ch->t_ifjoin_prune_pending_timer = NULL; diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 0ce12f1ad7..f47028b2ba 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -153,9 +153,7 @@ static int pim_igmp_other_querier_expire(struct thread *t) { struct igmp_sock *igmp; - zassert(t); igmp = THREAD_ARG(t); - zassert(igmp); zassert(igmp->t_other_querier_timer); zassert(!igmp->t_igmp_query_timer); @@ -598,11 +596,8 @@ static int pim_igmp_general_query(struct thread *t) struct pim_interface *pim_ifp; int query_buf_size; - zassert(t); - igmp = THREAD_ARG(t); - zassert(igmp); zassert(igmp->interface); zassert(igmp->interface->info); @@ -898,9 +893,7 @@ static int igmp_group_timer(struct thread *t) { struct igmp_group *group; - zassert(t); group = THREAD_ARG(t); - zassert(group); if (PIM_DEBUG_IGMP_TRACE) { char group_str[INET_ADDRSTRLEN]; diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index 706f708dd1..2e23cdb10f 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -115,9 +115,7 @@ static int igmp_source_timer(struct thread *t) struct igmp_source *source; struct igmp_group *group; - zassert(t); source = THREAD_ARG(t); - zassert(source); group = source->source_group; @@ -1245,9 +1243,7 @@ static int igmp_group_retransmit(struct thread *t) int num_retransmit_sources_left; int send_with_sflag_set; /* boolean */ - zassert(t); group = THREAD_ARG(t); - zassert(group); if (PIM_DEBUG_IGMP_TRACE) { char group_str[INET_ADDRSTRLEN]; diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 9cd323a2d0..57dc5550db 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -528,11 +528,8 @@ static int mroute_read(struct thread *t) int fd; int result; - zassert(t); - zassert(!THREAD_ARG(t)); fd = THREAD_FD(t); - zassert(fd == qpim_mroute_socket_fd); result = mroute_read_msg(fd); diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 9ca9244823..d8237469c8 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -106,9 +106,7 @@ pim_msdp_sa_state_timer_cb(struct thread *t) { struct pim_msdp_sa *sa; - zassert(t); sa = THREAD_ARG(t); - zassert(sa); if (PIM_DEBUG_MSDP_EVENTS) { pim_msdp_sa_timer_expiry_log(sa, "state"); @@ -595,9 +593,7 @@ pim_msdp_peer_hold_timer_cb(struct thread *t) { struct pim_msdp_peer *mp; - zassert(t); mp = THREAD_ARG(t); - zassert(mp); if (PIM_DEBUG_MSDP_EVENTS) { pim_msdp_peer_timer_expiry_log(mp, "hold"); @@ -630,9 +626,7 @@ pim_msdp_peer_ka_timer_cb(struct thread *t) { struct pim_msdp_peer *mp; - zassert(t); mp = THREAD_ARG(t); - zassert(mp); if (PIM_DEBUG_MSDP_EVENTS) { pim_msdp_peer_timer_expiry_log(mp, "ka"); @@ -695,9 +689,7 @@ pim_msdp_peer_cr_timer_cb(struct thread *t) { struct pim_msdp_peer *mp; - zassert(t); mp = THREAD_ARG(t); - zassert(mp); if (PIM_DEBUG_MSDP_EVENTS) { pim_msdp_peer_timer_expiry_log(mp, "connect-retry"); diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index abca609421..1b58b98502 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -211,9 +211,7 @@ static int on_neighbor_timer(struct thread *t) struct interface *ifp; char msg[100]; - zassert(t); neigh = THREAD_ARG(t); - zassert(neigh); ifp = neigh->interface; diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 1e71b0ad78..80e69e276b 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -295,11 +295,7 @@ static int pim_sock_read(struct thread *t) ifindex_t ifindex = -1; int result = -1; /* defaults to bad */ - zassert(t); - ifp = THREAD_ARG(t); - zassert(ifp); - fd = THREAD_FD(t); pim_ifp = ifp->info; @@ -695,9 +691,7 @@ static int on_pim_hello_send(struct thread *t) struct pim_interface *pim_ifp; struct interface *ifp; - zassert(t); ifp = THREAD_ARG(t); - zassert(ifp); pim_ifp = ifp->info; diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c index 3d08552de8..d308d80e3a 100644 --- a/pimd/pim_ssmpingd.c +++ b/pimd/pim_ssmpingd.c @@ -315,10 +315,7 @@ static int ssmpingd_sock_read(struct thread *t) int sock_fd; int result; - zassert(t); - ss = THREAD_ARG(t); - zassert(ss); sock_fd = THREAD_FD(t); zassert(sock_fd == ss->sock_fd); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 3cfe0887ef..b3b6fdce21 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -243,9 +243,7 @@ static int on_join_timer(struct thread *t) { struct pim_upstream *up; - zassert(t); up = THREAD_ARG(t); - zassert(up); up->t_join_timer = NULL; diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index a92d55b2af..815fbbd2d3 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -531,7 +531,6 @@ void pim_scan_oil() static int on_rpf_cache_refresh(struct thread *t) { - zassert(t); zassert(qpim_rpf_cache_refresher); qpim_rpf_cache_refresher = 0; From b76d6e718e0f28d1ce7fcd23df57979c3e5abb49 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 9 Nov 2016 08:30:04 -0500 Subject: [PATCH 276/386] pimd: Modify downstream JP state to take into account all states When we make a decision about downstream state let's take into account all states. Signed-off-by: Donald Sharp --- pimd/pim_macro.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/pimd/pim_macro.c b/pimd/pim_macro.c index 177de66673..da12146be1 100644 --- a/pimd/pim_macro.c +++ b/pimd/pim_macro.c @@ -42,7 +42,20 @@ */ static int downstream_jpstate_isjoined(const struct pim_ifchannel *ch) { - return (ch->ifjoin_state != PIM_IFJOIN_NOINFO); + switch (ch->ifjoin_state) + { + case PIM_IFJOIN_NOINFO: + case PIM_IFJOIN_PRUNE: + case PIM_IFJOIN_PRUNE_TMP: + case PIM_IFJOIN_PRUNE_PENDING_TMP: + return 0; + break; + case PIM_IFJOIN_JOIN: + case PIM_IFJOIN_PRUNE_PENDING: + return 1; + break; + } + return 0; } /* From b72f79a92b7e858b0eccb6f65d85a6e16a6f0db8 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 10 Nov 2016 07:35:02 -0500 Subject: [PATCH 277/386] pimd: Fix possible crash when leaving a channel When leaving a channel, there exists a possibility that we have not created the channel oil yet. Ensure that we have channel oil before dereferencing Ticket: CM-13522 Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index ca1f2f6b42..b3b2748359 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -905,7 +905,7 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, buff, ifp->name, pim_str_sg_dump (&child->sg)); } - if (!pim_upstream_evaluate_join_desired (child)) + if (c_oil && !pim_upstream_evaluate_join_desired (child)) pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); /* @@ -913,7 +913,7 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, * has output here then the *,G was supplying the implied * if channel. So remove it. */ - if (!chchannel && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) + 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); } } From ce0ddb4e79d28addd02a7156ef97cd45eaaa1fc1 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 10 Nov 2016 09:41:28 -0500 Subject: [PATCH 278/386] pimd: Write pim_upstream_empty_inherited_olist A empty inherited_olist implies that we have no outgoing interfaces. Signed-off-by: Donald Sharp --- pimd/pim_oil.c | 21 +++++++++++++++++++++ pimd/pim_oil.h | 1 + pimd/pim_upstream.c | 3 +-- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 9416503204..acebd6ace6 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -432,3 +432,24 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, return 0; } + +int +pim_channel_oil_empty (struct channel_oil *c_oil) +{ + static uint32_t zero[MAXVIFS]; + static int inited = 0; + + if (!c_oil) + return 1; + /* + * Not sure that this is necessary, but I would rather ensure + * that this works. + */ + if (!inited) + { + memset(&zero, 0, sizeof(uint32_t) * MAXVIFS); + inited = 1; + } + + return !memcmp(c_oil->oif_flags, zero, MAXVIFS * sizeof(uint32_t)); +} diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index 0c99afb625..939ef4b3fc 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -95,4 +95,5 @@ int pim_channel_del_oif (struct channel_oil *c_oil, struct interface *oif, uint32_t proto_mask); +int pim_channel_oil_empty (struct channel_oil *c_oil); #endif /* PIM_OIL_H */ diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index b3b6fdce21..fe6e81ef63 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1242,8 +1242,7 @@ pim_upstream_inherited_olist (struct pim_upstream *up) int pim_upstream_empty_inherited_olist (struct pim_upstream *up) { - // FIXME: Currently this is not implemented - return 0; + return pim_channel_oil_empty (up->channel_oil); } /* From 1405c852fc8545266ed775f18a3ed97e09200eb5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 10 Nov 2016 10:25:36 -0500 Subject: [PATCH 279/386] pimd: Add code to handle pim prune(S,G) with sptbit Add some more code to handle the prune(S,G) with the sptbit set. Turns this ifchannel into a (S,G,rpt). Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 131 ++++++++++++++++++++++++++----------------- pimd/pim_join.c | 5 +- 2 files changed, 83 insertions(+), 53 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index b3b2748359..0da3abe99e 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -493,8 +493,6 @@ static int on_ifjoin_expiry_timer(struct thread *t) ch->t_ifjoin_expiry_timer = NULL; - zassert(ch->ifjoin_state == PIM_IFJOIN_JOIN); - ifjoin_to_noinfo(ch); /* ch may have been deleted */ @@ -753,6 +751,7 @@ void pim_ifchannel_prune(struct interface *ifp, uint16_t holdtime) { struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; int jp_override_interval_msec; if (nonlocal_upstream(0 /* prune */, ifp, upstream, @@ -773,49 +772,82 @@ void pim_ifchannel_prune(struct interface *ifp, if (!ch) return; + pim_ifp = ifp->info; + switch (ch->ifjoin_state) { case PIM_IFJOIN_NOINFO: + if (source_flags & PIM_ENCODE_RPT_BIT) + { + PIM_IF_FLAG_SET_S_G_RPT(ch->flags); + ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; + if (listcount(pim_ifp->pim_neighbor_list) > 1) + jp_override_interval_msec = pim_if_jp_override_interval_msec(ifp); + else + jp_override_interval_msec = 0; /* schedule to expire immediately */ + /* If we called ifjoin_prune() directly instead, care should + be taken not to use "ch" afterwards since it would be + deleted. */ + + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + THREAD_OFF(ch->t_ifjoin_expiry_timer); + THREAD_TIMER_MSEC_ON(master, ch->t_ifjoin_prune_pending_timer, + on_ifjoin_prune_pending_timer, + ch, jp_override_interval_msec); + THREAD_TIMER_ON(master, ch->t_ifjoin_expiry_timer, + on_ifjoin_expiry_timer, + ch, holdtime); + } + break; case PIM_IFJOIN_PRUNE_PENDING: /* nothing to do */ break; case PIM_IFJOIN_JOIN: - { - struct pim_interface *pim_ifp; + THREAD_OFF(ch->t_ifjoin_expiry_timer); - pim_ifp = ifp->info; + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_PRUNE_PENDING); - zassert(ch->t_ifjoin_expiry_timer); - zassert(!ch->t_ifjoin_prune_pending_timer); - - THREAD_OFF(ch->t_ifjoin_expiry_timer); - - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_PRUNE_PENDING); - - if (listcount(pim_ifp->pim_neighbor_list) > 1) { - jp_override_interval_msec = pim_if_jp_override_interval_msec(ifp); - } - else { - jp_override_interval_msec = 0; /* schedule to expire immediately */ - /* If we called ifjoin_prune() directly instead, care should - be taken not to use "ch" afterwards since it would be - deleted. */ - } - - THREAD_TIMER_MSEC_ON(master, ch->t_ifjoin_prune_pending_timer, - on_ifjoin_prune_pending_timer, - ch, jp_override_interval_msec); - - zassert(!ch->t_ifjoin_expiry_timer); - zassert(ch->t_ifjoin_prune_pending_timer); - } + if (listcount(pim_ifp->pim_neighbor_list) > 1) + jp_override_interval_msec = pim_if_jp_override_interval_msec(ifp); + else + jp_override_interval_msec = 0; /* schedule to expire immediately */ + /* If we called ifjoin_prune() directly instead, care should + be taken not to use "ch" afterwards since it would be + deleted. */ + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + THREAD_TIMER_MSEC_ON(master, ch->t_ifjoin_prune_pending_timer, + on_ifjoin_prune_pending_timer, + ch, jp_override_interval_msec); break; case PIM_IFJOIN_PRUNE: + if (source_flags & PIM_ENCODE_RPT_BIT) + { + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + THREAD_TIMER_ON(master, ch->t_ifjoin_expiry_timer, + on_ifjoin_expiry_timer, + ch, holdtime); + } + break; case PIM_IFJOIN_PRUNE_TMP: + if (source_flags & PIM_ENCODE_RPT_BIT) + { + ch->ifjoin_state = PIM_IFJOIN_PRUNE; + THREAD_OFF(ch->t_ifjoin_expiry_timer); + THREAD_TIMER_ON(master, ch->t_ifjoin_expiry_timer, + on_ifjoin_expiry_timer, + ch, holdtime); + } + break; case PIM_IFJOIN_PRUNE_PENDING_TMP: - zlog_debug ("CASE NOT HANDLED"); + if (source_flags & PIM_ENCODE_RPT_BIT) + { + ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; + THREAD_OFF(ch->t_ifjoin_expiry_timer); + THREAD_TIMER_ON(master, ch->t_ifjoin_expiry_timer, + on_ifjoin_expiry_timer, + ch, holdtime); + } break; } - } void pim_ifchannel_local_membership_add(struct interface *ifp, @@ -1097,24 +1129,23 @@ pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom) continue; switch (child->ifjoin_state) - { - case PIM_IFJOIN_NOINFO: - case PIM_IFJOIN_JOIN: - break; - case PIM_IFJOIN_PRUNE: - if (!eom) - child->ifjoin_state = PIM_IFJOIN_PRUNE_TMP; - break; - case PIM_IFJOIN_PRUNE_PENDING: - if (!eom) - child->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING_TMP; - break; - case PIM_IFJOIN_PRUNE_TMP: - case PIM_IFJOIN_PRUNE_PENDING_TMP: - if (eom) - child->ifjoin_state = PIM_IFJOIN_NOINFO; - break; - - } + { + case PIM_IFJOIN_NOINFO: + case PIM_IFJOIN_JOIN: + break; + case PIM_IFJOIN_PRUNE: + if (!eom) + child->ifjoin_state = PIM_IFJOIN_PRUNE_TMP; + break; + case PIM_IFJOIN_PRUNE_PENDING: + if (!eom) + child->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING_TMP; + break; + case PIM_IFJOIN_PRUNE_TMP: + case PIM_IFJOIN_PRUNE_PENDING_TMP: + if (eom) + child->ifjoin_state = PIM_IFJOIN_NOINFO; + break; + } } } diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 7f5c46004a..42d4a51874 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -127,7 +127,6 @@ static void recv_join(struct interface *ifp, } } } - } static void recv_prune(struct interface *ifp, @@ -352,8 +351,8 @@ int pim_joinprune_recv(struct interface *ifp, if (sg.src.s_addr == INADDR_ANY) { ch = pim_ifchannel_find (ifp, &sg); - if (ch) - pim_ifchannel_set_star_g_join_state (ch, 0); + if (ch) + pim_ifchannel_set_star_g_join_state (ch, 0); } } From a2012b80b1e045c94e6c93a2f959df75d9ce1fa3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 10 Nov 2016 13:58:40 -0500 Subject: [PATCH 280/386] lib: Slight Optimization of thread handling. This commit does these things: 1) Make thread_add_unuse own the setting of THREAD_UNUSED. 2) Move thread->hist finding to to thread_get. We are storing the thread->hist even when the thread is on the unused. This means that we check to see if the funcname or func have changed and we get new history. Else we've probably just retrieved the last unused which has the same func/funcanme. This is a common practice to do THREAD_OFF/THREAD_ON in quick succession. Signed-off-by: Donald Sharp next == NULL); assert (thread->prev == NULL); - assert (thread->type == THREAD_UNUSED); + + thread->type = THREAD_UNUSED; thread_list_add (&m->unuse, thread); } @@ -693,6 +694,7 @@ thread_get (struct thread_master *m, u_char type, int (*func) (struct thread *), void *arg, debugargdef) { struct thread *thread = thread_trim_head (&m->unuse); + struct cpu_thread_history tmp; if (! thread) { @@ -702,11 +704,29 @@ thread_get (struct thread_master *m, u_char type, thread->type = type; thread->add_type = type; thread->master = m; - thread->func = func; thread->arg = arg; thread->index = -1; thread->yield = THREAD_YIELD_TIME_SLOT; /* default */ + /* + * So if the passed in funcname is not what we have + * stored that means the thread->hist needs to be + * updated. We keep the last one around in unused + * under the assumption that we are probably + * going to immediately allocate the same + * type of thread. + * This hopefully saves us some serious + * hash_get lookups. + */ + if (thread->funcname != funcname || + thread->func != func) + { + tmp.func = func; + tmp.funcname = funcname; + thread->hist = hash_get (cpu_record, &tmp, + (void * (*) (void *))cpu_record_hash_alloc); + } + thread->func = func; thread->funcname = funcname; thread->schedfrom = schedfrom; thread->schedfrom_line = fromln; @@ -1063,7 +1083,6 @@ thread_cancel (struct thread *thread) assert(!"Thread should be either in queue or list or array!"); } - thread->type = THREAD_UNUSED; thread_add_unuse (thread->master, thread); } @@ -1086,7 +1105,6 @@ thread_cancel_event (struct thread_master *m, void *arg) { ret++; thread_list_delete (&m->event, t); - t->type = THREAD_UNUSED; thread_add_unuse (m, t); } } @@ -1104,7 +1122,6 @@ thread_cancel_event (struct thread_master *m, void *arg) { ret++; thread_list_delete (&m->ready, t); - t->type = THREAD_UNUSED; thread_add_unuse (m, t); } } @@ -1128,7 +1145,6 @@ thread_run (struct thread_master *m, struct thread *thread, struct thread *fetch) { *fetch = *thread; - thread->type = THREAD_UNUSED; thread_add_unuse (m, thread); return fetch; } @@ -1427,23 +1443,6 @@ thread_call (struct thread *thread) unsigned long realtime, cputime; RUSAGE_T before, after; - /* Cache a pointer to the relevant cpu history thread, if the thread - * does not have it yet. - * - * Callers submitting 'dummy threads' hence must take care that - * thread->cpu is NULL - */ - if (!thread->hist) - { - struct cpu_thread_history tmp; - - tmp.func = thread->func; - tmp.funcname = thread->funcname; - - thread->hist = hash_get (cpu_record, &tmp, - (void * (*) (void *))cpu_record_hash_alloc); - } - GETRUSAGE (&before); thread->real = before.real; From e4fe5b196e6228fdbd221db1f9ffe09cf9930c09 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 10 Nov 2016 14:25:39 -0500 Subject: [PATCH 281/386] lib: Fix 'show thread cpu' to display active threads Fix the display of 'show thread cpu' to keep track of the number of active threads and to display that information. Signed-off-by: Donald Sharp --- lib/thread.c | 9 ++++++--- lib/thread.h | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/thread.c b/lib/thread.c index 59c0b77b90..ba1386af21 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -221,8 +221,8 @@ static void vty_out_cpu_thread_history(struct vty* vty, struct cpu_thread_history *a) { - vty_out(vty, "%10ld.%03ld %9d %8ld %9ld %8ld %9ld", - a->cpu.total/1000, a->cpu.total%1000, a->total_calls, + vty_out(vty, "%5d %10ld.%03ld %9d %8ld %9ld %8ld %9ld", + a->total_active, a->cpu.total/1000, a->cpu.total%1000, a->total_calls, a->cpu.total/a->total_calls, a->cpu.max, a->real.total/a->total_calls, a->real.max); vty_out(vty, " %c%c%c%c%c%c %s%s", @@ -247,6 +247,7 @@ cpu_record_hash_print(struct hash_backet *bucket, if ( !(a->types & *filter) ) return; vty_out_cpu_thread_history(vty,a); + totals->total_active += a->total_active; totals->total_calls += a->total_calls; totals->real.total += a->real.total; if (totals->real.max < a->real.max) @@ -268,7 +269,7 @@ cpu_record_print(struct vty *vty, thread_type filter) vty_out(vty, "%21s %18s %18s%s", "", "CPU (user+system):", "Real (wall-clock):", VTY_NEWLINE); - vty_out(vty, " Runtime(ms) Invoked Avg uSec Max uSecs"); + vty_out(vty, "Active Runtime(ms) Invoked Avg uSec Max uSecs"); vty_out(vty, " Avg uSec Max uSecs"); vty_out(vty, " Type Thread%s", VTY_NEWLINE); hash_iterate(cpu_record, @@ -572,6 +573,7 @@ thread_add_unuse (struct thread_master *m, struct thread *thread) assert (thread->prev == NULL); thread->type = THREAD_UNUSED; + thread->hist->total_active--; thread_list_add (&m->unuse, thread); } @@ -726,6 +728,7 @@ thread_get (struct thread_master *m, u_char type, thread->hist = hash_get (cpu_record, &tmp, (void * (*) (void *))cpu_record_hash_alloc); } + thread->hist->total_active++; thread->func = func; thread->funcname = funcname; thread->schedfrom = schedfrom; diff --git a/lib/thread.h b/lib/thread.h index 5c6b96a32d..c22bb4828d 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -115,6 +115,7 @@ struct cpu_thread_history { int (*func)(struct thread *); unsigned int total_calls; + unsigned int total_active; struct time_stats { unsigned long total, max; From f21597f04d9ac8519128b409b73be99687ed529f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 10 Nov 2016 20:09:01 -0500 Subject: [PATCH 282/386] pimd: Fix the test to see if a upstream is (S,G,rpt) Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index fe6e81ef63..8552966782 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -991,8 +991,15 @@ pim_upstream_switch_to_spt_desired (struct prefix_sg *sg) int pim_upstream_is_sg_rpt (struct pim_upstream *up) { - if (up->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) - return 1; + struct listnode *chnode; + struct pim_ifchannel *ch; + + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, chnode, ch)) + { + if ((ch->upstream == up) && + (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))) + return 1; + } return 0; } From 7c69a429b7a92819f2718dbe0074a06b626f3633 Mon Sep 17 00:00:00 2001 From: vivek Date: Thu, 10 Nov 2016 18:49:43 -0800 Subject: [PATCH 283/386] zebra: Perform safe walk of RIB entries in rib_process() There is a scenario where a RIB entry is unlinked and freed during RIB processing. However, the walk of the entries is not being performed in a safe manner. Fix the code to do this correctly. Signed-off-by: Vivek Venkatraman Ticket: CM-13393 Reviewed By: Trivial Testing Done: Basic manual test --- zebra/zebra_rib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index c573f6bd5c..1d46289ece 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1633,7 +1633,7 @@ rib_process (struct route_node *rn) if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug ("%u:%s/%d: Processing rn %p", vrf_id, buf, rn->p.prefixlen, rn); - RNODE_FOREACH_RIB (rn, rib) + RNODE_FOREACH_RIB_SAFE (rn, rib, next) { if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug ("%u:%s/%d: Examine rib %p (type %d) status %x flags %x " From 46c8aab88af4aa4ab2aca68ee854aed43227260f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 10 Nov 2016 21:08:48 -0500 Subject: [PATCH 284/386] pimd: Add (-) PRUNE(S,G,rpt) from interface determination. When determining the inherited_olist(S,G) add the determination that we have received a prune(S,G,rpt) from a neighbor. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 8552966782..2596f8c6e1 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -658,7 +658,11 @@ pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up, { if (!pim_macro_ch_lost_assert(ch) && pim_macro_chisin_joins_or_include(ch)) return 1; + + if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) + return 0; } + /* * joins (*,G) */ From 7667c5568fdff287ad124e6d6d39653da2241968 Mon Sep 17 00:00:00 2001 From: anuradhak Date: Tue, 8 Nov 2016 10:34:31 -0800 Subject: [PATCH 285/386] 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 */ From c8ff19f7bef4b6f7dbb2ded951929190f00a022a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 11 Nov 2016 13:57:49 -0500 Subject: [PATCH 286/386] lib: Fix thread_execute_crash With the change to have thread_get fill inthe ->hist pointer, thread_execute was missed and it needs to fill in the .hist pointer for the dummy thread created. I'm not really sure why we need to call a thread_execute on a function. When we could, you know, just call the bloody thing. Signed-off-by: Donald Sharp --- lib/thread.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/thread.c b/lib/thread.c index ba1386af21..64eaae45b9 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -1490,18 +1490,22 @@ funcname_thread_execute (struct thread_master *m, int val, debugargdef) { - struct thread dummy; + struct cpu_thread_history tmp; + struct thread dummy; memset (&dummy, 0, sizeof (struct thread)); dummy.type = THREAD_EVENT; dummy.add_type = THREAD_EXECUTE; dummy.master = NULL; - dummy.func = func; dummy.arg = arg; dummy.u.val = val; - dummy.funcname = funcname; + tmp.func = dummy.func = func; + tmp.funcname = dummy.funcname = funcname; + dummy.hist = hash_get (cpu_record, &tmp, + (void * (*) (void *))cpu_record_hash_alloc); + dummy.schedfrom = schedfrom; dummy.schedfrom_line = fromln; From 0490c22d20fb091d8bb1411c3b5df61a4fdd7c2e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 11 Nov 2016 19:13:55 -0500 Subject: [PATCH 287/386] pimd: Start handling of wrong interface for (*,G) When we get a callback for a specific (S,G) and we have no ifchannel for it, see if we have a (*,G) channel and handle it appropriately. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 57dc5550db..c3f572c716 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -235,32 +235,39 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms */ if (!ifp) { - if (PIM_DEBUG_MROUTE) { + if (PIM_DEBUG_MROUTE) zlog_debug("%s: WRONGVIF (S,G)=%s could not find input interface for input_vif_index=%d", __PRETTY_FUNCTION__, pim_str_sg_dump (&sg), msg->im_vif); - } return -1; } pim_ifp = ifp->info; if (!pim_ifp) { - if (PIM_DEBUG_MROUTE) { + if (PIM_DEBUG_MROUTE) zlog_debug("%s: WRONGVIF (S,G)=%s multicast not enabled on interface %s", __PRETTY_FUNCTION__, pim_str_sg_dump (&sg), ifp->name); - } return -2; } ch = pim_ifchannel_find(ifp, &sg); if (!ch) { - if (PIM_DEBUG_MROUTE) { + struct prefix_sg star_g = sg; + if (PIM_DEBUG_MROUTE) zlog_debug("%s: WRONGVIF (S,G)=%s could not find channel on interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), ifp->name); + pim_str_sg_dump(&sg), ifp->name); + + star_g.src.s_addr = INADDR_ANY; + ch = pim_ifchannel_find(ifp, &star_g); + if (!ch) { + if (PIM_DEBUG_MROUTE) + zlog_debug("%s: WRONGVIF (*,G)=%s could not find channel on interface %s", + __PRETTY_FUNCTION__, + pim_str_sg_dump(&star_g), ifp->name); + return -3; } - return -3; } /* @@ -281,7 +288,7 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms if (PIM_DEBUG_MROUTE) { zlog_debug("%s: WRONGVIF (S,G)=%s channel is not on Assert NoInfo state for interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), ifp->name); + pim_str_sg_dump (&ch->sg), ifp->name); } return -4; } @@ -290,7 +297,7 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms if (PIM_DEBUG_MROUTE) { zlog_debug("%s: WRONGVIF (S,G)=%s interface %s is not downstream for channel", __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), ifp->name); + pim_str_sg_dump (&ch->sg), ifp->name); } return -5; } @@ -299,7 +306,7 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms if (PIM_DEBUG_MROUTE) { zlog_debug("%s: WRONGVIF (S,G)=%s assert_action_a1 failure on interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), ifp->name); + pim_str_sg_dump (&ch->sg), ifp->name); } return -6; } @@ -314,6 +321,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) struct pim_interface *pim_ifp; struct pim_ifchannel *ch; struct pim_upstream *up; + struct prefix_sg star_g; struct prefix_sg sg; struct channel_oil *oil; @@ -333,6 +341,16 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) pim_str_sg_dump (&sg), ifp->name); return -1; } + star_g = sg; + star_g.src.s_addr = INADDR_ANY; + ch = pim_ifchannel_find(ifp, &star_g); + if (ch) + { + if (PIM_DEBUG_MROUTE) + zlog_debug ("WRVIFWHOLE (*,G)=%s found ifchannel on interface %s", + pim_str_sg_dump (&star_g), ifp->name); + return -1; + } if (PIM_DEBUG_MROUTE) zlog_debug ("If channel: %p", ch); From deab75f73acbe01d57da29f1f0446a1ce7006af2 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 11 Nov 2016 20:00:15 -0500 Subject: [PATCH 288/386] pimd: Reduce pim oil scan timer to 50ms We need to react to route changes/Interface up/down events faster in PIM. Reduce the timer down to 50ms. Ticket:CM-13549 Signed-off-by: Donald Sharp --- pimd/pimd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pimd.c b/pimd/pimd.c index bd8ee755c3..69803a6b56 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -55,7 +55,7 @@ int qpim_mroute_oif_highest_vif_index = -1; int qpim_t_periodic = PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */ struct zclient *qpim_zclient_update = NULL; struct pim_assert_metric qpim_infinite_assert_metric; -long qpim_rpf_cache_refresh_delay_msec = 2000; +long qpim_rpf_cache_refresh_delay_msec = 50; struct thread *qpim_rpf_cache_refresher = NULL; int64_t qpim_rpf_cache_refresh_requests = 0; int64_t qpim_rpf_cache_refresh_events = 0; From f0242f68c9372d12bbd990ffec2d06df8c42fb19 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 11 Nov 2016 21:07:50 -0500 Subject: [PATCH 289/386] zebra: Fix clang SA warnings The mr value was not being initialized to anything and as such could contain garbage. Signed-off-by: Donald Sharp --- zebra/rt_netlink.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index b968a84e76..15dd7ef1cb 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -541,7 +541,10 @@ netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h if (mroute) m = mroute; else - m = &mr; + { + memset (&mr, 0, sizeof (mr)); + m = &mr; + } rtm = NLMSG_DATA (h); From 27bc3ae3d4bca97ebaeda698cca25e3b4d8959b3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 11 Nov 2016 21:21:49 -0500 Subject: [PATCH 290/386] pimd: Removing impossible code We've already allocated the mp data structure and am using hash_alloc_intern for the hash_get function. This will return the passed in data structure. There is no possibility of mp being NULL. Signed-off-by: Donald Sharp --- pimd/pim_msdp.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 8e933222c6..43e2e888f5 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -995,11 +995,6 @@ pim_msdp_peer_new(struct in_addr peer_addr, struct in_addr local_addr, /* insert into misc tables for easy access */ mp = hash_get(msdp->peer_hash, mp, hash_alloc_intern); - if (!mp) { - zlog_err("%s: PIM hash get failure", __PRETTY_FUNCTION__); - pim_msdp_peer_free(mp); - return PIM_MSDP_ERR_OOM; - } listnode_add_sort(msdp->peer_list, mp); if (PIM_DEBUG_MSDP_EVENTS) { From 8e7702bc34d71064e4c2f137021c4efa4c8d2f64 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 12 Nov 2016 22:12:13 -0500 Subject: [PATCH 291/386] zebra: Cleanup zebra_static CLANG/SA issues. When compiling using CLANG's SA, cleanup the SA issues found. Signed-off-by: Donald Sharp --- zebra/kernel_netlink.c | 14 ++++++++++++-- zebra/zebra_fpm.c | 6 ++++-- zebra/zebra_fpm_netlink.c | 16 +++++++++------- zebra/zebra_static.c | 2 ++ zebra/zebra_static.h | 15 +++++++++------ zebra/zebra_vty.c | 11 +++++++++++ zebra/zserv.c | 2 +- 7 files changed, 48 insertions(+), 18 deletions(-) diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 20c4b5afe2..02da17af63 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -337,7 +337,12 @@ addattr_l (struct nlmsghdr *n, unsigned int maxlen, int type, rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len)); rta->rta_type = type; rta->rta_len = len; - memcpy (RTA_DATA (rta), data, alen); + + if (data) + memcpy (RTA_DATA (rta), data, alen); + else + assert (len == 0); + n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + RTA_ALIGN (len); return 0; @@ -358,7 +363,12 @@ rta_addattr_l (struct rtattr *rta, unsigned int maxlen, int type, subrta = (struct rtattr *) (((char *) rta) + RTA_ALIGN (rta->rta_len)); subrta->rta_type = type; subrta->rta_len = len; - memcpy (RTA_DATA (subrta), data, alen); + + if (data) + memcpy (RTA_DATA (subrta), data, alen); + else + assert (len == 0); + rta->rta_len = NLMSG_ALIGN (rta->rta_len) + RTA_ALIGN (len); return 0; diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index 80512c71f6..8b337152b4 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -1622,14 +1622,16 @@ zfpm_init_message_format (const char *format) { int have_netlink, have_protobuf; - have_netlink = have_protobuf = 0; - #ifdef HAVE_NETLINK have_netlink = 1; +#else + have_netlink = 0; #endif #ifdef HAVE_PROTOBUF have_protobuf = 1; +#else + have_protobuf = 0; #endif zfpm_g->message_format = ZFPM_MSG_FORMAT_NONE; diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c index 5dd08ca782..771bd837d8 100644 --- a/zebra/zebra_fpm_netlink.c +++ b/zebra/zebra_fpm_netlink.c @@ -255,10 +255,15 @@ netlink_route_info_fill (netlink_route_info_t *ri, int cmd, * particularly in our communication with the FPM. */ if (cmd == RTM_DELROUTE && !rib) - goto skip; + return 1; - if (rib) - ri->rtm_protocol = netlink_proto_from_route_type (rib->type); + if (!rib) + { + zfpm_debug ("%s: Expected non-NULL rib pointer", __PRETTY_FUNCTION__); + return 0; + } + + ri->rtm_protocol = netlink_proto_from_route_type (rib->type); if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) || (rib->flags & ZEBRA_FLAG_REJECT)) discard = 1; @@ -283,9 +288,7 @@ netlink_route_info_fill (netlink_route_info_t *ri, int cmd, ri->metric = &rib->metric; if (discard) - { - goto skip; - } + return 1; for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) { @@ -311,7 +314,6 @@ netlink_route_info_fill (netlink_route_info_t *ri, int cmd, return 0; } - skip: return 1; } diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c index e6ae9c71d4..d55ec055e6 100644 --- a/zebra/zebra_static.c +++ b/zebra/zebra_static.c @@ -50,6 +50,8 @@ static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_ro if (! table) return; + memset (&nh_p, 0, sizeof (nh_p)); + /* Lookup existing route */ rn = route_node_get (table, p); RNODE_FOREACH_RIB (rn, rib) diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h index 5e3177e3b8..233436f02d 100644 --- a/zebra/zebra_static.h +++ b/zebra/zebra_static.h @@ -31,6 +31,14 @@ struct static_nh_label mpls_label_t label[2]; }; +typedef enum { + STATIC_IFINDEX, + STATIC_IPV4_GATEWAY, + STATIC_BLACKHOLE, + STATIC_IPV6_GATEWAY, + STATIC_IPV6_GATEWAY_IFINDEX, +} zebra_static_types; + /* Static route information. */ struct static_route { @@ -48,12 +56,7 @@ struct static_route route_tag_t tag; /* Flag for this static route's type. */ - u_char type; -#define STATIC_IFINDEX 1 -#define STATIC_IPV4_GATEWAY 2 -#define STATIC_BLACKHOLE 3 -#define STATIC_IPV6_GATEWAY 4 -#define STATIC_IPV6_GATEWAY_IFINDEX 5 + zebra_static_types type; /* * Nexthop value. diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 1fe55b072e..0c802fd3dc 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -2283,6 +2283,14 @@ static_config_ipv4 (struct vty *vty, safi_t safi, const char *cmd) case STATIC_BLACKHOLE: vty_out (vty, " Null0"); break; + case STATIC_IPV6_GATEWAY: + vty_out (vty, " %s", inet_ntop (AF_INET6, &si->addr.ipv6, buf, BUFSIZ)); + break; + case STATIC_IPV6_GATEWAY_IFINDEX: + vty_out (vty, " %s %s", + inet_ntop (AF_INET6, &si->addr.ipv6, buf, BUFSIZ), + ifindex2ifname_vrf (si->ifindex, si->vrf_id)); + break; } /* flags are incompatible with STATIC_BLACKHOLE */ @@ -3595,6 +3603,9 @@ static_config_ipv6 (struct vty *vty) switch (si->type) { + case STATIC_IPV4_GATEWAY: + vty_out (vty, " %s", inet_ntoa (si->addr.ipv4)); + break; case STATIC_IPV6_GATEWAY: vty_out (vty, " %s", inet_ntop (AF_INET6, &si->addr.ipv6, buf, BUFSIZ)); break; diff --git a/zebra/zserv.c b/zebra/zserv.c index bdfa03e1ee..38680a312e 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1518,7 +1518,7 @@ zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) struct stream *s; struct zapi_ipv6 api; struct in6_addr nexthop; - union g_addr *pnexthop; + union g_addr *pnexthop = NULL; unsigned long ifindex; struct prefix p; From 8f21cf48a1fd3e8d4a8b3a5ab4af1b16a7d93b27 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 12 Nov 2016 22:45:25 -0500 Subject: [PATCH 292/386] lib: Fix clang SA warnings. Signed-off-by: Donald Sharp --- lib/imsg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/imsg.c b/lib/imsg.c index 246430cdd5..fc62c13734 100644 --- a/lib/imsg.c +++ b/lib/imsg.c @@ -182,7 +182,8 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) else imsg->fd = -1; - memcpy(imsg->data, ibuf->r.rptr, datalen); + if (imsg->data) + memcpy(imsg->data, ibuf->r.rptr, datalen); if (imsg->hdr.len < av) { left = av - imsg->hdr.len; From 5cd11e3cd00579272fa6f30a448e8c8ac3fbe9a3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 14 Nov 2016 08:45:44 -0500 Subject: [PATCH 293/386] pimd: Backing up broken state. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index c3f572c716..7309774548 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -321,7 +321,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) struct pim_interface *pim_ifp; struct pim_ifchannel *ch; struct pim_upstream *up; - struct prefix_sg star_g; + //struct prefix_sg star_g; struct prefix_sg sg; struct channel_oil *oil; @@ -341,6 +341,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) pim_str_sg_dump (&sg), ifp->name); return -1; } +#if 0 star_g = sg; star_g.src.s_addr = INADDR_ANY; ch = pim_ifchannel_find(ifp, &star_g); @@ -351,6 +352,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) pim_str_sg_dump (&star_g), ifp->name); return -1; } +#endif if (PIM_DEBUG_MROUTE) zlog_debug ("If channel: %p", ch); From 977d71cc7abc10e9ee4d496de3a4b9fb118df002 Mon Sep 17 00:00:00 2001 From: anuradhak Date: Sat, 12 Nov 2016 05:39:44 -0800 Subject: [PATCH 294/386] pim-msdp: part-4: cli cleanup 1. Add support for mesh-group based configuration that is easy to apply via automation. The older per-peer configuartion is temporarily hidden and will be cleaned up later. Sample config - ip msdp mesh-group cumulus source 100.1.1.4 ip msdp mesh-group cumulus member 100.1.1.5 ip msdp mesh-group cumulus member 100.1.1.6 2. Added support for detail peer and sa-cache displays. Along with filter keys. 3. Add json output for all the msdp displays. With this commit basic support for anycast-RP with MSDP (in numbered network is complete). Unnumbered support will be added separately. Ticket: CM-13306 Signed-off-by: Anuradha Karuppiah Acked-by: Donald Sharp --- pimd/pim_cmd.c | 662 +++++++++++++++++++++++++++++++++++++++++++--- pimd/pim_cmd.h | 1 + pimd/pim_memory.c | 4 +- pimd/pim_memory.h | 4 +- pimd/pim_msdp.c | 383 +++++++++++++++++++++++++-- pimd/pim_msdp.h | 34 ++- pimd/pim_vty.c | 4 + 7 files changed, 1024 insertions(+), 68 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 03856bdfcf..84350676a7 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -5170,7 +5170,7 @@ ip_msdp_peer_cmd_worker (struct vty *vty, const char *peer, const char *local) return CMD_WARNING; } - result = pim_msdp_peer_add(peer_addr, local_addr, "default"); + result = pim_msdp_peer_add(peer_addr, local_addr, "default", NULL/* mp_p */); switch (result) { case PIM_MSDP_ERR_NONE: break; @@ -5190,7 +5190,7 @@ ip_msdp_peer_cmd_worker (struct vty *vty, const char *peer, const char *local) return result?CMD_WARNING:CMD_SUCCESS; } -DEFUN (ip_msdp_peer, +DEFUN_HIDDEN (ip_msdp_peer, ip_msdp_peer_cmd, "ip msdp peer A.B.C.D source A.B.C.D", IP_STR @@ -5230,9 +5230,10 @@ ip_no_msdp_peer_cmd_worker (struct vty *vty, const char *peer) return result?CMD_WARNING:CMD_SUCCESS; } -DEFUN (no_ip_msdp_peer, +DEFUN_HIDDEN (no_ip_msdp_peer, no_ip_msdp_peer_cmd, "no ip msdp peer A.B.C.D", + NO_STR IP_STR CFG_MSDP_STR "Delete MSDP peer\n" @@ -5241,6 +5242,275 @@ DEFUN (no_ip_msdp_peer, return ip_no_msdp_peer_cmd_worker (vty, argv[4]->arg); } +static int +ip_msdp_mesh_group_member_cmd_worker(struct vty *vty, const char *mg, const char *mbr) +{ + enum pim_msdp_err result; + struct in_addr mbr_ip; + + result = inet_pton(AF_INET, mbr, &mbr_ip); + if (result <= 0) { + vty_out(vty, "%% Bad member address %s: errno=%d: %s%s", + mbr, errno, safe_strerror(errno), VTY_NEWLINE); + return CMD_WARNING; + } + + result = pim_msdp_mg_mbr_add(mg, mbr_ip); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_OOM: + vty_out(vty, "%% Out of memory%s", VTY_NEWLINE); + break; + case PIM_MSDP_ERR_MG_MBR_EXISTS: + vty_out(vty, "%% mesh-group member exists%s", VTY_NEWLINE); + break; + case PIM_MSDP_ERR_MAX_MESH_GROUPS: + vty_out(vty, "%% Only one mesh-group allowed currently%s", VTY_NEWLINE); + break; + default: + vty_out(vty, "%% member add failed%s", VTY_NEWLINE); + } + + return result?CMD_WARNING:CMD_SUCCESS; +} + +DEFUN (ip_msdp_mesh_group_member, + ip_msdp_mesh_group_member_cmd, + "ip msdp mesh-group WORD member A.B.C.D", + IP_STR + CFG_MSDP_STR + "Configure MSDP mesh-group\n" + "mesh group name\n" + "mesh group member\n" + "peer ip address\n") +{ + return ip_msdp_mesh_group_member_cmd_worker(vty, argv[3]->arg, argv[5]->arg); +} + +static int +ip_no_msdp_mesh_group_member_cmd_worker(struct vty *vty, const char *mg, const char *mbr) +{ + enum pim_msdp_err result; + struct in_addr mbr_ip; + + result = inet_pton(AF_INET, mbr, &mbr_ip); + if (result <= 0) { + vty_out(vty, "%% Bad member address %s: errno=%d: %s%s", + mbr, errno, safe_strerror(errno), VTY_NEWLINE); + return CMD_WARNING; + } + + result = pim_msdp_mg_mbr_del(mg, mbr_ip); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_NO_MG: + vty_out(vty, "%% mesh-group does not exist%s", VTY_NEWLINE); + break; + case PIM_MSDP_ERR_NO_MG_MBR: + vty_out(vty, "%% mesh-group member does not exist%s", VTY_NEWLINE); + break; + default: + vty_out(vty, "%% mesh-group member del failed%s", VTY_NEWLINE); + } + + return result?CMD_WARNING:CMD_SUCCESS; +} +DEFUN (no_ip_msdp_mesh_group_member, + no_ip_msdp_mesh_group_member_cmd, + "no ip msdp mesh-group WORD member A.B.C.D", + NO_STR + IP_STR + CFG_MSDP_STR + "Delete MSDP mesh-group member\n" + "mesh group name\n" + "mesh group member\n" + "peer ip address\n") +{ + return ip_no_msdp_mesh_group_member_cmd_worker(vty, argv[4]->arg, argv[6]->arg); +} + +static int +ip_msdp_mesh_group_source_cmd_worker(struct vty *vty, const char *mg, const char *src) +{ + enum pim_msdp_err result; + struct in_addr src_ip; + + result = inet_pton(AF_INET, src, &src_ip); + if (result <= 0) { + vty_out(vty, "%% Bad source address %s: errno=%d: %s%s", + src, errno, safe_strerror(errno), VTY_NEWLINE); + return CMD_WARNING; + } + + result = pim_msdp_mg_src_add(mg, src_ip); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_OOM: + vty_out(vty, "%% Out of memory%s", VTY_NEWLINE); + break; + case PIM_MSDP_ERR_MAX_MESH_GROUPS: + vty_out(vty, "%% Only one mesh-group allowed currently%s", VTY_NEWLINE); + break; + default: + vty_out(vty, "%% source add failed%s", VTY_NEWLINE); + } + + return result?CMD_WARNING:CMD_SUCCESS; +} + + +DEFUN (ip_msdp_mesh_group_source, + ip_msdp_mesh_group_source_cmd, + "ip msdp mesh-group WORD source A.B.C.D", + IP_STR + CFG_MSDP_STR + "Configure MSDP mesh-group\n" + "mesh group name\n" + "mesh group local address\n" + "source ip address for the TCP connection\n") +{ + return ip_msdp_mesh_group_source_cmd_worker(vty, argv[3]->arg, argv[5]->arg); +} + +static int +ip_no_msdp_mesh_group_source_cmd_worker(struct vty *vty, const char *mg) +{ + enum pim_msdp_err result; + + result = pim_msdp_mg_src_del(mg); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_NO_MG: + vty_out(vty, "%% mesh-group does not exist%s", VTY_NEWLINE); + break; + default: + vty_out(vty, "%% mesh-group source del failed%s", VTY_NEWLINE); + } + + return result?CMD_WARNING:CMD_SUCCESS; +} + +DEFUN (no_ip_msdp_mesh_group_source, + no_ip_msdp_mesh_group_source_cmd, + "no ip msdp mesh-group WORD source", + NO_STR + IP_STR + CFG_MSDP_STR + "Delete MSDP mesh-group source\n" + "mesh group name\n" + "mesh group local address\n") +{ + return ip_no_msdp_mesh_group_source_cmd_worker(vty, argv[4]->arg); +} + +static int +ip_no_msdp_mesh_group_cmd_worker(struct vty *vty, const char *mg) +{ + enum pim_msdp_err result; + + result = pim_msdp_mg_del(mg); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_NO_MG: + vty_out(vty, "%% mesh-group does not exist%s", VTY_NEWLINE); + break; + default: + vty_out(vty, "%% mesh-group source del failed%s", VTY_NEWLINE); + } + + return result?CMD_WARNING:CMD_SUCCESS; +} + +DEFUN (no_ip_msdp_mesh_group, + no_ip_msdp_mesh_group_cmd, + "no ip msdp mesh-group WORD", + NO_STR + IP_STR + CFG_MSDP_STR + "Delete MSDP mesh-group\n" + "mesh group name") +{ + return ip_no_msdp_mesh_group_cmd_worker(vty, argv[4]->arg); +} + +static void +ip_msdp_show_mesh_group(struct vty *vty, u_char uj) +{ + struct listnode *mbrnode; + struct pim_msdp_mg_mbr *mbr; + struct pim_msdp_mg *mg = msdp->mg; + char mbr_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; + char state_str[PIM_MSDP_STATE_STRLEN]; + enum pim_msdp_peer_state state; + json_object *json = NULL; + json_object *json_mg_row = NULL; + json_object *json_row = NULL; + + if (!mg) { + return; + } + + pim_inet4_dump("", mg->src_ip, src_str, sizeof(src_str)); + if (uj) { + json = json_object_new_object(); + /* currently there is only one mesh group but we should still make + * it a dict with mg-name as key */ + json_mg_row = json_object_new_object(); + json_object_string_add(json_mg_row, "name", mg->mesh_group_name); + json_object_string_add(json_mg_row, "source", src_str); + } else { + vty_out(vty, "Mesh group : %s%s", mg->mesh_group_name, VTY_NEWLINE); + vty_out(vty, " Source : %s%s", src_str, VTY_NEWLINE); + vty_out(vty, " Member State%s", VTY_NEWLINE); + } + + for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) { + pim_inet4_dump("", mbr->mbr_ip, mbr_str, sizeof(mbr_str)); + if (mbr->mp) { + state = mbr->mp->state; + } else { + state = PIM_MSDP_DISABLED; + } + pim_msdp_state_dump(state, state_str, sizeof(state_str)); + if (uj) { + json_row = json_object_new_object(); + json_object_string_add(json_row, "member", mbr_str); + json_object_string_add(json_row, "state", state_str); + json_object_object_add(json_mg_row, mbr_str, json_row); + } else { + vty_out(vty, " %-15s %11s%s", + mbr_str, state_str, VTY_NEWLINE); + } + } + + if (uj) { + json_object_object_add(json, mg->mesh_group_name, json_mg_row); + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); + json_object_free(json); + } +} + +DEFUN (show_ip_msdp_mesh_group, + show_ip_msdp_mesh_group_cmd, + "show ip msdp mesh-group [json]", + SHOW_STR + IP_STR + MSDP_STR + "MSDP mesh-group information\n" + "JavaScript Object Notation\n") +{ + u_char uj = use_json(argc, argv); + ip_msdp_show_mesh_group(vty, uj); + + return CMD_SUCCESS; +} + static void ip_msdp_show_peers(struct vty *vty, u_char uj) { @@ -5251,40 +5521,148 @@ ip_msdp_show_peers(struct vty *vty, u_char uj) char state_str[PIM_MSDP_STATE_STRLEN]; char timebuf[PIM_MSDP_UPTIME_STRLEN]; int64_t now; + json_object *json = NULL; + json_object *json_row = NULL; + if (uj) { - // XXX: blah - return; + json = json_object_new_object(); } else { vty_out(vty, "Peer Local Mesh-group State Uptime%s", VTY_NEWLINE); - for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { - if (mp->state == PIM_MSDP_ESTABLISHED) { - now = pim_time_monotonic_sec(); - pim_time_uptime(timebuf, sizeof(timebuf), now - mp->uptime); - } else { - strcpy(timebuf, "-"); - } - pim_inet4_dump("", mp->peer, peer_str, sizeof(peer_str)); - pim_inet4_dump("", mp->local, local_str, sizeof(local_str)); - pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); + } + + for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { + if (mp->state == PIM_MSDP_ESTABLISHED) { + now = pim_time_monotonic_sec(); + pim_time_uptime(timebuf, sizeof(timebuf), now - mp->uptime); + } else { + strcpy(timebuf, "-"); + } + pim_inet4_dump("", mp->peer, peer_str, sizeof(peer_str)); + pim_inet4_dump("", mp->local, local_str, sizeof(local_str)); + pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); + if (uj) { + json_row = json_object_new_object(); + json_object_string_add(json_row, "peer", peer_str); + json_object_string_add(json_row, "local", local_str); + json_object_string_add(json_row, "meshGroupName", mp->mesh_group_name); + json_object_string_add(json_row, "state", state_str); + json_object_string_add(json_row, "upTime", timebuf); + json_object_object_add(json, peer_str, json_row); + } else { vty_out(vty, "%-15s %15s %16s %11s %8s%s", peer_str, local_str, mp->mesh_group_name, state_str, timebuf, VTY_NEWLINE); } } + + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); + json_object_free(json); + } } -DEFUN (show_ip_msdp_peer, - show_ip_msdp_peer_cmd, - "show ip msdp peer [json]", +static void +ip_msdp_show_peers_detail(struct vty *vty, const char *peer, u_char uj) +{ + struct listnode *mpnode; + struct pim_msdp_peer *mp; + char peer_str[INET_ADDRSTRLEN]; + char local_str[INET_ADDRSTRLEN]; + char state_str[PIM_MSDP_STATE_STRLEN]; + char timebuf[PIM_MSDP_UPTIME_STRLEN]; + char katimer[PIM_MSDP_TIMER_STRLEN]; + char crtimer[PIM_MSDP_TIMER_STRLEN]; + char holdtimer[PIM_MSDP_TIMER_STRLEN]; + int64_t now; + json_object *json = NULL; + json_object *json_row = NULL; + + if (uj) { + json = json_object_new_object(); + } + + for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { + pim_inet4_dump("", mp->peer, peer_str, sizeof(peer_str)); + if (strcmp(peer, "detail") && + strcmp(peer, peer_str)) + continue; + + if (mp->state == PIM_MSDP_ESTABLISHED) { + now = pim_time_monotonic_sec(); + pim_time_uptime(timebuf, sizeof(timebuf), now - mp->uptime); + } else { + strcpy(timebuf, "-"); + } + pim_inet4_dump("", mp->local, local_str, sizeof(local_str)); + pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); + pim_time_timer_to_hhmmss(katimer, sizeof(katimer), mp->ka_timer); + pim_time_timer_to_hhmmss(crtimer, sizeof(crtimer), mp->cr_timer); + pim_time_timer_to_hhmmss(holdtimer, sizeof(holdtimer), mp->hold_timer); + + if (uj) { + json_row = json_object_new_object(); + json_object_string_add(json_row, "peer", peer_str); + json_object_string_add(json_row, "local", local_str); + json_object_string_add(json_row, "meshGroupName", mp->mesh_group_name); + json_object_string_add(json_row, "state", state_str); + json_object_string_add(json_row, "upTime", timebuf); + json_object_string_add(json_row, "keepAliveTime", katimer); + json_object_string_add(json_row, "connRetryTime", crtimer); + json_object_string_add(json_row, "holdTime", holdtimer); + json_object_string_add(json_row, "lastReset", mp->last_reset); + json_object_int_add(json_row, "connAttempts", mp->conn_attempts); + json_object_int_add(json_row, "establishedFlaps", mp->est_flaps); + json_object_int_add(json_row, "kaSent", mp->ka_tx_cnt); + json_object_int_add(json_row, "kaRcvd", mp->ka_rx_cnt); + json_object_int_add(json_row, "saSent", mp->sa_tx_cnt); + json_object_int_add(json_row, "saRcvd", mp->sa_rx_cnt); + json_object_object_add(json, peer_str, json_row); + } else { + vty_out(vty, "Peer : %s%s", peer_str, VTY_NEWLINE); + vty_out(vty, " Local : %s%s", local_str, VTY_NEWLINE); + vty_out(vty, " Mesh Group : %s%s", mp->mesh_group_name, VTY_NEWLINE); + vty_out(vty, " State : %s%s", state_str, VTY_NEWLINE); + vty_out(vty, " Uptime : %s%s", timebuf, VTY_NEWLINE); + + vty_out(vty, " Keepalive Time : %s%s", katimer, VTY_NEWLINE); + vty_out(vty, " Conn Retry Time : %s%s", crtimer, VTY_NEWLINE); + vty_out(vty, " Hold Time : %s%s", holdtimer, VTY_NEWLINE); + vty_out(vty, " Last Reset : %s%s", mp->last_reset, VTY_NEWLINE); + vty_out(vty, " Conn Attempts : %d%s", mp->conn_attempts, VTY_NEWLINE); + vty_out(vty, " Established Flaps: %d%s", mp->est_flaps, VTY_NEWLINE); + vty_out(vty, " Statistics :%s", VTY_NEWLINE); + vty_out(vty, " Sent Rcvd%s", VTY_NEWLINE); + vty_out(vty, " Keepalives : %10d %10d%s", + mp->ka_tx_cnt, mp->ka_rx_cnt, VTY_NEWLINE); + vty_out(vty, " SAs : %10d %10d%s", + mp->sa_tx_cnt, mp->sa_rx_cnt, VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + } + } + + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); + json_object_free(json); + } +} + +DEFUN (show_ip_msdp_peer_detail, + show_ip_msdp_peer_detail_cmd, + "show ip msdp peer [detail|A.B.C.D] [json]", SHOW_STR IP_STR MSDP_STR "MSDP peer information\n" + "Detailed output\n" + "peer ip address\n" "JavaScript Object Notation\n") { u_char uj = use_json(argc, argv); - ip_msdp_show_peers(vty, uj); + if (argv[4]->arg) + ip_msdp_show_peers_detail(vty, argv[4]->arg, uj); + else + ip_msdp_show_peers(vty, uj); return CMD_SUCCESS; } @@ -5298,47 +5676,238 @@ 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]; + char spt_str[8]; int64_t now; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_row = NULL; if (uj) { - // XXX: blah - return; + json = json_object_new_object(); } else { 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); - pim_inet4_dump("", sa->sg.src, src_str, sizeof(src_str)); - 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, "-"); + } + + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + now = pim_time_monotonic_sec(); + pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime); + pim_inet4_dump("", sa->sg.src, src_str, sizeof(src_str)); + 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 (uj) { + if (sa->up) { + strcpy(spt_str, "yes"); } else { - pim_inet4_dump("", sa->rp, rp_str, sizeof(rp_str)); - if (sa->up) { - strcpy(spt_str, "y"); - } else { - strcpy(spt_str, "n"); - } + strcpy(spt_str, "no"); + } + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, json_group); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "rp", rp_str); + json_object_string_add(json_row, "sptSetup", spt_str); + json_object_string_add(json_row, "upTime", timebuf); + json_object_object_add(json_group, src_str, json_row); + } else { + if (sa->up) { + strcpy(spt_str, "y"); + } else { + strcpy(spt_str, "n"); } vty_out(vty, "%-15s %15s %15s %3s %8s%s", src_str, grp_str, rp_str, spt_str, timebuf, VTY_NEWLINE); } } + + + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); + json_object_free(json); + } } -DEFUN (show_ip_msdp_sa, - show_ip_msdp_sa_cmd, - "show ip msdp sa [json]", +static void +ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa, const char *src_str, + const char *grp_str, struct vty *vty, + u_char uj, json_object *json) +{ + char rp_str[INET_ADDRSTRLEN]; + char peer_str[INET_ADDRSTRLEN]; + char timebuf[PIM_MSDP_UPTIME_STRLEN]; + char spt_str[8]; + char statetimer[PIM_MSDP_TIMER_STRLEN]; + int64_t now; + json_object *json_group = NULL; + json_object *json_row = NULL; + + now = pim_time_monotonic_sec(); + pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime); + if (sa->flags & PIM_MSDP_SAF_LOCAL) { + strcpy(rp_str, "local"); + strcpy(peer_str, "-"); + strcpy(spt_str, "-"); + } else { + pim_inet4_dump("", sa->rp, rp_str, sizeof(rp_str)); + pim_inet4_dump("", sa->peer, peer_str, sizeof(peer_str)); + if (sa->up) { + strcpy(spt_str, "yes"); + } else { + strcpy(spt_str, "no"); + } + } + pim_time_timer_to_hhmmss(statetimer, sizeof(statetimer), sa->sa_state_timer); + if (uj) { + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, json_group); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "rp", rp_str); + json_object_string_add(json_row, "sptSetup", spt_str); + json_object_string_add(json_row, "upTime", timebuf); + json_object_string_add(json_row, "stateTime", statetimer); + json_object_object_add(json_group, src_str, json_row); + } else { + vty_out(vty, "SA : %s%s", pim_str_sg_dump(&sa->sg), VTY_NEWLINE); + vty_out(vty, " RP : %s%s", rp_str, VTY_NEWLINE); + vty_out(vty, " Peer : %s%s", peer_str, VTY_NEWLINE); + vty_out(vty, " SPT Setup : %s%s", spt_str, VTY_NEWLINE); + vty_out(vty, " Uptime : %s%s", timebuf, VTY_NEWLINE); + vty_out(vty, " State Time : %s%s", statetimer, VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + } +} + +static void +ip_msdp_show_sa_detail(struct vty *vty, u_char uj) +{ + struct listnode *sanode; + struct pim_msdp_sa *sa; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + json_object *json = NULL; + + if (uj) { + json = json_object_new_object(); + } + + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + pim_inet4_dump("", sa->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", sa->sg.grp, grp_str, sizeof(grp_str)); + ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj, json); + } + + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); + json_object_free(json); + } +} + +DEFUN (show_ip_msdp_sa_detail, + show_ip_msdp_sa_detail_cmd, + "show ip msdp sa detail [json]", SHOW_STR IP_STR MSDP_STR "MSDP active-source information\n" + "Detailed output\n" "JavaScript Object Notation\n") { u_char uj = use_json(argc, argv); - ip_msdp_show_sa(vty, uj); + ip_msdp_show_sa_detail(vty, uj); + + return CMD_SUCCESS; +} + +static void +ip_msdp_show_sa_addr(struct vty *vty, const char *addr, u_char uj) +{ + struct listnode *sanode; + struct pim_msdp_sa *sa; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + json_object *json = NULL; + + if (uj) { + json = json_object_new_object(); + } + + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + pim_inet4_dump("", sa->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", sa->sg.grp, grp_str, sizeof(grp_str)); + if (!strcmp(addr, src_str) || !strcmp(addr, grp_str)) { + ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj, json); + } + } + + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); + json_object_free(json); + } +} + +static void +ip_msdp_show_sa_sg(struct vty *vty, const char *src, const char *grp, u_char uj) +{ + struct listnode *sanode; + struct pim_msdp_sa *sa; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + json_object *json = NULL; + + if (uj) { + json = json_object_new_object(); + } + + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + pim_inet4_dump("", sa->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", sa->sg.grp, grp_str, sizeof(grp_str)); + if (!strcmp(src, src_str) && !strcmp(grp, grp_str)) { + ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj, json); + } + } + + if (uj) { + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); + json_object_free(json); + } +} + +DEFUN (show_ip_msdp_sa_sg, + show_ip_msdp_sa_sg_cmd, + "show ip msdp sa [A.B.C.D] [A.B.C.D] [json]", + SHOW_STR + IP_STR + MSDP_STR + "MSDP active-source information\n" + "source or group ip\n" + "group ip\n" + "JavaScript Object Notation\n") +{ + u_char uj = use_json(argc, argv); + if (argv[5]->arg) + ip_msdp_show_sa_sg(vty, argv[4]->arg, argv[5]->arg, uj); + else if (argv[4]->arg) + ip_msdp_show_sa_addr(vty, argv[4]->arg, uj); + else + ip_msdp_show_sa(vty, uj); return CMD_SUCCESS; } @@ -5419,8 +5988,6 @@ void pim_cmd_init() install_element (VIEW_NODE, &show_ip_mroute_count_cmd); install_element (VIEW_NODE, &show_ip_rib_cmd); install_element (VIEW_NODE, &show_ip_ssmpingd_cmd); - install_element (VIEW_NODE, &show_ip_msdp_peer_cmd); - install_element (VIEW_NODE, &show_ip_msdp_sa_cmd); install_element (VIEW_NODE, &show_debugging_pim_cmd); install_element (ENABLE_NODE, &clear_ip_interfaces_cmd); @@ -5508,4 +6075,15 @@ void pim_cmd_init() install_element (CONFIG_NODE, &debug_msdp_packets_cmd); install_element (CONFIG_NODE, &no_debug_msdp_packets_cmd); install_element (CONFIG_NODE, &undebug_msdp_packets_cmd); + install_element (CONFIG_NODE, &ip_msdp_peer_cmd); + install_element (CONFIG_NODE, &no_ip_msdp_peer_cmd); + install_element (CONFIG_NODE, &ip_msdp_mesh_group_member_cmd); + install_element (CONFIG_NODE, &no_ip_msdp_mesh_group_member_cmd); + install_element (CONFIG_NODE, &ip_msdp_mesh_group_source_cmd); + install_element (CONFIG_NODE, &no_ip_msdp_mesh_group_source_cmd); + install_element (CONFIG_NODE, &no_ip_msdp_mesh_group_cmd); + install_element (VIEW_NODE, &show_ip_msdp_peer_detail_cmd); + install_element (VIEW_NODE, &show_ip_msdp_sa_detail_cmd); + install_element (VIEW_NODE, &show_ip_msdp_sa_sg_cmd); + install_element (VIEW_NODE, &show_ip_msdp_mesh_group_cmd); } diff --git a/pimd/pim_cmd.h b/pimd/pim_cmd.h index dd9300df8e..2d09da4b58 100644 --- a/pimd/pim_cmd.h +++ b/pimd/pim_cmd.h @@ -63,6 +63,7 @@ #define MSDP_STR "MSDP information\n" #define DEBUG_MSDP_STR "MSDP protocol activity\n" #define DEBUG_MSDP_EVENTS_STR "MSDP protocol events\n" +#define DEBUG_MSDP_INTERNAL_STR "MSDP protocol internal\n" #define DEBUG_MSDP_PACKETS_STR "MSDP protocol packets\n" void pim_cmd_init(void); diff --git a/pimd/pim_memory.c b/pimd/pim_memory.c index da37da6997..a8d4c3404e 100644 --- a/pimd/pim_memory.c +++ b/pimd/pim_memory.c @@ -42,5 +42,7 @@ DEFINE_MTYPE(PIMD, PIM_BR, "PIM Bridge Router info") DEFINE_MTYPE(PIMD, PIM_RP, "PIM RP info") DEFINE_MTYPE(PIMD, PIM_FILTER_NAME, "PIM RP filter info") DEFINE_MTYPE(PIMD, PIM_MSDP_PEER, "PIM MSDP peer") -DEFINE_MTYPE(PIMD, PIM_MSDP_PEER_MG_NAME, "PIM MSDP peer mesh-group") +DEFINE_MTYPE(PIMD, PIM_MSDP_MG_NAME, "PIM MSDP mesh-group name") DEFINE_MTYPE(PIMD, PIM_MSDP_SA, "PIM MSDP source-active cache") +DEFINE_MTYPE(PIMD, PIM_MSDP_MG, "PIM MSDP mesh group") +DEFINE_MTYPE(PIMD, PIM_MSDP_MG_MBR, "PIM MSDP mesh group mbr") diff --git a/pimd/pim_memory.h b/pimd/pim_memory.h index 434de0b194..0f47fc22b4 100644 --- a/pimd/pim_memory.h +++ b/pimd/pim_memory.h @@ -41,7 +41,9 @@ DECLARE_MTYPE(PIM_BR) DECLARE_MTYPE(PIM_RP) DECLARE_MTYPE(PIM_FILTER_NAME) DECLARE_MTYPE(PIM_MSDP_PEER) -DECLARE_MTYPE(PIM_MSDP_PEER_MG_NAME) +DECLARE_MTYPE(PIM_MSDP_MG_NAME) DECLARE_MTYPE(PIM_MSDP_SA) +DECLARE_MTYPE(PIM_MSDP_MG) +DECLARE_MTYPE(PIM_MSDP_MG_MBR) #endif /* _QUAGGA_PIM_MEMORY_H */ diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 43e2e888f5..76127245ce 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -51,6 +51,9 @@ static void pim_msdp_peer_free(struct pim_msdp_peer *mp); static void pim_msdp_enable(void); static void pim_msdp_sa_adv_timer_setup(bool start); static void pim_msdp_sa_deref(struct pim_msdp_sa *sa, enum pim_msdp_sa_flags flags); +static int pim_msdp_mg_mbr_comp(const void *p1, const void *p2); +static void pim_msdp_mg_mbr_free(struct pim_msdp_mg_mbr *mbr); +static void pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, struct pim_msdp_mg_mbr *mbr); /************************ SA cache management ******************************/ char * @@ -714,6 +717,10 @@ pim_msdp_peer_listen(struct pim_msdp_peer *mp) void pim_msdp_peer_established(struct pim_msdp_peer *mp) { + if (mp->state != PIM_MSDP_ESTABLISHED) { + ++mp->est_flaps; + } + mp->state = PIM_MSDP_ESTABLISHED; mp->uptime = pim_time_monotonic_sec(); @@ -740,6 +747,9 @@ void pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state) { if (chg_state) { + if (mp->state == PIM_MSDP_ESTABLISHED) { + ++mp->est_flaps; + } mp->state = PIM_MSDP_INACTIVE; if (PIM_DEBUG_MSDP_EVENTS) { pim_msdp_peer_state_chg_log(mp); @@ -783,6 +793,7 @@ pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str) pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), false); zlog_debug("%s tcp reset %s", key_str, rc_str); + snprintf(mp->last_reset, sizeof(mp->last_reset), "%s", rc_str); } /* close the connection and transition to listening or connecting */ @@ -868,6 +879,7 @@ static void pim_msdp_peer_active_connect(struct pim_msdp_peer *mp) { int rc; + ++mp->conn_attempts; rc = pim_msdp_sock_connect(mp); if (PIM_DEBUG_MSDP_INTERNAL) { @@ -879,6 +891,7 @@ pim_msdp_peer_active_connect(struct pim_msdp_peer *mp) switch (rc) { case connect_error: + case -1: /* connect failed restart the connect-retry timer */ pim_msdp_peer_cr_timer_setup(mp, true /* start */); break; @@ -962,7 +975,7 @@ static void pim_msdp_addr2su(union sockunion *su, struct in_addr addr) /* 11.2.A1: create a new peer and transition state to listen or connecting */ static enum pim_msdp_err pim_msdp_peer_new(struct in_addr peer_addr, struct in_addr local_addr, - const char *mesh_group_name) + const char *mesh_group_name, struct pim_msdp_peer **mp_p) { struct pim_msdp_peer *mp; @@ -981,9 +994,10 @@ pim_msdp_peer_new(struct in_addr peer_addr, struct in_addr local_addr, /* XXX: originator_id setting needs to move to the mesh group */ msdp->originator_id = local_addr; pim_msdp_addr2su(&mp->su_local, mp->local); - mp->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_PEER_MG_NAME, mesh_group_name); + mp->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name); mp->state = PIM_MSDP_INACTIVE; mp->fd = -1; + strcpy(mp->last_reset, "-"); /* higher IP address is listener */ if (ntohl(mp->local.s_addr) > ntohl(mp->peer.s_addr)) { mp->flags |= PIM_MSDP_PEERF_LISTENER; @@ -1012,6 +1026,9 @@ pim_msdp_peer_new(struct in_addr peer_addr, struct in_addr local_addr, } else { pim_msdp_peer_connect(mp); } + if (mp_p) { + *mp_p = mp; + } return PIM_MSDP_ERR_NONE; } @@ -1027,16 +1044,34 @@ pim_msdp_peer_find(struct in_addr peer_addr) /* add peer configuration if it doesn't already exist */ enum pim_msdp_err pim_msdp_peer_add(struct in_addr peer_addr, struct in_addr local_addr, - const char *mesh_group_name) + const char *mesh_group_name, struct pim_msdp_peer **mp_p) { struct pim_msdp_peer *mp; + if (mp_p) { + *mp_p = NULL; + } + + if (peer_addr.s_addr == local_addr.s_addr) { + /* skip session setup if config is invalid */ + if (PIM_DEBUG_MSDP_EVENTS) { + char peer_str[INET_ADDRSTRLEN]; + + pim_inet4_dump("", peer_addr, peer_str, sizeof(peer_str)); + zlog_debug("%s add skipped as DIP=SIP", peer_str); + } + return PIM_MSDP_ERR_SIP_EQ_DIP; + } + mp = pim_msdp_peer_find(peer_addr); if (mp) { + if (mp_p) { + *mp_p = mp; + } return PIM_MSDP_ERR_PEER_EXISTS; } - return pim_msdp_peer_new(peer_addr, local_addr, mesh_group_name); + return pim_msdp_peer_new(peer_addr, local_addr, mesh_group_name, mp_p); } /* release all mem associated with a peer */ @@ -1052,22 +1087,15 @@ pim_msdp_peer_free(struct pim_msdp_peer *mp) } if (mp->mesh_group_name) { - XFREE(MTYPE_PIM_MSDP_PEER_MG_NAME, mp->mesh_group_name); + XFREE(MTYPE_PIM_MSDP_MG_NAME, mp->mesh_group_name); } XFREE(MTYPE_PIM_MSDP_PEER, mp); } /* delete the peer config */ -enum pim_msdp_err -pim_msdp_peer_del(struct in_addr peer_addr) +static enum pim_msdp_err +pim_msdp_peer_do_del(struct pim_msdp_peer *mp) { - struct pim_msdp_peer *mp; - - mp = pim_msdp_peer_find(peer_addr); - if (!mp) { - return PIM_MSDP_ERR_NO_PEER; - } - /* stop the tcp connection and shutdown all timers */ pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); @@ -1088,6 +1116,19 @@ pim_msdp_peer_del(struct in_addr peer_addr) return PIM_MSDP_ERR_NONE; } +enum pim_msdp_err +pim_msdp_peer_del(struct in_addr peer_addr) +{ + struct pim_msdp_peer *mp; + + mp = pim_msdp_peer_find(peer_addr); + if (!mp) { + return PIM_MSDP_ERR_NO_PEER; + } + + return pim_msdp_peer_do_del(mp); +} + /* peer hash and peer list helpers */ static unsigned int pim_msdp_peer_hash_key_make(void *p) @@ -1120,21 +1161,317 @@ pim_msdp_peer_comp(const void *p1, const void *p2) return 0; } +/************************** Mesh group management **************************/ +static void +pim_msdp_mg_free(struct pim_msdp_mg *mg) +{ + /* If the mesh-group has valid member or src_ip don't delete it */ + if (!mg || mg->mbr_cnt || (mg->src_ip.s_addr != INADDR_ANY)) { + return; + } + + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP mesh-group %s deleted", mg->mesh_group_name); + } + if (mg->mesh_group_name) + XFREE(MTYPE_PIM_MSDP_MG_NAME, mg->mesh_group_name); + XFREE(MTYPE_PIM_MSDP_MG, mg); + + msdp->mg = NULL; +} + +static struct pim_msdp_mg * +pim_msdp_mg_new(const char *mesh_group_name) +{ + struct pim_msdp_mg *mg; + + mg = XCALLOC(MTYPE_PIM_MSDP_MG, sizeof(*mg)); + if (!mg) { + zlog_err("%s: PIM XCALLOC(%zu) failure", + __PRETTY_FUNCTION__, sizeof(*mg)); + return NULL; + } + + mg->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name); + mg->mbr_list = list_new(); + mg->mbr_list->del = (void (*)(void *))pim_msdp_mg_mbr_free; + mg->mbr_list->cmp = (int (*)(void *, void *))pim_msdp_mg_mbr_comp; + + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP mesh-group %s created", mg->mesh_group_name); + } + return mg; +} + +enum pim_msdp_err +pim_msdp_mg_del(const char *mesh_group_name) +{ + struct pim_msdp_mg *mg = msdp->mg; + struct pim_msdp_mg_mbr *mbr; + + if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { + return PIM_MSDP_ERR_NO_MG; + } + + /* delete all the mesh-group members */ + while (!list_isempty(mg->mbr_list)) { + mbr = listnode_head(mg->mbr_list); + pim_msdp_mg_mbr_do_del(mg, mbr); + } + + /* clear src ip */ + mg->src_ip.s_addr = INADDR_ANY; + + /* free up the mesh-group */ + pim_msdp_mg_free(mg); + return PIM_MSDP_ERR_NONE; +} + +static enum pim_msdp_err +pim_msdp_mg_add(const char *mesh_group_name) +{ + if (msdp->mg) { + if (!strcmp(msdp->mg->mesh_group_name, mesh_group_name)) { + return PIM_MSDP_ERR_NONE; + } + /* currently only one mesh-group can exist at a time */ + return PIM_MSDP_ERR_MAX_MESH_GROUPS; + } + + msdp->mg = pim_msdp_mg_new(mesh_group_name); + if (!msdp->mg) { + return PIM_MSDP_ERR_OOM; + } + + return PIM_MSDP_ERR_NONE; +} + +static int +pim_msdp_mg_mbr_comp(const void *p1, const void *p2) +{ + const struct pim_msdp_mg_mbr *mbr1 = p1; + const struct pim_msdp_mg_mbr *mbr2 = p2; + + if (ntohl(mbr1->mbr_ip.s_addr) < ntohl(mbr2->mbr_ip.s_addr)) + return -1; + + if (ntohl(mbr1->mbr_ip.s_addr) > ntohl(mbr2->mbr_ip.s_addr)) + return 1; + + return 0; +} + +static void +pim_msdp_mg_mbr_free(struct pim_msdp_mg_mbr *mbr) +{ + XFREE(MTYPE_PIM_MSDP_MG_MBR, mbr); +} + +static struct pim_msdp_mg_mbr * +pim_msdp_mg_mbr_find(struct in_addr mbr_ip) +{ + struct pim_msdp_mg_mbr *mbr; + struct listnode *mbr_node; + + if (!msdp->mg) { + return NULL; + } + /* we can move this to a hash but considering that number of peers in + * a mesh-group that seems like bit of an overkill */ + for (ALL_LIST_ELEMENTS_RO(msdp->mg->mbr_list, mbr_node, mbr)) { + if (mbr->mbr_ip.s_addr == mbr_ip.s_addr) { + return mbr; + } + } + return mbr; +} + +enum pim_msdp_err +pim_msdp_mg_mbr_add(const char *mesh_group_name, struct in_addr mbr_ip) +{ + int rc; + struct pim_msdp_mg_mbr *mbr; + struct pim_msdp_mg *mg; + + rc = pim_msdp_mg_add(mesh_group_name); + if (rc != PIM_MSDP_ERR_NONE) { + return rc; + } + + mg = msdp->mg; + mbr = pim_msdp_mg_mbr_find(mbr_ip); + if (mbr) { + return PIM_MSDP_ERR_MG_MBR_EXISTS; + } + + mbr = XCALLOC(MTYPE_PIM_MSDP_MG_MBR, sizeof(*mbr)); + if (!mbr) { + zlog_err("%s: PIM XCALLOC(%zu) failure", + __PRETTY_FUNCTION__, sizeof(*mbr)); + /* if there are no references to the mg free it */ + pim_msdp_mg_free(mg); + return PIM_MSDP_ERR_OOM; + } + mbr->mbr_ip = mbr_ip; + listnode_add_sort(mg->mbr_list, mbr); + + /* if valid SIP has been configured add peer session */ + if (mg->src_ip.s_addr != INADDR_ANY) { + pim_msdp_peer_add(mbr_ip, mg->src_ip, mesh_group_name, + &mbr->mp); + } + + if (PIM_DEBUG_MSDP_EVENTS) { + char ip_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", mbr->mbr_ip, ip_str, sizeof(ip_str)); + zlog_debug("MSDP mesh-group %s mbr %s created", mg->mesh_group_name, ip_str); + } + ++mg->mbr_cnt; + return PIM_MSDP_ERR_NONE; +} + +static void +pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, struct pim_msdp_mg_mbr *mbr) +{ + /* Delete active peer session if any */ + if (mbr->mp) { + pim_msdp_peer_do_del(mbr->mp); + } + + listnode_delete(mg->mbr_list, mbr); + if (PIM_DEBUG_MSDP_EVENTS) { + char ip_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", mbr->mbr_ip, ip_str, sizeof(ip_str)); + zlog_debug("MSDP mesh-group %s mbr %s deleted", mg->mesh_group_name, ip_str); + } + pim_msdp_mg_mbr_free(mbr); + if (mg->mbr_cnt) { + --mg->mbr_cnt; + } +} + +enum pim_msdp_err +pim_msdp_mg_mbr_del(const char *mesh_group_name, struct in_addr mbr_ip) +{ + struct pim_msdp_mg_mbr *mbr; + struct pim_msdp_mg *mg = msdp->mg; + + if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { + return PIM_MSDP_ERR_NO_MG; + } + + mbr = pim_msdp_mg_mbr_find(mbr_ip); + if (!mbr) { + return PIM_MSDP_ERR_NO_MG_MBR; + } + + pim_msdp_mg_mbr_do_del(mg, mbr); + /* if there are no references to the mg free it */ + pim_msdp_mg_free(mg); + + return PIM_MSDP_ERR_NONE; +} + +static void +pim_msdp_mg_src_do_del(void) +{ + struct pim_msdp_mg_mbr *mbr; + struct listnode *mbr_node; + struct pim_msdp_mg *mg = msdp->mg; + + /* SIP is being removed - tear down all active peer sessions */ + for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) { + if (mbr->mp) { + pim_msdp_peer_do_del(mbr->mp); + mbr->mp = NULL; + } + } + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP mesh-group %s src cleared", mg->mesh_group_name); + } +} + +enum pim_msdp_err +pim_msdp_mg_src_del(const char *mesh_group_name) +{ + struct pim_msdp_mg *mg = msdp->mg; + + if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { + return PIM_MSDP_ERR_NO_MG; + } + + if (mg->src_ip.s_addr != INADDR_ANY) { + mg->src_ip.s_addr = INADDR_ANY; + pim_msdp_mg_src_do_del(); + /* if there are no references to the mg free it */ + pim_msdp_mg_free(mg); + } + return PIM_MSDP_ERR_NONE; +} + +enum pim_msdp_err +pim_msdp_mg_src_add(const char *mesh_group_name, struct in_addr src_ip) +{ + int rc; + struct pim_msdp_mg_mbr *mbr; + struct listnode *mbr_node; + struct pim_msdp_mg *mg; + + if (src_ip.s_addr == INADDR_ANY) { + pim_msdp_mg_src_del(mesh_group_name); + return PIM_MSDP_ERR_NONE; + } + + rc = pim_msdp_mg_add(mesh_group_name); + if (rc != PIM_MSDP_ERR_NONE) { + return rc; + } + + mg = msdp->mg; + if (mg->src_ip.s_addr != INADDR_ANY) { + pim_msdp_mg_src_do_del(); + } + mg->src_ip = src_ip; + + for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) { + pim_msdp_peer_add(mbr->mbr_ip, mg->src_ip, mesh_group_name, + &mbr->mp); + } + + if (PIM_DEBUG_MSDP_EVENTS) { + char ip_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", mg->src_ip, ip_str, sizeof(ip_str)); + zlog_debug("MSDP mesh-group %s src %s set", mg->mesh_group_name, ip_str); + } + return PIM_MSDP_ERR_NONE; +} + /*********************** MSDP feature APIs *********************************/ int pim_msdp_config_write(struct vty *vty) { - struct listnode *mpnode; - struct pim_msdp_peer *mp; - char peer_str[INET_ADDRSTRLEN]; - char local_str[INET_ADDRSTRLEN]; + struct listnode *mbrnode; + struct pim_msdp_mg_mbr *mbr; + struct pim_msdp_mg *mg = msdp->mg; + char mbr_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; int count = 0; - for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { - pim_inet4_dump("", mp->peer, peer_str, sizeof(peer_str)); - pim_inet4_dump("", mp->local, local_str, sizeof(local_str)); - vty_out(vty, "ip msdp peer %s source %s%s", - peer_str, local_str, VTY_NEWLINE); + if (!mg) { + return count; + } + + if (mg->src_ip.s_addr != INADDR_ANY) { + pim_inet4_dump("", mg->src_ip, src_str, sizeof(src_str)); + vty_out(vty, "ip msdp mesh-group %s source %s%s", + mg->mesh_group_name, src_str, VTY_NEWLINE); + ++count; + } + + for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) { + pim_inet4_dump("", mbr->mbr_ip, mbr_str, sizeof(mbr_str)); + vty_out(vty, "ip msdp mesh-group %s member %s%s", + mg->mesh_group_name, mbr_str, VTY_NEWLINE); ++count; } return count; diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h index 5e13b33b5b..4809749b94 100644 --- a/pimd/pim_msdp.h +++ b/pimd/pim_msdp.h @@ -46,12 +46,17 @@ enum pim_msdp_err { PIM_MSDP_ERR_PEER_EXISTS = -2, PIM_MSDP_ERR_MAX_MESH_GROUPS = -3, PIM_MSDP_ERR_NO_PEER = -4, + PIM_MSDP_ERR_MG_MBR_EXISTS = -5, + PIM_MSDP_ERR_NO_MG = -6, + PIM_MSDP_ERR_NO_MG_MBR = -7, + PIM_MSDP_ERR_SIP_EQ_DIP = -8, }; #define PIM_MSDP_STATE_STRLEN 16 #define PIM_MSDP_PEER_KEY_STRLEN 80 #define PIM_MSDP_SA_KEY_STRLEN 80 #define PIM_MSDP_UPTIME_STRLEN 80 +#define PIM_MSDP_TIMER_STRLEN 12 #define PIM_MSDP_TCP_PORT 639 #define PIM_MSDP_SOCKET_SNDBUF_SIZE 65536 @@ -123,6 +128,12 @@ struct pim_msdp_peer { struct thread *t_write; /* stats */ + uint32_t conn_attempts; + uint32_t est_flaps; +#define PIM_MSDP_PEER_LAST_RESET_STR 20 + char last_reset[PIM_MSDP_PEER_LAST_RESET_STR]; + + /* packet stats */ uint32_t ka_tx_cnt; uint32_t sa_tx_cnt; uint32_t ka_rx_cnt; @@ -133,6 +144,19 @@ struct pim_msdp_peer { int64_t uptime; }; +struct pim_msdp_mg_mbr { + struct in_addr mbr_ip; + struct pim_msdp_peer *mp; +}; + +/* PIM MSDP mesh-group */ +struct pim_msdp_mg { + char *mesh_group_name; + struct in_addr src_ip; + uint32_t mbr_cnt; + struct list *mbr_list; +}; + enum pim_msdp_flags { PIM_MSDPF_NONE = 0, PIM_MSDPF_ENABLE = (1 << 0), @@ -166,6 +190,9 @@ struct pim_msdp { struct stream *work_obuf; struct in_addr originator_id; + + /* currently only one mesh-group is supported - so just stash it here */ + struct pim_msdp_mg *mg; }; #define PIM_MSDP_PEER_READ_ON(mp) THREAD_READ_ON(msdp->master, mp->t_read, pim_msdp_read, mp, mp->fd); @@ -177,7 +204,7 @@ struct pim_msdp { extern struct pim_msdp *msdp; void pim_msdp_init(struct thread_master *master); void pim_msdp_exit(void); -enum pim_msdp_err pim_msdp_peer_add(struct in_addr peer, struct in_addr local, const char *mesh_group_name); +enum pim_msdp_err pim_msdp_peer_add(struct in_addr peer, struct in_addr local, const char *mesh_group_name, struct pim_msdp_peer **mp_p); enum pim_msdp_err pim_msdp_peer_del(struct in_addr peer_addr); char *pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf, int buf_size); struct pim_msdp_peer *pim_msdp_peer_find(struct in_addr peer_addr); @@ -197,4 +224,9 @@ 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); +enum pim_msdp_err pim_msdp_mg_mbr_add(const char *mesh_group_name, struct in_addr mbr_ip); +enum pim_msdp_err pim_msdp_mg_mbr_del(const char *mesh_group_name, struct in_addr mbr_ip); +enum pim_msdp_err pim_msdp_mg_src_del(const char *mesh_group_name); +enum pim_msdp_err pim_msdp_mg_src_add(const char *mesh_group_name, struct in_addr src_ip); +enum pim_msdp_err pim_msdp_mg_del(const char *mesh_group_name); #endif diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index d336051f2b..d7251e0348 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -53,6 +53,10 @@ pim_debug_config_write (struct vty *vty) vty_out(vty, "debug msdp packets%s", VTY_NEWLINE); ++writes; } + if (PIM_DEBUG_MSDP_INTERNAL) { + vty_out(vty, "debug msdp internal%s", VTY_NEWLINE); + ++writes; + } if (PIM_DEBUG_IGMP_EVENTS) { vty_out(vty, "debug igmp events%s", VTY_NEWLINE); ++writes; From 3440bd157353d67808eb77cd9045b730900a21d5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 14 Nov 2016 19:54:36 -0500 Subject: [PATCH 295/386] pimd: Fix crash in pim_rp_show_information When a 'show ip pim rp-info' is issued shortly after a restart/start, pim will crash because nexthop information has not been fully resolved and the outgoing interface is NULL. Ticket: CM-13567 Signed-off-by: Donald Sharp --- pimd/pim_rp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 1bd48798c6..abc06b4eff 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -734,7 +734,8 @@ pim_rp_show_information (struct vty *vty, u_char uj) json_rp_rows = json_object_new_array(); json_row = json_object_new_object(); - json_object_string_add(json_row, "outboundInterface", rp_info->rp.source_nexthop.interface->name); + if (rp_info->rp.source_nexthop.interface) + json_object_string_add(json_row, "outboundInterface", rp_info->rp.source_nexthop.interface->name); if (rp_info->i_am_rp) json_object_boolean_true_add(json_row, "iAmRP"); @@ -755,7 +756,10 @@ pim_rp_show_information (struct vty *vty, u_char uj) else vty_out (vty, "%-18s ", prefix2str(&rp_info->group, buf, 48)); - vty_out (vty, "%-10s ", rp_info->rp.source_nexthop.interface->name); + if (rp_info->rp.source_nexthop.interface) + vty_out (vty, "%-10s ", rp_info->rp.source_nexthop.interface->name); + else + vty_out (vty, "%-10s ", "(Unknown)"); if (rp_info->i_am_rp) vty_out (vty, "yes%s", VTY_NEWLINE); From c83778f769238f9e9e943addb638825e9ed2b1da Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 15 Nov 2016 12:09:14 -0500 Subject: [PATCH 296/386] pimd: Allow 'no ip pim sm' to not turn off igmp When we receive a 'no ip pim sm' for an interface that has both pim and igmp on it, only turn off pim. Ticket: CM-12985 Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 84350676a7..c28aad0384 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4315,12 +4315,6 @@ pim_cmd_interface_delete (struct interface *ifp) pim_if_membership_clear(ifp); - /* - pim_if_addr_del_all() removes all sockets from - pim_ifp->igmp_socket_list. - */ - pim_if_addr_del_all(ifp); - /* pim_sock_delete() removes all neighbors from pim_ifp->pim_neighbor_list. @@ -4328,6 +4322,7 @@ pim_cmd_interface_delete (struct interface *ifp) pim_sock_delete(ifp, "pim unconfigured on interface"); if (!PIM_IF_TEST_IGMP(pim_ifp->options)) { + pim_if_addr_del_all(ifp); pim_if_delete(ifp); } From e30a4d4afe1027f2b129597410bafc4c159ed834 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 15 Nov 2016 12:22:34 -0500 Subject: [PATCH 297/386] pimd: Allow 'ip pim rp ...' config after bringup If you specified the 'ip pim rp ...' after the system has been configured it was not accepting the new rp. This fixes that issue. Ticket:CM-12623 Signed-off-by: Donald Sharp --- pimd/pim_rp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index abc06b4eff..1181cea819 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -489,6 +489,9 @@ pim_rp_setup (void) for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { + if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) + continue; + if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1) != 0) { if (PIM_DEBUG_PIM_TRACE) From 980e939362dfb298f14a520851ba4804d753cdb9 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 15 Nov 2016 12:27:17 -0500 Subject: [PATCH 298/386] pimd: Use NULL to signify NULL pointer Use the NULL c symbol to signify that we are intentionally setting the pointer to NULL instead of 0. Signed-off-by: Donald Sharp --- pimd/pim_igmpv3.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index 2e23cdb10f..987ab895ae 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -131,7 +131,7 @@ static int igmp_source_timer(struct thread *t) } zassert(source->t_source_timer); - source->t_source_timer = 0; + source->t_source_timer = NULL; /* RFC 3376: 6.3. IGMPv3 Source-Specific Forwarding Rules @@ -338,7 +338,7 @@ static void source_channel_oil_detach(struct igmp_source *source) { if (source->source_channel_oil) { pim_channel_oil_del(source->source_channel_oil); - source->source_channel_oil = 0; + source->source_channel_oil = NULL; } } @@ -1276,7 +1276,7 @@ static int igmp_group_retransmit(struct thread *t) num_retransmit_sources_left = group_retransmit_sources(group, send_with_sflag_set); - group->t_group_query_retransmit_timer = 0; + group->t_group_query_retransmit_timer = NULL; /* Keep group retransmit timer running if there is any retransmit From 5f9cf1d209e4980f6ade2c98db3eb90391815f35 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Tue, 15 Nov 2016 19:08:22 +0000 Subject: [PATCH 299/386] pimd: 'show ip pim rp-info json' should use JSON_C_TO_STRING_PRETTY Signed-off-by: Daniel Walton --- pimd/pim_rp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 1181cea819..118c8a3130 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -778,7 +778,7 @@ pim_rp_show_information (struct vty *vty, u_char uj) if (prev_rp_info && json_rp_rows) json_object_object_add(json, inet_ntoa (prev_rp_info->rp.rpf_addr.u.prefix4), json_rp_rows); - vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE); + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); json_object_free(json); } } From def1e8073227ea17ee24971b2114be520b7bca8d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 15 Nov 2016 21:27:28 -0500 Subject: [PATCH 300/386] pimd: Protect log messages with debug in pim_pim.c Protect the log messages in pim_pim.c with PIM_DEBUG_PIM_PACKETS Signed-off-by: Donald Sharp --- pimd/pim_pim.c | 59 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 80e69e276b..c2082ce3d0 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -143,14 +143,16 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) struct pim_neighbor *neigh; if (!ifp->info) { - zlog_warn("%s: PIM not enabled on interface %s", - __PRETTY_FUNCTION__, ifp->name); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("%s: PIM not enabled on interface %s", + __PRETTY_FUNCTION__, ifp->name); return -1; } if (len < sizeof(*ip_hdr)) { - zlog_warn("PIM packet size=%zu shorter than minimum=%zu", - len, sizeof(*ip_hdr)); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("PIM packet size=%zu shorter than minimum=%zu", + len, sizeof(*ip_hdr)); return -1; } @@ -167,19 +169,22 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) } if (ip_hdr->ip_p != PIM_IP_PROTO_PIM) { - zlog_warn("IP packet protocol=%d is not PIM=%d", - ip_hdr->ip_p, PIM_IP_PROTO_PIM); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("IP packet protocol=%d is not PIM=%d", + ip_hdr->ip_p, PIM_IP_PROTO_PIM); return -1; } if (ip_hlen < PIM_IP_HEADER_MIN_LEN) { - zlog_warn("IP packet header size=%zu shorter than minimum=%d", - ip_hlen, PIM_IP_HEADER_MIN_LEN); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("IP packet header size=%zu shorter than minimum=%d", + ip_hlen, PIM_IP_HEADER_MIN_LEN); return -1; } if (ip_hlen > PIM_IP_HEADER_MAX_LEN) { - zlog_warn("IP packet header size=%zu greater than maximum=%d", - ip_hlen, PIM_IP_HEADER_MAX_LEN); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("IP packet header size=%zu greater than maximum=%d", + ip_hlen, PIM_IP_HEADER_MAX_LEN); return -1; } @@ -200,8 +205,9 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) pim_type = PIM_MSG_HDR_GET_TYPE(pim_msg); if (pim_version != PIM_PROTO_VERSION) { - zlog_warn("Ignoring PIM pkt from %s with unsupported version: %d", - ifp->name, pim_version); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("Ignoring PIM pkt from %s with unsupported version: %d", + ifp->name, pim_version); return -1; } @@ -213,8 +219,9 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) checksum = in_cksum(pim_msg, pim_msg_len); if (checksum != pim_checksum) { - zlog_warn("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x", - ifp->name, pim_checksum, checksum); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x", + ifp->name, pim_checksum, checksum); return -1; } @@ -246,9 +253,10 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) case PIM_MSG_TYPE_JOIN_PRUNE: neigh = pim_neighbor_find(ifp, ip_hdr->ip_src); if (!neigh) { - zlog_warn("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", - __FILE__, __PRETTY_FUNCTION__, - pim_type, src_str, ifp->name); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", + __FILE__, __PRETTY_FUNCTION__, + pim_type, src_str, ifp->name); return -1; } return pim_joinprune_recv(ifp, neigh, @@ -259,9 +267,10 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) case PIM_MSG_TYPE_ASSERT: neigh = pim_neighbor_find(ifp, ip_hdr->ip_src); if (!neigh) { - zlog_warn("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", - __FILE__, __PRETTY_FUNCTION__, - pim_type, src_str, ifp->name); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", + __FILE__, __PRETTY_FUNCTION__, + pim_type, src_str, ifp->name); return -1; } return pim_assert_recv(ifp, neigh, @@ -790,8 +799,9 @@ int pim_sock_add(struct interface *ifp) zassert(pim_ifp); if (pim_ifp->pim_sock_fd >= 0) { - zlog_warn("Can't recreate existing PIM socket fd=%d for interface %s", - pim_ifp->pim_sock_fd, ifp->name); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("Can't recreate existing PIM socket fd=%d for interface %s", + pim_ifp->pim_sock_fd, ifp->name); return -1; } @@ -799,8 +809,9 @@ int pim_sock_add(struct interface *ifp) pim_ifp->pim_sock_fd = pim_sock_open(ifaddr, ifp->ifindex); if (pim_ifp->pim_sock_fd < 0) { - zlog_warn("Could not open PIM socket on interface %s", - ifp->name); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("Could not open PIM socket on interface %s", + ifp->name); return -2; } From 7a90f85c1a0fb8a28dd222f49a76dd1c87eed825 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 16 Nov 2016 15:12:25 -0500 Subject: [PATCH 301/386] pimd: Move pim_mroute.c global data to file local static Move the qpim_mroute_socket_reader thread to pim_mroute.c and make it static to the file. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 4 +++- pimd/pimd.c | 1 - pimd/pimd.h | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 7309774548..2557ac9710 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -44,6 +44,8 @@ /* GLOBAL VARS */ extern struct zebra_privs_t pimd_privs; +static struct thread *qpim_mroute_socket_reader = NULL; + static void mroute_read_on(void); static int pim_mroute_set(int fd, int enable) @@ -554,7 +556,7 @@ static int mroute_read(struct thread *t) result = mroute_read_msg(fd); /* Keep reading */ - qpim_mroute_socket_reader = 0; + qpim_mroute_socket_reader = NULL; mroute_read_on(); return result; diff --git a/pimd/pimd.c b/pimd/pimd.c index 69803a6b56..bc8b88444a 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -50,7 +50,6 @@ struct thread_master *master = NULL; uint32_t qpim_debugs = 0; int qpim_mroute_socket_fd = -1; int64_t qpim_mroute_socket_creation = 0; /* timestamp of creation */ -struct thread *qpim_mroute_socket_reader = NULL; int qpim_mroute_oif_highest_vif_index = -1; int qpim_t_periodic = PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */ struct zclient *qpim_zclient_update = NULL; diff --git a/pimd/pimd.h b/pimd/pimd.h index 3f59b36df2..75a13a1e6b 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -95,7 +95,6 @@ extern struct thread_master *master; uint32_t qpim_debugs; int qpim_mroute_socket_fd; int64_t qpim_mroute_socket_creation; /* timestamp of creation */ -struct thread *qpim_mroute_socket_reader; int qpim_mroute_oif_highest_vif_index; struct in_addr qpim_all_pim_routers_addr; int qpim_t_periodic; /* Period between Join/Prune Messages */ From 191f5695df6b66e95ab028cc15eea53966a058b4 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 16 Nov 2016 18:11:49 -0500 Subject: [PATCH 302/386] pimd: Add 'ip pim register-suppress-time <5-60000>' Add the 'ip pim register-suppress-time ...' command. Remove the 'no ip pim rp keep-al...' command as that the register suppress set that value. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 62 ++++++++++++++++++++++++-------------------------- pimd/pim_vty.c | 12 +++++----- 2 files changed, 36 insertions(+), 38 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index c28aad0384..ebe8b362ba 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3360,15 +3360,40 @@ pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, const cha return CMD_SUCCESS; } +DEFUN (ip_pim_register_suppress, + ip_pim_register_suppress_cmd, + "ip pim register-suppress-time <5-60000>", + IP_STR + "pim multicast routing\n" + "Register Suppress Timer\n" + "Seconds\n") +{ + qpim_keep_alive_time = atoi (argv[3]->arg); + return CMD_SUCCESS; +} + +DEFUN (no_ip_pim_register_suppress, + no_ip_pim_register_suppress_cmd, + "no ip pim register-suppress-time <5-60000>", + NO_STR + IP_STR + "pim multicast routing\n" + "Register Suppress Timer\n" + "Seconds\n") +{ + qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; + return CMD_SUCCESS; +} + DEFUN (ip_pim_keep_alive, ip_pim_keep_alive_cmd, "ip pim keep-alive-timer <31-60000>", IP_STR "pim multicast routing\n" - "Keep alive Timer" - "Seconds") + "Keep alive Timer\n" + "Seconds\n") { - qpim_keep_alive_time = atoi (argv[3]->arg); + qpim_rp_keep_alive_time = atoi (argv[4]->arg); return CMD_SUCCESS; } @@ -3385,33 +3410,6 @@ DEFUN (no_ip_pim_keep_alive, return CMD_SUCCESS; } -DEFUN (ip_pim_rp_keep_alive, - ip_pim_rp_keep_alive_cmd, - "ip pim rp keep-alive-timer <31-60000>", - IP_STR - "pim multicast routing\n" - "Rendevous Point\n" - "Keep alive Timer\n" - "Seconds\n") -{ - qpim_rp_keep_alive_time = atoi (argv[4]->arg); - return CMD_SUCCESS; -} - -DEFUN (no_ip_pim_rp_keep_alive, - no_ip_pim_rp_keep_alive_cmd, - "no ip pim rp keep-alive-timer <31-60000>", - NO_STR - IP_STR - "pim multicast routing\n" - "Rendevous Point\n" - "Keep alive Timer\n" - "Seconds\n") -{ - qpim_rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD; - return CMD_SUCCESS; -} - DEFUN (ip_pim_rp, ip_pim_rp_cmd, "ip pim rp A.B.C.D [A.B.C.D/M]", @@ -5921,10 +5919,10 @@ void pim_cmd_init() install_element (CONFIG_NODE, &no_ip_pim_rp_cmd); install_element (CONFIG_NODE, &ip_pim_rp_prefix_list_cmd); install_element (CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd); + install_element (CONFIG_NODE, &ip_pim_register_suppress_cmd); + install_element (CONFIG_NODE, &no_ip_pim_register_suppress_cmd); install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd); install_element (CONFIG_NODE, &no_ip_pim_keep_alive_cmd); - install_element (CONFIG_NODE, &ip_pim_rp_keep_alive_cmd); - install_element (CONFIG_NODE, &no_ip_pim_rp_keep_alive_cmd); install_element (CONFIG_NODE, &ip_ssmpingd_cmd); install_element (CONFIG_NODE, &no_ip_ssmpingd_cmd); install_element (CONFIG_NODE, &ip_msdp_peer_cmd); diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index d7251e0348..b72602e22e 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -156,18 +156,18 @@ int pim_global_config_write(struct vty *vty) writes += pim_rp_config_write (vty); + if (qpim_register_suppress_time != PIM_REGISTER_SUPPRESSION_TIME_DEFAULT) + { + vty_out (vty, "ip pim register-suppress-time %d%s", + qpim_register_suppress_time, VTY_NEWLINE); + ++writes; + } if (qpim_keep_alive_time != PIM_KEEPALIVE_PERIOD) { vty_out (vty, "ip pim keep-alive-timer %d%s", qpim_keep_alive_time, VTY_NEWLINE); ++writes; } - if (qpim_rp_keep_alive_time != PIM_RP_KEEPALIVE_PERIOD) - { - vty_out (vty, "ip pim rp keep-alive-timer %d%s", - qpim_rp_keep_alive_time, VTY_NEWLINE); - ++writes; - } if (qpim_ssmpingd_list) { struct listnode *node; From 4f7c4a76d8cb3e5863e3f23df2b4ff4f89055f6b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 16 Nov 2016 14:38:14 -0500 Subject: [PATCH 303/386] pimd: Increase kernel socket rcvbuf size. We are receiving notifications from the linux kernel that we are filling up the receive buffer for upcalls into pimd. Let's increase the size to something a bit bigger. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 2557ac9710..3b8aed033c 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -53,6 +53,7 @@ static int pim_mroute_set(int fd, int enable) int err; int opt = enable ? MRT_INIT : MRT_DONE; socklen_t opt_len = sizeof(opt); + int rcvbuf = 1024 * 1024 * 8; err = setsockopt(fd, IPPROTO_IP, opt, &opt, opt_len); if (err) { @@ -62,6 +63,12 @@ static int pim_mroute_set(int fd, int enable) return -1; } + err = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); + if (err) { + zlog_warn("%s: failure: setsockopt(fd=%d, SOL_SOCKET, %d): errno=%d: %s", + __PRETTY_FUNCTION__, fd, rcvbuf, errno, safe_strerror(errno)); + } + if (enable) { int upcalls = IGMPMSG_WRVIFWHOLE; From 0e3b3d5d1023543618d7c792f32b93e171bd250b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 16 Nov 2016 19:20:33 -0500 Subject: [PATCH 304/386] pimd: Add appropriate (S,G) debugs for register When we send a register record the S,G if debugs are turned on. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 3 +-- pimd/pim_register.c | 5 +++-- pimd/pim_register.h | 2 +- pimd/pim_upstream.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 3b8aed033c..5fba681a73 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -216,8 +216,7 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf) */ if (!up->t_rs_timer) pim_register_send((uint8_t *)buf + sizeof(struct ip), ntohs (ip_hdr->ip_len), - pim_ifp->primary_address, rpg, 0); - + pim_ifp->primary_address, rpg, 0, up); return 0; } diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 3058df1af4..eb880bdffb 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -145,7 +145,7 @@ pim_register_stop_recv (uint8_t *buf, int buf_size) } void -pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct pim_rpf *rpg, int null_register) +pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct pim_rpf *rpg, int null_register, struct pim_upstream *up) { unsigned char buffer[10000]; unsigned char *b1; @@ -156,7 +156,8 @@ pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct { char rp_str[INET_ADDRSTRLEN]; strcpy (rp_str, inet_ntoa (rpg->rpf_addr.u.prefix4)); - zlog_debug ("Sending %sRegister Packet to %s", null_register ? "NULL " : "", rp_str); + zlog_debug ("Sending %s %sRegister Packet to %s", + pim_str_sg_dump (&up->sg), null_register ? "NULL " : "", rp_str); } ifp = rpg->source_nexthop.interface; diff --git a/pimd/pim_register.h b/pimd/pim_register.h index 4200c5e269..695f0beb82 100644 --- a/pimd/pim_register.h +++ b/pimd/pim_register.h @@ -42,7 +42,7 @@ int pim_register_recv (struct interface *ifp, struct in_addr src_addr, uint8_t *tlv_buf, int tlv_buf_size); -void pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct pim_rpf *rpg, int null_register); +void pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct pim_rpf *rpg, int null_register, struct pim_upstream *up); void pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, struct in_addr src, struct in_addr originator); #endif diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 2abf0b296f..a6d7f6e749 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1170,7 +1170,7 @@ pim_upstream_register_stop_timer (struct thread *t) ip_hdr.ip_len = htons (20); // checksum is broken pim_register_send ((uint8_t *)&ip_hdr, sizeof (struct ip), - pim_ifp->primary_address, rpg, 1); + pim_ifp->primary_address, rpg, 1, up); break; default: break; From 2ecd52cd357072f0d0a9975ead2a6cad99108b6a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 16 Nov 2016 19:44:23 -0500 Subject: [PATCH 305/386] pimd: Remove dead code from pim_register.c Remove the dead test code from pim_register.c Signed-off-by: Donald Sharp --- pimd/pim_register.c | 31 ------------------------------- pimd/pim_register.h | 4 ---- 2 files changed, 35 deletions(-) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index eb880bdffb..914d196339 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -405,34 +405,3 @@ pim_register_recv (struct interface *ifp, return 1; } - - -static int -pim_register_send_test_packet (struct thread *t) -{ - uint8_t *packet; - - packet = THREAD_ARG(t); - - *packet = 4; - - return 1; -} - -/* - * pim_register_send_test_packet - * - * Send a test packet to the RP from source, in group and pps packets per second - */ -void -pim_register_send_test_packet_start (struct in_addr source, - struct in_addr group, - uint32_t pps) -{ - uint8_t *packet = NULL; - - THREAD_TIMER_MSEC_ON(master, send_test_packet_timer, - pim_register_send_test_packet, packet, 1000/pps); - - return; -} diff --git a/pimd/pim_register.h b/pimd/pim_register.h index 695f0beb82..42a908b225 100644 --- a/pimd/pim_register.h +++ b/pimd/pim_register.h @@ -31,10 +31,6 @@ #define PIM_MSG_REGISTER_LEN (8) #define PIM_MSG_REGISTER_STOP_LEN (4) -void pim_register_send_test_packet_start (struct in_addr source, - struct in_addr group, - uint32_t pps); - int pim_register_stop_recv (uint8_t *buf, int buf_size); int pim_register_recv (struct interface *ifp, From 1bf1644338146f843194e44c0abc7c4cdff29056 Mon Sep 17 00:00:00 2001 From: anuradhak Date: Tue, 15 Nov 2016 15:39:11 -0800 Subject: [PATCH 306/386] pim-kat: changed kat handling to match rfc-4601 more closely. 1. This is needed to layout the MSDP macros for determining what SAs are originated by a MSDP speaker. 2. We no longer let the kat timer expire on an active flow. Activity counters/lastuse is polled via a wheel for every SG entry. If new activity is detected the keepalive timer is started and SPT bit set. A SRC_STREAM reference is also created for the entry if one doesn't already exist. 3. If KAT actually expires it means the flow is no longer active. At this point we stop advertising the SA to MSDP peers. We also pull the SRC_STREAM reference (deleting the entry if there are no other references). PS: Checking counters on KAT expiry will come in the next change. Signed-off-by: Anuradha Karuppiah Acked-by: Donald Sharp --- pimd/pim_cmd.c | 63 ++++++++---- pimd/pim_mroute.c | 4 - pimd/pim_msdp.c | 122 +++++++++++++++-------- pimd/pim_msdp.h | 2 +- pimd/pim_register.c | 5 +- pimd/pim_upstream.c | 231 ++++++++++++++++++++++++++++++-------------- pimd/pim_upstream.h | 14 +-- 7 files changed, 292 insertions(+), 149 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index ebe8b362ba..0690130edf 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1632,6 +1632,7 @@ static void pim_show_upstream(struct vty *vty, u_char uj) char join_timer[10]; char rs_timer[10]; char ka_timer[10]; + char msdp_reg_timer[10]; pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); @@ -1639,6 +1640,7 @@ static void pim_show_upstream(struct vty *vty, u_char uj) pim_time_timer_to_hhmmss (join_timer, sizeof(join_timer), up->t_join_timer); pim_time_timer_to_hhmmss (rs_timer, sizeof (rs_timer), up->t_rs_timer); pim_time_timer_to_hhmmss (ka_timer, sizeof (ka_timer), up->t_ka_timer); + pim_time_timer_to_hhmmss (msdp_reg_timer, sizeof (msdp_reg_timer), up->t_msdp_reg_timer); if (uj) { json_object_object_get_ex(json, grp_str, &json_group); @@ -1658,6 +1660,7 @@ static void pim_show_upstream(struct vty *vty, u_char uj) json_object_string_add(json_row, "joinTimer", join_timer); json_object_string_add(json_row, "resetTimer", rs_timer); json_object_string_add(json_row, "keepaliveTimer", ka_timer); + json_object_string_add(json_row, "msdpRegTimer", msdp_reg_timer); json_object_int_add(json_row, "refCount", up->ref_count); json_object_int_add(json_row, "sptBit", up->sptbit); json_object_object_add(json_group, src_str, json_row); @@ -5431,6 +5434,15 @@ DEFUN (no_ip_msdp_mesh_group, return ip_no_msdp_mesh_group_cmd_worker(vty, argv[4]->arg); } +static void +print_empty_json_obj(struct vty *vty) +{ + json_object *json; + json = json_object_new_object(); + vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); + json_object_free(json); +} + static void ip_msdp_show_mesh_group(struct vty *vty, u_char uj) { @@ -5446,6 +5458,8 @@ ip_msdp_show_mesh_group(struct vty *vty, u_char uj) json_object *json_row = NULL; if (!mg) { + if (uj) + print_empty_json_obj(vty); return; } @@ -5670,6 +5684,7 @@ ip_msdp_show_sa(struct vty *vty, u_char uj) char rp_str[INET_ADDRSTRLEN]; char timebuf[PIM_MSDP_UPTIME_STRLEN]; char spt_str[8]; + char local_str[8]; int64_t now; json_object *json = NULL; json_object *json_group = NULL; @@ -5678,7 +5693,7 @@ ip_msdp_show_sa(struct vty *vty, u_char uj) if (uj) { json = json_object_new_object(); } else { - vty_out(vty, "Source Group RP SPT Uptime%s", VTY_NEWLINE); + vty_out(vty, "Source Group RP Local SPT Uptime%s", VTY_NEWLINE); } for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { @@ -5686,19 +5701,23 @@ ip_msdp_show_sa(struct vty *vty, u_char uj) pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime); pim_inet4_dump("", sa->sg.src, src_str, sizeof(src_str)); 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 { + if (sa->flags & PIM_MSDP_SAF_PEER) { pim_inet4_dump("", sa->rp, rp_str, sizeof(rp_str)); - } - - if (uj) { if (sa->up) { strcpy(spt_str, "yes"); } else { strcpy(spt_str, "no"); } + } else { + strcpy(rp_str, "-"); + strcpy(spt_str, "-"); + } + if (sa->flags & PIM_MSDP_SAF_LOCAL) { + strcpy(local_str, "yes"); + } else { + strcpy(local_str, "no"); + } + if (uj) { json_object_object_get_ex(json, grp_str, &json_group); if (!json_group) { @@ -5710,17 +5729,13 @@ ip_msdp_show_sa(struct vty *vty, u_char uj) json_object_string_add(json_row, "source", src_str); json_object_string_add(json_row, "group", grp_str); json_object_string_add(json_row, "rp", rp_str); + json_object_string_add(json_row, "local", local_str); json_object_string_add(json_row, "sptSetup", spt_str); json_object_string_add(json_row, "upTime", timebuf); json_object_object_add(json_group, src_str, json_row); } else { - if (sa->up) { - strcpy(spt_str, "y"); - } else { - strcpy(spt_str, "n"); - } - vty_out(vty, "%-15s %15s %15s %3s %8s%s", - src_str, grp_str, rp_str, spt_str, timebuf, VTY_NEWLINE); + vty_out(vty, "%-15s %15s %15s %5c %3c %8s%s", + src_str, grp_str, rp_str, local_str[0], spt_str[0], timebuf, VTY_NEWLINE); } } @@ -5740,6 +5755,7 @@ ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa, const char *src_str, char peer_str[INET_ADDRSTRLEN]; char timebuf[PIM_MSDP_UPTIME_STRLEN]; char spt_str[8]; + char local_str[8]; char statetimer[PIM_MSDP_TIMER_STRLEN]; int64_t now; json_object *json_group = NULL; @@ -5747,11 +5763,7 @@ ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa, const char *src_str, now = pim_time_monotonic_sec(); pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime); - if (sa->flags & PIM_MSDP_SAF_LOCAL) { - strcpy(rp_str, "local"); - strcpy(peer_str, "-"); - strcpy(spt_str, "-"); - } else { + if (sa->flags & PIM_MSDP_SAF_PEER) { pim_inet4_dump("", sa->rp, rp_str, sizeof(rp_str)); pim_inet4_dump("", sa->peer, peer_str, sizeof(peer_str)); if (sa->up) { @@ -5759,6 +5771,15 @@ ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa, const char *src_str, } else { strcpy(spt_str, "no"); } + } else { + strcpy(rp_str, "-"); + strcpy(peer_str, "-"); + strcpy(spt_str, "-"); + } + if (sa->flags & PIM_MSDP_SAF_LOCAL) { + strcpy(local_str, "yes"); + } else { + strcpy(local_str, "no"); } pim_time_timer_to_hhmmss(statetimer, sizeof(statetimer), sa->sa_state_timer); if (uj) { @@ -5773,6 +5794,7 @@ ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa, const char *src_str, json_object_string_add(json_row, "source", src_str); json_object_string_add(json_row, "group", grp_str); json_object_string_add(json_row, "rp", rp_str); + json_object_string_add(json_row, "local", local_str); json_object_string_add(json_row, "sptSetup", spt_str); json_object_string_add(json_row, "upTime", timebuf); json_object_string_add(json_row, "stateTime", statetimer); @@ -5781,6 +5803,7 @@ ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa, const char *src_str, vty_out(vty, "SA : %s%s", pim_str_sg_dump(&sa->sg), VTY_NEWLINE); vty_out(vty, " RP : %s%s", rp_str, VTY_NEWLINE); vty_out(vty, " Peer : %s%s", peer_str, VTY_NEWLINE); + vty_out(vty, " Local : %s%s", local_str, VTY_NEWLINE); vty_out(vty, " SPT Setup : %s%s", spt_str, VTY_NEWLINE); vty_out(vty, " Uptime : %s%s", timebuf, VTY_NEWLINE); vty_out(vty, " State Time : %s%s", statetimer, VTY_NEWLINE); diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 5fba681a73..3f8ec35587 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -160,8 +160,6 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg return 0; } PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); - pim_upstream_set_created_by_upstream(up); - pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); up->channel_oil = oil; @@ -422,8 +420,6 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) return -2; } PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); - pim_upstream_set_created_by_upstream(up); - pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); up->channel_oil = oil; up->channel_oil->cc.pktcnt++; diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 76127245ce..12f363e6fe 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -36,6 +36,7 @@ #include "pim_rp.h" #include "pim_str.h" #include "pim_time.h" +#include "pim_upstream.h" #include "pim_msdp.h" #include "pim_msdp_packet.h" @@ -139,10 +140,6 @@ pim_msdp_sa_upstream_del(struct pim_msdp_sa *sa) } 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__); @@ -158,12 +155,6 @@ pim_msdp_sa_upstream_del(struct pim_msdp_sa *sa) 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; @@ -194,10 +185,9 @@ pim_msdp_sa_upstream_add_ok(struct pim_msdp_sa *sa, struct pim_upstream *xg_up) /* 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 + * 2. The RP for a group changes. + * 3. joinDesired for the associated (*, G) changes + * 4. associated (*, G) is removed - this seems like a bit redundant * (considering #4); but just in case an entry gets nuked without * upstream state transition * */ @@ -359,12 +349,17 @@ static void pim_msdp_sa_deref(struct pim_msdp_sa *sa, enum pim_msdp_sa_flags flags) { char key_str[PIM_MSDP_SA_KEY_STRLEN]; + bool update_up = false; - pim_msdp_sa_key_dump(sa, key_str, sizeof(key_str), true); + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_sa_key_dump(sa, key_str, sizeof(key_str), true); + } if ((sa->flags &PIM_MSDP_SAF_LOCAL)) { if (flags & PIM_MSDP_SAF_LOCAL) { - zlog_debug("%s local reference removed", key_str); + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("%s local reference removed", key_str); + } if (msdp->local_cnt) --msdp->local_cnt; } @@ -372,13 +367,21 @@ pim_msdp_sa_deref(struct pim_msdp_sa *sa, enum pim_msdp_sa_flags flags) if ((sa->flags &PIM_MSDP_SAF_PEER)) { if (flags & PIM_MSDP_SAF_PEER) { - zlog_debug("%s peer reference removed", key_str); + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("%s peer reference removed", key_str); + } pim_msdp_sa_state_timer_setup(sa, false /* start */); + /* if peer ref was removed we need to remove the msdp reference on the + * msdp entry */ + update_up = true; } } sa->flags &= ~flags; - pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "sa-deref"); + if (update_up) { + pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "sa-deref"); + } + if (!(sa->flags & PIM_MSDP_SAF_REF)) { pim_msdp_sa_del(sa); } @@ -424,27 +427,53 @@ pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, } /* 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; } } -void +/* The following criteria must be met to originate an SA from the MSDP + * speaker - + * 1. KAT must be running i.e. source is active. + * 2. We must be RP for the group. + * 3. Source must be registrable to the RP (this is where the RFC is vague + * and especially ambiguous in CLOS networks; with anycast RP all sources + * are potentially registrable to all RPs in the domain). We assume #3 is + * satisfied if - + * a. We are also the FHR-DR for the source (OR) + * b. We rxed a pim register (null or data encapsulated) within the last + * (3 * (1.5 * register_suppression_timer))). + */ +static bool +pim_msdp_sa_local_add_ok(struct pim_upstream *up) +{ + if (!(msdp->flags & PIM_MSDPF_ENABLE)) { + return false; + } + + if (!up->t_ka_timer) { + /* stream is not active */ + return false; + } + + if (!I_am_RP(up->sg.grp)) { + /* we are not RP for the group */ + return false; + } + + /* we are the FHR-DR for this stream or we are RP and have seen registers + * from a FHR for this source */ + if (PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) || up->t_msdp_reg_timer) { + return true; + } + + return false; +} + +static void pim_msdp_sa_local_add(struct prefix_sg *sg) { struct in_addr rp; - - if (!(msdp->flags & PIM_MSDPF_ENABLE)) { - /* if the feature is not enabled do nothing; we will collect all local - * sources whenever it is */ - return; - } - - /* check if I am RP for this group. XXX: is this check really needed? */ - if (!I_am_RP(sg->grp)) { - return; - } rp.s_addr = 0; pim_msdp_sa_ref(NULL /* mp */, sg, rp); } @@ -454,18 +483,31 @@ pim_msdp_sa_local_del(struct prefix_sg *sg) { struct pim_msdp_sa *sa; - if (!(msdp->flags & PIM_MSDPF_ENABLE)) { - /* if the feature is not enabled do nothing; we will collect all local - * sources whenever it is */ - return; - } - sa = pim_msdp_sa_find(sg); if (sa) { pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); } } +/* Local SA qualification needs to be re-evaluated when - + * 1. KAT is started or stopped + * 2. on RP changes + * 3. Whenever FHR status changes for a (S,G) - XXX - currently there + * is no clear path to transition an entry out of "MASK_FHR" need + * to discuss this with Donald. May result in some strangeness if the + * FHR is also the RP. + * 4. When msdp_reg timer is started or stopped + */ +void +pim_msdp_sa_local_update(struct pim_upstream *up) +{ + if (pim_msdp_sa_local_add_ok(up)) { + pim_msdp_sa_local_add(&up->sg); + } else { + pim_msdp_sa_local_del(&up->sg); + } +} + static void pim_msdp_sa_local_setup(void) { @@ -473,9 +515,7 @@ pim_msdp_sa_local_setup(void) struct listnode *up_node; for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) { - if (PIM_UPSTREAM_FLAG_TEST_CREATED_BY_UPSTREAM(up->flags)) { - pim_msdp_sa_local_add(&up->sg); - } + pim_msdp_sa_local_update(up); } } @@ -548,8 +588,6 @@ pim_msdp_up_join_state_changed(struct pim_upstream *xg_up) } } -/* XXX: Need to maintain SAs per-group to avoid all this unnecessary - * walking */ void pim_msdp_up_xg_del(struct prefix_sg *sg) { diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h index 4809749b94..38ac4aa337 100644 --- a/pimd/pim_msdp.h +++ b/pimd/pim_msdp.h @@ -218,7 +218,7 @@ int pim_msdp_config_write(struct vty *vty); void pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp); char *pim_msdp_sa_key_dump(struct pim_msdp_sa *sa, char *buf, int buf_size, bool long_format); void pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, struct in_addr rp); -void pim_msdp_sa_local_add(struct prefix_sg *sg); +void pim_msdp_sa_local_update(struct pim_upstream *up); 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); diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 914d196339..8f3edc7580 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -342,7 +342,7 @@ pim_register_recv (struct interface *ifp, zlog_warn ("Failure to create upstream state"); return 1; } - pim_upstream_set_created_by_upstream(upstream); + PIM_UPSTREAM_FLAG_SET_SRC_STREAM(upstream->flags); upstream->upstream_register = src_addr; pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.src, sg.grp); @@ -353,7 +353,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_FLAG_UNSET_SRC_STREAM(upstream->flags); pim_upstream_del (upstream, __PRETTY_FUNCTION__); return 1; } @@ -390,6 +390,7 @@ pim_register_recv (struct interface *ifp, //inherited_olist(S,G,rpt) // This is taken care of by the kernel for us } + pim_upstream_msdp_reg_timer_start(upstream); } else { if (PIM_DEBUG_PIM_REG) { diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index a6d7f6e749..01b0b3ac69 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -112,20 +112,6 @@ pim_upstream_find_new_children (struct pim_upstream *up) } } -void -pim_upstream_set_created_by_upstream(struct pim_upstream *up) -{ - PIM_UPSTREAM_FLAG_SET_CREATED_BY_UPSTREAM(up->flags); - pim_msdp_sa_local_add(&up->sg); -} - -void -pim_upstream_unset_created_by_upstream(struct pim_upstream *up) -{ - PIM_UPSTREAM_FLAG_UNSET_CREATED_BY_UPSTREAM(up->flags); - pim_msdp_sa_local_del(&up->sg); -} - /* * If we have a (*,*) || (S,*) there is no parent * If we have a (S,G), find the (*,G) @@ -188,6 +174,7 @@ pim_upstream_del(struct pim_upstream *up, const char *name) THREAD_OFF(up->t_join_timer); THREAD_OFF(up->t_ka_timer); THREAD_OFF(up->t_rs_timer); + THREAD_OFF(up->t_msdp_reg_timer); if (up->join_state == PIM_UPSTREAM_JOINED) { pim_joinprune_send (up->rpf.source_nexthop.interface, @@ -576,6 +563,7 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, up->t_join_timer = NULL; up->t_ka_timer = NULL; up->t_rs_timer = NULL; + up->t_msdp_reg_timer = NULL; up->join_state = 0; up->state_transition = pim_time_monotonic_sec(); up->channel_oil = NULL; @@ -634,6 +622,12 @@ struct pim_upstream *pim_upstream_find(struct prefix_sg *sg) return up; } +static void pim_upstream_ref(struct pim_upstream *up, int flags) +{ + up->flags |= flags; + ++up->ref_count; +} + struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, struct interface *incoming, int flags, const char *name) @@ -642,8 +636,7 @@ struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, int found = 0; up = pim_upstream_find(sg); if (up) { - ++up->ref_count; - up->flags |= flags; + pim_upstream_ref(up, flags); found = 1; } else { @@ -908,9 +901,48 @@ static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up) } /* scan iface channel list */ } +/* When kat is stopped CouldRegister goes to false so we need to + * transition the (S, G) on FHR to NI state and remove reg tunnel + * from the OIL */ +static void pim_upstream_fhr_kat_expiry(struct pim_upstream *up) +{ + if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) + return; + + if (PIM_DEBUG_TRACE) + zlog_debug ("kat expired on %s; clear fhr reg state", + pim_str_sg_dump (&up->sg)); + /* stop reg-stop timer */ + THREAD_OFF(up->t_rs_timer); + /* remove regiface from the OIL if it is there*/ + pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); + /* move to "not-joined" */ + up->join_state = PIM_UPSTREAM_NOTJOINED; + PIM_UPSTREAM_FLAG_UNSET_FHR(up->flags); +} + +/* When kat is started CouldRegister can go to true. And if it does we + * need to transition the (S, G) on FHR to JOINED state and add reg tunnel + * to the OIL */ +static void pim_upstream_fhr_kat_start(struct pim_upstream *up) +{ + if (pim_upstream_could_register(up)) { + if (PIM_DEBUG_TRACE) + zlog_debug ("kat started on %s; set fhr reg state to joined", + pim_str_sg_dump (&up->sg)); + PIM_UPSTREAM_FLAG_SET_FHR(up->flags); + if (up->join_state == PIM_UPSTREAM_NOTJOINED) { + pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); + up->join_state = PIM_UPSTREAM_JOINED; + } + } +} + /* * On an RP, the PMBR value must be cleared when the * Keepalive Timer expires + * KAT expiry indicates that flow is inactive. If the flow was created or + * maintained by activity now is the time to deref it. */ static int pim_upstream_keep_alive_timer (struct thread *t) @@ -918,56 +950,75 @@ pim_upstream_keep_alive_timer (struct thread *t) struct pim_upstream *up; up = THREAD_ARG(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. + */ + } - pim_mroute_update_counters (up->channel_oil); + /* source is no longer active - pull the SA from MSDP's cache */ + pim_msdp_sa_local_del(&up->sg); - if (PIM_DEBUG_MROUTE) - { - zlog_debug ("New: %llu %lu %lu %lu", up->channel_oil->cc.lastused, up->channel_oil->cc.pktcnt, - up->channel_oil->cc.bytecnt, up->channel_oil->cc.wrong_if); - zlog_debug ("old: %llu %lu %lu %lu", up->channel_oil->cc.lastused, up->channel_oil->cc.oldpktcnt, - up->channel_oil->cc.oldbytecnt, up->channel_oil->cc.oldwrong_if); - } - if ((up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt) && - (up->channel_oil->cc.lastused/100 >= qpim_keep_alive_time)) - { - pim_mroute_del (up->channel_oil); - THREAD_OFF (up->t_ka_timer); - THREAD_OFF (up->t_rs_timer); - PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM (up->flags); - if (PIM_UPSTREAM_FLAG_TEST_CREATED_BY_UPSTREAM(up->flags)) - { - pim_upstream_unset_created_by_upstream(up); - pim_upstream_del (up, __PRETTY_FUNCTION__); - } - } - else - { - up->t_ka_timer = NULL; - pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - } + /* 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", + pim_str_sg_dump (&up->sg)); + PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags); + pim_upstream_del(up, __PRETTY_FUNCTION__); + } - return 1; + return 0; } void pim_upstream_keep_alive_timer_start (struct pim_upstream *up, uint32_t time) { + if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) { + if (PIM_DEBUG_TRACE) + zlog_debug ("kat start on %s with no stream reference", + pim_str_sg_dump (&up->sg)); + } THREAD_OFF (up->t_ka_timer); THREAD_TIMER_ON (master, up->t_ka_timer, pim_upstream_keep_alive_timer, up, time); + + /* any time keepalive is started against a SG we will have to + * re-evaluate our active source database */ + pim_msdp_sa_local_update(up); +} + +/* MSDP on RP needs to know if a source is registerable to this RP */ +static int +pim_upstream_msdp_reg_timer(struct thread *t) +{ + struct pim_upstream *up; + + up = THREAD_ARG(t); + up->t_msdp_reg_timer = NULL; + + /* source is no longer active - pull the SA from MSDP's cache */ + pim_msdp_sa_local_del(&up->sg); + return 1; +} +void +pim_upstream_msdp_reg_timer_start(struct pim_upstream *up) +{ + THREAD_OFF(up->t_msdp_reg_timer); + THREAD_TIMER_ON(master, up->t_msdp_reg_timer, + pim_upstream_msdp_reg_timer, up, PIM_MSDP_REG_RXED_PERIOD); + + pim_msdp_sa_local_update(up); } /* @@ -1130,7 +1181,6 @@ pim_upstream_register_stop_timer (struct thread *t) struct ip ip_hdr; up = THREAD_ARG (t); - THREAD_TIMER_OFF (up->t_rs_timer); up->t_rs_timer = NULL; if (PIM_DEBUG_TRACE) @@ -1330,6 +1380,43 @@ pim_upstream_equal (const void *arg1, const void *arg2) return 0; } +/* rfc4601:section-4.2:"Data Packet Forwarding Rules" defines + * the cases where kat has to be restarted on rxing traffic - + * + * if( DirectlyConnected(S) == TRUE AND iif == RPF_interface(S) ) { + * set KeepaliveTimer(S,G) to Keepalive_Period + * # Note: a register state transition or UpstreamJPState(S,G) + * # transition may happen as a result of restarting + * # KeepaliveTimer, and must be dealt with here. + * } + * if( iif == RPF_interface(S) AND UpstreamJPState(S,G) == Joined AND + * inherited_olist(S,G) != NULL ) { + * set KeepaliveTimer(S,G) to Keepalive_Period + * } + */ +static bool pim_upstream_kat_start_ok(struct pim_upstream *up) +{ + /* "iif == RPF_interface(S)" check has to be done by the kernel or hw + * so we will skip that here */ + if (pim_if_connected_to_source(up->rpf.source_nexthop.interface, + up->sg.src)) { + return true; + } + + if ((up->join_state == PIM_UPSTREAM_JOINED) && + !pim_upstream_empty_inherited_olist(up)) { + /* XXX: I have added this RP check just for 3.2 and it's a digression from + * what rfc-4601 says. Till now we were only running KAT on FHR and RP and + * there is some angst around making the change to run it all routers that + * maintain the (S, G) state. This is tracked via CM-13601 and MUST be + * removed to handle spt turn-arounds correctly in a 3-tier clos */ + if (I_am_RP (up->sg.grp)) + return true; + } + + return false; +} + /* * Code to check and see if we've received packets on a S,G mroute * and if so to set the SPT bit appropriately @@ -1338,16 +1425,6 @@ static void pim_upstream_sg_running (void *arg) { struct pim_upstream *up = (struct pim_upstream *)arg; - long long now; - - // If we are TRUE already no need to do more work - if (up->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: %s sptbit is true", __PRETTY_FUNCTION__, - pim_str_sg_dump(&up->sg)); - return; - } // No packet can have arrived here if this is the case if (!up->channel_oil || !up->channel_oil->installed) @@ -1358,21 +1435,11 @@ pim_upstream_sg_running (void *arg) return; } - // We need at least 30 seconds to see if we are getting packets - now = pim_time_monotonic_sec(); - if (now - up->state_transition <= 30) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: %s uptime is %lld", - __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg), - now - up->state_transition); - return; - } pim_mroute_update_counters (up->channel_oil); // Have we seen packets? - if ((up->channel_oil->cc.oldpktcnt <= up->channel_oil->cc.pktcnt) && + if ((up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt) && (up->channel_oil->cc.lastused/100 > 30)) { if (PIM_DEBUG_TRACE) @@ -1384,7 +1451,25 @@ pim_upstream_sg_running (void *arg) return; } - pim_upstream_set_sptbit (up, up->rpf.source_nexthop.interface); + 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_DEBUG_TRACE) + zlog_debug ("source reference created on kat restart %s", + pim_str_sg_dump (&up->sg)); + 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); + } + + if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) + { + pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface); + } return; } diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index a073125021..b3823604c1 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -33,8 +33,7 @@ #define PIM_UPSTREAM_FLAG_MASK_SRC_IGMP (1 << 3) #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_MASK_SRC_MSDP (1 << 6) #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,7 +41,6 @@ #define PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) #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) @@ -51,7 +49,6 @@ #define PIM_UPSTREAM_FLAG_SET_SRC_IGMP(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) #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) @@ -60,7 +57,6 @@ #define PIM_UPSTREAM_FLAG_UNSET_SRC_IGMP(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) #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 { @@ -114,6 +110,11 @@ struct pim_upstream { #define PIM_KEEPALIVE_PERIOD (210) #define PIM_RP_KEEPALIVE_PERIOD ( 3 * qpim_register_suppress_time + qpim_register_probe_time ) + /* on the RP we restart a timer to indicate if registers are being rxed for + * SG. This is needed by MSDP to determine its local SA cache */ + struct thread *t_msdp_reg_timer; +#define PIM_MSDP_REG_RXED_PERIOD (3 * (1.5 * qpim_register_suppress_time)) + int64_t state_transition; /* Record current state uptime */ }; @@ -164,9 +165,8 @@ int pim_upstream_inherited_olist (struct pim_upstream *up); int pim_upstream_empty_inherited_olist (struct pim_upstream *up); void pim_upstream_find_new_rpf (void); +void pim_upstream_msdp_reg_timer_start(struct pim_upstream *up); 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 */ From 70989c7c20b4b2ed5d826ba875fbced0384ddafd Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 16 Nov 2016 22:12:57 -0500 Subject: [PATCH 307/386] pimd: Modify wait time for response from Null Register Give ourselves a few more seconds to wait for a response for a NULL Register. This will benefit us under heavy mroute churn on the RP. Signed-off-by: Donald Sharp --- pimd/pim_upstream.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index b3823604c1..a40265a906 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -101,7 +101,7 @@ struct pim_upstream { */ struct thread *t_rs_timer; #define PIM_REGISTER_SUPPRESSION_PERIOD (60) -#define PIM_REGISTER_PROBE_PERIOD (5) +#define PIM_REGISTER_PROBE_PERIOD (15) /* * KAT(S,G) From 9d8b5695fe8229c86fc606f90a0078e599384c6d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 16 Nov 2016 22:59:32 -0500 Subject: [PATCH 308/386] pimd: Cleanup handling of pim_sock_read Cleanup some turned on debug code that is no longer needed to be turned on in the pim_sock_read code path. Signed-off-by: Donald Sharp --- pimd/Makefile.am | 2 +- pimd/pim_pim.c | 28 ++++++++-------------------- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/pimd/Makefile.am b/pimd/Makefile.am index bab0d00ebc..6ce4f678a9 100644 --- a/pimd/Makefile.am +++ b/pimd/Makefile.am @@ -28,7 +28,7 @@ PIM_DEFS = #PIM_DEFS += -DPIM_DEBUG_BYDEFAULT -PIM_DEFS += -DPIM_CHECK_RECV_IFINDEX_SANITY +#PIM_DEFS += -DPIM_CHECK_RECV_IFINDEX_SANITY #PIM_DEFS += -DPIM_REPORT_RECV_IFINDEX_MISMATCH PIM_DEFS += -DPIM_ZCLIENT_DEBUG PIM_DEFS += -DPIM_ENFORCE_LOOPFREE_MFC diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index c2082ce3d0..bef3a8a34a 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -142,13 +142,6 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) uint16_t checksum; /* computed checksum */ struct pim_neighbor *neigh; - if (!ifp->info) { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("%s: PIM not enabled on interface %s", - __PRETTY_FUNCTION__, ifp->name); - return -1; - } - if (len < sizeof(*ip_hdr)) { if (PIM_DEBUG_PIM_PACKETS) zlog_debug("PIM packet size=%zu shorter than minimum=%zu", @@ -158,8 +151,11 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) ip_hdr = (struct ip *) buf; - pim_inet4_dump("", ip_hdr->ip_src, src_str, sizeof(src_str)); - pim_inet4_dump("", ip_hdr->ip_dst, dst_str, sizeof(dst_str)); + if (PIM_DEBUG_PIM_PACKETS) + { + pim_inet4_dump("", ip_hdr->ip_src, src_str, sizeof(src_str)); + pim_inet4_dump("", ip_hdr->ip_dst, dst_str, sizeof(dst_str)); + } ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */ @@ -308,19 +304,11 @@ static int pim_sock_read(struct thread *t) fd = THREAD_FD(t); pim_ifp = ifp->info; - zassert(pim_ifp); - - zassert(fd == pim_ifp->pim_sock_fd); len = pim_socket_recvfromto(fd, buf, sizeof(buf), &from, &fromlen, &to, &tolen, &ifindex); - if (len < 0) { - zlog_warn("Failure receiving IP PIM packet on fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - goto done; - } if (PIM_DEBUG_PIM_PACKETS) { char from_str[INET_ADDRSTRLEN]; @@ -333,10 +321,10 @@ static int pim_sock_read(struct thread *t) zlog_debug("Recv IP PIM pkt size=%d from %s to %s on fd=%d on ifindex=%d (sock_ifindex=%d)", len, from_str, to_str, fd, ifindex, ifp->ifindex); - } - if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { - pim_pkt_dump(__PRETTY_FUNCTION__, buf, len); + if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { + pim_pkt_dump(__PRETTY_FUNCTION__, buf, len); + } } #ifdef PIM_CHECK_RECV_IFINDEX_SANITY From 8bfb8b67ae63eb0ee81e9c928b11836dcd690d6c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 17 Nov 2016 08:17:25 -0500 Subject: [PATCH 309/386] pimd: Allow storing of sg in string format Debugs are extremely expensive currently. Let's store 'struct prefix_sg sg' string format in the ifchannel, upstream and msdp_sa structures. Signed-off-by: Donald Sharp --- pimd/pim_assert.c | 26 ++++++++--------- pimd/pim_cmd.c | 2 +- pimd/pim_ifchannel.c | 38 ++++++++++-------------- pimd/pim_ifchannel.h | 1 + pimd/pim_join.c | 19 ++++-------- pimd/pim_macro.c | 18 +++++------- pimd/pim_mroute.c | 23 +++++++++------ pimd/pim_msdp.c | 7 +++-- pimd/pim_msdp.h | 1 + pimd/pim_msg.c | 16 +++++----- pimd/pim_register.c | 16 +++++----- pimd/pim_rpf.c | 8 ++--- pimd/pim_ssmpingd.c | 3 +- pimd/pim_str.c | 18 ++++++++++-- pimd/pim_str.h | 10 +++++++ pimd/pim_upstream.c | 69 ++++++++++++++++++++++---------------------- pimd/pim_upstream.h | 1 + pimd/pim_zebra.c | 6 ++-- pimd/pimd.h | 1 + 19 files changed, 146 insertions(+), 137 deletions(-) diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index 505d1f1ec1..3e8f1b7d3d 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -57,7 +57,7 @@ void pim_ifassert_winner_set(struct pim_ifchannel *ch, if (ch->ifassert_state != new_state) { zlog_debug("%s: (S,G)=%s assert state changed from %s to %s on interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg), + ch->sg_str, pim_ifchannel_ifassert_name(ch->ifassert_state), pim_ifchannel_ifassert_name(new_state), ch->interface->name); @@ -70,7 +70,7 @@ void pim_ifassert_winner_set(struct pim_ifchannel *ch, pim_inet4_dump("", winner, winner_str, sizeof(winner_str)); zlog_debug("%s: (S,G)=%s assert winner changed from %s to %s on interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg), + ch->sg_str, was_str, winner_str, ch->interface->name); } } /* PIM_DEBUG_PIM_EVENTS */ @@ -133,7 +133,7 @@ static void if_could_assert_do_a1(const char *caller, if (assert_action_a1(ch)) { zlog_warn("%s: %s: (S,G)=%s assert_action_a1 failure on interface %s", __PRETTY_FUNCTION__, caller, - pim_str_sg_dump (&ch->sg), ch->interface->name); + ch->sg_str, ch->interface->name); /* log warning only */ } } @@ -213,7 +213,7 @@ static int dispatch_assert(struct interface *ifp, { zlog_warn("%s: (S,G)=%s invalid assert state %d on interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), ch->ifassert_state, ifp->name); + ch->sg_str, ch->ifassert_state, ifp->name); } return -2; } @@ -468,7 +468,7 @@ static int pim_assert_do(struct pim_ifchannel *ch, if (PIM_DEBUG_PIM_TRACE) { zlog_debug("%s: to %s: (S,G)=%s pref=%u metric=%u rpt_bit=%u", __PRETTY_FUNCTION__, - ifp->name, pim_str_sg_dump (&ch->sg), + ifp->name, ch->sg_str, metric.metric_preference, metric.route_metric, PIM_FORCE_BOOLEAN(metric.rpt_bit_flag)); @@ -523,7 +523,7 @@ static int on_assert_timer(struct thread *t) if (PIM_DEBUG_PIM_TRACE) { zlog_debug("%s: (S,G)=%s timer expired on interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg), ifp->name); + ch->sg_str, ifp->name); } ch->t_ifassert_timer = NULL; @@ -540,7 +540,7 @@ static int on_assert_timer(struct thread *t) { zlog_warn("%s: (S,G)=%s invalid assert state %d on interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg), ch->ifassert_state, ifp->name); + ch->sg_str, ch->ifassert_state, ifp->name); } } @@ -559,7 +559,7 @@ static void assert_timer_off(struct pim_ifchannel *ch) if (ch->t_ifassert_timer) { zlog_debug("%s: (S,G)=%s cancelling timer on interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg), ifp->name); + ch->sg_str, ifp->name); } } THREAD_OFF(ch->t_ifassert_timer); @@ -580,7 +580,7 @@ static void pim_assert_timer_set(struct pim_ifchannel *ch, if (PIM_DEBUG_PIM_TRACE) { zlog_debug("%s: (S,G)=%s starting %u sec timer on interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump(&ch->sg), interval, ifp->name); + ch->sg_str, interval, ifp->name); } THREAD_TIMER_ON(master, ch->t_ifassert_timer, @@ -614,7 +614,7 @@ int assert_action_a1(struct pim_ifchannel *ch) if (!pim_ifp) { zlog_warn("%s: (S,G)=%s multicast not enabled on interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg), ifp->name); + ch->sg_str, ifp->name); return -1; /* must return since pim_ifp is used below */ } @@ -628,7 +628,7 @@ int assert_action_a1(struct pim_ifchannel *ch) if (assert_action_a3(ch)) { zlog_warn("%s: (S,G)=%s assert_action_a3 failure on interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg), ifp->name); + ch->sg_str, ifp->name); /* warning only */ } @@ -675,7 +675,7 @@ static int assert_action_a3(struct pim_ifchannel *ch) if (pim_assert_send(ch)) { zlog_warn("%s: (S,G)=%s failure sending assert on interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg), ch->interface->name); + ch->sg_str, ch->interface->name); return -1; } @@ -699,7 +699,7 @@ void assert_action_a4(struct pim_ifchannel *ch) if (pim_assert_cancel(ch)) { zlog_warn("%s: failure sending AssertCancel%s on interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg), ch->interface->name); + ch->sg_str, ch->interface->name); /* log warning only */ } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 0690130edf..ecfa94cba9 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -5800,7 +5800,7 @@ ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa, const char *src_str, json_object_string_add(json_row, "stateTime", statetimer); json_object_object_add(json_group, src_str, json_row); } else { - vty_out(vty, "SA : %s%s", pim_str_sg_dump(&sa->sg), VTY_NEWLINE); + vty_out(vty, "SA : %s%s", sa->sg_str, VTY_NEWLINE); vty_out(vty, " RP : %s%s", rp_str, VTY_NEWLINE); vty_out(vty, " Peer : %s%s", peer_str, VTY_NEWLINE); vty_out(vty, " Local : %s%s", local_str, VTY_NEWLINE); diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 0da3abe99e..ef4c23e95f 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -213,7 +213,7 @@ void pim_ifchannel_ifjoin_switch(const char *caller, if (PIM_DEBUG_PIM_EVENTS) zlog_debug ("PIM_IFCHANNEL(%s): %s is switching from %s to %s", ch->interface->name, - pim_str_sg_dump (&ch->sg), + ch->sg_str, pim_ifchannel_ifjoin_name (ch->ifjoin_state), pim_ifchannel_ifjoin_name (new_state)); @@ -236,7 +236,7 @@ void pim_ifchannel_ifjoin_switch(const char *caller, if (PIM_DEBUG_PIM_EVENTS) { zlog_debug("PIM_IFCHANNEL_%s: (S,G)=%s on interface %s", ((new_state == PIM_IFJOIN_NOINFO) ? "DOWN" : "UP"), - pim_str_sg_dump (&ch->sg), ch->interface->name); + ch->sg_str, ch->interface->name); } /* @@ -331,7 +331,7 @@ static void ifmembership_set(struct pim_ifchannel *ch, if (PIM_DEBUG_PIM_EVENTS) { zlog_debug("%s: (S,G)=%s membership now is %s on interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg), + ch->sg_str, membership == PIM_IFMEMBERSHIP_INCLUDE ? "INCLUDE" : "NOINFO", ch->interface->name); } @@ -426,7 +426,7 @@ pim_ifchannel_add(struct interface *ifp, if (!ch) { zlog_warn("%s: pim_ifchannel_new() failure for (S,G)=%s on interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (sg), ifp->name); + up->sg_str, ifp->name); pim_upstream_del (up, __PRETTY_FUNCTION__); return NULL; @@ -436,6 +436,7 @@ pim_ifchannel_add(struct interface *ifp, ch->upstream = up; ch->interface = ifp; ch->sg = *sg; + pim_str_sg_set (sg, ch->sg_str); ch->parent = pim_ifchannel_find_parent (ch); if (ch->sg.src.s_addr == INADDR_ANY) { @@ -549,7 +550,7 @@ static void check_recv_upstream(int is_join, /* RPF'(S,G) not found */ zlog_warn("%s %s: RPF'%s not found", __FILE__, __PRETTY_FUNCTION__, - pim_str_sg_dump (sg)); + up->sg_str); return; } @@ -561,7 +562,7 @@ static void check_recv_upstream(int is_join, pim_addr_dump("", &up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); zlog_warn("%s %s: (S,G)=%s upstream=%s not directed to RPF'(S,G)=%s on interface %s", __FILE__, __PRETTY_FUNCTION__, - pim_str_sg_dump (sg), + up->sg_str, up_str, rpf_str, recv_ifp->name); return; } @@ -673,7 +674,7 @@ void pim_ifchannel_join_add(struct interface *ifp, pim_inet4_dump("", neigh_addr, neigh_str, sizeof(neigh_str)); zlog_warn("%s: Assert Loser recv Join%s from %s on %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (sg), neigh_str, ifp->name); + ch->sg_str, neigh_str, ifp->name); assert_action_a5(ch); } @@ -879,14 +880,9 @@ void pim_ifchannel_local_membership_add(struct interface *ifp, for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) { if (PIM_DEBUG_EVENTS) - { - char buff[100]; - - strcpy (buff, pim_str_sg_dump (&child->sg)); - zlog_debug("%s %s: IGMP (S,G)=%s(%s) from %s", - __FILE__, __PRETTY_FUNCTION__, - buff, ifp->name, pim_str_sg_dump (sg)); - } + zlog_debug("%s %s: IGMP (S,G)=%s(%s) from %s", + __FILE__, __PRETTY_FUNCTION__, + child->sg_str, ifp->name, up->sg_str); if (pim_upstream_evaluate_join_desired (child)) { @@ -929,13 +925,9 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, struct pim_interface *pim_ifp = ifp->info; if (PIM_DEBUG_EVENTS) - { - char buff[100]; - strcpy (buff, pim_str_sg_dump (&child->sg)); - zlog_debug("%s %s: Prune(S,G)=%s(%s) from %s", - __FILE__, __PRETTY_FUNCTION__, - buff, ifp->name, pim_str_sg_dump (&child->sg)); - } + zlog_debug("%s %s: Prune(S,G)=%s(%s) from %s", + __FILE__, __PRETTY_FUNCTION__, + 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); @@ -1119,7 +1111,7 @@ pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom) if (PIM_DEBUG_PIM_TRACE) zlog_debug ("%s: %s %s eom: %d", __PRETTY_FUNCTION__, pim_ifchannel_ifjoin_name(ch->ifjoin_state), - pim_str_sg_dump(&ch->sg), eom); + ch->sg_str, eom); if (!ch->sources) return; diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index b640cfd4df..a95f66551b 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -86,6 +86,7 @@ struct pim_ifchannel { struct pim_ifchannel *parent; struct list *sources; struct prefix_sg sg; + char sg_str[PIM_SG_LEN]; struct interface *interface; /* backpointer to interface */ uint32_t flags; diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 42d4a51874..ff41b28ba4 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -112,13 +112,10 @@ static void recv_join(struct interface *ifp, for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) { - char buff[100]; - - strcpy (buff, pim_str_sg_dump (&child->sg)); if (PIM_DEBUG_PIM_TRACE) zlog_debug("%s %s: Join(S,G)=%s from %s", __FILE__, __PRETTY_FUNCTION__, - buff, pim_str_sg_dump (sg)); + child->sg_str, up->sg_str); if (pim_upstream_evaluate_join_desired (child)) { @@ -183,13 +180,9 @@ static void recv_prune(struct interface *ifp, struct pim_interface *pim_ifp = ifp->info; if (PIM_DEBUG_PIM_TRACE) - { - char buff[100]; - strcpy (buff, pim_str_sg_dump (&child->sg)); - zlog_debug("%s %s: Prune(S,G)=%s from %s", - __FILE__, __PRETTY_FUNCTION__, - buff, pim_str_sg_dump (sg)); - } + zlog_debug("%s %s: Prune(S,G)=%s from %s", + __FILE__, __PRETTY_FUNCTION__, + child->sg_str, up->sg_str); if (!c_oil) continue; @@ -408,7 +401,7 @@ int pim_joinprune_send(struct interface *ifp, zlog_debug("%s: sending %s(S,G)=%s to upstream=%s on interface %s", __PRETTY_FUNCTION__, send_join ? "Join" : "Prune", - pim_str_sg_dump (&up->sg), dst_str, ifp->name); + up->sg_str, dst_str, ifp->name); } if (PIM_INADDR_IS_ANY(upstream_addr)) { @@ -418,7 +411,7 @@ int pim_joinprune_send(struct interface *ifp, zlog_debug("%s: %s(S,G)=%s: upstream=%s is myself on interface %s", __PRETTY_FUNCTION__, send_join ? "Join" : "Prune", - pim_str_sg_dump (&up->sg), dst_str, ifp->name); + up->sg_str, dst_str, ifp->name); } return 0; } diff --git a/pimd/pim_macro.c b/pimd/pim_macro.c index da12146be1..c339fce49d 100644 --- a/pimd/pim_macro.c +++ b/pimd/pim_macro.c @@ -26,9 +26,8 @@ #include "vty.h" #include "plist.h" -#include "pim_macro.h" #include "pimd.h" -#include "pim_str.h" +#include "pim_macro.h" #include "pim_iface.h" #include "pim_ifchannel.h" #include "pim_rp.h" @@ -121,7 +120,7 @@ int pim_macro_ch_lost_assert(const struct pim_ifchannel *ch) if (!ifp) { zlog_warn("%s: (S,G)=%s: null interface", __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg)); + ch->sg_str); return 0; /* false */ } @@ -133,7 +132,7 @@ int pim_macro_ch_lost_assert(const struct pim_ifchannel *ch) if (!pim_ifp) { zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg), ifp->name); + ch->sg_str, ifp->name); return 0; /* false */ } @@ -170,7 +169,7 @@ int pim_macro_chisin_pim_include(const struct pim_ifchannel *ch) if (!pim_ifp) { zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg), ch->interface->name); + ch->sg_str, ch->interface->name); return 0; /* false */ } @@ -233,8 +232,7 @@ int pim_macro_ch_could_assert_eval(const struct pim_ifchannel *ch) ifp = ch->interface; if (!ifp) { zlog_warn("%s: (S,G)=%s: null interface", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg)); + __PRETTY_FUNCTION__, ch->sg_str); return 0; /* false */ } @@ -390,16 +388,14 @@ int pim_macro_assert_tracking_desired_eval(const struct pim_ifchannel *ch) ifp = ch->interface; if (!ifp) { zlog_warn("%s: (S,G)=%s: null interface", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg)); + __PRETTY_FUNCTION__, ch->sg_str); return 0; /* false */ } pim_ifp = ifp->info; if (!pim_ifp) { zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg), ch->interface->name); + __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name); return 0; /* false */ } diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 3f8ec35587..c7730acc04 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -135,11 +135,6 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg sg.src = msg->im_src; sg.grp = msg->im_dst; - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: Adding a Route %s for WHOLEPKT consumption", - __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); - } - oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); if (!oil) { if (PIM_DEBUG_MROUTE) { @@ -159,6 +154,16 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg } return 0; } + + /* + * I moved this debug till after the actual add because + * I want to take advantage of the up->sg_str being filled in. + */ + if (PIM_DEBUG_MROUTE) { + zlog_debug("%s: Adding a Route %s for WHOLEPKT consumption", + __PRETTY_FUNCTION__, up->sg_str); + } + PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); @@ -294,7 +299,7 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms if (PIM_DEBUG_MROUTE) { zlog_debug("%s: WRONGVIF (S,G)=%s channel is not on Assert NoInfo state for interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg), ifp->name); + ch->sg_str, ifp->name); } return -4; } @@ -303,7 +308,7 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms if (PIM_DEBUG_MROUTE) { zlog_debug("%s: WRONGVIF (S,G)=%s interface %s is not downstream for channel", __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg), ifp->name); + ch->sg_str, ifp->name); } return -5; } @@ -312,7 +317,7 @@ pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *ms if (PIM_DEBUG_MROUTE) { zlog_debug("%s: WRONGVIF (S,G)=%s assert_action_a1 failure on interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg), ifp->name); + ch->sg_str, ifp->name); } return -6; } @@ -344,7 +349,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) { if (PIM_DEBUG_MROUTE) zlog_debug ("WRVIFWHOLE (S,G)=%s found ifchannel on interface %s", - pim_str_sg_dump (&sg), ifp->name); + ch->sg_str, ifp->name); return -1; } #if 0 diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 12f363e6fe..bee5e734db 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -65,9 +65,9 @@ pim_msdp_sa_key_dump(struct pim_msdp_sa *sa, char *buf, int buf_size, bool long_ if (long_format && (sa->flags & PIM_MSDP_SAF_PEER)) { pim_inet4_dump("", sa->rp, rp_str, sizeof(rp_str)); snprintf(buf, buf_size, "MSDP SA %s rp %s", - pim_str_sg_dump(&sa->sg), rp_str); + sa->sg_str, rp_str); } else { - snprintf(buf, buf_size, "MSDP SA %s", pim_str_sg_dump(&sa->sg)); + snprintf(buf, buf_size, "MSDP SA %s", sa->sg_str); } return buf; @@ -268,6 +268,7 @@ pim_msdp_sa_new(struct prefix_sg *sg, struct in_addr rp) } sa->sg = *sg; + pim_str_sg_set (sg, sa->sg_str); sa->rp = rp; sa->uptime = pim_time_monotonic_sec(); @@ -569,7 +570,7 @@ pim_msdp_up_join_state_changed(struct pim_upstream *xg_up) 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)); + zlog_debug("MSDP join state changed for %s", xg_up->sg_str); } /* If this is not really an XG entry just move on */ diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h index 38ac4aa337..0f64021805 100644 --- a/pimd/pim_msdp.h +++ b/pimd/pim_msdp.h @@ -77,6 +77,7 @@ enum pim_msdp_sa_flags { struct pim_msdp_sa { struct prefix_sg sg; + char sg_str[PIM_SG_LEN]; struct in_addr rp; /* Last RP address associated with this SA */ struct in_addr peer; /* last peer from who we heard this SA */ enum pim_msdp_sa_flags flags; diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index c22011b576..bb73e34062 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -211,11 +211,9 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, struct pim_upstream *child; struct listnode *up_node; int send_prune = 0; - char star_g[100]; - strcpy (star_g, pim_str_sg_dump (&up->sg)); zlog_debug ("%s: Considering (%s) children for (S,G,rpt) prune", - __PRETTY_FUNCTION__, star_g); + __PRETTY_FUNCTION__, up->sg_str); for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) { if (child->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) @@ -225,12 +223,12 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, send_prune = 1; if (PIM_DEBUG_PIM_PACKETS) zlog_debug ("%s: SPT Bit and RPF'(%s) != RPF'(S,G): Add Prune (%s,rpt) to compound message", - __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); + __PRETTY_FUNCTION__, up->sg_str, child->sg_str); } else if (PIM_DEBUG_PIM_PACKETS) zlog_debug ("%s: SPT Bit and RPF'(%s) == RPF'(S,G): Not adding Prune for (%s,rpt)", - __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); + __PRETTY_FUNCTION__, up->sg_str, child->sg_str); } else if (pim_upstream_is_sg_rpt (child)) { @@ -239,24 +237,24 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, send_prune = 1; if (PIM_DEBUG_PIM_PACKETS) zlog_debug ("%s: inherited_olist(%s,rpt) is NULL, Add Prune to compound message", - __PRETTY_FUNCTION__, pim_str_sg_dump (&child->sg)); + __PRETTY_FUNCTION__, child->sg_str); } else if (!pim_rpf_is_same (&up->rpf, &child->rpf)) { send_prune = 1; if (PIM_DEBUG_PIM_PACKETS) zlog_debug ("%s: RPF'(%s) != RPF'(%s,rpt), Add Prune to compound message", - __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); + __PRETTY_FUNCTION__, up->sg_str, child->sg_str); } else if (PIM_DEBUG_PIM_PACKETS) zlog_debug ("%s: RPF'(%s) == RPF'(%s,rpt), Do not add Prune to compound message", - __PRETTY_FUNCTION__, star_g, pim_str_sg_dump (&child->sg)); + __PRETTY_FUNCTION__, up->sg_str, child->sg_str); } else if (PIM_DEBUG_PIM_PACKETS) zlog_debug ("%s: SPT bit is not set for (%s)", - __PRETTY_FUNCTION__, pim_str_sg_dump (&child->sg)); + __PRETTY_FUNCTION__, child->sg_str); if (send_prune) { pim_msg_curr = pim_msg_addr_encode_ipv4_source (pim_msg_curr, remain, diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 8f3edc7580..490a05be37 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -112,18 +112,16 @@ pim_register_stop_recv (uint8_t *buf, int buf_size) pim_parse_addr_ucast (&source, buf, buf_size); sg.src = source.u.prefix4; - if (PIM_DEBUG_PIM_REG) - { - zlog_debug ("Received Register stop for %s", - pim_str_sg_dump (&sg)); - } - upstream = pim_upstream_find (&sg); if (!upstream) { return 0; } + if (PIM_DEBUG_PIM_REG) + zlog_debug ("Received Register stop for %s", + upstream->sg_str); + switch (upstream->join_state) { case PIM_UPSTREAM_NOTJOINED: @@ -157,7 +155,7 @@ pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct char rp_str[INET_ADDRSTRLEN]; strcpy (rp_str, inet_ntoa (rpg->rpf_addr.u.prefix4)); zlog_debug ("Sending %s %sRegister Packet to %s", - pim_str_sg_dump (&up->sg), null_register ? "NULL " : "", rp_str); + up->sg_str, null_register ? "NULL " : "", rp_str); } ifp = rpg->source_nexthop.interface; @@ -351,7 +349,7 @@ pim_register_recv (struct interface *ifp, { if (PIM_DEBUG_PIM_REG) { - zlog_debug ("Received Register(%s), for which I have no path back", pim_str_sg_dump (&upstream->sg)); + zlog_debug ("Received Register(%s), for which I have no path back", upstream->sg_str); } PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(upstream->flags); pim_upstream_del (upstream, __PRETTY_FUNCTION__); @@ -372,7 +370,7 @@ pim_register_recv (struct interface *ifp, sentRegisterStop = 1; } else { if (PIM_DEBUG_PIM_REG) - zlog_debug ("(%s) sptbit: %d", pim_str_sg_dump (&upstream->sg), upstream->sptbit); + zlog_debug ("(%s) sptbit: %d", upstream->sg_str, upstream->sptbit); } if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || (SwitchToSptDesired(&sg))) { diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index b71024711a..48cb2e4017 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -206,7 +206,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_ /* RPF'(S,G) not found */ zlog_debug("%s %s: RPF'%s not found: won't send join upstream", __FILE__, __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg)); + up->sg_str); /* warning only */ } @@ -218,7 +218,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_ pim_addr_dump("", &rpf->source_nexthop.mrib_nexthop_addr, nhaddr_str, sizeof(nhaddr_str)); zlog_debug("%s %s: (S,G)=%s source nexthop now is: interface=%s address=%s pref=%d metric=%d", __FILE__, __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg), + up->sg_str, rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "", nhaddr_str, rpf->source_nexthop.mrib_metric_preference, @@ -236,7 +236,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_ if (PIM_DEBUG_ZEBRA) { zlog_debug("%s %s: (S,G)=%s RPF_interface(S) changed from %s to %s", __FILE__, __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg), + up->sg_str, save_nexthop.interface ? save_nexthop.interface->name : "", rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : ""); /* warning only */ @@ -282,7 +282,7 @@ static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up) if (!up->rpf.source_nexthop.interface) { zlog_warn("%s: missing RPF interface for upstream (S,G)=%s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg)); + up->sg_str); rpf_addr.s_addr = PIM_NET_INADDR_ANY; return rpf_addr; diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c index d308d80e3a..00abc5f60a 100644 --- a/pimd/pim_ssmpingd.c +++ b/pimd/pim_ssmpingd.c @@ -26,11 +26,10 @@ #include "memory.h" #include "sockopt.h" +#include "pimd.h" #include "pim_ssmpingd.h" #include "pim_time.h" #include "pim_sock.h" -#include "pim_str.h" -#include "pimd.h" static const char * const PIM_SSMPINGD_REPLY_GROUP = "232.43.211.234"; diff --git a/pimd/pim_str.c b/pimd/pim_str.c index 4c25c00294..5144031794 100644 --- a/pimd/pim_str.c +++ b/pimd/pim_str.c @@ -67,10 +67,24 @@ pim_str_sg_dump (const struct prefix_sg *sg) { char src_str[INET_ADDRSTRLEN]; char grp_str[INET_ADDRSTRLEN]; - static char sg_str[200]; + static char sg_str[PIM_SG_LEN]; pim_inet4_dump ("", sg->src, src_str, sizeof(src_str)); pim_inet4_dump ("", sg->grp, grp_str, sizeof(grp_str)); - snprintf (sg_str, 200, "(%s,%s)", src_str, grp_str); + snprintf (sg_str, PIM_SG_LEN, "(%s,%s)", src_str, grp_str); + + return sg_str; +} + +char * +pim_str_sg_set (const struct prefix_sg *sg, char *sg_str) +{ + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + + pim_inet4_dump ("", sg->src, src_str, sizeof(src_str)); + pim_inet4_dump ("", sg->grp, grp_str, sizeof(grp_str)); + snprintf (sg_str, PIM_SG_LEN, "(%s,%s)", src_str, grp_str); + return sg_str; } diff --git a/pimd/pim_str.h b/pimd/pim_str.h index 15f5227de8..da72573570 100644 --- a/pimd/pim_str.h +++ b/pimd/pim_str.h @@ -28,8 +28,18 @@ #include +/* + * Longest possible length of a (S,G) string is 36 bytes + * 123.123.123.123 = 16 * 2 + * (,) = 3 + * NULL Character at end = 1 + * (123.123.123.123,123,123,123,123) + */ +#define PIM_SG_LEN 36 + void pim_addr_dump (const char *onfail, struct prefix *p, char *buf, int buf_size); void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, int buf_size); char *pim_str_sg_dump (const struct prefix_sg *sg); +char *pim_str_sg_set (const struct prefix_sg *sg, char *sg_str); #endif diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 01b0b3ac69..ec985076df 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -160,7 +160,7 @@ pim_upstream_del(struct pim_upstream *up, const char *name) if (PIM_DEBUG_PIM_TRACE) { zlog_debug ("%s: Delete (%s) ref count: %d", - name, pim_str_sg_dump (&up->sg), up->ref_count); + name, up->sg_str, up->ref_count); } --up->ref_count; @@ -169,8 +169,8 @@ pim_upstream_del(struct pim_upstream *up, const char *name) if (PIM_DEBUG_PIM_TRACE) zlog_debug ("%s: %s is being deleted", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg)); + __PRETTY_FUNCTION__, up->sg_str); + THREAD_OFF(up->t_join_timer); THREAD_OFF(up->t_ka_timer); THREAD_OFF(up->t_rs_timer); @@ -224,12 +224,12 @@ pim_upstream_send_join (struct pim_upstream *up) char rpf_str[PREFIX_STRLEN]; pim_addr_dump("", &up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); zlog_debug ("%s: RPF'%s=%s(%s) for Interface %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg), rpf_str, pim_upstream_state2str (up->join_state), + up->sg_str, rpf_str, pim_upstream_state2str (up->join_state), up->rpf.source_nexthop.interface->name); if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { zlog_debug("%s: can't send join upstream: RPF'%s=%s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg), rpf_str); + up->sg_str, rpf_str); /* warning only */ } } @@ -273,7 +273,7 @@ static void join_timer_start(struct pim_upstream *up) zlog_debug("%s: starting %d sec timer for upstream (S,G)=%s", __PRETTY_FUNCTION__, qpim_t_periodic, - pim_str_sg_dump (&up->sg)); + up->sg_str); } THREAD_OFF (up->t_join_timer); @@ -295,7 +295,7 @@ static void pim_upstream_join_timer_restart_msec(struct pim_upstream *up, zlog_debug("%s: restarting %d msec timer for upstream (S,G)=%s", __PRETTY_FUNCTION__, interval_msec, - pim_str_sg_dump (&up->sg)); + up->sg_str); } THREAD_OFF(up->t_join_timer); @@ -321,7 +321,7 @@ void pim_upstream_join_suppress(struct pim_upstream *up, pim_inet4_dump("", rpf_addr, rpf_str, sizeof(rpf_str)); zlog_debug("%s %s: detected Join%s to RPF'(S,G)=%s: join_timer=%ld msec t_joinsuppress=%ld msec", __FILE__, __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg), + up->sg_str, rpf_str, join_timer_remain_msec, t_joinsuppress_msec); } @@ -330,7 +330,7 @@ void pim_upstream_join_suppress(struct pim_upstream *up, if (PIM_DEBUG_PIM_TRACE) { zlog_debug("%s %s: suppressing Join(S,G)=%s for %ld msec", __FILE__, __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg), t_joinsuppress_msec); + up->sg_str, t_joinsuppress_msec); } pim_upstream_join_timer_restart_msec(up, t_joinsuppress_msec); @@ -352,7 +352,7 @@ void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label, pim_inet4_dump("", rpf_addr, rpf_str, sizeof(rpf_str)); zlog_debug("%s: to RPF'%s=%s: join_timer=%ld msec t_override=%d msec", debug_label, - pim_str_sg_dump (&up->sg), rpf_str, + up->sg_str, rpf_str, join_timer_remain_msec, t_override_msec); } @@ -360,7 +360,7 @@ void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label, if (PIM_DEBUG_PIM_TRACE) { zlog_debug("%s: decreasing (S,G)=%s join timer to t_override=%d msec", debug_label, - pim_str_sg_dump (&up->sg), + up->sg_str, t_override_msec); } @@ -432,7 +432,7 @@ pim_upstream_switch(struct pim_upstream *up, if (PIM_DEBUG_PIM_EVENTS) { zlog_debug("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg), + up->sg_str, pim_upstream_state2str (up->join_state), pim_upstream_state2str (new_state)); } @@ -537,6 +537,7 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, } up->sg = *sg; + pim_str_sg_set (sg, up->sg_str); up = hash_get (pim_upstream_hash, up, hash_alloc_intern); if (!pim_rp_set_upstream_addr (&up->upstream_addr, sg->src, sg->grp)) { @@ -584,7 +585,7 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, if (rpf_result == PIM_RPF_FAILURE) { if (PIM_DEBUG_PIM_TRACE) zlog_debug ("%s: Attempting to create upstream(%s), Unable to RPF for source", __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg)); + up->sg_str); if (up->parent) { @@ -607,7 +608,7 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, listnode_add_sort(pim_upstream_list, up); if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: Created Upstream %s", __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg)); + zlog_debug ("%s: Created Upstream %s", __PRETTY_FUNCTION__, up->sg_str); return up; } @@ -648,7 +649,7 @@ struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, if (up) zlog_debug("%s(%s): (%s), found: %d: ref_count: %d", __PRETTY_FUNCTION__, name, - pim_str_sg_dump (&up->sg), found, + up->sg_str, found, up->ref_count); else zlog_debug("%s(%s): (%s) failure to create", @@ -786,7 +787,7 @@ void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr) pim_addr_dump("", &up->rpf.rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); zlog_debug("%s: matching neigh=%s against upstream (S,G)=%s joined=%d rpf_addr=%s", __PRETTY_FUNCTION__, - neigh_str, pim_str_sg_dump (&up->sg), + neigh_str, up->sg_str, up->join_state == PIM_UPSTREAM_JOINED, rpf_addr_str); } @@ -910,8 +911,8 @@ static void pim_upstream_fhr_kat_expiry(struct pim_upstream *up) return; if (PIM_DEBUG_TRACE) - zlog_debug ("kat expired on %s; clear fhr reg state", - pim_str_sg_dump (&up->sg)); + zlog_debug ("kat expired on %s; clear fhr reg state", up->sg_str); + /* stop reg-stop timer */ THREAD_OFF(up->t_rs_timer); /* remove regiface from the OIL if it is there*/ @@ -928,8 +929,8 @@ static void pim_upstream_fhr_kat_start(struct pim_upstream *up) { if (pim_upstream_could_register(up)) { if (PIM_DEBUG_TRACE) - zlog_debug ("kat started on %s; set fhr reg state to joined", - pim_str_sg_dump (&up->sg)); + zlog_debug ("kat started on %s; set fhr reg state to joined", up->sg_str); + PIM_UPSTREAM_FLAG_SET_FHR(up->flags); if (up->join_state == PIM_UPSTREAM_NOTJOINED) { pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); @@ -969,8 +970,7 @@ pim_upstream_keep_alive_timer (struct thread *t) { pim_upstream_fhr_kat_expiry(up); if (PIM_DEBUG_TRACE) - zlog_debug ("kat expired on %s; remove stream reference", - pim_str_sg_dump (&up->sg)); + 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__); } @@ -984,8 +984,7 @@ pim_upstream_keep_alive_timer_start (struct pim_upstream *up, { if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) { if (PIM_DEBUG_TRACE) - zlog_debug ("kat start on %s with no stream reference", - pim_str_sg_dump (&up->sg)); + zlog_debug ("kat start on %s with no stream reference", up->sg_str); } THREAD_OFF (up->t_ka_timer); THREAD_TIMER_ON (master, @@ -1111,7 +1110,7 @@ pim_upstream_set_sptbit (struct pim_upstream *up, struct interface *incoming) { if (PIM_DEBUG_TRACE) zlog_debug ("%s: %s is directly connected to the source", __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg)); + up->sg_str); up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; return; } @@ -1122,7 +1121,7 @@ pim_upstream_set_sptbit (struct pim_upstream *up, struct interface *incoming) { if (PIM_DEBUG_TRACE) zlog_debug ("%s: %s RPF_interface(S) != RPF_interface(RP(G))", - __PRETTY_FUNCTION__, pim_str_sg_dump(&up->sg)); + __PRETTY_FUNCTION__, up->sg_str); up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; return; } @@ -1132,7 +1131,7 @@ pim_upstream_set_sptbit (struct pim_upstream *up, struct interface *incoming) { if (PIM_DEBUG_TRACE) zlog_debug ("%s: %s OR inherited_olist(S,G,rpt) == NULL", __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg)); + up->sg_str); up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; return; } @@ -1143,7 +1142,7 @@ pim_upstream_set_sptbit (struct pim_upstream *up, struct interface *incoming) { if (PIM_DEBUG_TRACE) zlog_debug ("%s: %s RPF'(S,G) is the same as RPF'(*,G)", __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg)); + up->sg_str); up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; return; } @@ -1186,7 +1185,7 @@ pim_upstream_register_stop_timer (struct thread *t) if (PIM_DEBUG_TRACE) { zlog_debug ("%s: (S,G)=%s upstream register stop timer %s", - __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg), + __PRETTY_FUNCTION__, up->sg_str, pim_upstream_state2str(up->join_state)); } @@ -1252,7 +1251,7 @@ pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_regist if (PIM_DEBUG_TRACE) { zlog_debug ("%s: (S,G)=%s Starting upstream register stop timer %d", - __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg), time); + __PRETTY_FUNCTION__, up->sg_str, time); } THREAD_TIMER_ON (master, up->t_rs_timer, pim_upstream_register_stop_timer, @@ -1343,7 +1342,7 @@ pim_upstream_find_new_rpf (void) { if (PIM_DEBUG_PIM_TRACE) zlog_debug ("Upstream %s without a path to send join, checking", - pim_str_sg_dump (&up->sg)); + up->sg_str); pim_rpf_update (up, NULL); } } @@ -1431,7 +1430,7 @@ pim_upstream_sg_running (void *arg) { if (PIM_DEBUG_TRACE) zlog_debug ("%s: %s is not installed in mroute", - __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg)); + __PRETTY_FUNCTION__, up->sg_str); return; } @@ -1445,7 +1444,7 @@ pim_upstream_sg_running (void *arg) if (PIM_DEBUG_TRACE) { zlog_debug ("%s: %s old packet count is equal or lastused is greater than 30", - __PRETTY_FUNCTION__, pim_str_sg_dump (&up->sg)); + __PRETTY_FUNCTION__, up->sg_str); zlog_debug ("%s: %ld %ld %lld", __PRETTY_FUNCTION__, up->channel_oil->cc.oldpktcnt, up->channel_oil->cc.pktcnt, up->channel_oil->cc.lastused/100); } return; @@ -1457,8 +1456,8 @@ pim_upstream_sg_running (void *arg) if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) { if (PIM_DEBUG_TRACE) - zlog_debug ("source reference created on kat restart %s", - pim_str_sg_dump (&up->sg)); + 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); diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index a40265a906..cc4860a215 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -83,6 +83,7 @@ struct pim_upstream { struct in_addr upstream_addr;/* Who we are talking to */ struct in_addr upstream_register; /*Who we received a register from*/ struct prefix_sg sg; /* (S,G) group key */ + char sg_str[PIM_SG_LEN]; uint32_t flags; struct channel_oil *channel_oil; struct list *sources; diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 815fbbd2d3..f5c73efe2d 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -1188,7 +1188,7 @@ void pim_forward_start(struct pim_ifchannel *ch) if (PIM_DEBUG_PIM_TRACE) zlog_debug("%s %s: could not create OIL for channel (S,G)=%s", __FILE__, __PRETTY_FUNCTION__, - pim_str_sg_dump (&up->sg)); + up->sg_str); return; } } @@ -1205,14 +1205,14 @@ void pim_forward_stop(struct pim_ifchannel *ch) if (PIM_DEBUG_PIM_TRACE) { zlog_debug("%s: (S,G)=%s oif=%s", __PRETTY_FUNCTION__, - pim_str_sg_dump (&ch->sg), ch->interface->name); + ch->sg_str, ch->interface->name); } if (!up->channel_oil) { if (PIM_DEBUG_PIM_TRACE) zlog_debug("%s: (S,G)=%s oif=%s missing channel OIL", __PRETTY_FUNCTION__, - pim_str_sg_dump(&ch->sg), ch->interface->name); + ch->sg_str, ch->interface->name); return; } diff --git a/pimd/pimd.h b/pimd/pimd.h index 75a13a1e6b..0899d831e6 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -24,6 +24,7 @@ #include +#include "pim_str.h" #include "pim_memory.h" #include "pim_assert.h" From 0f055c0d5d2be277d2ecb0271e55620b13f5f341 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 17 Nov 2016 09:39:56 -0500 Subject: [PATCH 310/386] pimd: Further refine debugs in pim_sock_read path When we received a packet we were dumping packet information with debugs on 2 times for each packet where we had overlapping data being passed. Since debugs are expensive, reduce the count to 1. Signed-off-by: Donald Sharp --- pimd/pim_pim.c | 47 ++++++++++------------------------------------- 1 file changed, 10 insertions(+), 37 deletions(-) diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index bef3a8a34a..96d2111ce2 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -150,20 +150,8 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) } ip_hdr = (struct ip *) buf; - - if (PIM_DEBUG_PIM_PACKETS) - { - pim_inet4_dump("", ip_hdr->ip_src, src_str, sizeof(src_str)); - pim_inet4_dump("", ip_hdr->ip_dst, dst_str, sizeof(dst_str)); - } - ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */ - if (PIM_DEBUG_PIM_PACKETS) { - zlog_debug("Recv IP packet from %s to %s on %s: size=%zu ip_header_size=%zu ip_proto=%d", - src_str, dst_str, ifp->name, len, ip_hlen, ip_hdr->ip_p); - } - if (ip_hdr->ip_p != PIM_IP_PROTO_PIM) { if (PIM_DEBUG_PIM_PACKETS) zlog_debug("IP packet protocol=%d is not PIM=%d", @@ -174,26 +162,23 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) if (ip_hlen < PIM_IP_HEADER_MIN_LEN) { if (PIM_DEBUG_PIM_PACKETS) zlog_debug("IP packet header size=%zu shorter than minimum=%d", - ip_hlen, PIM_IP_HEADER_MIN_LEN); + ip_hlen, PIM_IP_HEADER_MIN_LEN); return -1; } if (ip_hlen > PIM_IP_HEADER_MAX_LEN) { if (PIM_DEBUG_PIM_PACKETS) zlog_debug("IP packet header size=%zu greater than maximum=%d", - ip_hlen, PIM_IP_HEADER_MAX_LEN); + ip_hlen, PIM_IP_HEADER_MAX_LEN); return -1; } pim_msg = buf + ip_hlen; pim_msg_len = len - ip_hlen; - if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { - pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_len); - } - if (pim_msg_len < PIM_PIM_MIN_LEN) { - zlog_warn("PIM message size=%d shorter than minimum=%d", - pim_msg_len, PIM_PIM_MIN_LEN); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("PIM message size=%d shorter than minimum=%d", + pim_msg_len, PIM_PIM_MIN_LEN); return -1; } @@ -222,9 +207,14 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) } if (PIM_DEBUG_PIM_PACKETS) { + pim_inet4_dump("", ip_hdr->ip_src, src_str, sizeof(src_str)); + pim_inet4_dump("", ip_hdr->ip_dst, dst_str, sizeof(dst_str)); zlog_debug("Recv PIM %s packet from %s to %s on %s: ttl=%d pim_version=%d pim_msg_size=%d checksum=%x", pim_pim_msgtype2str (pim_type), src_str, dst_str, ifp->name, ip_hdr->ip_ttl, pim_version, pim_msg_len, checksum); + if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { + pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_len); + } } switch (pim_type) @@ -310,23 +300,6 @@ static int pim_sock_read(struct thread *t) &to, &tolen, &ifindex); - if (PIM_DEBUG_PIM_PACKETS) { - char from_str[INET_ADDRSTRLEN]; - char to_str[INET_ADDRSTRLEN]; - - if (!inet_ntop(AF_INET, &from.sin_addr, from_str, sizeof(from_str))) - sprintf(from_str, ""); - if (!inet_ntop(AF_INET, &to.sin_addr, to_str, sizeof(to_str))) - sprintf(to_str, ""); - - zlog_debug("Recv IP PIM pkt size=%d from %s to %s on fd=%d on ifindex=%d (sock_ifindex=%d)", - len, from_str, to_str, fd, ifindex, ifp->ifindex); - - if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { - pim_pkt_dump(__PRETTY_FUNCTION__, buf, len); - } - } - #ifdef PIM_CHECK_RECV_IFINDEX_SANITY /* ifindex sanity check */ if (ifindex != (int) ifp->ifindex) { From 5441e690487700235ee7b5411f3d7aac0e9b2f2c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 17 Nov 2016 10:03:21 -0500 Subject: [PATCH 311/386] pimd: Reduce duplicate debug messages in wrvifwhole When we get a wrong vif whole callback, reduce the duplicate debug messages being processed. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index c7730acc04..d58cfaa9a2 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -340,10 +340,6 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) sg.src = ip_hdr->ip_src; sg.grp = ip_hdr->ip_dst; - if (PIM_DEBUG_MROUTE) - zlog_debug ("Received WHOLEPKT Wrong Vif for %s on %s", - pim_str_sg_dump (&sg), ifp->name); - ch = pim_ifchannel_find(ifp, &sg); if (ch) { @@ -365,9 +361,6 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) } #endif - if (PIM_DEBUG_MROUTE) - zlog_debug ("If channel: %p", ch); - up = pim_upstream_find (&sg); if (up) { From db48bcb23e920c1ee746c212ba5ed39e4954fe5e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 17 Nov 2016 10:50:05 -0500 Subject: [PATCH 312/386] pimd: Modify pim_sock_read to read 3 times before yielding Modify pim_sock_read to read up to 3 packets before yielding the cpu to something else. Signed-off-by: Donald Sharp --- pimd/pim_pim.c | 82 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 96d2111ce2..775293ce60 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -289,51 +289,73 @@ static int pim_sock_read(struct thread *t) int len; ifindex_t ifindex = -1; int result = -1; /* defaults to bad */ + static long long count = 0; + int cont = 1; ifp = THREAD_ARG(t); fd = THREAD_FD(t); pim_ifp = ifp->info; - len = pim_socket_recvfromto(fd, buf, sizeof(buf), - &from, &fromlen, - &to, &tolen, - &ifindex); + while (cont) + { + len = pim_socket_recvfromto(fd, buf, sizeof(buf), + &from, &fromlen, + &to, &tolen, + &ifindex); + if (len < 0) + { + if (errno == EINTR) + continue; + if (errno == EWOULDBLOCK || errno == EAGAIN) + { + cont = 0; + break; + } + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug ("Received errno: %d %s", errno, safe_strerror (errno)); + goto done; + } #ifdef PIM_CHECK_RECV_IFINDEX_SANITY - /* ifindex sanity check */ - if (ifindex != (int) ifp->ifindex) { - char from_str[INET_ADDRSTRLEN]; - char to_str[INET_ADDRSTRLEN]; - struct interface *recv_ifp; + /* ifindex sanity check */ + if (ifindex != (int) ifp->ifindex) { + char from_str[INET_ADDRSTRLEN]; + char to_str[INET_ADDRSTRLEN]; + struct interface *recv_ifp; - if (!inet_ntop(AF_INET, &from.sin_addr, from_str , sizeof(from_str))) - sprintf(from_str, ""); - if (!inet_ntop(AF_INET, &to.sin_addr, to_str , sizeof(to_str))) - sprintf(to_str, ""); + if (!inet_ntop(AF_INET, &from.sin_addr, from_str , sizeof(from_str))) + sprintf(from_str, ""); + if (!inet_ntop(AF_INET, &to.sin_addr, to_str , sizeof(to_str))) + sprintf(to_str, ""); - recv_ifp = if_lookup_by_index(ifindex); - if (recv_ifp) { - zassert(ifindex == (int) recv_ifp->ifindex); - } + recv_ifp = if_lookup_by_index(ifindex); + if (recv_ifp) { + zassert(ifindex == (int) recv_ifp->ifindex); + } #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH - zlog_warn("Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)", - from_str, to_str, fd, - ifindex, recv_ifp ? recv_ifp->name : "", - ifp->ifindex, ifp->name); + zlog_warn("Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)", + from_str, to_str, fd, + ifindex, recv_ifp ? recv_ifp->name : "", + ifp->ifindex, ifp->name); #endif - goto done; - } + goto done; + } #endif - int fail = pim_pim_packet(ifp, buf, len); - if (fail) { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("%s: pim_pim_packet() return=%d", - __PRETTY_FUNCTION__, fail); - goto done; - } + int fail = pim_pim_packet(ifp, buf, len); + if (fail) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("%s: pim_pim_packet() return=%d", + __PRETTY_FUNCTION__, fail); + goto done; + } + + count++; + if (count % 3 == 0) + cont = 0; + } result = 0; /* good */ From 6806e04d04bbf59cff7f7ca96151c334cd95af30 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 17 Nov 2016 11:18:06 -0500 Subject: [PATCH 313/386] pimd: Modify mroute_read to be non-blocking Modify mroute_read to be non-blocking and then to read in up to 3 packets at a time to be handled. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 63 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 18 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index d58cfaa9a2..34fc24c506 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -54,6 +54,7 @@ static int pim_mroute_set(int fd, int enable) int opt = enable ? MRT_INIT : MRT_DONE; socklen_t opt_len = sizeof(opt); int rcvbuf = 1024 * 1024 * 8; + long flags; err = setsockopt(fd, IPPROTO_IP, opt, &opt, opt_len); if (err) { @@ -69,6 +70,22 @@ static int pim_mroute_set(int fd, int enable) __PRETTY_FUNCTION__, fd, rcvbuf, errno, safe_strerror(errno)); } + flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) + { + zlog_warn("Could not get flags on socket fd:%d %d %s", + fd, errno, safe_strerror(errno)); + close (fd); + return -1; + } + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) + { + zlog_warn("Could not set O_NONBLOCK on socket fd:%d %d %s", + fd, errno, safe_strerror(errno)); + close(fd); + return -1; + } + if (enable) { int upcalls = IGMPMSG_WRVIFWHOLE; @@ -530,32 +547,42 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size) return 0; } -static int mroute_read_msg(int fd) -{ - char buf[10000]; - int rd; - - rd = read(fd, buf, sizeof(buf)); - if (rd < 0) { - zlog_warn("%s: failure reading fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); - return -1; - } - - return pim_mroute_msg(fd, buf, rd); -} - static int mroute_read(struct thread *t) { + static long long count; + char buf[10000]; + int result = 0; + int cont = 1; int fd; - int result; - + int rd; fd = THREAD_FD(t); - result = mroute_read_msg(fd); + while (cont) + { + rd = read(fd, buf, sizeof(buf)); + if (rd < 0) { + if (errno == EINTR) + continue; + if (errno == EWOULDBLOCK || errno == EAGAIN) + { + cont = 0; + break; + } + if (PIM_DEBUG_MROUTE) + zlog_warn("%s: failure reading fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); + goto done; + } + result = pim_mroute_msg(fd, buf, rd); + + count++; + if (count % 3 == 0) + cont = 0; + } /* Keep reading */ + done: qpim_mroute_socket_reader = NULL; mroute_read_on(); From 55a645a636fbfcd0920775933cd3bb9e51660d4f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 17 Nov 2016 19:57:10 -0500 Subject: [PATCH 314/386] pimd: Set pim socket receive buffer to a larger value There exists situations where we can receive data faster than we can process it. Make the buffer large enough to catch these situations for the pim sockets. Signed-off-by: Donald Sharp --- pimd/pim_sock.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index 681b5fe5c1..12f222bb80 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -113,6 +113,7 @@ pim_socket_bind (int fd, struct interface *ifp) int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, u_char loop) { + int rcvbuf = 1024 * 1024 * 8; struct ip_mreqn mreq; int fd; @@ -225,6 +226,10 @@ int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, u_char lo return PIM_SOCK_ERR_IFACE; } + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf))) + zlog_warn("%s: Failure to set buffer size to %d", + __PRETTY_FUNCTION__, rcvbuf); + { long flags; From 7176984f745f73c1350b69100295b25824d20dd4 Mon Sep 17 00:00:00 2001 From: anuradhak Date: Fri, 18 Nov 2016 09:12:27 -0800 Subject: [PATCH 315/386] pim-anycast-rp: Add limited support for secondary addresses. Anycast requires that the lo interface be associated with multiple addresses. One is the anycast IP address (which is the same on all RPs participating in RP redundancy) and the second is the unique IP address that will be used as the router id by routing protocols. To accomodate that we maintain a list of secondary addresses per-pim iface and allow any of them to be the RP address. This lets the I_am_RP macro succeed on anycast RPs. Note that the support is limited i.e. we don't actually advertise a secondary list to the neighbors. This is assuming the anycast IP will never be used as a router id i.e. will never be an RPF neighbor. Sample output: ============== dell-s6000-04# sh ip pim interface lo Interface : lo State : up Address : 100.1.1.1 (primary) 100.1.1.2 100.1.1.3 100.1.2.1 >>>>>>> SNIP >>>>>>>>>>>>>>> dell-s6000-04# sh ip pim interface lo json { "lo":{ "name":"lo", "state":"up", "address":"100.1.1.1", "index":1, "lanDelayEnabled":true, "secondaryAddressList":[ "100.1.1.2", "100.1.1.3", "100.1.2.1" ], >>>>>>> SNIP >>>>>>>>>>>>>>> dell-s6000-04#sh ip pim rp-info RP address group/prefix-list OIF I am RP 100.1.2.1 224.0.0.0/4 lo yes dell-s6000-04# Signed-off-by: Anuradha Karuppiah Acked-by: Donald Sharp --- pimd/pim_cmd.c | 26 ++++++- pimd/pim_iface.c | 182 ++++++++++++++++++++++++++++++++++++++++++++-- pimd/pim_iface.h | 11 +++ pimd/pim_main.c | 1 + pimd/pim_memory.c | 1 + pimd/pim_memory.h | 1 + pimd/pim_msdp.c | 16 ++-- pimd/pim_msg.c | 1 + pimd/pim_rp.c | 119 ++++++++++++++++++++++-------- pimd/pim_rp.h | 3 +- pimd/pim_zebra.c | 17 ++--- 11 files changed, 317 insertions(+), 61 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index ecfa94cba9..aa97907a30 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -787,6 +787,8 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch json_object *json_group = NULL; json_object *json_group_source = NULL; json_object *json_fhr_sources = NULL; + struct pim_secondary_addr *sec_addr; + struct listnode *sec_node; now = pim_time_monotonic_sec(); @@ -818,6 +820,16 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch json_row = json_object_new_object(); json_object_pim_ifp_add(json_row, ifp); + if (pim_ifp->sec_addr_list) { + json_object *sec_list = NULL; + + sec_list = json_object_new_array(); + for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) { + json_object_array_add(sec_list, json_object_new_string(inet_ntoa(sec_addr->addr))); + } + json_object_object_add(json_row, "secondaryAddressList", sec_list); + } + // PIM neighbors if (pim_ifp->pim_neighbor_list->count) { json_pim_neighbors = json_object_new_object(); @@ -900,7 +912,16 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch } else { vty_out(vty, "Interface : %s%s", ifp->name, VTY_NEWLINE); vty_out(vty, "State : %s%s", if_is_up(ifp) ? "up" : "down", VTY_NEWLINE); - vty_out(vty, "Address : %s%s", inet_ntoa(ifaddr), VTY_NEWLINE); + if (pim_ifp->sec_addr_list) { + vty_out(vty, "Address : %s (primary)%s", + inet_ntoa(ifaddr), VTY_NEWLINE); + for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) { + vty_out(vty, " %s%s", + inet_ntoa(sec_addr->addr), VTY_NEWLINE); + } + } else { + vty_out(vty, "Address : %s%s", inet_ntoa(ifaddr), VTY_NEWLINE); + } vty_out(vty, "%s", VTY_NEWLINE); // PIM neighbors @@ -4248,7 +4269,6 @@ static int pim_cmd_interface_add (struct interface *ifp, enum pim_interface_type itype) { struct pim_interface *pim_ifp = ifp->info; - struct in_addr null = { .s_addr = 0 }; if (!pim_ifp) { pim_ifp = pim_if_new(ifp, 0 /* igmp=false */, 1 /* pim=true */); @@ -4263,8 +4283,6 @@ pim_cmd_interface_add (struct interface *ifp, enum pim_interface_type itype) pim_ifp->itype = itype; pim_if_addr_add_all(ifp); pim_if_membership_refresh(ifp); - - pim_rp_check_rp (null, pim_ifp->primary_address); return 1; } diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index b83e8c1785..fcf07c253a 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -27,6 +27,7 @@ #include "prefix.h" #include "vrf.h" #include "linklist.h" +#include "plist.h" #include "pimd.h" #include "pim_iface.h" @@ -40,6 +41,7 @@ #include "pim_sock.h" #include "pim_time.h" #include "pim_ssmpingd.h" +#include "pim_rp.h" struct interface *pim_regiface = NULL; struct list *pim_ifchannel_list = NULL; @@ -304,17 +306,177 @@ static int detect_primary_address_change(struct interface *ifp, return changed; } +static int pim_sec_addr_comp(const void *p1, const void *p2) +{ + const struct pim_secondary_addr *sec1 = p1; + const struct pim_secondary_addr *sec2 = p2; + + if (ntohl(sec1->addr.s_addr) < ntohl(sec2->addr.s_addr)) + return -1; + + if (ntohl(sec1->addr.s_addr) > ntohl(sec2->addr.s_addr)) + return 1; + + return 0; +} + +static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr) +{ + XFREE(MTYPE_PIM_SEC_ADDR, sec_addr); +} + +static struct pim_secondary_addr * +pim_sec_addr_find(struct pim_interface *pim_ifp, struct in_addr addr) +{ + struct pim_secondary_addr *sec_addr; + struct listnode *node; + + if (!pim_ifp->sec_addr_list) { + return NULL; + } + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { + if (sec_addr->addr.s_addr == addr.s_addr) { + return sec_addr; + } + } + + return NULL; +} + +static void pim_sec_addr_del(struct pim_interface *pim_ifp, + struct pim_secondary_addr *sec_addr) +{ + listnode_delete(pim_ifp->sec_addr_list, sec_addr); + pim_sec_addr_free(sec_addr); +} + +static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct in_addr addr) +{ + int changed = 0; + struct pim_secondary_addr *sec_addr; + + sec_addr = pim_sec_addr_find(pim_ifp, addr); + if (sec_addr) { + sec_addr->flags &= ~PIM_SEC_ADDRF_STALE; + return changed; + } + + if (!pim_ifp->sec_addr_list) { + pim_ifp->sec_addr_list = list_new(); + pim_ifp->sec_addr_list->del = (void (*)(void *))pim_sec_addr_free; + pim_ifp->sec_addr_list->cmp = (int (*)(void *, void *))pim_sec_addr_comp; + } + + sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr)); + if (!sec_addr) { + if (list_isempty(pim_ifp->sec_addr_list)) { + list_free(pim_ifp->sec_addr_list); + pim_ifp->sec_addr_list = NULL; + } + return changed; + } + + changed = 1; + sec_addr->addr = addr; + listnode_add_sort(pim_ifp->sec_addr_list, sec_addr); + + return changed; +} + +static int pim_sec_addr_del_all(struct pim_interface *pim_ifp) +{ + int changed = 0; + + if (!pim_ifp->sec_addr_list) { + return changed; + } + if (!list_isempty(pim_ifp->sec_addr_list)) { + changed = 1; + /* remove all nodes and free up the list itself */ + list_delete_all_node(pim_ifp->sec_addr_list); + list_free(pim_ifp->sec_addr_list); + pim_ifp->sec_addr_list = NULL; + } + + return changed; +} + +static int pim_sec_addr_update(struct interface *ifp) +{ + struct pim_interface *pim_ifp = ifp->info; + struct connected *ifc; + struct listnode *node; + struct listnode *nextnode; + struct pim_secondary_addr *sec_addr; + int changed = 0; + + if (pim_ifp->sec_addr_list) { + for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { + sec_addr->flags |= PIM_SEC_ADDRF_STALE; + } + } + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { + struct prefix *p = ifc->address; + + if (p->family != AF_INET) { + continue; + } + + if (PIM_INADDR_IS_ANY(p->u.prefix4)) { + continue; + } + + if (pim_ifp->primary_address.s_addr == p->u.prefix4.s_addr) { + /* don't add the primary address into the secondary address list */ + continue; + } + + if (pim_sec_addr_add(pim_ifp, p->u.prefix4)) { + changed = 1; + } + } + + if (pim_ifp->sec_addr_list) { + /* Drop stale entries */ + for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode, sec_addr)) { + if (sec_addr->flags & PIM_SEC_ADDRF_STALE) { + pim_sec_addr_del(pim_ifp, sec_addr); + changed = 1; + } + } + + /* If the list went empty free it up */ + if (list_isempty(pim_ifp->sec_addr_list)) { + list_free(pim_ifp->sec_addr_list); + pim_ifp->sec_addr_list = NULL; + } + } + + return changed; +} + static void detect_secondary_address_change(struct interface *ifp, + int force_prim_as_any, const char *caller) { struct pim_interface *pim_ifp; - int changed; + int changed = 0; pim_ifp = ifp->info; if (!pim_ifp) return; - changed = 1; /* true */ + if (force_prim_as_any) { + /* if primary address is being forced to zero just flush the + * secondary address list */ + pim_sec_addr_del_all(pim_ifp); + } else { + /* re-evaluate the secondary address list */ + changed = pim_sec_addr_update(ifp); + } + if (PIM_DEBUG_ZEBRA) zlog_debug("FIXME T31 C15 %s: on interface %s: acting on any addr change", __PRETTY_FUNCTION__, ifp->name); @@ -327,7 +489,8 @@ static void detect_secondary_address_change(struct interface *ifp, return; } - pim_addr_change(ifp); + /* XXX - re-evaluate i_am_rp on addr change */ + //pim_addr_change(ifp); } static void detect_address_change(struct interface *ifp, @@ -343,7 +506,7 @@ static void detect_address_change(struct interface *ifp, return; } - detect_secondary_address_change(ifp, caller); + detect_secondary_address_change(ifp, force_prim_as_any, caller); } void pim_if_addr_add(struct connected *ifc) @@ -506,9 +669,11 @@ void pim_if_addr_add_all(struct interface *ifp) struct listnode *nextnode; int v4_addrs = 0; int v6_addrs = 0; + struct pim_interface *pim_ifp = ifp->info; + /* PIM/IGMP enabled ? */ - if (!ifp->info) + if (!pim_ifp) return; for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { @@ -526,9 +691,7 @@ void pim_if_addr_add_all(struct interface *ifp) if (!v4_addrs && v6_addrs && !if_is_loopback (ifp)) { - struct pim_interface *pim_ifp = ifp->info; - - if (pim_ifp && PIM_IF_TEST_PIM(pim_ifp->options)) { + if (PIM_IF_TEST_PIM(pim_ifp->options)) { /* Interface has a valid primary address ? */ if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { @@ -544,6 +707,8 @@ void pim_if_addr_add_all(struct interface *ifp) } } /* pim */ } + + pim_rp_check_on_if_add(pim_ifp); } void pim_if_addr_del_all(struct interface *ifp) @@ -564,6 +729,7 @@ void pim_if_addr_del_all(struct interface *ifp) pim_if_addr_del(ifc, 1 /* force_prim_as_any=true */); } + pim_i_am_rp_re_evaluate(); } void pim_if_addr_del_all_igmp(struct interface *ifp) diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index b1759c0da9..e2097c870e 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -59,11 +59,22 @@ enum pim_interface_type { PIM_INTERFACE_SM }; +enum pim_secondary_addr_flags { + PIM_SEC_ADDRF_NONE = 0, + PIM_SEC_ADDRF_STALE = (1 << 0) +}; + +struct pim_secondary_addr { + struct in_addr addr; + enum pim_secondary_addr_flags flags; +}; + struct pim_interface { enum pim_interface_type itype; uint32_t options; /* bit vector */ ifindex_t mroute_vif_index; struct in_addr primary_address; /* remember addr to detect change */ + struct list *sec_addr_list; /* list of struct pim_secondary_addr */ int igmp_version; /* IGMP version */ int igmp_default_robustness_variable; /* IGMPv3 QRV */ diff --git a/pimd/pim_main.c b/pimd/pim_main.c index 24163b0bd0..39cab7fb97 100644 --- a/pimd/pim_main.c +++ b/pimd/pim_main.c @@ -45,6 +45,7 @@ #include "pim_signals.h" #include "pim_zebra.h" #include "pim_msdp.h" +#include "pim_iface.h" #include "pim_rp.h" #ifdef PIM_ZCLIENT_DEBUG diff --git a/pimd/pim_memory.c b/pimd/pim_memory.c index a8d4c3404e..ccd0fa81ac 100644 --- a/pimd/pim_memory.c +++ b/pimd/pim_memory.c @@ -46,3 +46,4 @@ DEFINE_MTYPE(PIMD, PIM_MSDP_MG_NAME, "PIM MSDP mesh-group name") DEFINE_MTYPE(PIMD, PIM_MSDP_SA, "PIM MSDP source-active cache") DEFINE_MTYPE(PIMD, PIM_MSDP_MG, "PIM MSDP mesh group") DEFINE_MTYPE(PIMD, PIM_MSDP_MG_MBR, "PIM MSDP mesh group mbr") +DEFINE_MTYPE(PIMD, PIM_SEC_ADDR, "PIM secondary address") diff --git a/pimd/pim_memory.h b/pimd/pim_memory.h index 0f47fc22b4..b6b9b23239 100644 --- a/pimd/pim_memory.h +++ b/pimd/pim_memory.h @@ -45,5 +45,6 @@ DECLARE_MTYPE(PIM_MSDP_MG_NAME) DECLARE_MTYPE(PIM_MSDP_SA) DECLARE_MTYPE(PIM_MSDP_MG) DECLARE_MTYPE(PIM_MSDP_MG_MBR) +DECLARE_MTYPE(PIM_SEC_ADDR) #endif /* _QUAGGA_PIM_MEMORY_H */ diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index bee5e734db..e10289e90c 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -33,6 +33,7 @@ #include "pimd.h" #include "pim_cmd.h" #include "pim_memory.h" +#include "pim_iface.h" #include "pim_rp.h" #include "pim_str.h" #include "pim_time.h" @@ -526,6 +527,7 @@ void pim_msdp_i_am_rp_changed(void) { struct listnode *sanode; + struct listnode *nextnode; struct pim_msdp_sa *sa; if (!(msdp->flags & PIM_MSDPF_ENABLE)) { @@ -547,16 +549,18 @@ pim_msdp_i_am_rp_changed(void) /* re-setup local SA entries */ pim_msdp_sa_local_setup(); - for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + for (ALL_LIST_ELEMENTS(msdp->sa_list, sanode, nextnode, 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; + /* sa_deref can end up freeing the sa; so don't access contents after */ pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); + } else { + /* if the souce is still active check if we can influence SPT */ + pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "rp-change"); } - /* also check if we can still influence SPT */ - pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "rp-change"); } } @@ -1216,6 +1220,8 @@ pim_msdp_mg_free(struct pim_msdp_mg *mg) XFREE(MTYPE_PIM_MSDP_MG_NAME, mg->mesh_group_name); XFREE(MTYPE_PIM_MSDP_MG, mg); + if (mg->mbr_list) + list_free(mg->mbr_list); msdp->mg = NULL; } @@ -1536,10 +1542,6 @@ pim_msdp_enable(void) void pim_msdp_init(struct thread_master *master) { - /* XXX: temporarily enable noisy logs; will be disabled once dev is - * complete */ - PIM_DO_DEBUG_MSDP_INTERNAL; - msdp->master = master; msdp->peer_hash = hash_create(pim_msdp_peer_hash_key_make, diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index bb73e34062..0de9518d76 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -33,6 +33,7 @@ #include "pim_msg.h" #include "pim_util.h" #include "pim_str.h" +#include "pim_iface.h" #include "pim_rp.h" #include "pim_rpf.h" diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 118c8a3130..b6d604b59a 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -34,6 +34,7 @@ #include "pimd.h" #include "pim_vty.h" #include "pim_str.h" +#include "pim_iface.h" #include "pim_rp.h" #include "pim_str.h" #include "pim_rpf.h" @@ -250,12 +251,36 @@ pim_rp_prefix_list_update (struct prefix_list *plist) pim_rp_refresh_group_to_rp_mapping(); } +static int +pim_rp_check_interface_addrs(struct rp_info *rp_info, + struct pim_interface *pim_ifp) +{ + struct listnode *node; + struct pim_secondary_addr *sec_addr; + + if (pim_ifp->primary_address.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) + return 1; + + if (!pim_ifp->sec_addr_list) { + return 0; + } + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { + if (sec_addr->addr.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) { + return 1; + } + } + + return 0; +} + static void pim_rp_check_interfaces (struct rp_info *rp_info) { struct listnode *node; struct interface *ifp; + rp_info->i_am_rp = 0; for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { struct pim_interface *pim_ifp = ifp->info; @@ -263,8 +288,9 @@ pim_rp_check_interfaces (struct rp_info *rp_info) if (!pim_ifp) continue; - if (pim_ifp->primary_address.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) - rp_info->i_am_rp = 1; + if (pim_rp_check_interface_addrs(rp_info, pim_ifp)) { + rp_info->i_am_rp = 1; + } } } @@ -507,10 +533,11 @@ pim_rp_setup (void) } /* - * Checks to see if we should elect ourself the actual RP + * Checks to see if we should elect ourself the actual RP when new if + * addresses are added against an interface. */ void -pim_rp_check_rp (struct in_addr old, struct in_addr new) +pim_rp_check_on_if_add(struct pim_interface *pim_ifp) { struct listnode *node; struct rp_info *rp_info; @@ -519,40 +546,70 @@ pim_rp_check_rp (struct in_addr old, struct in_addr new) if (qpim_rp_list == NULL) return; - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { + for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { + if (pim_rpf_addr_is_inaddr_none (&rp_info->rp)) + continue; + + /* if i_am_rp is already set nothing to be done (adding new addresses + * is not going to make a difference). */ + if (rp_info->i_am_rp) { + continue; + } + + if (pim_rp_check_interface_addrs(rp_info, pim_ifp)) { + i_am_rp_changed = true; + rp_info->i_am_rp = 1; if (PIM_DEBUG_ZEBRA) { - char sold[INET_ADDRSTRLEN]; - char snew[INET_ADDRSTRLEN]; char rp[PREFIX_STRLEN]; pim_addr_dump("", &rp_info->rp.rpf_addr, rp, sizeof(rp)); - pim_inet4_dump("", old, sold, sizeof(sold)); - pim_inet4_dump("", new, snew, sizeof(snew)); - zlog_debug("%s: %s for old %s new %s", __func__, rp, sold, snew ); + zlog_debug("%s: %s: i am rp", __func__, rp); } - if (pim_rpf_addr_is_inaddr_none (&rp_info->rp)) - continue; - - if (new.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 = 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(); + if (i_am_rp_changed) { + pim_msdp_i_am_rp_changed(); + } +} + +/* up-optimized re-evaluation of "i_am_rp". this is used when ifaddresses + * are removed. Removing numbers is an uncommon event in an active network + * so I have made no attempt to optimize it. */ +void +pim_i_am_rp_re_evaluate(void) +{ + struct listnode *node; + struct rp_info *rp_info; + bool i_am_rp_changed = false; + int old_i_am_rp; + + if (qpim_rp_list == NULL) + return; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (pim_rpf_addr_is_inaddr_none(&rp_info->rp)) + continue; + + old_i_am_rp = rp_info->i_am_rp; + pim_rp_check_interfaces(rp_info); + + if (old_i_am_rp != rp_info->i_am_rp) { + i_am_rp_changed = true; + if (PIM_DEBUG_ZEBRA) { + char rp[PREFIX_STRLEN]; + pim_addr_dump("", &rp_info->rp.rpf_addr, rp, sizeof(rp)); + if (rp_info->i_am_rp) { + zlog_debug("%s: %s: i am rp", __func__, rp); + } else { + zlog_debug("%s: %s: i am no longer rp", __func__, rp); + } + } } + } + + if (i_am_rp_changed) { + pim_msdp_i_am_rp_changed(); + } } /* diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index 1e1912ff96..b32228ed49 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -32,8 +32,9 @@ int pim_rp_config_write (struct vty *vty); int pim_rp_setup (void); -void pim_rp_check_rp (struct in_addr old, struct in_addr new); int pim_rp_i_am_rp (struct in_addr group); +void pim_rp_check_on_if_add(struct pim_interface *pim_ifp); +void pim_i_am_rp_re_evaluate(void); int pim_rp_check_is_my_ip_address (struct in_addr group, struct in_addr dest_addr); diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index f5c73efe2d..294d8bba25 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -223,7 +223,7 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient, { struct connected *c; struct prefix *p; - struct in_addr old = { .s_addr = 0 }; + struct pim_interface *pim_ifp; /* zebra api notifies address adds/dels events by using the same call @@ -237,6 +237,7 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient, if (!c) return 0; + pim_ifp = c->ifp->info; p = c->address; if (PIM_DEBUG_ZEBRA) { @@ -254,7 +255,6 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient, if (p->family != AF_INET) { - struct pim_interface *pim_ifp = c->ifp->info; struct listnode *cnode; struct connected *conn; int v4addrs = 0; @@ -273,8 +273,6 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient, return 0; } - pim_rp_check_rp (old, p->u.prefix4); - if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) { /* trying to add primary address */ @@ -284,20 +282,20 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient, /* but we had a primary address already */ char buf[BUFSIZ]; - char old[INET_ADDRSTRLEN]; prefix2str(p, buf, BUFSIZ); - pim_inet4_dump("", primary_addr, old, sizeof(old)); - zlog_warn("%s: %s primary addr old=%s: forcing secondary flag on new=%s", + zlog_warn("%s: %s : forcing secondary flag on %s", __PRETTY_FUNCTION__, - c->ifp->name, old, buf); + c->ifp->name, buf); } SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY); } } pim_if_addr_add(c); + if (pim_ifp) + pim_rp_check_on_if_add(pim_ifp); if (if_is_loopback (c->ifp)) { @@ -319,7 +317,6 @@ static int pim_zebra_if_address_del(int command, struct zclient *client, { struct connected *c; struct prefix *p; - struct in_addr new = { .s_addr = 0 }; /* zebra api notifies address adds/dels events by using the same call @@ -350,8 +347,8 @@ static int pim_zebra_if_address_del(int command, struct zclient *client, #endif } - pim_rp_check_rp (p->u.prefix4, new); pim_if_addr_del(c, 0); + pim_i_am_rp_re_evaluate(); return 0; } From 8e4c9ef376c2b376f72b6b061c38107522c3aecc Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 18 Nov 2016 12:50:46 -0500 Subject: [PATCH 316/386] pimd: Add knob to control # of packets read in at one time Add 'ip pim packets <1-100>' command. Allows you to control the number of packets read in before giving control back to another part of the process. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 25 +++++++++++++++++++++++++ pimd/pim_mroute.c | 2 +- pimd/pim_pim.c | 2 +- pimd/pim_vty.c | 6 ++++++ pimd/pimd.c | 1 + pimd/pimd.h | 2 ++ 6 files changed, 36 insertions(+), 2 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index aa97907a30..0507ef2681 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3434,6 +3434,29 @@ DEFUN (no_ip_pim_keep_alive, return CMD_SUCCESS; } +DEFUN (ip_pim_packets, + ip_pim_packets_cmd, + "ip pim packets <1-100>", + IP_STR + "pim multicast routing\n" + "Number of packets to process at one time per fd\n") +{ + qpim_packet_process = atoi (argv[3]->arg); + return CMD_SUCCESS; +} + +DEFUN (no_ip_pim_packets, + no_ip_pim_packets_cmd, + "no ip pim packets <1-100>", + NO_STR + IP_STR + "pim multicast routing\n" + "Number of packets to process at one time per fd\n") +{ + qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS; + return CMD_SUCCESS; +} + DEFUN (ip_pim_rp, ip_pim_rp_cmd, "ip pim rp A.B.C.D [A.B.C.D/M]", @@ -5964,6 +5987,8 @@ void pim_cmd_init() install_element (CONFIG_NODE, &no_ip_pim_register_suppress_cmd); install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd); install_element (CONFIG_NODE, &no_ip_pim_keep_alive_cmd); + install_element (CONFIG_NODE, &ip_pim_packets_cmd); + install_element (CONFIG_NODE, &no_ip_pim_packets_cmd); install_element (CONFIG_NODE, &ip_ssmpingd_cmd); install_element (CONFIG_NODE, &no_ip_ssmpingd_cmd); install_element (CONFIG_NODE, &ip_msdp_peer_cmd); diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 34fc24c506..01fa529525 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -578,7 +578,7 @@ static int mroute_read(struct thread *t) result = pim_mroute_msg(fd, buf, rd); count++; - if (count % 3 == 0) + if (count % qpim_packet_process == 0) cont = 0; } /* Keep reading */ diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 775293ce60..c7fee4a66f 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -353,7 +353,7 @@ static int pim_sock_read(struct thread *t) } count++; - if (count % 3 == 0) + if (count % qpim_packet_process == 0) cont = 0; } diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index b72602e22e..527ca5a507 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -168,6 +168,12 @@ int pim_global_config_write(struct vty *vty) qpim_keep_alive_time, VTY_NEWLINE); ++writes; } + if (qpim_packet_process != PIM_DEFAULT_PACKET_PROCESS) + { + vty_out (vty, "ip pim packets %d%s", + qpim_packet_process, VTY_NEWLINE); + ++writes; + } if (qpim_ssmpingd_list) { struct listnode *node; diff --git a/pimd/pimd.c b/pimd/pimd.c index bc8b88444a..0e5313906f 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -72,6 +72,7 @@ struct list *qpim_static_route_list = NULL; unsigned int qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; signed int qpim_rp_keep_alive_time = 0; int64_t qpim_nexthop_lookups = 0; +int qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS; int32_t qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; int32_t qpim_register_probe_time = PIM_REGISTER_PROBE_TIME_DEFAULT; diff --git a/pimd/pimd.h b/pimd/pimd.h index 0899d831e6..0f4efe91f0 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -119,6 +119,8 @@ int64_t qpim_nexthop_lookups; struct list *qpim_static_route_list; /* list of routes added statically */ extern unsigned int qpim_keep_alive_time; extern signed int qpim_rp_keep_alive_time; +extern int qpim_packet_process; +#define PIM_DEFAULT_PACKET_PROCESS 3 #define PIM_JP_HOLDTIME (qpim_t_periodic * 7 / 2) From 18e565fd96f69d7dd445d1c5c07dd7a0dfafd6f9 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 18 Nov 2016 14:11:31 -0500 Subject: [PATCH 317/386] pimd: Only make the pim sockets non blocking. Only make the pim sockets non-blocking on reads. Signed-off-by: Donald Sharp --- pimd/pim_sock.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index 12f222bb80..6ce336d605 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -230,24 +230,25 @@ int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, u_char lo zlog_warn("%s: Failure to set buffer size to %d", __PRETTY_FUNCTION__, rcvbuf); - { - long flags; + if (protocol == IPPROTO_PIM) + { + long flags; - flags = fcntl(fd, F_GETFL, 0); - if (flags < 0) { - zlog_warn("Could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_NONBLOCK_GETFL; - } + flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) { + zlog_warn("Could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_NONBLOCK_GETFL; + } - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { - zlog_warn("Could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_NONBLOCK_SETFL; + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { + zlog_warn("Could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_NONBLOCK_SETFL; + } } - } return fd; } From 4763cd0ed51565db9bc32eeadee8b91c12eb3623 Mon Sep 17 00:00:00 2001 From: anuradhak Date: Fri, 18 Nov 2016 16:19:26 -0800 Subject: [PATCH 318/386] pim-anycast-rp: Support in BGP unnumbered networks. Anycast rp requires multiple ip addresses on the lo. If PIM is used in an unnumbered BGP network it picks one of the lo addresses as the pim-primary for the swp interfaces. But if the anycast IP is picked up by both sides pim nbr will never converge. So a static "use-source" config is provided to allow the administrator to force the the hello source to the unique IP address. Sample output: ============= dell-s6000-04(config-if)# do show running-config pimd >>>>>> SNIPPED >>>>>>>>>>>>>>>>> interface lo ip pim sm ip pim use-source 100.1.1.5 ! >>>>>> SNIPPED >>>>>>>>>>>>>>>>> dell-s6000-04(config-if)# do show ip pim interface lo Interface : lo State : up Use Source : 100.1.1.5 Address : 100.1.1.5 (primary) 100.1.1.100 >>>>>> SNIPPED >>>>>>>>>>>>>>>>> dell-s6000-04(config-if)# do show ip pim interface lo json { "lo":{ "name":"lo", "state":"up", "address":"100.1.1.5", "index":1, "lanDelayEnabled":true, "useSource":"100.1.1.5", "secondaryAddressList":[ "100.1.1.100" ], >>>>>> SNIPPED >>>>>>>>>>>>>>>>> Signed-off-by: Anuradha Karuppiah Acked-by: Donald Sharp --- pimd/pim_cmd.c | 68 +++++++++++++++++++++++++++++++++--- pimd/pim_iface.c | 89 +++++++++++++++++++++++++++--------------------- pimd/pim_iface.h | 3 ++ pimd/pim_vty.c | 9 +++++ pimd/pimd.h | 2 ++ 5 files changed, 128 insertions(+), 43 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 0507ef2681..ab16943431 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -820,6 +820,9 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch json_row = json_object_new_object(); json_object_pim_ifp_add(json_row, ifp); + if (pim_ifp->update_source.s_addr != INADDR_ANY) { + json_object_string_add(json_row, "useSource", inet_ntoa(pim_ifp->update_source)); + } if (pim_ifp->sec_addr_list) { json_object *sec_list = NULL; @@ -910,17 +913,20 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch json_object_object_add(json, ifp->name, json_row); } else { - vty_out(vty, "Interface : %s%s", ifp->name, VTY_NEWLINE); - vty_out(vty, "State : %s%s", if_is_up(ifp) ? "up" : "down", VTY_NEWLINE); + vty_out(vty, "Interface : %s%s", ifp->name, VTY_NEWLINE); + vty_out(vty, "State : %s%s", if_is_up(ifp) ? "up" : "down", VTY_NEWLINE); + if (pim_ifp->update_source.s_addr != INADDR_ANY) { + vty_out(vty, "Use Source : %s%s", inet_ntoa(pim_ifp->update_source), VTY_NEWLINE); + } if (pim_ifp->sec_addr_list) { - vty_out(vty, "Address : %s (primary)%s", + vty_out(vty, "Address : %s (primary)%s", inet_ntoa(ifaddr), VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) { - vty_out(vty, " %s%s", + vty_out(vty, " %s%s", inet_ntoa(sec_addr->addr), VTY_NEWLINE); } } else { - vty_out(vty, "Address : %s%s", inet_ntoa(ifaddr), VTY_NEWLINE); + vty_out(vty, "Address : %s%s", inet_ntoa(ifaddr), VTY_NEWLINE); } vty_out(vty, "%s", VTY_NEWLINE); @@ -5186,6 +5192,56 @@ DEFUN (show_debugging_pim, return CMD_SUCCESS; } +static int +interface_pim_use_src_cmd_worker(struct vty *vty, const char *source) +{ + int result; + struct in_addr source_addr; + VTY_DECLVAR_CONTEXT(interface, ifp); + + result = inet_pton(AF_INET, source, &source_addr); + if (result <= 0) { + vty_out(vty, "%% Bad source address %s: errno=%d: %s%s", + source, errno, safe_strerror(errno), VTY_NEWLINE); + return CMD_WARNING; + } + + result = pim_update_source_set(ifp, source_addr); + switch (result) { + case PIM_SUCCESS: + break; + case PIM_UPDATE_SOURCE_DUP: + vty_out(vty, "%% Source already set to %s%s", source, VTY_NEWLINE); + break; + default: + vty_out(vty, "%% Source set failed%s", VTY_NEWLINE); + } + + return result?CMD_WARNING:CMD_SUCCESS; +} + +DEFUN (interface_pim_use_source, + interface_pim_use_source_cmd, + "ip pim use-source A.B.C.D", + IP_STR + "pim multicast routing\n" + "Configure primary IP address\n" + "source ip address\n") +{ + return interface_pim_use_src_cmd_worker (vty, argv[3]->arg); +} + +DEFUN (interface_no_pim_use_source, + interface_no_pim_use_source_cmd, + "no ip pim use-source", + NO_STR + IP_STR + "pim multicast routing\n" + "Delete source IP address\n") +{ + return interface_pim_use_src_cmd_worker (vty, "0.0.0.0"); +} + static int ip_msdp_peer_cmd_worker (struct vty *vty, const char *peer, const char *local) { @@ -6145,4 +6201,6 @@ void pim_cmd_init() install_element (VIEW_NODE, &show_ip_msdp_sa_detail_cmd); install_element (VIEW_NODE, &show_ip_msdp_sa_sg_cmd); install_element (VIEW_NODE, &show_ip_msdp_mesh_group_cmd); + install_element (INTERFACE_NODE, &interface_pim_use_source_cmd); + install_element (INTERFACE_NODE, &interface_no_pim_use_source_cmd); } diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index fcf07c253a..b5f1fadca5 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -267,14 +267,10 @@ static int detect_primary_address_change(struct interface *ifp, int force_prim_as_any, const char *caller) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp = ifp->info; struct in_addr new_prim_addr; int changed; - pim_ifp = ifp->info; - if (!pim_ifp) - return 0; - if (force_prim_as_any) new_prim_addr = qpim_inaddr_any; else @@ -295,12 +291,6 @@ static int detect_primary_address_change(struct interface *ifp, if (changed) { pim_ifp->primary_address = new_prim_addr; - - if (!PIM_IF_TEST_PIM(pim_ifp->options)) { - return changed; - } - - pim_addr_change(ifp); } return changed; @@ -457,56 +447,74 @@ static int pim_sec_addr_update(struct interface *ifp) return changed; } -static void detect_secondary_address_change(struct interface *ifp, +static int detect_secondary_address_change(struct interface *ifp, int force_prim_as_any, const char *caller) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp = ifp->info; int changed = 0; - pim_ifp = ifp->info; - if (!pim_ifp) - return; - if (force_prim_as_any) { /* if primary address is being forced to zero just flush the * secondary address list */ - pim_sec_addr_del_all(pim_ifp); + changed = pim_sec_addr_del_all(pim_ifp); } else { /* re-evaluate the secondary address list */ changed = pim_sec_addr_update(ifp); } - if (PIM_DEBUG_ZEBRA) - zlog_debug("FIXME T31 C15 %s: on interface %s: acting on any addr change", - __PRETTY_FUNCTION__, ifp->name); - - if (!changed) { - return; - } - - if (!PIM_IF_TEST_PIM(pim_ifp->options)) { - return; - } - - /* XXX - re-evaluate i_am_rp on addr change */ - //pim_addr_change(ifp); + return changed; } static void detect_address_change(struct interface *ifp, int force_prim_as_any, const char *caller) { - int prim_changed; + int changed = 0; + struct pim_interface *pim_ifp; - prim_changed = detect_primary_address_change(ifp, force_prim_as_any, caller); - if (prim_changed) { - /* no need to detect secondary change because - the reaction would be the same */ + pim_ifp = ifp->info; + if (!pim_ifp) return; + + if (detect_primary_address_change(ifp, force_prim_as_any, caller)) { + changed = 1; } - detect_secondary_address_change(ifp, force_prim_as_any, caller); + if (detect_secondary_address_change(ifp, force_prim_as_any, caller)) { + changed = 1; + } + + + if (changed) { + if (!PIM_IF_TEST_PIM(pim_ifp->options)) { + return; + } + + pim_addr_change(ifp); + } + + /* XXX: if we have unnumbered interfaces we need to run detect address + * address change on all of them when the lo address changes */ +} + +int pim_update_source_set(struct interface *ifp, struct in_addr source) +{ + struct pim_interface *pim_ifp = ifp->info; + + if (!pim_ifp) { + return PIM_IFACE_NOT_FOUND; + } + + if (pim_ifp->update_source.s_addr == source.s_addr) { + return PIM_UPDATE_SOURCE_DUP; + } + + pim_ifp->update_source = source; + detect_address_change(ifp, 0 /* force_prim_as_any */, + __PRETTY_FUNCTION__); + + return PIM_SUCCESS; } void pim_if_addr_add(struct connected *ifc) @@ -780,6 +788,11 @@ pim_find_primary_addr (struct interface *ifp) struct in_addr addr; int v4_addrs = 0; int v6_addrs = 0; + struct pim_interface *pim_ifp = ifp->info; + + if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) { + return pim_ifp->update_source; + } for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { struct prefix *p = ifc->address; diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index e2097c870e..17bbbd9937 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -75,6 +75,8 @@ struct pim_interface { ifindex_t mroute_vif_index; struct in_addr primary_address; /* remember addr to detect change */ struct list *sec_addr_list; /* list of struct pim_secondary_addr */ + struct in_addr update_source; /* user can statically set the primary + * address of the interface */ int igmp_version; /* IGMP version */ int igmp_default_robustness_variable; /* IGMPv3 QRV */ @@ -185,5 +187,6 @@ void pim_if_update_assert_tracking_desired(struct interface *ifp); void pim_if_create_pimreg(void); int pim_if_connected_to_source (struct interface *ifp, struct in_addr src); +int pim_update_source_set(struct interface *ifp, struct in_addr source); #endif /* PIM_IFACE_H */ diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 527ca5a507..38cefe7619 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -230,6 +230,15 @@ int pim_interface_config_write(struct vty *vty) vty_out(vty, "%s", VTY_NEWLINE); } + /* update source */ + if (PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", pim_ifp->update_source, src_str, + sizeof(src_str)); + vty_out(vty, " ip pim use-source %s%s", src_str, VTY_NEWLINE); + ++writes; + } + /* IF ip igmp */ if (PIM_IF_TEST_IGMP(pim_ifp->options)) { vty_out(vty, " ip igmp%s", VTY_NEWLINE); diff --git a/pimd/pimd.h b/pimd/pimd.h index 0f4efe91f0..54cecd19d2 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -86,6 +86,8 @@ #define PIM_RP_NO_PATH -6 #define PIM_RP_NOT_FOUND -7 #define PIM_RP_PFXLIST_IN_USE -8 +#define PIM_IFACE_NOT_FOUND -9 +#define PIM_UPDATE_SOURCE_DUP -10 const char *const PIM_ALL_SYSTEMS; const char *const PIM_ALL_ROUTERS; From 7923d3178ff6b5aab419a36869e777cb4be77636 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 19 Nov 2016 11:20:26 -0500 Subject: [PATCH 319/386] pimd: Cleanup igmp read socket With the change over to using the kernel upcall for igmp messages, we need to add in a read thread for the igmp socket to drain the igmp socket's receive queue. Signed-off-by: Donald Sharp --- pimd/pim_igmp.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++- pimd/pim_sock.c | 33 ++++++++++++++--------------- 2 files changed, 70 insertions(+), 18 deletions(-) diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index f47028b2ba..87a54d68d0 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -665,7 +665,6 @@ static void sock_close(struct igmp_sock *igmp) } } THREAD_OFF(igmp->t_igmp_read); - zassert(!igmp->t_igmp_read); if (close(igmp->fd)) { zlog_err("Failure closing IGMP socket %s fd=%d on interface %s: errno=%d: %s", @@ -841,6 +840,58 @@ static struct igmp_sock *igmp_sock_new(int fd, return igmp; } +static void igmp_read_on (struct igmp_sock *igmp); + +static int +pim_igmp_read (struct thread *t) +{ + uint8_t buf[10000]; + struct igmp_sock *igmp = (struct igmp_sock *)THREAD_ARG(t); + struct sockaddr_in from; + struct sockaddr_in to; + socklen_t fromlen = sizeof(from); + socklen_t tolen = sizeof(to); + ifindex_t ifindex = -1; + int cont = 1; + int len; + + while (cont) + { + len = pim_socket_recvfromto(igmp->fd, buf, sizeof(buf), + &from, &fromlen, + &to, &tolen, + &ifindex); + if (len < 0) + { + if (errno == EINTR) + continue; + if (errno == EWOULDBLOCK || errno == EAGAIN) + { + cont = 0; + break; + } + goto done; + } + } + + done: + igmp_read_on(igmp); + return 0; +} + +static void +igmp_read_on (struct igmp_sock *igmp) +{ + + if (PIM_DEBUG_IGMP_TRACE_DETAIL) { + zlog_debug("Scheduling READ event on IGMP socket fd=%d", + igmp->fd); + } + igmp->t_igmp_read = NULL; + THREAD_READ_ON(master, igmp->t_igmp_read, pim_igmp_read, igmp, igmp->fd); + +} + struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, struct in_addr ifaddr, struct interface *ifp) @@ -866,6 +917,8 @@ struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, return 0; } + igmp_read_on (igmp); + listnode_add(igmp_sock_list, igmp); #ifdef IGMP_SOCK_DUMP diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index 6ce336d605..12f222bb80 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -230,26 +230,25 @@ int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, u_char lo zlog_warn("%s: Failure to set buffer size to %d", __PRETTY_FUNCTION__, rcvbuf); - if (protocol == IPPROTO_PIM) - { - long flags; + { + long flags; - flags = fcntl(fd, F_GETFL, 0); - if (flags < 0) { - zlog_warn("Could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_NONBLOCK_GETFL; - } - - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { - zlog_warn("Could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_NONBLOCK_SETFL; - } + flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) { + zlog_warn("Could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_NONBLOCK_GETFL; } + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { + zlog_warn("Could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_NONBLOCK_SETFL; + } + } + return fd; } From 15ad0c71e0e7a58e68852bd749ebcf5cc755aa09 Mon Sep 17 00:00:00 2001 From: anuradhak Date: Mon, 21 Nov 2016 10:20:00 -0800 Subject: [PATCH 320/386] pim-msdp: CLI and debug cleanup No functional change. Signed-off-by: Anuradha Karuppiah --- pimd/pim_cmd.c | 56 +++++++++-------- pimd/pim_msdp.c | 136 +++++++++++++++-------------------------- pimd/pim_msdp.h | 5 +- pimd/pim_msdp_packet.c | 99 +++++++++++++++++++----------- pimd/pim_msdp_packet.h | 3 +- pimd/pim_msdp_socket.c | 28 ++++----- pimd/pimd.h | 2 + 7 files changed, 162 insertions(+), 167 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index ab16943431..ced7497e24 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -5632,7 +5632,7 @@ ip_msdp_show_peers(struct vty *vty, u_char uj) if (uj) { json = json_object_new_object(); } else { - vty_out(vty, "Peer Local Mesh-group State Uptime%s", VTY_NEWLINE); + vty_out(vty, "Peer Local State Uptime SaCnt%s", VTY_NEWLINE); } for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { @@ -5649,14 +5649,14 @@ ip_msdp_show_peers(struct vty *vty, u_char uj) json_row = json_object_new_object(); json_object_string_add(json_row, "peer", peer_str); json_object_string_add(json_row, "local", local_str); - json_object_string_add(json_row, "meshGroupName", mp->mesh_group_name); json_object_string_add(json_row, "state", state_str); json_object_string_add(json_row, "upTime", timebuf); + json_object_int_add(json_row, "saCount", mp->sa_cnt); json_object_object_add(json, peer_str, json_row); } else { - vty_out(vty, "%-15s %15s %16s %11s %8s%s", - peer_str, local_str, mp->mesh_group_name, state_str, - timebuf, VTY_NEWLINE); + vty_out(vty, "%-15s %15s %11s %8s %5d%s", + peer_str, local_str, state_str, + timebuf, mp->sa_cnt, VTY_NEWLINE); } } @@ -5711,12 +5711,13 @@ ip_msdp_show_peers_detail(struct vty *vty, const char *peer, u_char uj) json_object_string_add(json_row, "meshGroupName", mp->mesh_group_name); json_object_string_add(json_row, "state", state_str); json_object_string_add(json_row, "upTime", timebuf); - json_object_string_add(json_row, "keepAliveTime", katimer); - json_object_string_add(json_row, "connRetryTime", crtimer); - json_object_string_add(json_row, "holdTime", holdtimer); + json_object_string_add(json_row, "keepAliveTimer", katimer); + json_object_string_add(json_row, "connRetryTimer", crtimer); + json_object_string_add(json_row, "holdTimer", holdtimer); json_object_string_add(json_row, "lastReset", mp->last_reset); json_object_int_add(json_row, "connAttempts", mp->conn_attempts); - json_object_int_add(json_row, "establishedFlaps", mp->est_flaps); + json_object_int_add(json_row, "establishedChanges", mp->est_flaps); + json_object_int_add(json_row, "saCount", mp->sa_cnt); json_object_int_add(json_row, "kaSent", mp->ka_tx_cnt); json_object_int_add(json_row, "kaRcvd", mp->ka_rx_cnt); json_object_int_add(json_row, "saSent", mp->sa_tx_cnt); @@ -5724,18 +5725,19 @@ ip_msdp_show_peers_detail(struct vty *vty, const char *peer, u_char uj) json_object_object_add(json, peer_str, json_row); } else { vty_out(vty, "Peer : %s%s", peer_str, VTY_NEWLINE); - vty_out(vty, " Local : %s%s", local_str, VTY_NEWLINE); - vty_out(vty, " Mesh Group : %s%s", mp->mesh_group_name, VTY_NEWLINE); - vty_out(vty, " State : %s%s", state_str, VTY_NEWLINE); - vty_out(vty, " Uptime : %s%s", timebuf, VTY_NEWLINE); + vty_out(vty, " Local : %s%s", local_str, VTY_NEWLINE); + vty_out(vty, " Mesh Group : %s%s", mp->mesh_group_name, VTY_NEWLINE); + vty_out(vty, " State : %s%s", state_str, VTY_NEWLINE); + vty_out(vty, " Uptime : %s%s", timebuf, VTY_NEWLINE); - vty_out(vty, " Keepalive Time : %s%s", katimer, VTY_NEWLINE); - vty_out(vty, " Conn Retry Time : %s%s", crtimer, VTY_NEWLINE); - vty_out(vty, " Hold Time : %s%s", holdtimer, VTY_NEWLINE); - vty_out(vty, " Last Reset : %s%s", mp->last_reset, VTY_NEWLINE); - vty_out(vty, " Conn Attempts : %d%s", mp->conn_attempts, VTY_NEWLINE); - vty_out(vty, " Established Flaps: %d%s", mp->est_flaps, VTY_NEWLINE); - vty_out(vty, " Statistics :%s", VTY_NEWLINE); + vty_out(vty, " Keepalive Timer : %s%s", katimer, VTY_NEWLINE); + vty_out(vty, " Conn Retry Timer : %s%s", crtimer, VTY_NEWLINE); + vty_out(vty, " Hold Timer : %s%s", holdtimer, VTY_NEWLINE); + vty_out(vty, " Last Reset : %s%s", mp->last_reset, VTY_NEWLINE); + vty_out(vty, " Conn Attempts : %d%s", mp->conn_attempts, VTY_NEWLINE); + vty_out(vty, " Established Changes : %d%s", mp->est_flaps, VTY_NEWLINE); + vty_out(vty, " SA Count : %d%s", mp->sa_cnt, VTY_NEWLINE); + vty_out(vty, " Statistics :%s", VTY_NEWLINE); vty_out(vty, " Sent Rcvd%s", VTY_NEWLINE); vty_out(vty, " Keepalives : %10d %10d%s", mp->ka_tx_cnt, mp->ka_rx_cnt, VTY_NEWLINE); @@ -5894,16 +5896,16 @@ ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa, const char *src_str, json_object_string_add(json_row, "local", local_str); json_object_string_add(json_row, "sptSetup", spt_str); json_object_string_add(json_row, "upTime", timebuf); - json_object_string_add(json_row, "stateTime", statetimer); + json_object_string_add(json_row, "stateTimer", statetimer); json_object_object_add(json_group, src_str, json_row); } else { vty_out(vty, "SA : %s%s", sa->sg_str, VTY_NEWLINE); - vty_out(vty, " RP : %s%s", rp_str, VTY_NEWLINE); - vty_out(vty, " Peer : %s%s", peer_str, VTY_NEWLINE); - vty_out(vty, " Local : %s%s", local_str, VTY_NEWLINE); - vty_out(vty, " SPT Setup : %s%s", spt_str, VTY_NEWLINE); - vty_out(vty, " Uptime : %s%s", timebuf, VTY_NEWLINE); - vty_out(vty, " State Time : %s%s", statetimer, VTY_NEWLINE); + vty_out(vty, " RP : %s%s", rp_str, VTY_NEWLINE); + vty_out(vty, " Peer : %s%s", peer_str, VTY_NEWLINE); + vty_out(vty, " Local : %s%s", local_str, VTY_NEWLINE); + vty_out(vty, " SPT Setup : %s%s", spt_str, VTY_NEWLINE); + vty_out(vty, " Uptime : %s%s", timebuf, VTY_NEWLINE); + vty_out(vty, " State Timer : %s%s", statetimer, VTY_NEWLINE); vty_out(vty, "%s", VTY_NEWLINE); } } diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index e10289e90c..bc40352809 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -58,29 +58,10 @@ static void pim_msdp_mg_mbr_free(struct pim_msdp_mg_mbr *mbr); static void pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, struct pim_msdp_mg_mbr *mbr); /************************ SA cache management ******************************/ -char * -pim_msdp_sa_key_dump(struct pim_msdp_sa *sa, char *buf, int buf_size, bool long_format) -{ - char rp_str[INET_ADDRSTRLEN]; - - if (long_format && (sa->flags & PIM_MSDP_SAF_PEER)) { - pim_inet4_dump("", sa->rp, rp_str, sizeof(rp_str)); - snprintf(buf, buf_size, "MSDP SA %s rp %s", - sa->sg_str, rp_str); - } else { - snprintf(buf, buf_size, "MSDP SA %s", sa->sg_str); - } - - return buf; -} - static void pim_msdp_sa_timer_expiry_log(struct pim_msdp_sa *sa, const char *timer_str) { - char key_str[PIM_MSDP_SA_KEY_STRLEN]; - - pim_msdp_sa_key_dump(sa, key_str, sizeof(key_str), false); - zlog_debug("%s %s timer expired", key_str, timer_str); + zlog_debug("MSDP SA %s %s timer expired", sa->sg_str, timer_str); } /* RFC-3618:Sec-5.1 - global active source advertisement timer */ @@ -88,7 +69,7 @@ static int pim_msdp_sa_adv_timer_cb(struct thread *t) { msdp->sa_adv_timer = NULL; - if (PIM_DEBUG_MSDP_INTERNAL) { + if (PIM_DEBUG_MSDP_EVENTS) { zlog_debug("MSDP SA advertisment timer expired"); } @@ -147,9 +128,7 @@ pim_msdp_sa_upstream_del(struct pim_msdp_sa *sa) } 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); + zlog_debug("MSDP SA %s de-referenced SPT", sa->sg_str); } } @@ -197,15 +176,6 @@ 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); @@ -222,7 +192,7 @@ pim_msdp_sa_upstream_update(struct pim_msdp_sa *sa, /* 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); + zlog_debug("MSDP SA %s SPT reference missing", sa->sg_str); } return; } @@ -240,11 +210,11 @@ pim_msdp_sa_upstream_update(struct pim_msdp_sa *sa, /* 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); + zlog_debug("MSDP SA %s referenced SPT", sa->sg_str); } } else { if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("%s SPT reference failed", key_str); + zlog_debug("MSDP SA %s SPT reference failed", sa->sg_str); } } } @@ -269,7 +239,7 @@ pim_msdp_sa_new(struct prefix_sg *sg, struct in_addr rp) } sa->sg = *sg; - pim_str_sg_set (sg, sa->sg_str); + pim_str_sg_set(sg, sa->sg_str); sa->rp = rp; sa->uptime = pim_time_monotonic_sec(); @@ -283,10 +253,7 @@ pim_msdp_sa_new(struct prefix_sg *sg, struct in_addr rp) listnode_add_sort(msdp->sa_list, sa); 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 created", key_str); + zlog_debug("MSDP SA %s created", sa->sg_str); } return sa; @@ -329,16 +296,39 @@ pim_msdp_sa_del(struct pim_msdp_sa * sa) hash_release(msdp->sa_hash, sa); 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 /* long */); - zlog_debug("%s deleted", key_str); + zlog_debug("MSDP SA %s deleted", sa->sg_str); } /* free up any associated memory */ pim_msdp_sa_free(sa); } +static void +pim_msdp_sa_peer_ip_set(struct pim_msdp_sa *sa, struct pim_msdp_peer *mp) +{ + struct pim_msdp_peer *old_mp; + + /* optimize the "no change" case as it will happen + * frequently/periodically */ + if (mp && (sa->peer.s_addr == mp->peer.s_addr)) { + return; + } + + if (PIM_INADDR_ISNOT_ANY(sa->peer)) { + old_mp = pim_msdp_peer_find(sa->peer); + if (old_mp && old_mp->sa_cnt) { + --old_mp->sa_cnt; + } + } + + if (mp) { + ++mp->sa_cnt; + sa->peer = mp->peer; + } else { + sa->peer.s_addr = PIM_NET_INADDR_ANY; + } +} + /* When a local active-source is removed there is no way to withdraw the * source from peers. We will simply remove it from the SA cache so it will * not be sent in supsequent SA updates. Peers will consequently timeout the @@ -350,17 +340,12 @@ pim_msdp_sa_del(struct pim_msdp_sa * sa) static void pim_msdp_sa_deref(struct pim_msdp_sa *sa, enum pim_msdp_sa_flags flags) { - char key_str[PIM_MSDP_SA_KEY_STRLEN]; bool update_up = false; - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_sa_key_dump(sa, key_str, sizeof(key_str), true); - } - if ((sa->flags &PIM_MSDP_SAF_LOCAL)) { if (flags & PIM_MSDP_SAF_LOCAL) { if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("%s local reference removed", key_str); + zlog_debug("MSDP SA %s local reference removed", sa->sg_str); } if (msdp->local_cnt) --msdp->local_cnt; @@ -370,9 +355,10 @@ pim_msdp_sa_deref(struct pim_msdp_sa *sa, enum pim_msdp_sa_flags flags) if ((sa->flags &PIM_MSDP_SAF_PEER)) { if (flags & PIM_MSDP_SAF_PEER) { if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("%s peer reference removed", key_str); + zlog_debug("MSDP SA %s peer reference removed", sa->sg_str); } pim_msdp_sa_state_timer_setup(sa, false /* start */); + pim_msdp_sa_peer_ip_set(sa, NULL /* mp */); /* if peer ref was removed we need to remove the msdp reference on the * msdp entry */ update_up = true; @@ -394,26 +380,21 @@ pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, struct in_addr rp) { struct pim_msdp_sa *sa; - char key_str[PIM_MSDP_SA_KEY_STRLEN]; sa = pim_msdp_sa_add(sg, rp); if (!sa) { return; } - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_sa_key_dump(sa, key_str, sizeof(key_str), true); - } - /* reference it */ if (mp) { if (!(sa->flags & PIM_MSDP_SAF_PEER)) { sa->flags |= PIM_MSDP_SAF_PEER; if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("%s added by peer", key_str); + zlog_debug("MSDP SA %s added by peer", sa->sg_str); } } - sa->peer = mp->peer; + pim_msdp_sa_peer_ip_set(sa, mp); /* 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 @@ -425,7 +406,7 @@ pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, sa->flags |= PIM_MSDP_SAF_LOCAL; ++msdp->local_cnt; if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("%s added locally", key_str); + zlog_debug("MSDP SA %s added locally", sa->sg_str); } /* send an immediate SA update to peers */ pim_msdp_pkt_sa_tx_one(sa); @@ -719,11 +700,9 @@ static void pim_msdp_peer_state_chg_log(struct pim_msdp_peer *mp) { char state_str[PIM_MSDP_STATE_STRLEN]; - char key_str[PIM_MSDP_PEER_KEY_STRLEN]; pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); - pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), false); - zlog_debug("%s state chg to %s", key_str, state_str); + zlog_debug("MSDP peer %s state chg to %s", mp->key_str, state_str); } /* MSDP Connection State Machine actions (defined in RFC-3618:Sec-11.2) */ @@ -800,10 +779,7 @@ 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); + zlog_debug("MSDP peer %s pim_msdp_peer_stop_tcp_conn", mp->key_str); } /* stop read and write threads */ PIM_MSDP_PEER_READ_OFF(mp); @@ -832,10 +808,7 @@ void pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str) { if (PIM_DEBUG_EVENTS) { - char key_str[PIM_MSDP_PEER_KEY_STRLEN]; - - pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), false); - zlog_debug("%s tcp reset %s", key_str, rc_str); + zlog_debug("MSDP peer %s tcp reset %s", mp->key_str, rc_str); snprintf(mp->last_reset, sizeof(mp->last_reset), "%s", rc_str); } @@ -851,10 +824,7 @@ pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str) static void pim_msdp_peer_timer_expiry_log(struct pim_msdp_peer *mp, const char *timer_str) { - char key_str[PIM_MSDP_PEER_KEY_STRLEN]; - - pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), false); - zlog_debug("%s %s timer expired", key_str, timer_str); + zlog_debug("MSDP peer %s %s timer expired", mp->key_str, timer_str); } /* RFC-3618:Sec-5.4 - peer hold timer */ @@ -926,10 +896,7 @@ pim_msdp_peer_active_connect(struct pim_msdp_peer *mp) rc = pim_msdp_sock_connect(mp); 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_active_connect: %d", key_str, rc); + zlog_debug("MSDP peer %s pim_msdp_peer_active_connect: %d", mp->key_str, rc); } switch (rc) { @@ -1032,6 +999,7 @@ pim_msdp_peer_new(struct in_addr peer_addr, struct in_addr local_addr, } mp->peer = peer_addr; + pim_inet4_dump("", mp->peer, mp->key_str, sizeof(mp->key_str)); pim_msdp_addr2su(&mp->su_peer, mp->peer); mp->local = local_addr; /* XXX: originator_id setting needs to move to the mesh group */ @@ -1055,10 +1023,7 @@ pim_msdp_peer_new(struct in_addr peer_addr, struct in_addr local_addr, listnode_add_sort(msdp->peer_list, mp); if (PIM_DEBUG_MSDP_EVENTS) { - char key_str[PIM_MSDP_PEER_KEY_STRLEN]; - - pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), true); - zlog_debug("%s created", key_str); + zlog_debug("MSDP peer %s created", mp->key_str); pim_msdp_peer_state_chg_log(mp); } @@ -1147,10 +1112,7 @@ pim_msdp_peer_do_del(struct pim_msdp_peer *mp) hash_release(msdp->peer_hash, mp); if (PIM_DEBUG_MSDP_EVENTS) { - char key_str[PIM_MSDP_PEER_KEY_STRLEN]; - - pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), true); - zlog_debug("%s deleted", key_str); + zlog_debug("MSDP peer %s deleted", mp->key_str); } /* free up any associated memory */ diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h index 0f64021805..80d928a05d 100644 --- a/pimd/pim_msdp.h +++ b/pimd/pim_msdp.h @@ -53,8 +53,6 @@ enum pim_msdp_err { }; #define PIM_MSDP_STATE_STRLEN 16 -#define PIM_MSDP_PEER_KEY_STRLEN 80 -#define PIM_MSDP_SA_KEY_STRLEN 80 #define PIM_MSDP_UPTIME_STRLEN 80 #define PIM_MSDP_TIMER_STRLEN 12 #define PIM_MSDP_TCP_PORT 639 @@ -103,6 +101,7 @@ struct pim_msdp_peer { struct in_addr local; struct in_addr peer; char *mesh_group_name; + char key_str[INET_ADDRSTRLEN]; /* state */ enum pim_msdp_peer_state state; @@ -131,6 +130,7 @@ struct pim_msdp_peer { /* stats */ uint32_t conn_attempts; uint32_t est_flaps; + uint32_t sa_cnt; /* number of SAs attributed to this peer */ #define PIM_MSDP_PEER_LAST_RESET_STR 20 char last_reset[PIM_MSDP_PEER_LAST_RESET_STR]; @@ -217,7 +217,6 @@ int pim_msdp_write(struct thread *thread); char *pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size, bool long_format); int pim_msdp_config_write(struct vty *vty); void pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp); -char *pim_msdp_sa_key_dump(struct pim_msdp_sa *sa, char *buf, int buf_size, bool long_format); void pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, struct in_addr rp); void pim_msdp_sa_local_update(struct pim_upstream *up); void pim_msdp_sa_local_del(struct prefix_sg *sg); diff --git a/pimd/pim_msdp_packet.c b/pimd/pim_msdp_packet.c index bc6156325f..71dd00beca 100644 --- a/pimd/pim_msdp_packet.c +++ b/pimd/pim_msdp_packet.c @@ -64,17 +64,65 @@ pim_msdp_pkt_type_dump(enum pim_msdp_tlv type, char *buf, int buf_size) } static void -pim_msdp_pkt_dump(struct pim_msdp_peer *mp, int type, int len, bool rx) +pim_msdp_pkt_sa_dump_one(struct stream *s) +{ + struct prefix_sg sg; + + /* just throw away the three reserved bytes */ + stream_get3(s); + /* throw away the prefix length also */ + stream_getc(s); + + memset(&sg, 0, sizeof (struct prefix_sg)); + sg.grp.s_addr = stream_get_ipv4(s); + sg.src.s_addr = stream_get_ipv4(s); + + zlog_debug(" sg %s", pim_str_sg_dump(&sg)); +} + +static void +pim_msdp_pkt_sa_dump(struct stream *s) +{ + int entry_cnt; + int i; + struct in_addr rp; /* Last RP address associated with this SA */ + + entry_cnt = stream_getc(s); + rp.s_addr = stream_get_ipv4(s); + + if (PIM_DEBUG_MSDP_PACKETS) { + char rp_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", rp, rp_str, sizeof(rp_str)); + zlog_debug(" entry_cnt %d rp %s", entry_cnt, rp_str); + } + + /* dump SAs */ + for (i = 0; i < entry_cnt; ++i) { + pim_msdp_pkt_sa_dump_one(s); + } +} + +static void +pim_msdp_pkt_dump(struct pim_msdp_peer *mp, int type, int len, bool rx, + struct stream *s) { - char key_str[PIM_MSDP_PEER_KEY_STRLEN]; char type_str[PIM_MSDP_PKT_TYPE_STRLEN]; - pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), false); pim_msdp_pkt_type_dump(type, type_str, sizeof(type_str)); - zlog_debug("%s pkt %s type %s len %d", - key_str, rx?"rx":"tx", type_str, len); - /* XXX: dump actual data */ + zlog_debug("MSDP peer %s pkt %s type %s len %d", + mp->key_str, rx?"rx":"tx", type_str, len); + + if (!s) { + return; + } + + switch(type) { + case PIM_MSDP_V4_SOURCE_ACTIVE: + pim_msdp_pkt_sa_dump(s); + break; + default:; + } } /* Check file descriptor whether connect is established. */ @@ -88,7 +136,6 @@ pim_msdp_connect_check(struct pim_msdp_peer *mp) if (mp->state != PIM_MSDP_CONNECTING) { /* if we are here it means we are not in a connecting or established state * for now treat this as a fatal error */ - /* XXX:revisit; reset TCP connection */ pim_msdp_peer_reset_tcp_conn(mp, "invalid-state"); return; } @@ -103,22 +150,17 @@ pim_msdp_connect_check(struct pim_msdp_peer *mp) /* If getsockopt is fail, this is fatal error. */ if (ret < 0) { zlog_err("can't get sockopt for nonblocking connect"); - /* XXX:revisit; reset TCP connection */ pim_msdp_peer_reset_tcp_conn(mp, "connect-failed"); return; } /* When status is 0 then TCP connection is established. */ 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_connect_check %s", key_str, status?"fail":"success"); + zlog_debug("MSDP peer %s pim_connect_check %s", mp->key_str, status?"fail":"success"); } if (status == 0) { pim_msdp_peer_established(mp); } else { - /* XXX:revisit; reset TCP connection */ pim_msdp_peer_reset_tcp_conn(mp, "connect-failed"); } } @@ -150,18 +192,14 @@ pim_msdp_write(struct thread *thread) struct stream *s; int num; enum pim_msdp_tlv type; + int len; 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) { - 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); + zlog_debug("MSDP peer %s pim_msdp_write", mp->key_str); } if (mp->fd < 0) { return -1; @@ -195,12 +233,11 @@ pim_msdp_write(struct thread *thread) /* write failed either retry needed or error */ if (ERRNO_IO_RETRY(errno)) { if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("%s pim_msdp_write io retry", key_str); + zlog_debug("MSDP peer %s pim_msdp_write io retry", mp->key_str); } break; } - /* XXX:revisit; reset TCP connection */ pim_msdp_peer_reset_tcp_conn(mp, "pkt-tx-failed"); return 0; } @@ -209,7 +246,7 @@ pim_msdp_write(struct thread *thread) /* Partial write */ stream_forward_getp(s, num); if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("%s pim_msdp_partial_write", key_str); + zlog_debug("MSDP peer %s pim_msdp_partial_write", mp->key_str); } break; } @@ -217,6 +254,7 @@ pim_msdp_write(struct thread *thread) /* Retrieve msdp packet type. */ stream_set_getp(s,0); type = stream_getc(s); + len = stream_getw(s); switch (type) { case PIM_MSDP_KEEPALIVE: @@ -228,7 +266,7 @@ pim_msdp_write(struct thread *thread) default:; } if (PIM_DEBUG_MSDP_PACKETS) { - pim_msdp_pkt_dump(mp, type, writenum, false /*rx*/); + pim_msdp_pkt_dump(mp, type, len, false /*rx*/, s); } /* packet sent delete it. */ @@ -243,7 +281,7 @@ pim_msdp_write(struct thread *thread) sockopt_cork(mp->fd, 0); if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("%s pim_msdp_write wrote %d packets", key_str, work_cnt); + zlog_debug("MSDP peer %s pim_msdp_write wrote %d packets", mp->key_str, work_cnt); } return 0; @@ -301,10 +339,7 @@ pim_msdp_pkt_sa_push(struct pim_msdp_peer *mp) } else { for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { 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_pkt_sa_push", key_str); + zlog_debug("MSDP peer %s pim_msdp_pkt_sa_push", mp->key_str); } pim_msdp_pkt_sa_push_to_one_peer(mp); } @@ -413,7 +448,6 @@ pim_msdp_pkt_sa_tx_to_one_peer(struct pim_msdp_peer *mp) static void pim_msdp_pkt_rxed_with_fatal_error(struct pim_msdp_peer *mp) { - /* XXX:revisit; reset TCP connection */ pim_msdp_peer_reset_tcp_conn(mp, "invalid-pkt-rx"); } @@ -519,7 +553,7 @@ pim_msdp_pkt_rx(struct pim_msdp_peer *mp) } if (PIM_DEBUG_MSDP_PACKETS) { - pim_msdp_pkt_dump(mp, type, len, true /*rx*/); + pim_msdp_pkt_dump(mp, type, len, true /*rx*/, NULL /*s*/); } switch(type) { @@ -581,10 +615,7 @@ pim_msdp_read(struct thread *thread) mp->t_read = 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); - zlog_debug("%s pim_msdp_read", key_str); + zlog_debug("MSDP peer %s pim_msdp_read", mp->key_str); } if (mp->fd < 0) { diff --git a/pimd/pim_msdp_packet.h b/pimd/pim_msdp_packet.h index 30221a399a..a362ff11d5 100644 --- a/pimd/pim_msdp_packet.h +++ b/pimd/pim_msdp_packet.h @@ -57,8 +57,7 @@ #define PIM_MSDP_SA_TLV_MIN_SIZE PIM_MSDP_SA_ENTRY_CNT2SIZE(1) #define PIM_MSDP_SA_MAX_ENTRY_CNT ((PIM_MSDP_SA_TLV_MAX_SIZE - PIM_MSDP_SA_X_SIZE)/PIM_MSDP_SA_ONE_ENTRY_SIZE) -/* XXX: this is just a guesstimate - need to revist */ -#define PIM_MSDP_MAX_PACKET_SIZE (PIM_MSDP_SA_TLV_MAX_SIZE + PIM_MSDP_KA_TLV_MAX_SIZE) +#define PIM_MSDP_MAX_PACKET_SIZE max(PIM_MSDP_SA_TLV_MAX_SIZE, PIM_MSDP_KA_TLV_MAX_SIZE) #define PIM_MSDP_PKT_TYPE_STRLEN 16 diff --git a/pimd/pim_msdp_socket.c b/pimd/pim_msdp_socket.c index f71d23e4a1..bc9720f1f3 100644 --- a/pimd/pim_msdp_socket.c +++ b/pimd/pim_msdp_socket.c @@ -86,25 +86,26 @@ pim_msdp_sock_accept(struct thread *thread) mp = pim_msdp_peer_find(su.sin.sin_addr); if (!mp || !PIM_MSDP_PEER_IS_LISTENER(mp)) { ++msdp->rejected_accepts; - //XXX: make debug event - zlog_err("msdp peer connection refused from %s", - sockunion2str(&su, buf, SU_ADDRSTRLEN)); + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_err("msdp peer connection refused from %s", + sockunion2str(&su, buf, SU_ADDRSTRLEN)); + } close(msdp_sock); return -1; } 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 accept success%s", key_str, mp->fd>=0?"(dup)":""); + zlog_debug("MSDP peer %s accept success%s", mp->key_str, mp->fd>=0?"(dup)":""); } /* if we have an existing connection we need to kill that one * with this one */ if (mp->fd >= 0) { - /* XXX: revisit */ - pim_msdp_peer_stop_tcp_conn(mp, false /* chg_state */); + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_err("msdp peer new connection from %s stop old connection", + sockunion2str(&su, buf, SU_ADDRSTRLEN)); + } + pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); } mp->fd = msdp_sock; set_nonblocking(mp->fd); @@ -187,16 +188,15 @@ pim_msdp_sock_connect(struct pim_msdp_peer *mp) int rc; 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 attempt connect%s", key_str, mp->fd<0?"":"(dup)"); + zlog_debug("MSDP peer %s attempt connect%s", mp->key_str, mp->fd<0?"":"(dup)"); } /* if we have an existing connection we need to kill that one * with this one */ if (mp->fd >= 0) { - /* XXX: revisit */ + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_err("msdp duplicate connect to %s nuke old connection", mp->key_str); + } pim_msdp_peer_stop_tcp_conn(mp, false /* chg_state */); } diff --git a/pimd/pimd.h b/pimd/pimd.h index 54cecd19d2..cb0165c22c 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -52,6 +52,8 @@ #define PIM_INADDR_IS_ANY(addr) (addr).s_addr == PIM_NET_INADDR_ANY #define PIM_INADDR_ISNOT_ANY(addr) ((addr).s_addr != PIM_NET_INADDR_ANY) /* struct in_addr addr */ +#define max(x,y) ((x) > (y) ? (x) : (y)) + #define PIM_MASK_PIM_EVENTS (1 << 0) #define PIM_MASK_PIM_EVENTS_DETAIL (1 << 1) #define PIM_MASK_PIM_PACKETS (1 << 2) From 886d1e80f68e85be02ce1cef12a061ab5adeca0a Mon Sep 17 00:00:00 2001 From: anuradhak Date: Tue, 22 Nov 2016 11:26:45 -0800 Subject: [PATCH 321/386] pim-msdp: cleanup debug commands And fixup display spacing. No functional change. Signed-off-by: Anuradha Karuppiah --- pimd/pim_cmd.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index ced7497e24..7ab2bb7b48 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4837,6 +4837,8 @@ DEFUN (debug_pim, PIM_DO_DEBUG_PIM_EVENTS; PIM_DO_DEBUG_PIM_PACKETS; PIM_DO_DEBUG_PIM_TRACE; + PIM_DO_DEBUG_MSDP_EVENTS; + PIM_DO_DEBUG_MSDP_PACKETS; return CMD_SUCCESS; } @@ -4850,6 +4852,8 @@ DEFUN (no_debug_pim, PIM_DONT_DEBUG_PIM_EVENTS; PIM_DONT_DEBUG_PIM_PACKETS; PIM_DONT_DEBUG_PIM_TRACE; + PIM_DONT_DEBUG_MSDP_EVENTS; + PIM_DONT_DEBUG_MSDP_PACKETS; PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND; PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV; @@ -5632,7 +5636,7 @@ ip_msdp_show_peers(struct vty *vty, u_char uj) if (uj) { json = json_object_new_object(); } else { - vty_out(vty, "Peer Local State Uptime SaCnt%s", VTY_NEWLINE); + vty_out(vty, "Peer Local State Uptime SaCnt%s", VTY_NEWLINE); } for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { @@ -5654,7 +5658,7 @@ ip_msdp_show_peers(struct vty *vty, u_char uj) json_object_int_add(json_row, "saCount", mp->sa_cnt); json_object_object_add(json, peer_str, json_row); } else { - vty_out(vty, "%-15s %15s %11s %8s %5d%s", + vty_out(vty, "%-15s %15s %11s %8s %6d%s", peer_str, local_str, state_str, timebuf, mp->sa_cnt, VTY_NEWLINE); } From 11b7753a892ef125b3dc94879eb2d7506b4f86a8 Mon Sep 17 00:00:00 2001 From: anuradhak Date: Wed, 23 Nov 2016 13:22:13 -0800 Subject: [PATCH 322/386] pim-msdp: Update the RP address in the SA cache entry on peer ip change The RP address in the SA is only for informational/display purposes. It is still confusing if we show a stale value. Signed-off-by: Anuradha Karuppiah --- pimd/pim_msdp.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index bc40352809..0c5b1c7f2e 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -304,7 +304,7 @@ pim_msdp_sa_del(struct pim_msdp_sa * sa) } static void -pim_msdp_sa_peer_ip_set(struct pim_msdp_sa *sa, struct pim_msdp_peer *mp) +pim_msdp_sa_peer_ip_set(struct pim_msdp_sa *sa, struct pim_msdp_peer *mp, struct in_addr rp) { struct pim_msdp_peer *old_mp; @@ -314,6 +314,7 @@ pim_msdp_sa_peer_ip_set(struct pim_msdp_sa *sa, struct pim_msdp_peer *mp) return; } + /* any time the peer ip changes also update the rp address */ if (PIM_INADDR_ISNOT_ANY(sa->peer)) { old_mp = pim_msdp_peer_find(sa->peer); if (old_mp && old_mp->sa_cnt) { @@ -327,6 +328,7 @@ pim_msdp_sa_peer_ip_set(struct pim_msdp_sa *sa, struct pim_msdp_peer *mp) } else { sa->peer.s_addr = PIM_NET_INADDR_ANY; } + sa->rp = rp; } /* When a local active-source is removed there is no way to withdraw the @@ -354,11 +356,14 @@ pim_msdp_sa_deref(struct pim_msdp_sa *sa, enum pim_msdp_sa_flags flags) if ((sa->flags &PIM_MSDP_SAF_PEER)) { if (flags & PIM_MSDP_SAF_PEER) { + struct in_addr rp; + if (PIM_DEBUG_MSDP_EVENTS) { zlog_debug("MSDP SA %s peer reference removed", sa->sg_str); } pim_msdp_sa_state_timer_setup(sa, false /* start */); - pim_msdp_sa_peer_ip_set(sa, NULL /* mp */); + rp.s_addr = INADDR_ANY; + pim_msdp_sa_peer_ip_set(sa, NULL /* mp */, rp); /* if peer ref was removed we need to remove the msdp reference on the * msdp entry */ update_up = true; @@ -394,7 +399,7 @@ pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, zlog_debug("MSDP SA %s added by peer", sa->sg_str); } } - pim_msdp_sa_peer_ip_set(sa, mp); + pim_msdp_sa_peer_ip_set(sa, mp, rp); /* 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 From 58c51da21261a492c792a9393b78a1790f0bb041 Mon Sep 17 00:00:00 2001 From: anuradhak Date: Wed, 23 Nov 2016 13:35:45 -0800 Subject: [PATCH 323/386] pim-nexthop: set the correct nexthop address in the rpf info. When a nexthop lookup is done we can get an ECMP output. But not all nexthops are pim neighbors. If for this reason PIM chose a nexthop other than the first the rpf info was not being set correctly i.e. nexthop ip was still the one associated with the first path but interface was set to the one associated with second path. This problem is seen on a link flap in the CLOS topology. Ticket: CM-13714 Signed-off-by: Anuradha Karuppiah Acked-by: Donald Sharp --- pimd/pim_rpf.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 48cb2e4017..24ed621a0d 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -153,20 +153,20 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei if (PIM_DEBUG_ZEBRA) { char nexthop_str[PREFIX_STRLEN]; char addr_str[INET_ADDRSTRLEN]; - pim_addr_dump("", &nexthop_tab[0].nexthop_addr, nexthop_str, sizeof(nexthop_str)); + pim_addr_dump("", &nexthop_tab[i].nexthop_addr, nexthop_str, sizeof(nexthop_str)); pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_debug("%s %s: found nexthop %s for address %s: interface %s ifindex=%d metric=%d pref=%d", __FILE__, __PRETTY_FUNCTION__, nexthop_str, addr_str, ifp->name, first_ifindex, - nexthop_tab[0].route_metric, - nexthop_tab[0].protocol_distance); + nexthop_tab[i].route_metric, + nexthop_tab[i].protocol_distance); } /* update nextop data */ nexthop->interface = ifp; - nexthop->mrib_nexthop_addr = nexthop_tab[0].nexthop_addr; - nexthop->mrib_metric_preference = nexthop_tab[0].protocol_distance; - nexthop->mrib_route_metric = nexthop_tab[0].route_metric; + nexthop->mrib_nexthop_addr = nexthop_tab[i].nexthop_addr; + nexthop->mrib_metric_preference = nexthop_tab[i].protocol_distance; + nexthop->mrib_route_metric = nexthop_tab[i].route_metric; nexthop->last_lookup = addr; nexthop->last_lookup_time = pim_time_monotonic_usec(); return 0; From a770ef906378d2beb027dc48fa2c1062093e9ef8 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 28 Nov 2016 12:18:43 -0500 Subject: [PATCH 324/386] pimd: Remove redundant logging When receiving a JOIN/PRUNE message if we have trace turned on we output this: 2016/11/28 17:11:46.368827 PIM: pim_socket_recvfromto: HAVE_IP_PKTINFO to=224.0.0.13,103 2016/11/28 17:11:46.368956 PIM: Recv PIM JOINPRUNE packet from 169.254.0.6 to 224.0.0.13 on swp31s1: ttl=255 pim_version=2 pim_msg_size=34 checksum=e623 2016/11/28 17:11:46.369003 PIM: pim_joinprune_recv: from 169.254.0.6 on swp31s1 2016/11/28 17:11:46.369053 PIM: recv_prune: prune (S,G)=(20.0.11.253,229.1.2.3) rpt=0 wc=0 upstream=169.254.0.5 holdtime=210 from 169.254.0.6 on swp31s1 2016/11/28 17:11:46.369099 PIM: nonlocal_upstream: recv prune (S,G)=(20.0.11.253,229.1.2.3) to local upstream=169.254.0.5 on swp31s1 Clean up the messaging to this: 2016/11/28 17:11:46.368956 PIM: Recv PIM JOINPRUNE packet from 169.254.0.6 to 224.0.0.13 on swp31s1: ttl=255 pim_version=2 pim_msg_size=34 checksum=e623 2016/11/28 17:11:46.369053 PIM: recv_prune: prune (S,G)=(20.0.11.253,229.1.2.3) rpt=0 wc=0 upstream=169.254.0.5 holdtime=210 from 169.254.0.6 on swp31s1 Ticket: CM-13752 Signed-off-by: Donald Sharp Reviewed-by: Don Slice --- pimd/pim_ifchannel.c | 2 +- pimd/pim_join.c | 2 -- pimd/pim_sock.c | 16 ---------------- 3 files changed, 1 insertion(+), 19 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index ef4c23e95f..1222ac29c9 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -610,7 +610,7 @@ static int nonlocal_upstream(int is_join, is_local = (upstream.s_addr == recv_pim_ifp->primary_address.s_addr); - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_PIM_TRACE_DETAIL) { char up_str[INET_ADDRSTRLEN]; pim_inet4_dump("", upstream, up_str, sizeof(up_str)); zlog_warn("%s: recv %s (S,G)=%s to %s upstream=%s on %s", diff --git a/pimd/pim_join.c b/pimd/pim_join.c index ff41b28ba4..c12fc588ff 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -214,8 +214,6 @@ int pim_joinprune_recv(struct interface *ifp, int remain; int group; - on_trace(__PRETTY_FUNCTION__, ifp, src_addr); - buf = tlv_buf; pastend = tlv_buf + tlv_buf_size; diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index 12f222bb80..e69ad98f8c 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -384,14 +384,6 @@ int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len, if (ifindex) *ifindex = i->ipi_ifindex; - if (to && PIM_DEBUG_PACKETS) { - char to_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", to->sin_addr, to_str, sizeof(to_str)); - zlog_debug("%s: HAVE_IP_PKTINFO to=%s,%d", - __PRETTY_FUNCTION__, - to_str, ntohs(to->sin_port)); - } - break; } #endif @@ -404,14 +396,6 @@ int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len, if (tolen) *tolen = sizeof(struct sockaddr_in); - if (to && PIM_DEBUG_PACKETS) { - char to_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", to->sin_addr, to_str, sizeof(to_str)); - zlog_debug("%s: HAVE_IP_RECVDSTADDR to=%s,%d", - __PRETTY_FUNCTION__, - to_str, ntohs(to->sin_port)); - } - break; } #endif From da72c9fdc34c6d7cc5128886ab898e3cd080ff05 Mon Sep 17 00:00:00 2001 From: anuradhak Date: Mon, 28 Nov 2016 10:12:21 -0800 Subject: [PATCH 325/386] pim-nexthop: mroute and pim-upstream rpf are falling out of sync. Currently the mroute-IIF and upstream RPF-IIF/neigh are resolved separately. This must change i.e. be merged together for a couple of reasons - 1. In the case of ECMP we will use a load-share mechanism (based on G or SG) to pick an RPF neighbor in 3.2.1 (to use the load-sharing cap of anycast-RP). Using a different resolution mechanism for mroute-IIF will simply not work. 2. In a non-CLOS topology it is actually possible to have routers that do not participate in PIM. In this case the tree will be set up using different routers than the ones chosen for the mroute IIF. And traffic will not be forwarded. This change is however too big for 3.2.0. So to handle CM-13714 I have simply forced rpf update on neigh add which fixes the specific problem seen on link flap in a clos (it is not very efficient but traffic recovers). In problem state - (jessie-30-dev-switch-amd64-sbuild)root@spine-1:/home/cumulus# ip mr (0.0.0.0, 225.1.1.1) Iif: lo Oifs: swp3 lo (20.0.11.253, 225.1.1.1) Iif: swp1 Oifs: swp3 (jessie-30-dev-switch-amd64-sbuild)root@spine-1:/home/cumulus# vtysh -c "show ip pim upstream" Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt lo * 225.1.1.1 Joined 00:08:44 00:00:15 --:--:-- --:--:-- 1 swp2 20.0.11.253 225.1.1.1 Joined 00:08:35 00:00:56 --:--:-- 00:02:59 1 (jessie-30-dev-switch-amd64-sbuild)root@spine-1:/home/cumulus# Signed-off-by: Anuradha Karuppiah Acked-by: Donald Sharp --- pimd/pim_neighbor.c | 17 +++++++++++++++++ pimd/pim_zebra.c | 2 +- pimd/pim_zebra.h | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index 1b58b98502..a8a60f6f38 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -37,6 +37,7 @@ #include "pim_upstream.h" #include "pim_ifchannel.h" #include "pim_rp.h" +#include "pim_zebra.h" static void dr_election_by_addr(struct interface *ifp) { @@ -421,6 +422,18 @@ pim_neighbor_find_if (struct interface *ifp) return listnode_head (pim_ifp->pim_neighbor_list); } +/* rpf info associated with an upstream entry needs to be re-evaluated + * when an RPF neighbor comes or goes */ +static void +pim_neighbor_rpf_update(void) +{ + /* XXX: for the time being piggyback on the timer used on rib changes + * to scan and update the rpf nexthop. This is expensive processing + * and we should be able to optimize neighbor changes differently than + * nexthop changes. */ + sched_rpf_cache_refresh(); +} + struct pim_neighbor *pim_neighbor_add(struct interface *ifp, struct in_addr source_addr, pim_hello_options hello_options, @@ -483,6 +496,8 @@ struct pim_neighbor *pim_neighbor_add(struct interface *ifp, pim_upstream_find_new_rpf(); pim_rp_setup (); + + pim_neighbor_rpf_update(); return neigh; } @@ -595,6 +610,8 @@ void pim_neighbor_delete(struct interface *ifp, listnode_delete(pim_ifp->pim_neighbor_list, neigh); pim_neighbor_free(neigh); + + pim_neighbor_rpf_update(); } void pim_neighbor_delete_all(struct interface *ifp, diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 294d8bba25..9239f875c4 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -545,7 +545,7 @@ static int on_rpf_cache_refresh(struct thread *t) return 0; } -static void sched_rpf_cache_refresh() +void sched_rpf_cache_refresh(void) { ++qpim_rpf_cache_refresh_requests; diff --git a/pimd/pim_zebra.h b/pimd/pim_zebra.h index ae79ed815a..767cdf0541 100644 --- a/pimd/pim_zebra.h +++ b/pimd/pim_zebra.h @@ -39,4 +39,5 @@ void igmp_source_forward_stop(struct igmp_source *source); void pim_forward_start(struct pim_ifchannel *ch); void pim_forward_stop(struct pim_ifchannel *ch); +void sched_rpf_cache_refresh(void); #endif /* PIM_ZEBRA_H */ From b9b1e1f2bab7339fa9d761565cc9f21289a5b63c Mon Sep 17 00:00:00 2001 From: anuradhak Date: Mon, 28 Nov 2016 16:22:28 -0800 Subject: [PATCH 326/386] pim-msdp: Fix pimd crash on mesh-group delete. The mesh group contents were being accessed after memory was freed. Signed-off-by: Anuradha Karuppiah --- pimd/pim_msdp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 0c5b1c7f2e..3562a0e348 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -1185,10 +1185,11 @@ pim_msdp_mg_free(struct pim_msdp_mg *mg) } if (mg->mesh_group_name) XFREE(MTYPE_PIM_MSDP_MG_NAME, mg->mesh_group_name); - XFREE(MTYPE_PIM_MSDP_MG, mg); if (mg->mbr_list) list_free(mg->mbr_list); + + XFREE(MTYPE_PIM_MSDP_MG, mg); msdp->mg = NULL; } From 7cdb24da72694d72af12963d394a8da1e6fcaa38 Mon Sep 17 00:00:00 2001 From: anuradhak Date: Tue, 29 Nov 2016 08:07:20 -0800 Subject: [PATCH 327/386] pim-anycast-rp: Change the reason code on use-source config failure. Was failing with a vague error - "Source set failed" Changed to used the error string (used by the rest of the commands) - "Pim not enabled on this interface" Signed-off-by: Anuradha Karuppiah --- pimd/pim_cmd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 7ab2bb7b48..bfdcf93ddc 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -5214,6 +5214,9 @@ interface_pim_use_src_cmd_worker(struct vty *vty, const char *source) switch (result) { case PIM_SUCCESS: break; + case PIM_IFACE_NOT_FOUND: + vty_out(vty, "Pim not enabled on this interface%s", VTY_NEWLINE); + break; case PIM_UPDATE_SOURCE_DUP: vty_out(vty, "%% Source already set to %s%s", source, VTY_NEWLINE); break; From 86abfcb8972347a2e8a15fc38ad6d8fdda72f9f1 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 28 Nov 2016 19:05:09 -0500 Subject: [PATCH 328/386] pimd: Actually expedite a hello When we get a new neighbor for an interface, we need to send a hello out that interface in some situations. At this time we were tracking this by the pim_ifstat_hello_sent value but not reseting it when we received a new neighbor. Ticket: CM-13769 Signed-off-by: Donald Sharp Reviewed-by: Anuradha Karuppiah --- pimd/pim_neighbor.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index a8a60f6f38..83d3851d9e 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -318,6 +318,14 @@ static struct pim_neighbor *pim_neighbor_new(struct interface *ifp, neigh->interface = ifp; pim_neighbor_timer_reset(neigh, holdtime); + /* + * The pim_ifstat_hello_sent variable is used to decide if + * we should expedite a hello out the interface. If we + * establish a new neighbor, we unfortunately need to + * reset the value so that we can know to hurry up and + * hello + */ + pim_ifp->pim_ifstat_hello_sent = 0; pim_inet4_dump("", source_addr, src_str, sizeof(src_str)); From 44521e5d2d0c85129fb15e30757b0498cd3e36fc Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 29 Nov 2016 07:57:10 -0500 Subject: [PATCH 329/386] pimd: When specifying 224.0.0.0/4 as the RP group inform msdp When we modify the 224.0.0.0/4 rp address with a: 'ip pim rp A.B.C.D' We need to let msdp know that this command was entered. Signed-off-by: Donald Sharp Reviewed-by: Anuradha Karuppiah --- pimd/pim_rp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index b6d604b59a..98339ee095 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -404,6 +404,7 @@ pim_rp_new (const char *rp, const char *group_range, const char *plist) return PIM_RP_NO_PATH; pim_rp_check_interfaces (rp_all); + pim_rp_refresh_group_to_rp_mapping(); return PIM_SUCCESS; } From a04da05a5397f5397faaa70165735f2447e4a6cc Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 29 Nov 2016 08:14:35 -0500 Subject: [PATCH 330/386] pimd: Only check to see if current rp is 'right' or not. When a new rp is entered, pim is looking at all rp's and failing the check if any of the RP's have no path to the RP, instead of the one that was just entered being wrong. Ticket: CM-12623 Signed-off-by: Donald Sharp Reviewed-by: Don Slice --- pimd/pim_rp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 98339ee095..ba464e98c6 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -400,7 +400,7 @@ pim_rp_new (const char *rp, const char *group_range, const char *plist) rp_all->rp.rpf_addr = rp_info->rp.rpf_addr; XFREE (MTYPE_PIM_RP, rp_info); - if (!pim_rp_setup ()) + if (pim_nexthop_lookup (&rp_all->rp.source_nexthop, rp_all->rp.rpf_addr.u.prefix4, 1) != 0) return PIM_RP_NO_PATH; pim_rp_check_interfaces (rp_all); @@ -447,7 +447,7 @@ pim_rp_new (const char *rp, const char *group_range, const char *plist) listnode_add_sort (qpim_rp_list, rp_info); - if (!pim_rp_setup ()) + if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1) != 0) return PIM_RP_NO_PATH; pim_rp_check_interfaces (rp_info); From da3dcffb66615560647abd9a3825d24822571bdd Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 29 Nov 2016 08:47:40 -0500 Subject: [PATCH 331/386] pimd: Add more RP rescan points When we add in or delete ip addresses from an interface we may need to rescan the rp's that we know of to make sure that they are still available. Ticket: CM-12623 Signed-off-by: Donald Sharp Reviewed-by: Don Slice --- pimd/pim_iface.c | 4 +++- pimd/pim_zebra.c | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index b5f1fadca5..0a104acef1 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -715,7 +715,7 @@ void pim_if_addr_add_all(struct interface *ifp) } } /* pim */ } - + pim_rp_setup(); pim_rp_check_on_if_add(pim_ifp); } @@ -737,6 +737,8 @@ void pim_if_addr_del_all(struct interface *ifp) pim_if_addr_del(ifc, 1 /* force_prim_as_any=true */); } + + pim_rp_setup(); pim_i_am_rp_re_evaluate(); } diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 9239f875c4..44b92a8c0b 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -348,6 +348,7 @@ static int pim_zebra_if_address_del(int command, struct zclient *client, } pim_if_addr_del(c, 0); + pim_rp_setup(); pim_i_am_rp_re_evaluate(); return 0; From 802b226c8d9fe51919cd9388b37cb20e7d62fd46 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 29 Nov 2016 10:35:43 -0500 Subject: [PATCH 332/386] pimd: Cleanup nexthop debugging When debugging nexthops, we print allot of unnecessary data Move some debugs to trace detail to reduce log clutter. Signed-off-by: Donald Sharp --- pimd/pim_rpf.c | 2 +- pimd/pim_zlookup.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 24ed621a0d..914395e596 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -137,7 +137,7 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei struct pim_neighbor *nbr; nbr = pim_neighbor_find (ifp, nexthop_tab[i].nexthop_addr.u.prefix4); - if (PIM_DEBUG_ZEBRA) + if (PIM_DEBUG_PIM_TRACE_DETAIL) zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr); if (!nbr && !if_is_loopback (ifp)) i++; diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 53fd0ce071..1ed724d7de 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -164,7 +164,7 @@ static int zclient_read_nexthop(struct zclient *zlookup, int nexthop_num; int i, err; - if (PIM_DEBUG_ZEBRA) { + if (PIM_DEBUG_PIM_TRACE_DETAIL) { char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_debug("%s: addr=%s", @@ -283,7 +283,7 @@ zclient_lookup_nexthop_once (struct pim_zlookup_nexthop nexthop_tab[], struct stream *s; int ret; - if (PIM_DEBUG_ZEBRA) { + if (PIM_DEBUG_PIM_TRACE_DETAIL) { char addr_str[INET_ADDRSTRLEN]; pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_debug("%s: addr=%s", From 58344b652e4458833a3b265ee547aa892ba32c89 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 29 Nov 2016 15:48:54 -0500 Subject: [PATCH 333/386] pimd: Make igmp query max response time take input in dsec Make the 'ip igmp query-max-response-time' command take input in deci-seconds and make the 'ip igmp query-max-response-time-dsec' command hidden. Ticket:CM-13786 Signed-off-by: Donald Sharp Reviewed-by: Anuradha Karuppiah --- pimd/pim_cmd.c | 127 ++++++++++++------------------------------------- pimd/pim_vty.c | 2 +- 2 files changed, 32 insertions(+), 97 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index bfdcf93ddc..6f16a7e6d2 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4049,16 +4049,16 @@ DEFUN (interface_no_ip_igmp_version, return CMD_SUCCESS; } -#define IGMP_QUERY_MAX_RESPONSE_TIME_MIN (1) -#define IGMP_QUERY_MAX_RESPONSE_TIME_MAX (25) +#define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10) +#define IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC (250) DEFUN (interface_ip_igmp_query_max_response_time, interface_ip_igmp_query_max_response_time_cmd, - "ip igmp query-max-response-time (1-25)", + "ip igmp query-max-response-time (10-250)", IP_STR IFACE_IGMP_STR IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR - "Query response value in seconds\n") + "Query response value in deci-seconds\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct pim_interface *pim_ifp; @@ -4076,26 +4076,7 @@ DEFUN (interface_ip_igmp_query_max_response_time, query_max_response_time = atoi(argv[4]->arg); - /* - It seems we don't need to check bounds since command.c does it - already, but we verify them anyway for extra safety. - */ - if (query_max_response_time < IGMP_QUERY_MAX_RESPONSE_TIME_MIN) { - vty_out(vty, "Query max response time %d sec lower than minimum %d sec%s", - query_max_response_time, - IGMP_QUERY_MAX_RESPONSE_TIME_MIN, - VTY_NEWLINE); - return CMD_WARNING; - } - if (query_max_response_time > IGMP_QUERY_MAX_RESPONSE_TIME_MAX) { - vty_out(vty, "Query max response time %d sec higher than maximum %d sec%s", - query_max_response_time, - IGMP_QUERY_MAX_RESPONSE_TIME_MAX, - VTY_NEWLINE); - return CMD_WARNING; - } - - if (query_max_response_time >= pim_ifp->igmp_default_query_interval) { + if (query_max_response_time >= pim_ifp->igmp_default_query_interval * 10) { vty_out(vty, "Can't set query max response time %d sec >= general query interval %d sec%s", query_max_response_time, pim_ifp->igmp_default_query_interval, @@ -4103,7 +4084,7 @@ DEFUN (interface_ip_igmp_query_max_response_time, return CMD_WARNING; } - change_query_max_response_time(pim_ifp, 10 * query_max_response_time); + change_query_max_response_time(pim_ifp, query_max_response_time); return CMD_SUCCESS; } @@ -4127,14 +4108,6 @@ DEFUN (interface_no_ip_igmp_query_max_response_time, default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval; - if (IGMP_QUERY_MAX_RESPONSE_TIME_DSEC >= default_query_interval_dsec) { - vty_out(vty, - "Can't set default query max response time %d dsec >= general query interval %d dsec.%s", - IGMP_QUERY_MAX_RESPONSE_TIME_DSEC, default_query_interval_dsec, - VTY_NEWLINE); - return CMD_WARNING; - } - change_query_max_response_time(pim_ifp, IGMP_QUERY_MAX_RESPONSE_TIME_DSEC); return CMD_SUCCESS; @@ -4143,13 +4116,13 @@ DEFUN (interface_no_ip_igmp_query_max_response_time, #define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10) #define IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC (250) -DEFUN (interface_ip_igmp_query_max_response_time_dsec, - interface_ip_igmp_query_max_response_time_dsec_cmd, - "ip igmp query-max-response-time-dsec (10-250)", - IP_STR - IFACE_IGMP_STR - IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR - "Query response value in deciseconds\n") +DEFUN_HIDDEN (interface_ip_igmp_query_max_response_time_dsec, + interface_ip_igmp_query_max_response_time_dsec_cmd, + "ip igmp query-max-response-time-dsec (10-250)", + IP_STR + IFACE_IGMP_STR + IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR + "Query response value in deciseconds\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct pim_interface *pim_ifp; @@ -4168,25 +4141,6 @@ DEFUN (interface_ip_igmp_query_max_response_time_dsec, query_max_response_time_dsec = atoi(argv[4]->arg); - /* - It seems we don't need to check bounds since command.c does it - already, but we verify them anyway for extra safety. - */ - if (query_max_response_time_dsec < IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC) { - vty_out(vty, "Query max response time %d dsec lower than minimum %d dsec%s", - query_max_response_time_dsec, - IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC, - VTY_NEWLINE); - return CMD_WARNING; - } - if (query_max_response_time_dsec > IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC) { - vty_out(vty, "Query max response time %d dsec higher than maximum %d dsec%s", - query_max_response_time_dsec, - IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC, - VTY_NEWLINE); - return CMD_WARNING; - } - default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval; if (query_max_response_time_dsec >= default_query_interval_dsec) { @@ -4202,13 +4156,13 @@ DEFUN (interface_ip_igmp_query_max_response_time_dsec, return CMD_SUCCESS; } -DEFUN (interface_no_ip_igmp_query_max_response_time_dsec, - interface_no_ip_igmp_query_max_response_time_dsec_cmd, - "no ip igmp query-max-response-time-dsec", - NO_STR - IP_STR - IFACE_IGMP_STR - IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR) +DEFUN_HIDDEN (interface_no_ip_igmp_query_max_response_time_dsec, + interface_no_ip_igmp_query_max_response_time_dsec_cmd, + "no ip igmp query-max-response-time-dsec", + NO_STR + IP_STR + IFACE_IGMP_STR + IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); struct pim_interface *pim_ifp; @@ -4221,14 +4175,6 @@ DEFUN (interface_no_ip_igmp_query_max_response_time_dsec, default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval; - if (IGMP_QUERY_MAX_RESPONSE_TIME_DSEC >= default_query_interval_dsec) { - vty_out(vty, - "Can't set default query max response time %d dsec >= general query interval %d dsec.%s", - IGMP_QUERY_MAX_RESPONSE_TIME_DSEC, default_query_interval_dsec, - VTY_NEWLINE); - return CMD_WARNING; - } - change_query_max_response_time(pim_ifp, IGMP_QUERY_MAX_RESPONSE_TIME_DSEC); return CMD_SUCCESS; @@ -5494,19 +5440,6 @@ ip_no_msdp_mesh_group_source_cmd_worker(struct vty *vty, const char *mg) return result?CMD_WARNING:CMD_SUCCESS; } -DEFUN (no_ip_msdp_mesh_group_source, - no_ip_msdp_mesh_group_source_cmd, - "no ip msdp mesh-group WORD source", - NO_STR - IP_STR - CFG_MSDP_STR - "Delete MSDP mesh-group source\n" - "mesh group name\n" - "mesh group local address\n") -{ - return ip_no_msdp_mesh_group_source_cmd_worker(vty, argv[4]->arg); -} - static int ip_no_msdp_mesh_group_cmd_worker(struct vty *vty, const char *mg) { @@ -5523,19 +5456,23 @@ ip_no_msdp_mesh_group_cmd_worker(struct vty *vty, const char *mg) vty_out(vty, "%% mesh-group source del failed%s", VTY_NEWLINE); } - return result?CMD_WARNING:CMD_SUCCESS; + return result ? CMD_WARNING : CMD_SUCCESS; } -DEFUN (no_ip_msdp_mesh_group, - no_ip_msdp_mesh_group_cmd, - "no ip msdp mesh-group WORD", +DEFUN (no_ip_msdp_mesh_group_source, + no_ip_msdp_mesh_group_source_cmd, + "no ip msdp mesh-group WORD source [A.B.C.D]", NO_STR IP_STR CFG_MSDP_STR - "Delete MSDP mesh-group\n" - "mesh group name") + "Delete MSDP mesh-group source\n" + "mesh group name\n" + "mesh group local address\n") { - return ip_no_msdp_mesh_group_cmd_worker(vty, argv[4]->arg); + if (argv[6]->arg) + return ip_no_msdp_mesh_group_cmd_worker(vty, argv[6]->arg); + else + return ip_no_msdp_mesh_group_source_cmd_worker(vty, argv[4]->arg); } static void @@ -6020,7 +5957,6 @@ DEFUN (show_ip_msdp_sa_sg, MSDP_STR "MSDP active-source information\n" "source or group ip\n" - "group ip\n" "JavaScript Object Notation\n") { u_char uj = use_json(argc, argv); @@ -6205,7 +6141,6 @@ void pim_cmd_init() install_element (CONFIG_NODE, &no_ip_msdp_mesh_group_member_cmd); install_element (CONFIG_NODE, &ip_msdp_mesh_group_source_cmd); install_element (CONFIG_NODE, &no_ip_msdp_mesh_group_source_cmd); - install_element (CONFIG_NODE, &no_ip_msdp_mesh_group_cmd); install_element (VIEW_NODE, &show_ip_msdp_peer_detail_cmd); install_element (VIEW_NODE, &show_ip_msdp_sa_detail_cmd); install_element (VIEW_NODE, &show_ip_msdp_sa_sg_cmd); diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 38cefe7619..b8a361a260 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -266,7 +266,7 @@ int pim_interface_config_write(struct vty *vty) /* IF ip igmp query-max-response-time */ if (pim_ifp->igmp_query_max_response_time_dsec != IGMP_QUERY_MAX_RESPONSE_TIME_DSEC) { - vty_out(vty, " ip igmp query-max-response-time-dsec %d%s", + vty_out(vty, " ip igpm query-max-response-time %d%s", pim_ifp->igmp_query_max_response_time_dsec, VTY_NEWLINE); ++writes; From 80df099b48dd5316842b150e90c0f7df016f45cb Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 29 Nov 2016 18:39:50 -0500 Subject: [PATCH 334/386] pimd: Fix stupidity compile errors I introduced compile errors using gcc, that worked fine with clang. This removes the issue. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 6f16a7e6d2..78b4a569fb 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4099,15 +4099,12 @@ DEFUN (interface_no_ip_igmp_query_max_response_time, { VTY_DECLVAR_CONTEXT(interface, ifp); struct pim_interface *pim_ifp; - int default_query_interval_dsec; pim_ifp = ifp->info; if (!pim_ifp) return CMD_SUCCESS; - default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval; - change_query_max_response_time(pim_ifp, IGMP_QUERY_MAX_RESPONSE_TIME_DSEC); return CMD_SUCCESS; @@ -4166,15 +4163,12 @@ DEFUN_HIDDEN (interface_no_ip_igmp_query_max_response_time_dsec, { VTY_DECLVAR_CONTEXT(interface, ifp); struct pim_interface *pim_ifp; - int default_query_interval_dsec; pim_ifp = ifp->info; if (!pim_ifp) return CMD_SUCCESS; - default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval; - change_query_max_response_time(pim_ifp, IGMP_QUERY_MAX_RESPONSE_TIME_DSEC); return CMD_SUCCESS; From 5e9985887e6762afad914884805a82f371b925fc Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 29 Nov 2016 21:29:59 -0500 Subject: [PATCH 335/386] pimd: Fix pim_oil_equal function We are self testing for c2 being equal to c2. Bad Donald! No Donut! Signed-off-by: Donald Sharp --- pimd/pim_oil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index acebd6ace6..c8f6b504c1 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -62,7 +62,7 @@ pim_oil_equal (const void *arg1, const void *arg2) const struct channel_oil *c2 = (const struct channel_oil *)arg2; if ((c1->oil.mfcc_mcastgrp.s_addr == c2->oil.mfcc_mcastgrp.s_addr) && - (c2->oil.mfcc_origin.s_addr == c2->oil.mfcc_origin.s_addr)) + (c1->oil.mfcc_origin.s_addr == c2->oil.mfcc_origin.s_addr)) return 1; return 0; From cf3cd99f5db25a54d568c8766548b8e15fb11b6f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 29 Nov 2016 19:19:51 -0500 Subject: [PATCH 336/386] pimd: Lower Hello sent to be immediate There exists situations where an interface flaps and routing recovers and we attempt to install an upstream but since we have no neighbor out that interface still. Let's cause the hello to go out immediately for the 3.1 release to allow mrouting to recover in this situation. We will need to revisit this issue after we have proper nexthop tracking in place Ticket: CM-13185 Signed-off-by: Donald Sharp Reviewed-by: Anuradha Karuppiah --- pimd/pim_pim.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index c7fee4a66f..b77f39f1c4 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -746,7 +746,20 @@ void pim_hello_restart_triggered(struct interface *ifp) pim_ifp = ifp->info; zassert(pim_ifp); - triggered_hello_delay_msec = 1000 * pim_ifp->pim_triggered_hello_delay; + /* + * There exists situations where we have the a RPF out this + * interface, but we haven't formed a neighbor yet. This + * happens especially during interface flaps. While + * we would like to handle this more gracefully in other + * parts of the code. In order to get us up and running + * let's just send the hello immediate'ish + * This should be revisited when we get nexthop tracking + * in and when we have a better handle on safely + * handling the rpf information for upstreams that + * we cannot legally reach yet. + */ + triggered_hello_delay_msec = 1; + //triggered_hello_delay_msec = 1000 * pim_ifp->pim_triggered_hello_delay; if (pim_ifp->t_pim_hello_timer) { long remain_msec = pim_time_timer_remain_msec(pim_ifp->t_pim_hello_timer); @@ -760,7 +773,8 @@ void pim_hello_restart_triggered(struct interface *ifp) pim_ifp->t_pim_hello_timer = NULL; } - random_msec = random() % (triggered_hello_delay_msec + 1); + random_msec = triggered_hello_delay_msec; + //random_msec = random() % (triggered_hello_delay_msec + 1); if (PIM_DEBUG_PIM_HELLO) { zlog_debug("Scheduling %d msec triggered hello on interface %s", From a23ee35b2b5baf2453a0f5a0f2a3f53b6469fc26 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 30 Nov 2016 14:35:09 -0500 Subject: [PATCH 337/386] pimd: Fix show run output to be correct. When issuing a vtysh -m command it expects the output it receives to be the complete command not a partial match. The 'debug pim packets joins' command was being outputted as 'debug pim packets join' This was making quagga-reload.py unhappy. Adding the joins word allows it to complete successfully Ticket: CM-13805 Signed-off-by: Donald Sharp Reviewed-by: Daniel Walton --- pimd/pim_vty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index b8a361a260..3a7d056cb5 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -126,7 +126,7 @@ pim_debug_config_write (struct vty *vty) } if (PIM_DEBUG_PIM_J_P) { - vty_out (vty, "debug pim packets join%s", VTY_NEWLINE); + vty_out (vty, "debug pim packets joins%s", VTY_NEWLINE); ++writes; } From d52ff9b703bf4084a6a8fcd6c2e465c6f61d65b4 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 29 Nov 2016 10:49:00 -0500 Subject: [PATCH 338/386] pimd: Do not allow deletion of output interface. There exists conditions where PIM will have it's upstream route removed and an unreachable route is installed that points out the downstream interface. This unreachable route is removed from bgp as soon as it's path selection algorithim works properly, but pim has already deleted the oif and never puts it back in. Signed-off-by: Donald Sharp --- pimd/pim_zebra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 44b92a8c0b..4b8c36fbe1 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -486,7 +486,7 @@ pim_scan_individual_oil (struct channel_oil *c_oil) new_iif->name, input_iface_vif_index); } - del_oif(c_oil, new_iif, PIM_OIF_FLAG_PROTO_ANY); + //del_oif(c_oil, new_iif, PIM_OIF_FLAG_PROTO_ANY); } /* update iif vif_index */ From c024cfacea98cefd48cf50e1191c164359c19ebe Mon Sep 17 00:00:00 2001 From: anuradhak Date: Wed, 30 Nov 2016 16:14:20 -0800 Subject: [PATCH 339/386] pimd: Fix the number of SAs pushed into one MSDP SA-TLV The entry_cnt in a SA TLV is one byte. I was trying to push 765 SAs into each TLV resulting in strange problems in a scale setup. Signed-off-by: Anuradha Karuppiah --- pimd/pim_msdp_packet.c | 13 ++++++++++++- pimd/pim_msdp_packet.h | 4 +++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/pimd/pim_msdp_packet.c b/pimd/pim_msdp_packet.c index 71dd00beca..8ee45813ca 100644 --- a/pimd/pim_msdp_packet.c +++ b/pimd/pim_msdp_packet.c @@ -194,6 +194,7 @@ pim_msdp_write(struct thread *thread) enum pim_msdp_tlv type; int len; int work_cnt = 0; + int work_max_cnt = 1; mp = THREAD_ARG(thread); mp->t_write = NULL; @@ -273,8 +274,11 @@ pim_msdp_write(struct thread *thread) pim_msdp_pkt_delete(mp); ++work_cnt; - /* XXX - may need to pause if we have done too much work in this + /* may need to pause if we have done too much work in this * loop */ + if (work_cnt >= work_max_cnt) { + break; + } } while ((s = stream_fifo_head(mp->obuf)) != NULL); pim_msdp_write_proceed_actions(mp); @@ -380,6 +384,10 @@ pim_msdp_pkt_sa_gen(struct pim_msdp_peer *mp) int local_cnt = msdp->local_cnt; sa_count = 0; + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug(" sa gen %d", local_cnt); + } + local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt); for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { @@ -395,6 +403,9 @@ pim_msdp_pkt_sa_gen(struct pim_msdp_peer *mp) pim_msdp_pkt_sa_push(mp); /* reset headers */ sa_count = 0; + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug(" sa gen for remainder %d", local_cnt); + } local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt); } } diff --git a/pimd/pim_msdp_packet.h b/pimd/pim_msdp_packet.h index a362ff11d5..f6fcfee6bb 100644 --- a/pimd/pim_msdp_packet.h +++ b/pimd/pim_msdp_packet.h @@ -55,7 +55,9 @@ PIM_MSDP_SA_Y_SIZE(entry_cnt)) /* SA TLV has to have atleast only one entry in it so x=8 + y=12 */ #define PIM_MSDP_SA_TLV_MIN_SIZE PIM_MSDP_SA_ENTRY_CNT2SIZE(1) -#define PIM_MSDP_SA_MAX_ENTRY_CNT ((PIM_MSDP_SA_TLV_MAX_SIZE - PIM_MSDP_SA_X_SIZE)/PIM_MSDP_SA_ONE_ENTRY_SIZE) +/* XXX: theoretically we can fix a max of 255 but that may result in packet + * fragmentation */ +#define PIM_MSDP_SA_MAX_ENTRY_CNT 120 #define PIM_MSDP_MAX_PACKET_SIZE max(PIM_MSDP_SA_TLV_MAX_SIZE, PIM_MSDP_KA_TLV_MAX_SIZE) From 52d8f0d84f47e090b30544468953ab9060430322 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 30 Nov 2016 20:24:47 -0500 Subject: [PATCH 340/386] zebra: Cleanup compile for older linux platforms. Allow code to compile for older platforms. Ticket: CM-13745 Signed-off-by: Donald Sharp --- zebra/if_netlink.c | 42 ++++++++++++++++++++++++++++++++++++++++++ zebra/rt_netlink.c | 6 ++++++ 2 files changed, 48 insertions(+) diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 180e8c5de6..1748703a3e 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -173,6 +173,48 @@ netlink_to_zebra_link_type (unsigned int hwt) } } + +//Temporary Assignments to compile on older platforms. +#ifndef IFLA_BR_MAX +#define IFLA_BR_MAX 39 +#endif + +#ifndef IFLA_VXLAN_ID +#define IFLA_VXLAN_ID 1 +#endif + +#ifndef IFLA_VXLAN_LOCAL +#define IFLA_VXLAN_LOCAL 4 +#endif + +#ifndef IFLA_VXLAN_MAX +#define IFLA_VXLAN_MAX 26 +#endif + +#ifndef IFLA_BRIDGE_MAX +#define IFLA_BRIDGE_MAX 2 +#endif + +#ifndef IFLA_BRIDGE_VLAN_INFO +#define IFLA_BRIDGE_VLAN_INFO 2 +#endif + +#ifndef BRIDGE_VLAN_INFO_PVID +#define BRIDGE_VLAN_INFO_PVID (1<<1) +#endif + +#ifndef RTEXT_FILTER_BRVLAN +#define RTEXT_FILTER_BRVLAN (1<<1) +#endif + +#ifndef NTF_SELF +#define NTF_SELF 0x02 +#endif + +#ifndef IFLA_BR_VLAN_FILTERING +#define IFLA_BR_VLAN_FILTERING 7 +#endif + #define parse_rtattr_nested(tb, max, rta) \ netlink_parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)) diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 15dd7ef1cb..05a9940a93 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -86,6 +86,10 @@ #ifndef MPLS_IPTUNNEL_DST #define MPLS_IPTUNNEL_DST 1 #endif + +#ifndef NDA_MASTER +#define NDA_MASTER 9 +#endif /* End of temporary definitions */ struct gw_family_t @@ -562,8 +566,10 @@ netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h if (tb[RTA_DST]) m->sg.grp = *(struct in_addr *)RTA_DATA (tb[RTA_DST]); +#if defined RTA_EXPIRES if (tb[RTA_EXPIRES]) m->lastused = *(unsigned long long *)RTA_DATA (tb[RTA_EXPIRES]); +#endif if (tb[RTA_MULTIPATH]) { From 69053fb4f0bf1b66a91b28e43c1a9a64db739d65 Mon Sep 17 00:00:00 2001 From: anuradhak Date: Thu, 1 Dec 2016 15:46:36 -0800 Subject: [PATCH 341/386] pimd: restart the ka timer after the sa adv timer To avoid unnecessary ka activity in the network. When the SA advertisment timer fires we build SA TLVs and send them to peers. As a part of this tx we were also restarting the ka timer to avoid unnecessary ka generation in the next 60 seconds. However because the adv timer was restarted after tx (i.e. after ka restart) ka timer would always endup firing just before the adv timer. --- pimd/pim_msdp.c | 5 ++++- pimd/pim_msdp_packet.c | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 3562a0e348..d327984132 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -73,8 +73,8 @@ pim_msdp_sa_adv_timer_cb(struct thread *t) zlog_debug("MSDP SA advertisment timer expired"); } - pim_msdp_pkt_sa_tx(); pim_msdp_sa_adv_timer_setup(true /* start */); + pim_msdp_pkt_sa_tx(); return 0; } static void @@ -974,6 +974,9 @@ pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp) { if (mp->state == PIM_MSDP_ESTABLISHED) { pim_msdp_peer_ka_timer_setup(mp, true /* start */); + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP ka timer restart on pkt tx to %s", mp->key_str); + } } } diff --git a/pimd/pim_msdp_packet.c b/pimd/pim_msdp_packet.c index 8ee45813ca..3f3f9d1de0 100644 --- a/pimd/pim_msdp_packet.c +++ b/pimd/pim_msdp_packet.c @@ -194,7 +194,7 @@ pim_msdp_write(struct thread *thread) enum pim_msdp_tlv type; int len; int work_cnt = 0; - int work_max_cnt = 1; + int work_max_cnt = 12; mp = THREAD_ARG(thread); mp->t_write = NULL; From b815998a4296c6e7ce12faa37eaff0d7d0f697d7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 1 Dec 2016 17:12:21 -0500 Subject: [PATCH 342/386] pimd: Don't allow invalid groups to be passed for igmp When we receive a invalid group( say outside of the 224/4 range) don't allow it to create state. Nicely reject the rejectable. Ticket: CM-13821 Signed-off-by: Donald Sharp --- pimd/pim_igmp.c | 11 +++++++++-- pimd/pim_util.c | 18 ++++++++++++++++++ pimd/pim_util.h | 1 + 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 87a54d68d0..1ca79a5a54 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -1050,6 +1050,13 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, return group; } + if (!pim_is_group_224_4 (group_addr)) + { + zlog_warn("%s: Group Specified is not part of 224.0.0.0/4", + __PRETTY_FUNCTION__); + return NULL; + } + /* Non-existant group is created as INCLUDE {empty}: @@ -1067,7 +1074,7 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, if (!group) { zlog_warn("%s %s: XCALLOC() failure", __FILE__, __PRETTY_FUNCTION__); - return 0; /* error, not found, could not create */ + return NULL; /* error, not found, could not create */ } group->group_source_list = list_new(); @@ -1075,7 +1082,7 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, zlog_warn("%s %s: list_new() failure", __FILE__, __PRETTY_FUNCTION__); XFREE(MTYPE_PIM_IGMP_GROUP, group); /* discard group */ - return 0; /* error, not found, could not initialize */ + return NULL; /* error, not found, could not initialize */ } group->group_source_list->del = (void (*)(void *)) igmp_source_free; diff --git a/pimd/pim_util.c b/pimd/pim_util.c index daee941f8b..f5255a241d 100644 --- a/pimd/pim_util.c +++ b/pimd/pim_util.c @@ -22,6 +22,7 @@ #include #include "log.h" +#include "prefix.h" #include "pim_util.h" @@ -104,3 +105,20 @@ void pim_pkt_dump(const char *label, const uint8_t *buf, int size) size); zlog_hexdump(buf, size); } + +int +pim_is_group_224_4 (struct in_addr group_addr) +{ + static int first = 1; + static struct prefix group_all; + struct prefix group; + + if (first) + str2prefix ("224.0.0.0/4", &group_all); + + group.family = AF_INET; + group.u.prefix4 = group_addr; + group.prefixlen = 32; + + return prefix_match (&group_all, &group); +} diff --git a/pimd/pim_util.h b/pimd/pim_util.h index 23a9688647..a948f81ce8 100644 --- a/pimd/pim_util.h +++ b/pimd/pim_util.h @@ -33,4 +33,5 @@ uint16_t igmp_msg_decode8to16(uint8_t code); void pim_pkt_dump(const char *label, const uint8_t *buf, int size); +int pim_is_group_224_4 (struct in_addr group_addr); #endif /* PIM_UTIL_H */ From 1319c91f3baf41b247651c2145cc940d41e5a2b1 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 2 Dec 2016 08:09:15 -0500 Subject: [PATCH 343/386] pimd: Fix so creation of prefix happens one time Fix code so that the creation of the 224 prefix happens one time. Signed-off-by: Donald Sharp --- pimd/pim_util.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pimd/pim_util.c b/pimd/pim_util.c index f5255a241d..087101e1a2 100644 --- a/pimd/pim_util.c +++ b/pimd/pim_util.c @@ -114,7 +114,10 @@ pim_is_group_224_4 (struct in_addr group_addr) struct prefix group; if (first) - str2prefix ("224.0.0.0/4", &group_all); + { + str2prefix ("224.0.0.0/4", &group_all); + first = 0; + } group.family = AF_INET; group.u.prefix4 = group_addr; From 36e466fe98abf3537e641bc31e9f5cfa06c0fc64 Mon Sep 17 00:00:00 2001 From: anuradhak Date: Thu, 1 Dec 2016 21:01:34 -0800 Subject: [PATCH 344/386] pimd: Drop local SA reference when the upstream SG is deleted This is done irrespective of the reason for del and is intended as a catchall for cases (unclear which ones) where the RP can drop the SG without KAT expiry. Signed-off-by: Anuradha Karuppiah --- pimd/pim_msdp.c | 63 +++++++++++++++++++++++++++++++++++++++++++-- pimd/pim_msdp.h | 5 ++-- pimd/pim_upstream.c | 6 +++-- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index d327984132..c90a7e1e2a 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -124,7 +124,9 @@ pim_msdp_sa_upstream_del(struct pim_msdp_sa *sa) sa->up = NULL; if (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags)) { PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(up->flags); + sa->flags |= PIM_MSDP_SAF_UP_DEL_IN_PROG; pim_upstream_del(up, __PRETTY_FUNCTION__); + sa->flags &= ~PIM_MSDP_SAF_UP_DEL_IN_PROG; } if (PIM_DEBUG_MSDP_EVENTS) { @@ -234,7 +236,7 @@ pim_msdp_sa_new(struct prefix_sg *sg, struct in_addr rp) sa = XCALLOC(MTYPE_PIM_MSDP_SA, sizeof(*sa)); if (!sa) { zlog_err("%s: PIM XCALLOC(%zu) failure", - __PRETTY_FUNCTION__, sizeof(*sa)); + __PRETTY_FUNCTION__, sizeof(*sa)); return NULL; } @@ -477,6 +479,50 @@ pim_msdp_sa_local_del(struct prefix_sg *sg) } } +/* we need to be very cautious with this API as SA del too can trigger an + * upstream del and we will get stuck in a simple loop */ +static void +pim_msdp_sa_local_del_on_up_del(struct prefix_sg *sg) +{ + struct pim_msdp_sa *sa; + + sa = pim_msdp_sa_find(sg); + if (sa) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP local sa %s del on up del", sa->sg_str); + } + + /* if there is no local reference escape */ + if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP local sa %s del; no local ref", sa->sg_str); + } + return; + } + + if (sa->flags & PIM_MSDP_SAF_UP_DEL_IN_PROG) { + /* MSDP is the one that triggered the upstream del. if this happens + * we most certainly have a bug in the PIM upstream state machine. We + * will not have a local reference unless the KAT is running. And if the + * KAT is running there MUST be an additional source-stream reference to + * the flow. Accounting for such cases requires lot of changes; perhaps + * address this in the next release? - XXX */ + zlog_err("MSDP sa %s SPT teardown is causing the local entry to be removed", sa->sg_str); + return; + } + + /* we are dropping the sa on upstream del we should not have an + * upstream reference */ + if (sa->up) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP local sa %s del; up non-NULL", sa->sg_str); + } + sa->up = NULL; + } + pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); + } +} + /* Local SA qualification needs to be re-evaluated when - * 1. KAT is started or stopped * 2. on RP changes @@ -579,7 +625,7 @@ pim_msdp_up_join_state_changed(struct pim_upstream *xg_up) } } -void +static void pim_msdp_up_xg_del(struct prefix_sg *sg) { struct listnode *sanode; @@ -605,6 +651,19 @@ pim_msdp_up_xg_del(struct prefix_sg *sg) } } +void +pim_msdp_up_del(struct prefix_sg *sg) +{ + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP up %s del", pim_str_sg_dump(sg)); + } + if (sg->src.s_addr == INADDR_ANY) { + pim_msdp_up_xg_del(sg); + } else { + pim_msdp_sa_local_del_on_up_del(sg); + } +} + /* sa hash and peer list helpers */ static unsigned int pim_msdp_sa_hash_key_make(void *p) diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h index 80d928a05d..33c1d88a45 100644 --- a/pimd/pim_msdp.h +++ b/pimd/pim_msdp.h @@ -69,8 +69,9 @@ enum pim_msdp_sa_flags { * checks) */ PIM_MSDP_SAF_PEER = (1 << 1), PIM_MSDP_SAF_REF = (PIM_MSDP_SAF_LOCAL | PIM_MSDP_SAF_PEER), - PIM_MSDP_SAF_STALE = (1 << 2) /* local entries can get kicked out on + PIM_MSDP_SAF_STALE = (1 << 2), /* local entries can get kicked out on * misc pim events such as RP change */ + PIM_MSDP_SAF_UP_DEL_IN_PROG = (1 << 3) }; struct pim_msdp_sa { @@ -223,7 +224,7 @@ 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); +void pim_msdp_up_del(struct prefix_sg *sg); enum pim_msdp_err pim_msdp_mg_mbr_add(const char *mesh_group_name, struct in_addr mbr_ip); enum pim_msdp_err pim_msdp_mg_mbr_del(const char *mesh_group_name, struct in_addr mbr_ip); enum pim_msdp_err pim_msdp_mg_src_del(const char *mesh_group_name); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index ec985076df..d823934e8c 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -187,8 +187,10 @@ pim_upstream_del(struct pim_upstream *up, const char *name) } } - if (up->sg.src.s_addr != INADDR_ANY) + if (up->sg.src.s_addr != INADDR_ANY) { wheel_remove_item (pim_upstream_sg_wheel, up); + notify_msdp = true; + } pim_upstream_remove_children (up); pim_mroute_del (up->channel_oil); @@ -212,7 +214,7 @@ pim_upstream_del(struct pim_upstream *up, const char *name) hash_release (pim_upstream_hash, up); if (notify_msdp) { - pim_msdp_up_xg_del(&up->sg); + pim_msdp_up_del(&up->sg); } pim_upstream_free(up); } From 1e3a51321345bbec450cec0ef3f6a7e23e1afdbd Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 1 Dec 2016 20:32:03 -0500 Subject: [PATCH 345/386] pimd: Modify the Prune Pending Timer Pop to not assert So there exist conditions where we can start the Prune Pending Timer and receive other packets that cause us to not stop the pending timer. This was due to a missread of the state machine. Additionally when the prune pending timer pops and we are not in prune pending state, note the fact and move on with our life instead of crashing and burning Ticket: CM-13851 Signed-off-by: Donald Sharp Reviewed-by: --- pimd/pim_ifchannel.c | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 1222ac29c9..1753852654 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -511,19 +511,26 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) ch->t_ifjoin_prune_pending_timer = NULL; - zassert(ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING); + if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) + { + /* Send PruneEcho(S,G) ? */ + ifp = ch->interface; + pim_ifp = ifp->info; + send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1); - /* Send PruneEcho(S,G) ? */ - ifp = ch->interface; - pim_ifp = ifp->info; - send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1); + ifjoin_to_noinfo(ch); + /* from here ch may have been deleted */ - ifjoin_to_noinfo(ch); - /* from here ch may have been deleted */ - - if (send_prune_echo) - pim_joinprune_send (ifp, pim_ifp->primary_address, - ch->upstream, 0); + if (send_prune_echo) + pim_joinprune_send (ifp, pim_ifp->primary_address, + ch->upstream, 0); + } + else + { + zlog_warn("%s: IFCHANNEL%s Prune Pending Timer Popped while in %s state", + __PRETTY_FUNCTION__, pim_str_sg_dump (&ch->sg), + pim_ifchannel_ifjoin_name (ch->ifjoin_state)); + } return 0; } @@ -724,13 +731,14 @@ void pim_ifchannel_join_add(struct interface *ifp, pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); break; case PIM_IFJOIN_PRUNE_PENDING: + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); if (source_flags & PIM_ENCODE_RPT_BIT) - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); - else { - THREAD_OFF(ch->t_ifjoin_prune_pending_timer); - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN); + THREAD_OFF(ch->t_ifjoin_expiry_timer); + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); } + else + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN); break; case PIM_IFJOIN_PRUNE_TMP: break; From f041117e84d74e53f69fbbeaacf3ba80a8ddf907 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 2 Dec 2016 11:28:51 -0500 Subject: [PATCH 346/386] pimd: Fix 'no ip igmp query-max-response-time XX' to work Ticket:CM-13786 Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 78b4a569fb..6ab6af7ba8 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4091,7 +4091,7 @@ DEFUN (interface_ip_igmp_query_max_response_time, DEFUN (interface_no_ip_igmp_query_max_response_time, interface_no_ip_igmp_query_max_response_time_cmd, - "no ip igmp query-max-response-time", + "no ip igmp query-max-response-time <10-250>", NO_STR IP_STR IFACE_IGMP_STR From 06d1c450f355efa63dfe0cbe835db6d58ebb2672 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 2 Dec 2016 12:48:06 -0500 Subject: [PATCH 347/386] pimd: With igmpv2 turned on don't accept 224.0.0.0/24 groups When a group is in the 224.0.0.0/24 range and we have igmp v2 turned on do not allow it to be considered for inclusion as a mroute. Ticket: CM-13855 Signed-off-by: Donald Sharp Reviewed-by: --- pimd/pim_igmp.c | 6 ++++++ pimd/pim_util.c | 20 ++++++++++++++++++++ pimd/pim_util.h | 1 + 3 files changed, 27 insertions(+) diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 1ca79a5a54..456b9ad742 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -1057,6 +1057,12 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, return NULL; } + if (pim_is_group_224_0_0_0_24 (group_addr)) + { + zlog_warn("%s: Group specified is part of 224.0.0.0/24", + __PRETTY_FUNCTION__); + return NULL; + } /* Non-existant group is created as INCLUDE {empty}: diff --git a/pimd/pim_util.c b/pimd/pim_util.c index 087101e1a2..1b1b5ef8f3 100644 --- a/pimd/pim_util.c +++ b/pimd/pim_util.c @@ -106,6 +106,26 @@ void pim_pkt_dump(const char *label, const uint8_t *buf, int size) zlog_hexdump(buf, size); } +int +pim_is_group_224_0_0_0_24 (struct in_addr group_addr) +{ + static int first = 1; + static struct prefix group_224; + struct prefix group; + + if (first) + { + str2prefix ("224.0.0.0/24", &group_224); + first = 0; + } + + group.family = AF_INET; + group.u.prefix4 = group_addr; + group.prefixlen = 32; + + return prefix_match (&group_224, &group); +} + int pim_is_group_224_4 (struct in_addr group_addr) { diff --git a/pimd/pim_util.h b/pimd/pim_util.h index a948f81ce8..3a7844b402 100644 --- a/pimd/pim_util.h +++ b/pimd/pim_util.h @@ -33,5 +33,6 @@ uint16_t igmp_msg_decode8to16(uint8_t code); void pim_pkt_dump(const char *label, const uint8_t *buf, int size); +int pim_is_group_224_0_0_0_24 (struct in_addr group_addr); int pim_is_group_224_4 (struct in_addr group_addr); #endif /* PIM_UTIL_H */ From 489e06bbcfaab04d4589fb316c7f3a9c0197ce16 Mon Sep 17 00:00:00 2001 From: anuradhak Date: Fri, 2 Dec 2016 13:41:11 -0800 Subject: [PATCH 348/386] pimd: Add debug logs to help find problems with stream_read Logs only. No functional change Ticket: CM-13852 Signed-off-by: Anuradha Karuppiah --- pimd/pim_msdp_packet.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/pimd/pim_msdp_packet.c b/pimd/pim_msdp_packet.c index 3f3f9d1de0..62d0579757 100644 --- a/pimd/pim_msdp_packet.c +++ b/pimd/pim_msdp_packet.c @@ -586,16 +586,26 @@ pim_msdp_read_packet(struct pim_msdp_peer *mp) { int nbytes; int readsize; + int old_endp; + int new_endp; - readsize = mp->packet_size - stream_get_endp(mp->ibuf); + old_endp = stream_get_endp(mp->ibuf); + readsize = mp->packet_size - old_endp; if (!readsize) { return 0; } /* Read packet from fd */ nbytes = stream_read_try(mp->ibuf, mp->fd, readsize); + new_endp = stream_get_endp(mp->ibuf); if (nbytes < 0) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s read failed %d", mp->key_str, nbytes); + } if (nbytes == -2) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s pim_msdp_read io retry old_end: %d new_end: %d", mp->key_str, old_endp, new_endp); + } /* transient error retry */ return -1; } @@ -604,13 +614,20 @@ pim_msdp_read_packet(struct pim_msdp_peer *mp) } if (!nbytes) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s read failed %d", mp->key_str, nbytes); + } pim_msdp_peer_reset_tcp_conn(mp, "peer-down"); return -1; } /* We read partial packet. */ - if (stream_get_endp(mp->ibuf) != mp->packet_size) + if (stream_get_endp(mp->ibuf) != mp->packet_size) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s read partial len %d old_endp %d new_endp %d", mp->key_str, mp->packet_size, old_endp, new_endp); + } return -1; + } return 0; } From 3e5e42252e269f52dbdbd8c9866cb0c63b5cfcd5 Mon Sep 17 00:00:00 2001 From: anuradhak Date: Fri, 2 Dec 2016 16:12:35 -0800 Subject: [PATCH 349/386] pimd: reset packet size on tcp connection reset If we were in the middle of a partial read when the tcp connection is reset we were clearing the buffers but not the packet size. This can be problematic when the connection is re-established. There is no easy way to repro and test this without scale (and a timing pattern that is hard to predict). So this change is mostly untested. Ticket: CM-13852 Signed-off-by: Anuradha Karuppiah --- pimd/pim_msdp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index c90a7e1e2a..93141f39de 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -850,6 +850,7 @@ pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state) PIM_MSDP_PEER_WRITE_OFF(mp); /* reset buffers */ + mp->packet_size = 0; if (mp->ibuf) stream_reset(mp->ibuf); if (mp->obuf) From 8474f80e5ab01c4d8a221f3ff9ec35b213813784 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 2 Dec 2016 20:39:24 -0500 Subject: [PATCH 350/386] lib: Allow json to work across different versions. The json_object_object_get_ex function is not fully available across all versions of json. Write a wrapper to allow it to work. Ticket: CM-13872 Signed-off-by: Donald Sharp --- lib/json.c | 15 +++++++++++++++ lib/json.h | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/lib/json.c b/lib/json.c index 3edd146a8f..ccbecb726a 100644 --- a/lib/json.c +++ b/lib/json.c @@ -87,3 +87,18 @@ json_object_free(struct json_object *obj) { json_object_put(obj); } + +#if !defined(HAVE_JSON_C_JSON_H) +int +json_object_object_get_ex(struct json_object *obj, + const char *key, + struct json_object **value) +{ + *value = json_object_object_get(obj, key); + + if (*value) + return 1; + + return 0; +} +#endif diff --git a/lib/json.h b/lib/json.h index bacc799519..7e98614280 100644 --- a/lib/json.h +++ b/lib/json.h @@ -32,6 +32,10 @@ * so let's just turn it back to the original usage. */ #define json_object_to_json_string_ext(A, B) json_object_to_json_string (A) + +extern int json_object_object_get_ex(struct json_object *obj, + const char *key, + struct json_object **value); #endif #include "command.h" From 113db9450ed4fda1e1c2925998f995f59d261fd7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 4 Dec 2016 14:41:20 -0500 Subject: [PATCH 351/386] zebra: LastUsed needs to be updated properly. The change to allow 12.04 to work killed S,G age out. Put it back. Ticket: CM-13879 Signed-off-by: Donald Sharp --- zebra/rt_netlink.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 05a9940a93..2dc699a27e 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -79,6 +79,10 @@ #define RTA_ENCAP 22 #endif +#ifndef RTA_EXPIRES +#define RTA_EXPIRES 23 +#endif + #ifndef LWTUNNEL_ENCAP_MPLS #define LWTUNNEL_ENCAP_MPLS 1 #endif @@ -566,10 +570,8 @@ netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h if (tb[RTA_DST]) m->sg.grp = *(struct in_addr *)RTA_DATA (tb[RTA_DST]); -#if defined RTA_EXPIRES - if (tb[RTA_EXPIRES]) + if ((RTA_EXPIRES <= RTA_MAX) && tb[RTA_EXPIRES]) m->lastused = *(unsigned long long *)RTA_DATA (tb[RTA_EXPIRES]); -#endif if (tb[RTA_MULTIPATH]) { From 833331fbce9f4cf4e427c77f3460d261778b7557 Mon Sep 17 00:00:00 2001 From: anuradhak Date: Mon, 5 Dec 2016 08:27:06 -0800 Subject: [PATCH 352/386] pimd: increase the maximum msdp TLV burst to 100 from 12 12 is too slow of a slow-start in scale setup (say with 6000 SAs) when sources are being learnt one at a time (but in a rapid fire fashion). Signed-off-by: Anuradha Karuppiah --- pimd/pim_msdp_packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_msdp_packet.c b/pimd/pim_msdp_packet.c index 62d0579757..fbf34cd91c 100644 --- a/pimd/pim_msdp_packet.c +++ b/pimd/pim_msdp_packet.c @@ -194,7 +194,7 @@ pim_msdp_write(struct thread *thread) enum pim_msdp_tlv type; int len; int work_cnt = 0; - int work_max_cnt = 12; + int work_max_cnt = 100; mp = THREAD_ARG(thread); mp->t_write = NULL; From 70e7fda8a43de4368b71560a0b6cffdb6504db82 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 5 Dec 2016 07:39:59 -0500 Subject: [PATCH 353/386] pimd: Stop sending Register under certain situations When the switch in question is both a FHR and the RP for the received multicast group stream. When we go to send the NULL register to the RP( ourselves ) do not send it if we have not seen packets for that stream in time greater than PIM_KEEPALIVE_PERIOD and I_am_RP(G). Ticket: CM-13880 Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index d823934e8c..cfa8a3bc5c 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1211,6 +1211,13 @@ pim_upstream_register_stop_timer (struct thread *t) up->join_state = PIM_UPSTREAM_JOIN_PENDING; pim_upstream_start_register_stop_timer (up, 1); + if (((up->channel_oil->cc.lastused/100) > PIM_KEEPALIVE_PERIOD) && + (I_am_RP (up->sg.grp))) + { + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while", __PRETTY_FUNCTION__); + return 0; + } rpg = RP (up->sg.grp); memset (&ip_hdr, 0, sizeof (struct ip)); ip_hdr.ip_p = PIM_IP_PROTO_PIM; From 6578dfa37866ad90dcc988da932911dc4b0b616b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 5 Dec 2016 16:26:59 -0500 Subject: [PATCH 354/386] pimd: Fix where we handle the inherited_olist for ifchannel When we receive a new *,G ifchannel, handle the inherited_olist for S,G mroutes in a place where it is more appropriate. Ticket: CM-13892 Signed-off-by: Donald Sharp Reviewed-by: Anuradha Karuppiah --- pimd/pim_ifchannel.c | 52 ++++++++++++++++++++++++++++++++++ pimd/pim_join.c | 67 -------------------------------------------- 2 files changed, 52 insertions(+), 67 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 1753852654..efb1e3c65e 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -229,6 +229,58 @@ void pim_ifchannel_ifjoin_switch(const char *caller, ch->ifjoin_state = new_state; + if (ch->sg.src.s_addr == INADDR_ANY) + { + struct pim_upstream *up = ch->upstream; + struct pim_upstream *child; + struct listnode *up_node; + + if (up) + { + if (ch->ifjoin_state == PIM_IFJOIN_NOINFO) + { + for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) + { + struct channel_oil *c_oil = child->channel_oil; + struct pim_interface *pim_ifp = ch->interface->info; + + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s %s: Prune(S,G)=%s from %s", + __FILE__, __PRETTY_FUNCTION__, + child->sg_str, up->sg_str); + if (!c_oil) + continue; + + if (!pim_upstream_evaluate_join_desired (child)) + pim_channel_del_oif (c_oil, ch->interface, PIM_OIF_FLAG_PROTO_PIM); + + /* + * If the S,G has no if channel and the c_oil still + * has output here then the *,G was supplying the implied + * 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); + } + } + if (ch->ifjoin_state == PIM_IFJOIN_JOIN) + { + for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) + { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s %s: Join(S,G)=%s from %s", + __FILE__, __PRETTY_FUNCTION__, + child->sg_str, up->sg_str); + + if (pim_upstream_evaluate_join_desired (child)) + { + pim_channel_add_oif (child->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_PIM); + pim_upstream_switch (child, PIM_UPSTREAM_JOINED); + } + } + } + } + } /* Transition to/from NOINFO ? */ if ((old_state == PIM_IFJOIN_NOINFO) || (new_state == PIM_IFJOIN_NOINFO)) { diff --git a/pimd/pim_join.c b/pimd/pim_join.c index c12fc588ff..c0535c4844 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -95,35 +95,6 @@ static void recv_join(struct interface *ifp, pim_ifchannel_join_add(ifp, neigh->source_addr, upstream, sg, source_flags, holdtime); - if (sg->src.s_addr == INADDR_ANY) - { - struct pim_upstream *up = pim_upstream_find (sg); - struct pim_upstream *child; - struct listnode *up_node; - - /* - * If we are unable to create upstream information - * Due to any number of reasons it is possible - * That we might have not created the ifchannel - * and upstream above. So just fall out gracefully - */ - if (!up) - return; - - for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) - { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug("%s %s: Join(S,G)=%s from %s", - __FILE__, __PRETTY_FUNCTION__, - child->sg_str, up->sg_str); - - if (pim_upstream_evaluate_join_desired (child)) - { - pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); - pim_upstream_switch (child, PIM_UPSTREAM_JOINED); - } - } - } } static void recv_prune(struct interface *ifp, @@ -160,44 +131,6 @@ static void recv_prune(struct interface *ifp, pim_ifchannel_prune(ifp, upstream, sg, source_flags, holdtime); - if (sg->src.s_addr == INADDR_ANY) - { - struct pim_upstream *up = pim_upstream_find (sg); - struct pim_upstream *child; - struct listnode *up_node; - - /* - * If up is not found then there is nothing - * to do here (see recv_join above) - */ - if (!up) - return; - - for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) - { - struct channel_oil *c_oil = child->channel_oil; - struct pim_ifchannel *ch = pim_ifchannel_find (ifp, &child->sg); - struct pim_interface *pim_ifp = ifp->info; - - if (PIM_DEBUG_PIM_TRACE) - zlog_debug("%s %s: Prune(S,G)=%s from %s", - __FILE__, __PRETTY_FUNCTION__, - child->sg_str, up->sg_str); - if (!c_oil) - continue; - - if (!pim_upstream_evaluate_join_desired (child)) - pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); - - /* - * If the S,G has no if channel and the c_oil still - * has output here then the *,G was supplying the implied - * if channel. So remove it. - */ - if (!ch && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) - pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM); - } - } } int pim_joinprune_recv(struct interface *ifp, From 4bbcefe91f55eaf9d84fcf855400da823b1d0b24 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 5 Dec 2016 17:53:49 -0500 Subject: [PATCH 355/386] pimd: Cleanup debugs on --- pimd/pim_oil.c | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index c8f6b504c1..6e77afd40a 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -204,18 +204,6 @@ pim_channel_del_oif (struct channel_oil *channel_oil, pim_ifp = oif->info; - 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: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str, - proto_mask, oif->name, pim_ifp->mroute_vif_index); - } - /* * Don't do anything if we've been asked to remove a source * that is not actually on it. @@ -274,6 +262,18 @@ pim_channel_del_oif (struct channel_oil *channel_oil, return -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: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d", + __FILE__, __PRETTY_FUNCTION__, + source_str, group_str, + proto_mask, oif->name, pim_ifp->mroute_vif_index); + } + return 0; } @@ -297,17 +297,6 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, pim_ifp = oif->info; - 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: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str, - proto_mask, oif->name, pim_ifp->mroute_vif_index); - } - #ifdef PIM_ENFORCE_LOOPFREE_MFC /* Prevent creating MFC entry with OIF=IIF. From 3197cb1eb54ecfc48044d3f68a1c027a0dc53607 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 5 Dec 2016 23:27:37 -0500 Subject: [PATCH 356/386] pimd: Cleanup some more debugs Cleanup some pim debugs: 1) For some reason some PIM_DEBUG_PIM_TRACE were not showing up switched them to PIM_DEBUG_TRACE 2) Some mroute debugs were a bit redundant. Reduce. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index cfa8a3bc5c..2daa91080a 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -157,20 +157,15 @@ 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", - name, up->sg_str, up->ref_count); - } + if (PIM_DEBUG_TRACE) + zlog_debug ("%s(%s): Delete %s ref count: %d", + __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count); + --up->ref_count; if (up->ref_count >= 1) return; - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: %s is being deleted", - __PRETTY_FUNCTION__, up->sg_str); - THREAD_OFF(up->t_join_timer); THREAD_OFF(up->t_ka_timer); THREAD_OFF(up->t_rs_timer); @@ -222,7 +217,7 @@ pim_upstream_del(struct pim_upstream *up, const char *name) void pim_upstream_send_join (struct pim_upstream *up) { - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_TRACE) { char rpf_str[PREFIX_STRLEN]; pim_addr_dump("", &up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); zlog_debug ("%s: RPF'%s=%s(%s) for Interface %s", __PRETTY_FUNCTION__, @@ -318,7 +313,7 @@ void pim_upstream_join_suppress(struct pim_upstream *up, join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer); - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_TRACE) { char rpf_str[INET_ADDRSTRLEN]; pim_inet4_dump("", rpf_addr, rpf_str, sizeof(rpf_str)); zlog_debug("%s %s: detected Join%s to RPF'(S,G)=%s: join_timer=%ld msec t_joinsuppress=%ld msec", @@ -329,7 +324,7 @@ void pim_upstream_join_suppress(struct pim_upstream *up, } if (join_timer_remain_msec < t_joinsuppress_msec) { - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_TRACE) { zlog_debug("%s %s: suppressing Join(S,G)=%s for %ld msec", __FILE__, __PRETTY_FUNCTION__, up->sg_str, t_joinsuppress_msec); @@ -349,7 +344,7 @@ void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label, join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer); t_override_msec = pim_if_t_override_msec(up->rpf.source_nexthop.interface); - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_TRACE) { char rpf_str[INET_ADDRSTRLEN]; pim_inet4_dump("", rpf_addr, rpf_str, sizeof(rpf_str)); zlog_debug("%s: to RPF'%s=%s: join_timer=%ld msec t_override=%d msec", @@ -359,7 +354,7 @@ void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label, } if (join_timer_remain_msec > t_override_msec) { - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_TRACE) { zlog_debug("%s: decreasing (S,G)=%s join timer to t_override=%d msec", debug_label, up->sg_str, @@ -543,7 +538,7 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, up = hash_get (pim_upstream_hash, up, hash_alloc_intern); if (!pim_rp_set_upstream_addr (&up->upstream_addr, sg->src, sg->grp)) { - if (PIM_DEBUG_PIM_TRACE) + if (PIM_DEBUG_TRACE) zlog_debug("%s: Received a (*,G) with no RP configured", __PRETTY_FUNCTION__); hash_release (pim_upstream_hash, up); @@ -585,7 +580,7 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, rpf_result = pim_rpf_update(up, NULL); if (rpf_result == PIM_RPF_FAILURE) { - if (PIM_DEBUG_PIM_TRACE) + if (PIM_DEBUG_TRACE) zlog_debug ("%s: Attempting to create upstream(%s), Unable to RPF for source", __PRETTY_FUNCTION__, up->sg_str); @@ -609,7 +604,7 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, listnode_add_sort(pim_upstream_list, up); - if (PIM_DEBUG_PIM_TRACE) + if (PIM_DEBUG_TRACE) zlog_debug ("%s: Created Upstream %s", __PRETTY_FUNCTION__, up->sg_str); return up; @@ -649,7 +644,7 @@ struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, if (PIM_DEBUG_TRACE) { if (up) - zlog_debug("%s(%s): (%s), found: %d: ref_count: %d", + zlog_debug("%s(%s): %s, found: %d: ref_count: %d", __PRETTY_FUNCTION__, name, up->sg_str, found, up->ref_count); @@ -782,7 +777,7 @@ void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr) */ for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { - if (PIM_DEBUG_PIM_TRACE) { + if (PIM_DEBUG_TRACE) { char neigh_str[INET_ADDRSTRLEN]; char rpf_addr_str[PREFIX_STRLEN]; pim_inet4_dump("", neigh_addr, neigh_str, sizeof(neigh_str)); @@ -1349,7 +1344,7 @@ pim_upstream_find_new_rpf (void) { if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { - if (PIM_DEBUG_PIM_TRACE) + if (PIM_DEBUG_TRACE) zlog_debug ("Upstream %s without a path to send join, checking", up->sg_str); pim_rpf_update (up, NULL); From eeedae06ee5c13d225b3fbf2f01bf410846ead2f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 5 Dec 2016 17:53:49 -0500 Subject: [PATCH 357/386] pimd: Cleanup debugs for pim_upstream_sg_running In the normal case when we have debugs turned on and the stream is not running, only display one line of output instead of 2. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 2daa91080a..90adf60615 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1447,9 +1447,11 @@ pim_upstream_sg_running (void *arg) { if (PIM_DEBUG_TRACE) { - zlog_debug ("%s: %s old packet count is equal or lastused is greater than 30", - __PRETTY_FUNCTION__, up->sg_str); - zlog_debug ("%s: %ld %ld %lld", __PRETTY_FUNCTION__, up->channel_oil->cc.oldpktcnt, up->channel_oil->cc.pktcnt, up->channel_oil->cc.lastused/100); + zlog_debug ("%s: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)", + __PRETTY_FUNCTION__, up->sg_str, + up->channel_oil->cc.oldpktcnt, + up->channel_oil->cc.pktcnt, + up->channel_oil->cc.lastused/100); } return; } From 6a78764e468bd002d795309e17b3fd01a40ea707 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 6 Dec 2016 10:08:09 -0500 Subject: [PATCH 358/386] pimd: Clarify pim_mroute_[add|del] function debugging When debugging is turned on for 'debug mroute' we are unable to tell when a mroute has been added or deleted from the mrib. Notice when we do it and who called it. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 8 ++++---- pimd/pim_mroute.c | 29 +++++++++++++++++++++++++---- pimd/pim_mroute.h | 4 ++-- pimd/pim_oil.c | 4 ++-- pimd/pim_static.c | 22 +++++++++++----------- pimd/pim_upstream.c | 2 +- pimd/pim_zebra.c | 12 ++++++------ 7 files changed, 51 insertions(+), 30 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 6ab6af7ba8..093497d44e 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2303,7 +2303,7 @@ static void mroute_add_all() struct channel_oil *c_oil; for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { - if (pim_mroute_add(c_oil)) { + if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) { /* just log warning */ char source_str[INET_ADDRSTRLEN]; char group_str[INET_ADDRSTRLEN]; @@ -2322,7 +2322,7 @@ static void mroute_del_all() struct channel_oil *c_oil; for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { - if (pim_mroute_del(c_oil)) { + if (pim_mroute_del(c_oil, __PRETTY_FUNCTION__)) { /* just log warning */ char source_str[INET_ADDRSTRLEN]; char group_str[INET_ADDRSTRLEN]; @@ -2341,7 +2341,7 @@ static void static_mroute_add_all() struct static_route *s_route; for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { - if (pim_mroute_add(&s_route->c_oil)) { + if (pim_mroute_add(&s_route->c_oil, __PRETTY_FUNCTION__)) { /* just log warning */ char source_str[INET_ADDRSTRLEN]; char group_str[INET_ADDRSTRLEN]; @@ -2360,7 +2360,7 @@ static void static_mroute_del_all() struct static_route *s_route; for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { - if (pim_mroute_del(&s_route->c_oil)) { + if (pim_mroute_del(&s_route->c_oil, __PRETTY_FUNCTION__)) { /* just log warning */ char source_str[INET_ADDRSTRLEN]; char group_str[INET_ADDRSTRLEN]; diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 01fa529525..fdae0b9a22 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -402,7 +402,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) up->channel_oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); pim_upstream_inherited_olist (up); if (!up->channel_oil->installed) - pim_mroute_add (up->channel_oil); + pim_mroute_add (up->channel_oil, __PRETTY_FUNCTION__); pim_upstream_set_sptbit (up, ifp); } else @@ -423,7 +423,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) pim_ifp = ifp->info; oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); if (!oil->installed) - pim_mroute_add (oil); + pim_mroute_add (oil, __PRETTY_FUNCTION__); if (pim_if_connected_to_source (ifp, sg.src)) { up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, __PRETTY_FUNCTION__); @@ -745,7 +745,7 @@ int pim_mroute_del_vif(int vif_index) return 0; } -int pim_mroute_add(struct channel_oil *c_oil) +int pim_mroute_add(struct channel_oil *c_oil, const char *name) { int err; int orig = 0; @@ -805,11 +805,22 @@ int pim_mroute_add(struct channel_oil *c_oil) return -2; } + 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)); + } + c_oil->installed = 1; return 0; } -int pim_mroute_del (struct channel_oil *c_oil) +int pim_mroute_del (struct channel_oil *c_oil, const char *name) { int err; @@ -832,6 +843,16 @@ int pim_mroute_del (struct channel_oil *c_oil) return -2; } + 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)); + } c_oil->installed = 0; return 0; diff --git a/pimd/pim_mroute.h b/pimd/pim_mroute.h index ce300f0ab0..b3f56aa724 100644 --- a/pimd/pim_mroute.h +++ b/pimd/pim_mroute.h @@ -172,8 +172,8 @@ int pim_mroute_socket_disable(void); int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, unsigned char flags); int pim_mroute_del_vif(int vif_index); -int pim_mroute_add(struct channel_oil *c_oil); -int pim_mroute_del(struct channel_oil *c_oil); +int pim_mroute_add(struct channel_oil *c_oil, const char *name); +int pim_mroute_del(struct channel_oil *c_oil, const char *name); int pim_mroute_msg(int fd, const char *buf, int buf_size); diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 6e77afd40a..e002de0300 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -247,7 +247,7 @@ pim_channel_del_oif (struct channel_oil *channel_oil, channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0; - if (pim_mroute_add (channel_oil)) { + if (pim_mroute_add (channel_oil, __PRETTY_FUNCTION__)) { if (PIM_DEBUG_MROUTE) { char group_str[INET_ADDRSTRLEN]; @@ -387,7 +387,7 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = PIM_MROUTE_MIN_TTL; - if (pim_mroute_add(channel_oil)) { + if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) { if (PIM_DEBUG_MROUTE) { char group_str[INET_ADDRSTRLEN]; diff --git a/pimd/pim_static.c b/pimd/pim_static.c index 443e7cacaa..c3c40ff210 100644 --- a/pimd/pim_static.c +++ b/pimd/pim_static.c @@ -175,7 +175,7 @@ int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr listnode_add(qpim_static_route_list, s_route); } - if (pim_mroute_add(&s_route->c_oil)) + if (pim_mroute_add(&s_route->c_oil, __PRETTY_FUNCTION__)) { char gifaddr_str[INET_ADDRSTRLEN]; char sifaddr_str[INET_ADDRSTRLEN]; @@ -254,23 +254,23 @@ int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr /* If there are no more outputs then delete the whole route, otherwise set the route with the new outputs */ if (s_route->c_oil.oil_ref_count <= 0 ? - pim_mroute_del(&s_route->c_oil) : pim_mroute_add(&s_route->c_oil)) { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_warn("%s %s: Unable to remove static route(iif=%d,oif=%d,group=%s,source=%s)", + pim_mroute_del(&s_route->c_oil, __PRETTY_FUNCTION__) : pim_mroute_add(&s_route->c_oil, __PRETTY_FUNCTION__)) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group, gifaddr_str, sizeof(gifaddr_str)); + pim_inet4_dump("", source, sifaddr_str, sizeof(sifaddr_str)); + zlog_warn("%s %s: Unable to remove static route(iif=%d,oif=%d,group=%s,source=%s)", __FILE__, __PRETTY_FUNCTION__, iif_index, oif_index, gifaddr_str, sifaddr_str); - s_route->oif_ttls[oif_index] = 1; - s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; - ++s_route->c_oil.oil_ref_count; + s_route->oif_ttls[oif_index] = 1; + s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; + ++s_route->c_oil.oil_ref_count; - return -1; + return -1; } s_route->c_oil.oif_creation[oif_index] = 0; diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 90adf60615..2b76cb9172 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -188,7 +188,7 @@ pim_upstream_del(struct pim_upstream *up, const char *name) } pim_upstream_remove_children (up); - pim_mroute_del (up->channel_oil); + pim_mroute_del (up->channel_oil, __PRETTY_FUNCTION__); upstream_channel_oil_detach(up); if (up->sources) diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 4b8c36fbe1..cfce8909d6 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -379,7 +379,7 @@ static void scan_upstream_rpf_cache() * so install it. */ if (up->channel_oil && !up->channel_oil->installed) - pim_mroute_add (up->channel_oil); + pim_mroute_add (up->channel_oil, __PRETTY_FUNCTION__); /* RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages @@ -442,14 +442,14 @@ pim_scan_individual_oil (struct channel_oil *c_oil) __FILE__, __PRETTY_FUNCTION__, c_oil->oil.mfcc_parent, source_str, group_str); } - pim_mroute_del (c_oil); + pim_mroute_del (c_oil, __PRETTY_FUNCTION__); return; } if (input_iface_vif_index == c_oil->oil.mfcc_parent) { if (!c_oil->installed) - pim_mroute_add (c_oil); + pim_mroute_add (c_oil, __PRETTY_FUNCTION__); /* RPF unchanged */ return; @@ -494,7 +494,7 @@ pim_scan_individual_oil (struct channel_oil *c_oil) c_oil->oil.mfcc_parent = input_iface_vif_index; /* update kernel multicast forwarding cache (MFC) */ - if (pim_mroute_add(c_oil)) + if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) { if (PIM_DEBUG_MROUTE) { @@ -931,7 +931,7 @@ static int del_oif(struct channel_oil *channel_oil, channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0; - if (pim_mroute_add(channel_oil)) { + if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) { char group_str[INET_ADDRSTRLEN]; char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); @@ -948,7 +948,7 @@ static int del_oif(struct channel_oil *channel_oil, --channel_oil->oil_size; if (channel_oil->oil_size < 1) { - if (pim_mroute_del(channel_oil)) { + if (pim_mroute_del(channel_oil, __PRETTY_FUNCTION__)) { if (PIM_DEBUG_MROUTE) { /* just log a warning in case of failure */ From 8d90ffd05dd3bfb268e5d212d7f18c61eb3fa69a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 6 Dec 2016 13:52:14 -0500 Subject: [PATCH 359/386] pimd: Correctly associate channel oil with correct IIF There exists situations where PIM stores a S,G channel oil and doesn't delete it. When a new upstream comes in for it we were not ensuring that the IIF for the S,G channel oil was correct. Ticket: CM-13908 Signed-off-by: Donald Sharp --- pimd/pim_oil.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index e002de0300..88ace45ed9 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -176,6 +176,11 @@ struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg, c_oil = pim_find_channel_oil(sg); if (c_oil) { + if (c_oil->oil.mfcc_parent != input_vif_index) + if (PIM_DEBUG_MROUTE) + zlog_debug ("%s: Existing channel oil %s points to %d, modifying to point at %d", + __PRETTY_FUNCTION__, pim_str_sg_dump(sg), c_oil->oil.mfcc_parent, input_vif_index); + c_oil->oil.mfcc_parent = input_vif_index; ++c_oil->oil_ref_count; return c_oil; } From ee1a0718068320dae2f9711bd0aa41ab0b9c3c2a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 6 Dec 2016 15:48:42 -0500 Subject: [PATCH 360/386] pimd: Add ability to tweak join/prune send time Add the ability to tweak how often we can send the join prune message. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 27 +++++++++++++++++++++++++++ pimd/pim_vty.c | 6 ++++++ 2 files changed, 33 insertions(+) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 093497d44e..60893c8c10 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3390,6 +3390,31 @@ pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, const cha return CMD_SUCCESS; } +DEFUN (ip_pim_joinprune_time, + ip_pim_joinprune_time_cmd, + "ip pim join-prune-interval <60-600>", + IP_STR + "pim multicast routing\n" + "Join Prune Send Interval\n" + "Seconds\n") +{ + qpim_t_periodic = atoi(argv[3]->arg); + return CMD_SUCCESS; +} + +DEFUN (no_ip_pim_joinprune_time, + no_ip_pim_joinprune_time_cmd, + "no ip pim join-prune-interval <60-600>", + NO_STR + IP_STR + "pim multicast routing\n" + "Join Prune Send Interval\n" + "Seconds\n") +{ + qpim_t_periodic = PIM_DEFAULT_T_PERIODIC; + return CMD_SUCCESS; +} + DEFUN (ip_pim_register_suppress, ip_pim_register_suppress_cmd, "ip pim register-suppress-time <5-60000>", @@ -5980,6 +6005,8 @@ void pim_cmd_init() install_element (CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd); install_element (CONFIG_NODE, &ip_pim_register_suppress_cmd); install_element (CONFIG_NODE, &no_ip_pim_register_suppress_cmd); + install_element (CONFIG_NODE, &ip_pim_joinprune_time_cmd); + install_element (CONFIG_NODE, &no_ip_pim_joinprune_time_cmd); install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd); install_element (CONFIG_NODE, &no_ip_pim_keep_alive_cmd); install_element (CONFIG_NODE, &ip_pim_packets_cmd); diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 3a7d056cb5..8815813ce1 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -162,6 +162,12 @@ int pim_global_config_write(struct vty *vty) qpim_register_suppress_time, VTY_NEWLINE); ++writes; } + if (qpim_t_periodic != PIM_DEFAULT_T_PERIODIC) + { + vty_out (vty, "ip pim join-prune-interval %d%s", + qpim_t_periodic, VTY_NEWLINE); + ++writes; + } if (qpim_keep_alive_time != PIM_KEEPALIVE_PERIOD) { vty_out (vty, "ip pim keep-alive-timer %d%s", From 07335c8d082da51619883a9b4fff6f848e3dba1b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 7 Dec 2016 08:15:16 -0500 Subject: [PATCH 361/386] pimd: Modify pim_upstream_new behavior Modify pim_usptream_new to auto create the pim channel oil. Why? Because there exists situations where we have upstream state and we are attempting to set the inherited_olist on it and we have not created the channel oil yet. When that happens we end up with mroutes that are being meanies. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 5 ++++- pimd/pim_upstream.c | 14 ++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 60893c8c10..53bae4d5fd 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2909,7 +2909,7 @@ static void show_mroute(struct vty *vty, u_char uj) struct interface *ifp_in; found_oif = 0; first = 1; - if (!c_oil->installed) + if (!c_oil->installed && !uj) continue; pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, grp_str, sizeof(grp_str)); @@ -2941,6 +2941,9 @@ static void show_mroute(struct vty *vty, u_char uj) /* Find the inbound interface nested under the source, create it if it doesn't exist */ json_object_object_get_ex(json_source, in_ifname, &json_ifp_in); + json_object_int_add(json_source, "installed", c_oil->installed); + json_object_int_add(json_source, "refCount", c_oil->oil_ref_count); + json_object_int_add(json_source, "oilSize", c_oil->oil_size); if (!json_ifp_in) { json_ifp_in = json_object_new_object(); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 2b76cb9172..14508ad184 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -519,12 +519,14 @@ pim_upstream_compare (void *arg1, void *arg2) return 0; } -static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, - struct interface *incoming, - int flags) +static struct pim_upstream * +pim_upstream_new (struct prefix_sg *sg, + struct interface *incoming, + int flags) { - struct pim_upstream *up; enum pim_rpf_result rpf_result; + struct pim_interface *pim_ifp; + struct pim_upstream *up; up = XCALLOC(MTYPE_PIM_UPSTREAM, sizeof(*up)); if (!up) { @@ -602,6 +604,10 @@ static struct pim_upstream *pim_upstream_new(struct prefix_sg *sg, return NULL; } + pim_ifp = up->rpf.source_nexthop.interface->info; + if (pim_ifp) + up->channel_oil = pim_channel_oil_add(&up->sg, pim_ifp->mroute_vif_index); + listnode_add_sort(pim_upstream_list, up); if (PIM_DEBUG_TRACE) From 67f771b3a32deac5de2fed20da6317b9ccf2ed80 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 7 Dec 2016 08:18:09 -0500 Subject: [PATCH 362/386] pimd: Add guard for pim_msg_send_frame In certain error conditions it is possible to attempt to send packets when the socket is not ready instead of dumping to the log a million error messages only note the issue if we have packet debugs on. Signed-off-by: Donald Sharp --- pimd/pim_pim.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index b77f39f1c4..b973adacc4 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -506,11 +506,14 @@ pim_msg_send_frame (int fd, char *buf, size_t len, return -1; break; default: - pim_inet4_dump ("", ip->ip_dst, dst_str, sizeof (dst_str)); - zlog_warn ("%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s", - __PRETTY_FUNCTION__, - dst_str, fd, len, - errno, safe_strerror(errno)); + if (PIM_DEBUG_PIM_PACKETS) + { + pim_inet4_dump ("", ip->ip_dst, dst_str, sizeof (dst_str)); + zlog_warn ("%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s", + __PRETTY_FUNCTION__, + dst_str, fd, len, + errno, safe_strerror(errno)); + } return -1; break; } From a85d8802932986e35d2585d99b51e5a9c447b0e6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 7 Dec 2016 10:34:58 -0500 Subject: [PATCH 363/386] pimd: Rework zassert code in pim_assert.c When we encounter an error in the state machine for an individual ifchannel, do not bring the entirety of the pim daemon down. Notice the issue and continue on. Ticket-CM-13939 Signed-off-by: Donald Sharp --- pimd/pim_assert.c | 88 ++++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 35 deletions(-) diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index 3e8f1b7d3d..f28e2c0e85 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -182,7 +182,6 @@ static int dispatch_assert(struct interface *ifp, } else { if (inferior_assert(&ch->ifassert_my_metric, &recv_metric)) { - zassert(ch->ifassert_state == PIM_IFASSERT_I_AM_WINNER); /* a3 requirement */ assert_action_a3(ch); } } @@ -434,12 +433,18 @@ static int pim_assert_do(struct pim_ifchannel *ch, int pim_msg_size; ifp = ch->interface; - zassert(ifp); - + if (!ifp) + { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: channel%s has no associated interface!", + __PRETTY_FUNCTION__, ch->sg_str); + return -1; + } pim_ifp = ifp->info; if (!pim_ifp) { - zlog_warn("%s: pim not enabled on interface: %s", - __PRETTY_FUNCTION__, ifp->name); + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: channel %s pim not enabled on interface: %s", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); return -1; } @@ -530,7 +535,6 @@ static int on_assert_timer(struct thread *t) switch (ch->ifassert_state) { case PIM_IFASSERT_I_AM_WINNER: - zassert(ch->ifassert_state == PIM_IFASSERT_I_AM_WINNER); /* a3 requirement */ assert_action_a3(ch); break; case PIM_IFASSERT_I_AM_LOSER: @@ -538,9 +542,10 @@ static int on_assert_timer(struct thread *t) break; default: { - zlog_warn("%s: (S,G)=%s invalid assert state %d on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ch->ifassert_state, ifp->name); + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn("%s: (S,G)=%s invalid assert state %d on interface %s", + __PRETTY_FUNCTION__, + ch->sg_str, ch->ifassert_state, ifp->name); } } @@ -549,38 +554,25 @@ static int on_assert_timer(struct thread *t) static void assert_timer_off(struct pim_ifchannel *ch) { - struct interface *ifp; - - zassert(ch); - ifp = ch->interface; - zassert(ifp); - if (PIM_DEBUG_PIM_TRACE) { if (ch->t_ifassert_timer) { zlog_debug("%s: (S,G)=%s cancelling timer on interface %s", __PRETTY_FUNCTION__, - ch->sg_str, ifp->name); + ch->sg_str, ch->interface->name); } } THREAD_OFF(ch->t_ifassert_timer); - zassert(!ch->t_ifassert_timer); } static void pim_assert_timer_set(struct pim_ifchannel *ch, int interval) { - struct interface *ifp; - - zassert(ch); - ifp = ch->interface; - zassert(ifp); - assert_timer_off(ch); if (PIM_DEBUG_PIM_TRACE) { zlog_debug("%s: (S,G)=%s starting %u sec timer on interface %s", __PRETTY_FUNCTION__, - ch->sg_str, interval, ifp->name); + ch->sg_str, interval, ch->interface->name); } THREAD_TIMER_ON(master, ch->t_ifassert_timer, @@ -608,8 +600,6 @@ int assert_action_a1(struct pim_ifchannel *ch) struct interface *ifp = ch->interface; struct pim_interface *pim_ifp; - zassert(ifp); - pim_ifp = ifp->info; if (!pim_ifp) { zlog_warn("%s: (S,G)=%s multicast not enabled on interface %s", @@ -624,7 +614,6 @@ int assert_action_a1(struct pim_ifchannel *ch) pim_macro_spt_assert_metric(&ch->upstream->rpf, pim_ifp->primary_address)); - zassert(ch->ifassert_state == PIM_IFASSERT_I_AM_WINNER); /* a3 requirement */ if (assert_action_a3(ch)) { zlog_warn("%s: (S,G)=%s assert_action_a3 failure on interface %s", __PRETTY_FUNCTION__, @@ -632,7 +621,12 @@ int assert_action_a1(struct pim_ifchannel *ch) /* warning only */ } - zassert(ch->ifassert_state == PIM_IFASSERT_I_AM_WINNER); + if (ch->ifassert_state != PIM_IFASSERT_I_AM_WINNER) + { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn("%s: channel%s not in expected PIM_IFASSERT_I_AM_WINNER state", + __PRETTY_FUNCTION__, ch->sg_str); + } return 0; } @@ -655,7 +649,12 @@ static void assert_action_a2(struct pim_ifchannel *ch, pim_assert_timer_set(ch, PIM_ASSERT_TIME); - zassert(ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER); + if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) + { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn("%s: channel%s not in expected PIM_IFASSERT_I_AM_LOSER state", + __PRETTY_FUNCTION__, ch->sg_str); + } } /* @@ -668,7 +667,13 @@ static void assert_action_a2(struct pim_ifchannel *ch, */ static int assert_action_a3(struct pim_ifchannel *ch) { - zassert(ch->ifassert_state == PIM_IFASSERT_I_AM_WINNER); + if (ch->ifassert_state != PIM_IFASSERT_I_AM_WINNER) + { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn("%s: channel%s expected to be in PIM_IFASSERT_I_AM_WINNER state", + __PRETTY_FUNCTION__, ch->sg_str); + return -1; + } pim_assert_timer_reset(ch); @@ -679,8 +684,6 @@ static int assert_action_a3(struct pim_ifchannel *ch) return -1; } - zassert(ch->ifassert_state == PIM_IFASSERT_I_AM_WINNER); - return 0; } @@ -705,7 +708,12 @@ void assert_action_a4(struct pim_ifchannel *ch) assert_action_a5(ch); - zassert(ch->ifassert_state == PIM_IFASSERT_NOINFO); + if (ch->ifassert_state != PIM_IFASSERT_NOINFO) + { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn("%s: channel%s not in PIM_IFASSERT_NOINFO state as expected", + __PRETTY_FUNCTION__, ch->sg_str); + } } /* @@ -719,7 +727,12 @@ void assert_action_a4(struct pim_ifchannel *ch) void assert_action_a5(struct pim_ifchannel *ch) { reset_ifassert_state(ch); - zassert(ch->ifassert_state == PIM_IFASSERT_NOINFO); + if (ch->ifassert_state != PIM_IFASSERT_NOINFO) + { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn("%s: channel%s not in PIM_IFSSERT_NOINFO state as expected", + __PRETTY_FUNCTION__, ch->sg_str); + } } /* @@ -746,6 +759,11 @@ static void assert_action_a6(struct pim_ifchannel *ch, if (ch->upstream->join_state == PIM_UPSTREAM_JOINED) ch->upstream->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - zassert(ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER); + if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) + { + if(PIM_DEBUG_PIM_EVENTS) + zlog_warn("%s: channel%s not in PIM_IFASSERT_I_AM_LOSER state as expected", + __PRETTY_FUNCTION__, ch->sg_str); + } } From 5a515ebed0af700d8ec6020961559270d6a37e8c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 7 Dec 2016 11:01:57 -0500 Subject: [PATCH 364/386] pimd: Reset neighbor hold time when we receive packet When we receive a packet from a neighbor, reset the hold time as that we *know* that they are still alive. During heavy packet load, we were seeing cases where neighbors were being reset because we were timing out due to not processing the hello packet in time. Signed-off-by: Donald Sharp --- pimd/pim_neighbor.c | 19 ++----------------- pimd/pim_pim.c | 2 ++ 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index 83d3851d9e..d253ef5412 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -240,26 +240,11 @@ static int on_neighbor_timer(struct thread *t) return 0; } -static void neighbor_timer_off(struct pim_neighbor *neigh) -{ - if (PIM_DEBUG_PIM_TRACE_DETAIL) { - if (neigh->t_expire_timer) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", neigh->source_addr, src_str, sizeof(src_str)); - zlog_debug("%s: cancelling timer for neighbor %s on %s", - __PRETTY_FUNCTION__, - src_str, neigh->interface->name); - } - } - THREAD_OFF(neigh->t_expire_timer); - zassert(!neigh->t_expire_timer); -} - void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime) { neigh->holdtime = holdtime; - neighbor_timer_off(neigh); + THREAD_OFF(neigh->t_expire_timer); /* 0xFFFF is request for no holdtime @@ -571,7 +556,7 @@ void pim_neighbor_delete(struct interface *ifp, zlog_info("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s", src_str, ifp->name, delete_message); - neighbor_timer_off(neigh); + THREAD_OFF(neigh->t_expire_timer); pim_if_assert_on_neighbor_down(ifp, neigh->source_addr); diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index b973adacc4..f9d74ff039 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -245,6 +245,7 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) pim_type, src_str, ifp->name); return -1; } + pim_neighbor_timer_reset(neigh, neigh->holdtime); return pim_joinprune_recv(ifp, neigh, ip_hdr->ip_src, pim_msg + PIM_MSG_HEADER_LEN, @@ -259,6 +260,7 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) pim_type, src_str, ifp->name); return -1; } + pim_neighbor_timer_reset(neigh, neigh->holdtime); return pim_assert_recv(ifp, neigh, ip_hdr->ip_src, pim_msg + PIM_MSG_HEADER_LEN, From be5770d770d79d6436aa4e6d518dc93ccade99cd Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 7 Dec 2016 14:05:46 -0500 Subject: [PATCH 365/386] pimd: Remove unused zclient_debug variable Remove code that sets the pim_zclient_debug variable but is never used. Signed-off-by: Donald Sharp --- pimd/Makefile.am | 2 -- pimd/pim_main.c | 23 ----------------------- pimd/pim_zlookup.c | 2 -- 3 files changed, 27 deletions(-) diff --git a/pimd/Makefile.am b/pimd/Makefile.am index 6ce4f678a9..2bfe9c91ca 100644 --- a/pimd/Makefile.am +++ b/pimd/Makefile.am @@ -20,7 +20,6 @@ # 330, Boston, MA 02111-1307, USA. # PIM_DEBUG_BYDEFAULT: Automatically enables all pimd "debug ..." commands -# PIM_ZCLIENT_DEBUG: Support for internal ZEBRA client debugging # PIM_CHECK_RECV_IFINDEX_SANITY: Compare socket ifindex with recv ifindex # PIM_REPORT_RECV_IFINDEX_MISMATCH: Report sock/recv ifindex mismatch # PIM_ENFORCE_LOOPFREE_MFC: Refuse adding looping MFC entries @@ -30,7 +29,6 @@ PIM_DEFS = #PIM_DEFS += -DPIM_DEBUG_BYDEFAULT #PIM_DEFS += -DPIM_CHECK_RECV_IFINDEX_SANITY #PIM_DEFS += -DPIM_REPORT_RECV_IFINDEX_MISMATCH -PIM_DEFS += -DPIM_ZCLIENT_DEBUG PIM_DEFS += -DPIM_ENFORCE_LOOPFREE_MFC #PIM_DEFS += -DPIM_UNEXPECTED_KERNEL_UPCALL diff --git a/pimd/pim_main.c b/pimd/pim_main.c index 39cab7fb97..7fc9bc524e 100644 --- a/pimd/pim_main.c +++ b/pimd/pim_main.c @@ -48,10 +48,6 @@ #include "pim_iface.h" #include "pim_rp.h" -#ifdef PIM_ZCLIENT_DEBUG -extern int zclient_debug; -#endif - extern struct host host; char config_default[] = SYSCONFDIR PIMD_DEFAULT_CONFIG; @@ -109,15 +105,6 @@ Daemon which manages PIM.\n\n\ -A, --vty_addr Set vty's bind address\n\ -P, --vty_port Set vty's port number\n\ -v, --version Print program version\n\ -" - -#ifdef PIM_ZCLIENT_DEBUG -"\ --Z, --debug_zclient Enable zclient debugging\n\ -" -#endif - -"\ -h, --help Display this help and exit\n\ \n\ Report bugs to %s\n", progname, PACKAGE_BUGREPORT); @@ -182,11 +169,6 @@ int main(int argc, char** argv, char** envp) { print_version(QUAGGA_PROGNAME); exit (0); break; -#ifdef PIM_ZCLIENT_DEBUG - case 'Z': - zclient_debug = 1; - break; -#endif case 'h': usage (0); break; @@ -263,11 +245,6 @@ int main(int argc, char** argv, char** envp) { PIM_DO_DEBUG_ZEBRA; #endif -#ifdef PIM_ZCLIENT_DEBUG - zlog_notice("PIM_ZCLIENT_DEBUG: zclient debugging is supported, mode is %s (see option -Z)", - zclient_debug ? "ON" : "OFF"); -#endif - #ifdef PIM_CHECK_RECV_IFINDEX_SANITY zlog_notice("PIM_CHECK_RECV_IFINDEX_SANITY: will match sock/recv ifindex"); #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 1ed724d7de..f3193b28db 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -38,8 +38,6 @@ #include "pim_oil.h" #include "pim_zlookup.h" -extern int zclient_debug; - static struct zclient *zlookup = NULL; static void zclient_lookup_sched(struct zclient *zlookup, int delay); From b5183fd1ae63960f83868f0a25d6b82beaf7da22 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 7 Dec 2016 15:07:55 -0500 Subject: [PATCH 366/386] pimd: Tell ourselves to rescan when we discover an issue When we have network churn and we have an inherited_olist notice when we may have a situation where we need to recalculate the inherited_olist. Signed-off-by: Donald Sharp --- pimd/pim_oil.c | 10 +++++++--- pimd/pim_oil.h | 1 + pimd/pim_upstream.c | 42 +++++++++++++++++++++++++----------------- pimd/pim_upstream.h | 1 + pimd/pim_zebra.c | 16 +++++++++++++--- 5 files changed, 47 insertions(+), 23 deletions(-) diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 88ace45ed9..44c8324342 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -177,9 +177,12 @@ struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg, c_oil = pim_find_channel_oil(sg); if (c_oil) { if (c_oil->oil.mfcc_parent != input_vif_index) - if (PIM_DEBUG_MROUTE) - zlog_debug ("%s: Existing channel oil %s points to %d, modifying to point at %d", - __PRETTY_FUNCTION__, pim_str_sg_dump(sg), c_oil->oil.mfcc_parent, input_vif_index); + { + c_oil->oil_inherited_rescan = 1; + if (PIM_DEBUG_MROUTE) + zlog_debug ("%s: Existing channel oil %s points to %d, modifying to point at %d", + __PRETTY_FUNCTION__, pim_str_sg_dump(sg), c_oil->oil.mfcc_parent, input_vif_index); + } c_oil->oil.mfcc_parent = input_vif_index; ++c_oil->oil_ref_count; return c_oil; @@ -315,6 +318,7 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, TODO T22. */ if (pim_ifp->mroute_vif_index == channel_oil->oil.mfcc_parent) { + channel_oil->oil_inherited_rescan = 1; if (PIM_DEBUG_MROUTE) { char group_str[INET_ADDRSTRLEN]; diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index 939ef4b3fc..64107bfe88 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -71,6 +71,7 @@ struct channel_counts struct channel_oil { struct mfcctl oil; int installed; + int oil_inherited_rescan; int oil_size; int oil_ref_count; time_t oif_creation[MAXVIFS]; diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 14508ad184..32bc5f5749 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1268,24 +1268,8 @@ pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_regist up, time); } -/* - * For a given upstream, determine the inherited_olist - * and apply it. - * - * inherited_olist(S,G,rpt) = - * ( joins(*,*,RP(G)) (+) joins(*,G) (-) prunes(S,G,rpt) ) - * (+) ( pim_include(*,G) (-) pim_exclude(S,G)) - * (-) ( lost_assert(*,G) (+) lost_assert(S,G,rpt) ) - * - * inherited_olist(S,G) = - * inherited_olist(S,G,rpt) (+) - * joins(S,G) (+) pim_include(S,G) (-) lost_assert(S,G) - * - * return 1 if there are any output interfaces - * return 0 if there are not any output interfaces - */ int -pim_upstream_inherited_olist (struct pim_upstream *up) +pim_upstream_inherited_olist_decide (struct pim_upstream *up) { struct pim_interface *pim_ifp; struct listnode *chnextnode; @@ -1310,6 +1294,30 @@ pim_upstream_inherited_olist (struct pim_upstream *up) } } + return output_intf; +} + +/* + * For a given upstream, determine the inherited_olist + * and apply it. + * + * inherited_olist(S,G,rpt) = + * ( joins(*,*,RP(G)) (+) joins(*,G) (-) prunes(S,G,rpt) ) + * (+) ( pim_include(*,G) (-) pim_exclude(S,G)) + * (-) ( lost_assert(*,G) (+) lost_assert(S,G,rpt) ) + * + * inherited_olist(S,G) = + * inherited_olist(S,G,rpt) (+) + * joins(S,G) (+) pim_include(S,G) (-) lost_assert(S,G) + * + * return 1 if there are any output interfaces + * return 0 if there are not any output interfaces + */ +int +pim_upstream_inherited_olist (struct pim_upstream *up) +{ + int output_intf = pim_upstream_inherited_olist_decide (up); + /* * If we have output_intf switch state to Join and work like normal * If we don't have an output_intf that means we are probably a diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index cc4860a215..026cd7b9d6 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -162,6 +162,7 @@ void pim_upstream_switch (struct pim_upstream *up, enum pim_upstream_state new_s const char *pim_upstream_state2str (enum pim_upstream_state join_state); +int pim_upstream_inherited_olist_decide (struct pim_upstream *up); int pim_upstream_inherited_olist (struct pim_upstream *up); int pim_upstream_empty_inherited_olist (struct pim_upstream *up); diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index cfce8909d6..9d8c07cadb 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -371,15 +371,25 @@ static void scan_upstream_rpf_cache() continue; if (rpf_result == PIM_RPF_CHANGED) { - + + /* + * We have detected a case where we might need to rescan + * the inherited o_list so do it. + */ + if (up->channel_oil->oil_inherited_rescan) + { + pim_upstream_inherited_olist_decide (up); + up->channel_oil->oil_inherited_rescan = 0; + } + if (up->join_state == PIM_UPSTREAM_JOINED) { /* * If we come up real fast we can be here * where the mroute has not been installed * so install it. */ - if (up->channel_oil && !up->channel_oil->installed) - pim_mroute_add (up->channel_oil, __PRETTY_FUNCTION__); + if (!up->channel_oil->installed) + pim_mroute_add (up->channel_oil, __PRETTY_FUNCTION__); /* RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages From ef71d1f860eff7b04623000a33766bf4c2e52a78 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 8 Dec 2016 12:40:05 -0500 Subject: [PATCH 367/386] pimd: Allow bridges and bonds to up and down Bridges and bonds when ifdowned are removed from the kernel in it's entirety, while pim assumed that interfaces were kept around in some fashion. Basically when we had an ifdown event, for all ifchannels on that interface delete from the OIF. Also note the fact that the vif has gone away and we need to recreate it on the next ifup. Ticket: CM-13896 Signed-off-by: Donald Sharp --- pimd/pim_iface.c | 11 +++++++++++ pimd/pim_ifchannel.c | 19 +++++++++++++++++++ pimd/pim_zebra.c | 4 ++++ 3 files changed, 34 insertions(+) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 0a104acef1..3c8bbac6ec 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -715,6 +715,17 @@ void pim_if_addr_add_all(struct interface *ifp) } } /* pim */ } + if (PIM_MROUTE_IS_ENABLED) { + /* + * PIM or IGMP is enabled on interface, and there is at least one + * address assigned, then try to create a vif_index. + */ + if (pim_ifp->mroute_vif_index < 0) { + pim_if_add_vif(ifp); + } + pim_ifchannel_scan_forward_start (ifp); + } + pim_rp_setup(); pim_rp_check_on_if_add(pim_ifp); } diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index efb1e3c65e..77d8e82eec 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -141,6 +141,23 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) pim_ifp = ch->interface->info; + if (ch->upstream->channel_oil) + { + pim_channel_del_oif (ch->upstream->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_PIM); + /* + * Do we have any S,G's that are inheriting? + * Nuke from on high too. + */ + if (ch->upstream->sources) + { + struct pim_upstream *child; + 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); + } + } + /* * When this channel is removed * we need to find all our children @@ -187,6 +204,8 @@ pim_ifchannel_delete_all (struct interface *ifp) struct pim_ifchannel *ifchannel; pim_ifp = ifp->info; + if (!pim_ifp) + return; for (ALL_LIST_ELEMENTS (pim_ifp->pim_ifchannel_list, ifchannel_node, ifchannel_nextnode, ifchannel)) diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 9d8c07cadb..41934074e1 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -174,6 +174,7 @@ static int pim_zebra_if_state_down(int command, struct zclient *zclient, } if (!if_is_operative(ifp)) { + pim_ifchannel_delete_all(ifp); /* pim_if_addr_del_all() suffices for shutting down IGMP, but not for shutting down PIM @@ -189,6 +190,9 @@ static int pim_zebra_if_state_down(int command, struct zclient *zclient, } } + if (ifp->info) + pim_if_del_vif(ifp); + return 0; } From 38f380f56d703a75480aa4329ad5b5ccf2908edf Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 8 Dec 2016 13:50:46 -0500 Subject: [PATCH 368/386] pimd: Fix crash w/ ifp null in pim_mroute.c When you do a series of ifdown/ifup for an interface that is receiving packets through the kernel pim socket, it is possible that the interface has been deleted but the kernel is still going to deliver us a packet. In that case do not allow us to crash. Ticket: CM-13981 Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index fdae0b9a22..1489c70f08 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -511,6 +511,8 @@ int pim_mroute_msg(int fd, const char *buf, int buf_size) ifp = pim_if_find_by_vif_index(msg->im_vif); + if (!ifp) + return 0; if (PIM_DEBUG_MROUTE) { pim_inet4_dump("", msg->im_src, src_str, sizeof(src_str)); pim_inet4_dump("", msg->im_dst, grp_str, sizeof(grp_str)); From fa8489cb5cdb0b95955bfa15d3eebf377effd360 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 8 Dec 2016 15:53:06 -0500 Subject: [PATCH 369/386] pimd: Don't send (S,G)RPT prune Sending (S,G)RPT prune was causing issues due to not handling it properly at this point in time. So just don't send it right now Ticket: CM-13969 Signed-off-by: Donald Sharp --- pimd/pim_msg.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index 0de9518d76..d511123f98 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -207,6 +207,11 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, } remain = pim_msg_curr - pim_msg; + /* + * This is not implemented correctly at this point in time + * Make it stop. + */ +#if 0 if (up->sg.src.s_addr == INADDR_ANY) { struct pim_upstream *child; @@ -267,7 +272,7 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, } } } - +#endif pim_msg_build_header (pim_msg, remain, PIM_MSG_TYPE_JOIN_PRUNE); return remain; From bfdf409644f37429933eafef2af21c0f63ef43ff Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 8 Dec 2016 19:26:41 -0500 Subject: [PATCH 370/386] pimd: Allow us to repair missed inherited_olists There exists situations where we have noted that we need to rescan but have missed the window of opportunity to actually redo the scan so for the moment allow the S,G 30 second scanner notice the missed opportunity and fix it. We'll remove this later. Ticket: CM-13988 Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 1 + pimd/pim_upstream.c | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 53bae4d5fd..bc15336bac 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2944,6 +2944,7 @@ static void show_mroute(struct vty *vty, u_char uj) json_object_int_add(json_source, "installed", c_oil->installed); json_object_int_add(json_source, "refCount", c_oil->oil_ref_count); json_object_int_add(json_source, "oilSize", c_oil->oil_size); + json_object_int_add(json_source, "OilInheritedRescan", c_oil->oil_inherited_rescan); if (!json_ifp_in) { json_ifp_in = json_object_new_object(); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 32bc5f5749..b0bac7b7d4 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1452,7 +1452,21 @@ pim_upstream_sg_running (void *arg) return; } - + /* + * This is a bit of a hack + * We've noted that we should rescan but + * we've missed the window for doing so in + * pim_zebra.c for some reason. I am + * only doing this at this point in time + * to get us up and working for the moment + */ + if (up->channel_oil->oil_inherited_rescan) + { + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: Handling unscanned inherited_olist for %s", __PRETTY_FUNCTION__, up->sg_str); + pim_upstream_inherited_olist_decide (up); + up->channel_oil->oil_inherited_rescan = 0; + } pim_mroute_update_counters (up->channel_oil); // Have we seen packets? From 693c9259df885073c4f7bb36a4a0ec6311ed8e39 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 11 Dec 2016 15:24:13 -0500 Subject: [PATCH 371/386] pimd: Fix cleanup crash When shutting down, actually delete the right data structures. Stupid cut-n-paste error on my part. Ticket: CM-14018 Signed-off-by: Donald Sharp --- pimd/pim_oil.c | 3 ++- pimd/pim_upstream.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 44c8324342..aa059797da 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -100,7 +100,8 @@ pim_oil_terminate (void) pim_channel_oil_list = NULL; if (pim_channel_oil_hash) - hash_free (pim_upstream_hash); + hash_free (pim_channel_oil_hash); + pim_channel_oil_hash = NULL; } void pim_channel_oil_free(struct channel_oil *c_oil) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index b0bac7b7d4..d111289e5a 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1377,11 +1377,12 @@ pim_upstream_hash_key (void *arg) void pim_upstream_terminate (void) { if (pim_upstream_list) - list_free (pim_upstream_list); + list_delete (pim_upstream_list); pim_upstream_list = NULL; if (pim_upstream_hash) hash_free (pim_upstream_hash); + pim_upstream_hash = NULL; } static int From 28185336ed0c8219ce44454c3bd3f3495e71afd3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 12 Dec 2016 19:23:29 -0500 Subject: [PATCH 372/386] pimd: Fix core when bouncing interfaces When you bounce interfaces and the system is under heavy load there exists situations where zebra may or may not have told us the new ifindex, but we've requested a nexthop lookup, which bypasses normal mechanisms for zebra communication, we may get back a ifindex that we may have not created a ifp for yet. Ticket: CM-14052 Signed-off-by: Donald Sharp Reviewed-by: Don Slice --- pimd/pim_iface.c | 4 ++-- pimd/pim_rpf.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 3c8bbac6ec..0b5c7cc1eb 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -1044,9 +1044,9 @@ int pim_if_find_vifindex_by_ifindex(ifindex_t ifindex) struct interface *ifp; ifp = if_lookup_by_index_vrf (ifindex, VRF_DEFAULT); - pim_ifp = ifp->info; - if (!pim_ifp) + if (!ifp || !ifp->info) return -1; + pim_ifp = ifp->info; return pim_ifp->mroute_vif_index; } diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 914395e596..9c18c2482a 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -117,7 +117,8 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei __FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str); } - return -2; + i++; + continue; } if (!ifp->info) From 01cb1466423363a2f8b42246464feb3858df1c9f Mon Sep 17 00:00:00 2001 From: anuradhak Date: Tue, 13 Dec 2016 13:32:16 -0800 Subject: [PATCH 373/386] pimd: make the json output a bit more machine-friendly Mixing well-known and variable property names makes the output difficult to parse. so wrapped variable-keyed dicts with well-known property names (such as "oil") in the following outputs - "show ip mroute json" "show ip msdp mesh-group json" Signed-off-by: Anuradha Karuppiah Reviewed-by: Donald Sharp Reviewed-by: Daniel Walton --- pimd/pim_cmd.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index bc15336bac..3646145309 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2884,7 +2884,7 @@ static void show_mroute(struct vty *vty, u_char uj) json_object *json = NULL; json_object *json_group = NULL; json_object *json_source = NULL; - json_object *json_ifp_in = NULL; + json_object *json_oil = NULL; json_object *json_ifp_out = NULL; int found_oif = 0; int first = 1; @@ -2940,16 +2940,12 @@ static void show_mroute(struct vty *vty, u_char uj) } /* Find the inbound interface nested under the source, create it if it doesn't exist */ - json_object_object_get_ex(json_source, in_ifname, &json_ifp_in); json_object_int_add(json_source, "installed", c_oil->installed); json_object_int_add(json_source, "refCount", c_oil->oil_ref_count); json_object_int_add(json_source, "oilSize", c_oil->oil_size); json_object_int_add(json_source, "OilInheritedRescan", c_oil->oil_inherited_rescan); - - if (!json_ifp_in) { - json_ifp_in = json_object_new_object(); - json_object_object_add(json_source, in_ifname, json_ifp_in); - } + json_object_string_add(json_source, "iif", in_ifname); + json_oil = NULL; } for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) { @@ -2990,7 +2986,11 @@ static void show_mroute(struct vty *vty, u_char uj) json_object_int_add(json_ifp_out, "oVifI", oif_vif_index); json_object_int_add(json_ifp_out, "ttl", ttl); json_object_string_add(json_ifp_out, "upTime", oif_uptime); - json_object_object_add(json_ifp_in, out_ifname, json_ifp_out); + if (!json_oil) { + json_oil = json_object_new_object(); + json_object_object_add(json_source, "oil", json_oil); + } + json_object_object_add(json_oil, out_ifname, json_ifp_out); } else { if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) { strcpy(proto, "PIM"); @@ -3079,14 +3079,8 @@ static void show_mroute(struct vty *vty, u_char uj) json_object_object_add(json_group, src_str, json_source); } - /* Find the inbound interface nested under the source, create it if it doesn't exist */ - json_object_object_get_ex(json_source, in_ifname, &json_ifp_in); - - if (!json_ifp_in) { - json_ifp_in = json_object_new_object(); - json_object_object_add(json_source, in_ifname, json_ifp_in); - } - + json_object_string_add(json_source, "iif", in_ifname); + json_oil = NULL; } else { strcpy(proto, "STATIC"); } @@ -3120,7 +3114,11 @@ static void show_mroute(struct vty *vty, u_char uj) json_object_int_add(json_ifp_out, "oVifI", oif_vif_index); json_object_int_add(json_ifp_out, "ttl", ttl); json_object_string_add(json_ifp_out, "upTime", oif_uptime); - json_object_object_add(json_ifp_in, out_ifname, json_ifp_out); + if (!json_oil) { + json_oil = json_object_new_object(); + json_object_object_add(json_source, "oil", json_oil); + } + json_object_object_add(json_oil, out_ifname, json_ifp_out); } else { vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s%s", src_str, @@ -5519,6 +5517,7 @@ ip_msdp_show_mesh_group(struct vty *vty, u_char uj) enum pim_msdp_peer_state state; json_object *json = NULL; json_object *json_mg_row = NULL; + json_object *json_members = NULL; json_object *json_row = NULL; if (!mg) { @@ -5553,7 +5552,11 @@ ip_msdp_show_mesh_group(struct vty *vty, u_char uj) json_row = json_object_new_object(); json_object_string_add(json_row, "member", mbr_str); json_object_string_add(json_row, "state", state_str); - json_object_object_add(json_mg_row, mbr_str, json_row); + if (!json_members) { + json_members = json_object_new_object(); + json_object_object_add(json_mg_row, "members", json_members); + } + json_object_object_add(json_members, mbr_str, json_row); } else { vty_out(vty, " %-15s %11s%s", mbr_str, state_str, VTY_NEWLINE); From 8175a5464965cc942616bd0220f161aab62da3ed Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 17 Jan 2017 21:18:57 -0500 Subject: [PATCH 374/386] zebra: Fix compiles for non-linux based systems Signed-off-by: Donald Sharp --- zebra/kernel_netlink.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 02da17af63..fb1015e5d5 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -63,6 +63,14 @@ ((struct rtattr *) (((u_char *) (rta)) + RTA_ALIGN((rta)->rta_len))) #endif +#ifndef RTNL_FAMILY_IP6MR +#define RTNL_FAMILY_IP6MR 129 +#endif + +#ifndef RTPROT_MROUTED +#define RTPROT_MROUTED 17 +#endif + static const struct message nlmsg_str[] = { {RTM_NEWROUTE, "RTM_NEWROUTE"}, {RTM_DELROUTE, "RTM_DELROUTE"}, From 1498c0593a75a6beabafbb8ed2b19a9c11bee250 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 17 Jan 2017 22:01:36 -0500 Subject: [PATCH 375/386] zebra: Allow the collection of sg stats on more platforms. The code to collect the sg stats was written for linux. Abstract the call to allow it to work on all platforms. I have not implemented the call for non-linux systems. Signed-off-by: Donald Sharp --- zebra/kernel_null.c | 2 ++ zebra/rt.h | 1 + zebra/rt_netlink.c | 2 +- zebra/rt_netlink.h | 1 - zebra/rt_socket.c | 6 ++++++ zebra/zebra_mroute.c | 4 ++-- 6 files changed, 12 insertions(+), 4 deletions(-) diff --git a/zebra/kernel_null.c b/zebra/kernel_null.c index a20597882c..896ca96b48 100644 --- a/zebra/kernel_null.c +++ b/zebra/kernel_null.c @@ -60,3 +60,5 @@ int kernel_neigh_update (int a, int b, uint32_t c, char *d, int e) void kernel_init (struct zebra_ns *zns) { return; } void kernel_terminate (struct zebra_ns *zns) { return; } void route_read (struct zebra_ns *zns) { return; } + +int kernel_get_ipmr_sg_stats (void *m) { return 0; } diff --git a/zebra/rt.h b/zebra/rt.h index e56e3b8fe3..40beb6a45f 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -40,4 +40,5 @@ extern int kernel_upd_lsp (zebra_lsp_t *); extern int kernel_del_lsp (zebra_lsp_t *); extern int mpls_kernel_init (void); +extern int kernel_get_ipmr_sg_stats (void *mroute); #endif /* _ZEBRA_RT_H */ diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 2dfe43f5df..d2781f4c4e 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1526,7 +1526,7 @@ skip: } int -netlink_get_ipmr_sg_stats (void *in) +kernel_get_ipmr_sg_stats (void *in) { int suc = 0; struct mcast_route_data *mr = (struct mcast_route_data *)in; diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index 6774b7dd3d..7183525fba 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -37,7 +37,6 @@ extern int netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, ns_id_t ns_id); extern int netlink_route_read (struct zebra_ns *zns); -extern int netlink_get_ipmr_sg_stats (void *mroute); #endif /* HAVE_NETLINK */ #endif /* _ZEBRA_RT_NETLINK_H */ diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index b2c99d9813..404bdef57d 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -416,3 +416,9 @@ kernel_neigh_update (int add, int ifindex, uint32_t addr, char *lla, int llalen) /* TODO */ return 0; } + +extern void +kernel_get_ipmr_sg_stats (void *mroute) +{ + return; +} diff --git a/zebra/zebra_mroute.c b/zebra/zebra_mroute.c index d05c906704..86356104bd 100644 --- a/zebra/zebra_mroute.c +++ b/zebra/zebra_mroute.c @@ -30,7 +30,7 @@ #include "zebra/zserv.h" #include "zebra/zebra_vrf.h" #include "zebra/zebra_mroute.h" -#include "zebra/rt_netlink.h" +#include "zebra/rt.h" int zebra_ipmr_route_stats (struct zserv *client, int fd, u_short length, struct zebra_vrf *zvrf) @@ -50,7 +50,7 @@ zebra_ipmr_route_stats (struct zserv *client, int fd, u_short length, struct zeb strcpy (sbuf, inet_ntoa (mroute.sg.src)); strcpy (gbuf, inet_ntoa (mroute.sg.grp)); - suc = netlink_get_ipmr_sg_stats (&mroute); + suc = kernel_get_ipmr_sg_stats (&mroute); s = client->obuf; From a7d3a72e116afcf26d7aa9b77a487a2c2b7c43fb Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 17 Jan 2017 22:27:57 -0500 Subject: [PATCH 376/386] zebra: Fix wrong return type Signed-off-by: Donald Sharp --- zebra/rt_socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index 404bdef57d..5b067025e2 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -417,7 +417,7 @@ kernel_neigh_update (int add, int ifindex, uint32_t addr, char *lla, int llalen) return 0; } -extern void +extern int kernel_get_ipmr_sg_stats (void *mroute) { return; From f15bf553877254ec0cf2e5ccb87096ebd9efc9ba Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 17 Jan 2017 22:45:19 -0500 Subject: [PATCH 377/386] pimd: SO_BINDTODEVICE is not available on some platforms. Follow bgp's lead and don't allow SO_BINDTODEVICE on *bsd. Signed-off-by: Donald Sharp --- pimd/pim_sock.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index de56eb6076..43fe7b7d13 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -94,7 +94,8 @@ pim_socket_ip_hdr (int fd) int pim_socket_bind (int fd, struct interface *ifp) { - int ret; + int ret = 0; +#ifdef SO_BINDTODEVICE if (pimd_privs.change (ZPRIVS_RAISE)) zlog_err ("%s: could not raise privs, %s", @@ -107,6 +108,7 @@ pim_socket_bind (int fd, struct interface *ifp) zlog_err ("%s: could not lower privs, %s", __PRETTY_FUNCTION__, safe_strerror (errno)); +#endif return ret; } From 6f1d88a7305422bea4ca48316c9629eeea59dbc9 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 18 Jan 2017 06:49:40 -0500 Subject: [PATCH 378/386] zebra: Fix kernel_get_ipmr_sg_stats to return an value Signed-off-by: Donald Sharp --- zebra/rt_socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index 5b067025e2..f65ec887dd 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -420,5 +420,5 @@ kernel_neigh_update (int add, int ifindex, uint32_t addr, char *lla, int llalen) extern int kernel_get_ipmr_sg_stats (void *mroute) { - return; + return 0; } From c2403b25989831d8a12fedc3e1af38c58520510d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 18 Jan 2017 07:24:24 -0500 Subject: [PATCH 379/386] pimd: 'struct ip_mreqn' is not available on all platforms Signed-off-by: Donald Sharp --- pimd/pim_sock.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index 43fe7b7d13..5fcdfe1b9b 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -115,7 +115,11 @@ pim_socket_bind (int fd, struct interface *ifp) int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, u_char loop) { int rcvbuf = 1024 * 1024 * 8; +#ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX struct ip_mreqn mreq; +#else + struct ip_mreq mreq; +#endif int fd; fd = pim_socket_raw(protocol); @@ -218,7 +222,12 @@ int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, u_char lo } memset (&mreq, 0, sizeof (mreq)); +#ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX mreq.imr_ifindex = ifindex; +#else + mreq.imr_interface = ifindex; +#endif + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (void *) &mreq, sizeof(mreq))) { zlog_warn("Could not set Outgoing Interface Option on socket fd=%d: errno=%d: %s", From de6d2fa72ec622e26afdda32a7809f331483e8ca Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 18 Jan 2017 07:47:58 -0500 Subject: [PATCH 380/386] pimd: Remove bad merges Two functions were accidentally left around as part of the merge operation. Remove them. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 50578bf1e8..6fc8406bb2 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2556,34 +2556,6 @@ DEFUN (show_ip_pim_assert_winner_metric, return CMD_SUCCESS; } -DEFUN (show_ip_pim_dr, - show_ip_pim_dr_cmd, - "show ip pim designated-router [json]", - SHOW_STR - IP_STR - PIM_STR - "PIM interface designated router\n") -{ - u_char uj = use_json(argc, argv); - pim_show_dr(vty, uj); - - return CMD_SUCCESS; -} - -DEFUN (show_ip_pim_hello, - show_ip_pim_hello_cmd, - "show ip pim hello [json]", - SHOW_STR - IP_STR - PIM_STR - "PIM interface hello information\n") -{ - u_char uj = use_json(argc, argv); - pim_show_hello(vty, uj); - - return CMD_SUCCESS; -} - DEFUN (show_ip_pim_interface, show_ip_pim_interface_cmd, "show ip pim interface [detail|WORD] [json]", From 5fe80c1a8fc69e099d96b0cace455cdd07bc3d8e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 18 Jan 2017 07:50:19 -0500 Subject: [PATCH 381/386] pimd: Fix compilation error Signed-off-by: Donald Sharp Date: Thu, 19 Jan 2017 08:49:12 -0500 Subject: [PATCH 382/386] pimd: Missing include causes compile failure on some bsd's Signed-off-by: Donald Sharp --- pimd/pim_igmpv2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pimd/pim_igmpv2.c b/pimd/pim_igmpv2.c index 975ff9faa1..ee4aa7bd9d 100644 --- a/pimd/pim_igmpv2.c +++ b/pimd/pim_igmpv2.c @@ -19,6 +19,8 @@ * MA 02110-1301 USA */ +#include "zebra.h" + #include "pimd.h" #include "pim_igmp.h" #include "pim_igmpv2.h" From 7a6e6567880b656c4a62cdec0160446d7b6dbf58 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 19 Jan 2017 08:49:47 -0500 Subject: [PATCH 383/386] pimd: Cleanup compile warnings Cleanup some compile warnings in pim on *bsd. Signed-off-by: Donald Sharp --- pimd/pim_rpf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index e48320222f..ae00e347b5 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -53,8 +53,8 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei { struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; int num_ifindex; - struct interface *ifp; - int first_ifindex; + struct interface *ifp = NULL; + ifindex_t first_ifindex = 0; int found = 0; int i = 0; From 3629c61d11d6679d653ee6ae80e5b229710f1f1d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 19 Jan 2017 08:57:17 -0500 Subject: [PATCH 384/386] pimd: Fix README file for FRR Signed-off-by: Donald Sharp --- pimd/README | 81 ++++++----------------------------------------------- 1 file changed, 9 insertions(+), 72 deletions(-) diff --git a/pimd/README b/pimd/README index c8997808b6..3d03979a9a 100644 --- a/pimd/README +++ b/pimd/README @@ -1,18 +1,17 @@ INTRODUCTION qpimd aims to implement a PIM (Protocol Independent Multicast) - daemon for the Quagga Routing Suite. + daemon for the FRR Routing Suite. - Initially qpimd targets only PIM SSM (Source-Specific - Multicast) mode as defined in section 4.8.2 (PIM-SSM-Only - Routers) of RFC 4601. + qpimd implements PIM-SM (Sparse Mode) of RFC 4601. + Additionally MSDP has been implemented. In order to deliver end-to-end multicast routing control - plane, qpimd includes the router-side of IGMPv3 (RFC 3376). + plane, qpimd includes the router-side of IGMPv[2|3] (RFC 3376). LICENSE - qpimd - pimd for quagga + qpimd - pimd for FRR Copyright (C) 2008 Everton da Silva Marques qpimd is free software; you can redistribute it and/or modify @@ -34,78 +33,16 @@ HOME SITE qpimd lives at: - https://github.com/udhos/qpimd + https://github.com/freerangerouting/frr PLATFORMS - qpimd has been tested with Debian Lenny under Linux 2.6. + qpimd has been tested with Debian Jessie. REQUIREMENTS - qpimd requires Quagga (0.99.11 or higher from http://www.quagga.net) + qpimd requires FRR (2.0 or higher) - The GNU Build System (Autotools) is required to build from - source code repository. - - gawk is also needed to build with Autotools. Any other awk - usually won't work. - -BUILDING FROM QUAGGA GIT REPOSITORY - - 1) Get the latest quagga source tree - - # git clone git://code.quagga.net/quagga.git quagga - - 2) Apply qpimd patch into quagga source tree - - # patch -p1 -d quagga < pimd-0.153-quagga-git20090623.patch - - 3) Compile and install quagga - - # cd quagga - # ./bootstrap.sh - # ./configure --prefix=/usr/local/quagga --enable-pimd - # make - # make install - -BUILDING FROM QUAGGA TARBALL - - 1) Get the latest quagga tarball - - # wget http://www.quagga.net/download/quagga-0.99.13.tar.gz - - 2) Unpack the quagga tarball - - # tar xzf quagga-0.99.13.tar.gz - - 3) Apply qpimd patch into quagga source tree - - # patch -p1 -d quagga-0.99.13 < pimd-0.153-quagga-0.99.13.patch - - 4) Compile and install quagga - - # cd quagga-0.99.13 - # ./configure --prefix=/usr/local/quagga --enable-pimd - # make - # make install - -USAGE - - 1) Configure and start the zebra daemon - - # cp /usr/local/quagga/etc/zebra.conf.sample /usr/local/quagga/etc/zebra.conf - # vi /usr/local/quagga/etc/zebra.conf - # /usr/local/quagga/sbin/zebra - - 2) Configure and start the pimd daemon - - # cp /usr/local/quagga/etc/pimd.conf.sample /usr/local/quagga/etc/pimd.conf - # vi /usr/local/quagga/etc/pimd.conf - # /usr/local/quagga/sbin/pimd - - 3) Access pimd vty interface at port TCP 2611 - - # telnet localhost 2611 CONFIGURATION COMMANDS @@ -120,7 +57,7 @@ SUPPORT Please post comments, questions, patches, bug reports at the support site: - https://github.com/udhos/qpimd + https://freerangerouting/frr RELATED WORK From 77b7d90beb39efe4a25e8ef6eba6f6956ad77a7c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 19 Jan 2017 09:58:53 -0500 Subject: [PATCH 385/386] pimd: PIM_MRT is a linux specific piece of code. The PIM_MRT and registration for WRVIFWHOLECACHE is a bit of linux specific code. Until such time that this gets implemented we will have issues being able to work within the context of PIM-SM. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 8e97233d4b..dfd22b7022 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #include @@ -91,6 +87,7 @@ static int pim_mroute_set(int fd, int enable) if (enable) { +#if defined linux int upcalls = IGMPMSG_WRVIFWHOLE; opt = MRT_PIM; @@ -101,6 +98,9 @@ static int pim_mroute_set(int fd, int enable) errno, safe_strerror (errno)); return -1; } +#else + zlog_warn ("PIM-SM will not work properly on this platform, until the ability to receive the WRVIFWHOLE upcall"); +#endif } return 0; From 83190a40e2f44f149693bbbb591f6c28a1f68524 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 19 Jan 2017 10:01:02 -0500 Subject: [PATCH 386/386] pimd: Cleanup the headers. Signed-off-by: Donald Sharp --- pimd/DEBUG | 4 ---- pimd/pim_assert.c | 4 ---- pimd/pim_cmd.c | 4 ---- pimd/pim_hello.h | 4 ---- pimd/pim_iface.c | 4 ---- pimd/pim_iface.h | 2 +- pimd/pim_ifchannel.h | 4 ---- pimd/pim_igmp.c | 4 ---- pimd/pim_igmp_join.h | 4 ---- pimd/pim_igmpv3.c | 4 ---- pimd/pim_igmpv3.h | 4 ---- pimd/pim_join.c | 4 ---- pimd/pim_join.h | 4 ---- pimd/pim_main.c | 4 ---- pimd/pim_msg.c | 4 ---- pimd/pim_neighbor.h | 4 ---- pimd/pim_oil.c | 4 ---- pimd/pim_pim.h | 4 ---- pimd/pim_signals.c | 4 ---- pimd/pim_signals.h | 4 ---- pimd/pim_ssmpingd.c | 4 ---- pimd/pim_ssmpingd.h | 4 ---- pimd/pim_str.c | 4 ---- pimd/pim_str.h | 4 ---- pimd/pim_tlv.c | 4 ---- pimd/pim_tlv.h | 4 ---- pimd/pim_util.c | 4 ---- pimd/pim_util.h | 4 ---- pimd/pim_vty.c | 4 ---- pimd/pim_vty.h | 4 ---- pimd/test_igmpv3_join.c | 4 ---- 31 files changed, 1 insertion(+), 121 deletions(-) diff --git a/pimd/DEBUG b/pimd/DEBUG index b87542a4a2..a6ad260e82 100644 --- a/pimd/DEBUG +++ b/pimd/DEBUG @@ -1,7 +1,3 @@ -<<<<<<< HEAD - -======= ->>>>>>> origin/master DEBUG HINTS - Check the source is issuing multicast packets with TTL high enough diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index 385b897bf9..d6f372cc44 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #include diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 6fc8406bb2..85baa4eafe 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #include diff --git a/pimd/pim_hello.h b/pimd/pim_hello.h index f8e722cd04..3a6d3361ba 100644 --- a/pimd/pim_hello.h +++ b/pimd/pim_hello.h @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #ifndef PIM_HELLO_H diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 7b2c7e2e93..cc4f4f3dce 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -15,10 +15,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #include diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index bd4ebd257d..244de598db 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -16,7 +16,7 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -s*/ + */ #ifndef PIM_IFACE_H #define PIM_IFACE_H diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index c1ce52449a..bfe632135c 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #ifndef PIM_IFCHANNEL_H diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index a309de690b..4a23e4f668 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #include diff --git a/pimd/pim_igmp_join.h b/pimd/pim_igmp_join.h index d9542732b8..ba80db0696 100644 --- a/pimd/pim_igmp_join.h +++ b/pimd/pim_igmp_join.h @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #ifndef PIM_IGMP_JOIN_H diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index 4de3b65ec5..f7a6cbd0ce 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #include diff --git a/pimd/pim_igmpv3.h b/pimd/pim_igmpv3.h index 893fba60f2..3a4a81d97e 100644 --- a/pimd/pim_igmpv3.h +++ b/pimd/pim_igmpv3.h @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #ifndef PIM_IGMPV3_H diff --git a/pimd/pim_join.c b/pimd/pim_join.c index db17c3faec..028f77f532 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #include diff --git a/pimd/pim_join.h b/pimd/pim_join.h index 27333243db..1eeeef756f 100644 --- a/pimd/pim_join.h +++ b/pimd/pim_join.h @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #ifndef PIM_JOIN_H diff --git a/pimd/pim_main.c b/pimd/pim_main.c index e7b86a0404..0749d60b05 100644 --- a/pimd/pim_main.c +++ b/pimd/pim_main.c @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #include diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index e1f20b1496..7ea7b1ad82 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #include diff --git a/pimd/pim_neighbor.h b/pimd/pim_neighbor.h index 9e419aec18..211eda25c7 100644 --- a/pimd/pim_neighbor.h +++ b/pimd/pim_neighbor.h @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #ifndef PIM_NEIGHBOR_H diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 1c0a2f2bea..0cebe47355 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #include diff --git a/pimd/pim_pim.h b/pimd/pim_pim.h index 1f7e1e5d4f..00c5f9012e 100644 --- a/pimd/pim_pim.h +++ b/pimd/pim_pim.h @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #ifndef PIM_PIM_H diff --git a/pimd/pim_signals.c b/pimd/pim_signals.c index 0a60bba252..bd4d9e4857 100644 --- a/pimd/pim_signals.c +++ b/pimd/pim_signals.c @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #include diff --git a/pimd/pim_signals.h b/pimd/pim_signals.h index 8a3f836fa3..7b25608c10 100644 --- a/pimd/pim_signals.h +++ b/pimd/pim_signals.h @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #ifndef PIM_SIGNALS_H diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c index e443a92d61..0354083332 100644 --- a/pimd/pim_ssmpingd.c +++ b/pimd/pim_ssmpingd.c @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #include diff --git a/pimd/pim_ssmpingd.h b/pimd/pim_ssmpingd.h index 29759c9531..54f787e2a3 100644 --- a/pimd/pim_ssmpingd.h +++ b/pimd/pim_ssmpingd.h @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #ifndef PIM_SSMPINGD_H diff --git a/pimd/pim_str.c b/pimd/pim_str.c index 7f814fcda8..83f2a635b3 100644 --- a/pimd/pim_str.c +++ b/pimd/pim_str.c @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #include diff --git a/pimd/pim_str.h b/pimd/pim_str.h index 3536417a95..97263e6a37 100644 --- a/pimd/pim_str.h +++ b/pimd/pim_str.h @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #ifndef PIM_STR_H diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index 2b2a06d368..5223f60e1b 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #include diff --git a/pimd/pim_tlv.h b/pimd/pim_tlv.h index d176c26471..9c4ebc9f0f 100644 --- a/pimd/pim_tlv.h +++ b/pimd/pim_tlv.h @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #ifndef PIM_TLV_H diff --git a/pimd/pim_util.c b/pimd/pim_util.c index 6d7a8c1908..1125db00a9 100644 --- a/pimd/pim_util.c +++ b/pimd/pim_util.c @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #include diff --git a/pimd/pim_util.h b/pimd/pim_util.h index fbb7b0196b..94635466d9 100644 --- a/pimd/pim_util.h +++ b/pimd/pim_util.h @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #ifndef PIM_UTIL_H diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index ee4fcd3150..03ee7e92ec 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #include diff --git a/pimd/pim_vty.h b/pimd/pim_vty.h index 37ec07b2bf..18a632e016 100644 --- a/pimd/pim_vty.h +++ b/pimd/pim_vty.h @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #ifndef PIM_VTY_H diff --git a/pimd/test_igmpv3_join.c b/pimd/test_igmpv3_join.c index 81da867e03..29143f362e 100644 --- a/pimd/test_igmpv3_join.c +++ b/pimd/test_igmpv3_join.c @@ -16,10 +16,6 @@ along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -<<<<<<< HEAD - -======= ->>>>>>> origin/master */ #include