From 8f483f924eb7cdb07a1bf200bdcde2332ee9758f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 12 Jul 2016 21:40:35 -0400 Subject: [PATCH 001/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] 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/444] pimd: Fix compilation error Signed-off-by: Donald Sharp Date: Tue, 15 Nov 2016 19:00:39 +0900 Subject: [PATCH 382/444] Support for BGP Large Communities BGP Large Communities are a novel way to signal information between networks. An example of a Large Community is: "2914:65400:38016". Large BGP Communities are composed of three 4-byte integers, separated by a colon. This is easy to remember and accommodates advanced routing policies in relation to 4-Byte ASNs. This feature was developed by: Keyur Patel (Arrcus, Inc.), Job Snijders (NTT Communications), David Lamparter and Donald Sharp Signed-off-by: Job Snijders Signed-off-by: David Lamparter Signed-off-by: Donald Sharp --- bgpd/Makefile.am | 6 +- bgpd/bgp_attr.c | 101 +++++++- bgpd/bgp_attr.h | 3 + bgpd/bgp_clist.c | 312 +++++++++++++++++++++++ bgpd/bgp_clist.h | 18 +- bgpd/bgp_ecommunity.c | 1 + bgpd/bgp_encap.c | 1 + bgpd/bgp_lcommunity.c | 563 ++++++++++++++++++++++++++++++++++++++++++ bgpd/bgp_lcommunity.h | 75 ++++++ bgpd/bgp_memory.c | 4 + bgpd/bgp_memory.h | 3 + bgpd/bgp_mpath.c | 14 ++ bgpd/bgp_packet.c | 1 + bgpd/bgp_route.c | 122 ++++++++- bgpd/bgp_routemap.c | 409 ++++++++++++++++++++++++++++++ bgpd/bgp_vty.c | 445 ++++++++++++++++++++++++++++++++- bgpd/bgpd.c | 27 +- bgpd/bgpd.h | 2 + lib/routemap.c | 7 + lib/routemap.h | 2 + 20 files changed, 2093 insertions(+), 23 deletions(-) create mode 100644 bgpd/bgp_lcommunity.c create mode 100644 bgpd/bgp_lcommunity.h diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index 69c0504af4..6e36a950d6 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -75,7 +75,8 @@ libbgp_a_SOURCES = \ bgpd.c bgp_fsm.c bgp_aspath.c bgp_community.c bgp_attr.c \ bgp_debug.c bgp_route.c bgp_zebra.c bgp_open.c bgp_routemap.c \ bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \ - bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_mplsvpn.c bgp_nexthop.c \ + bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_lcommunity.c \ + bgp_mplsvpn.c bgp_nexthop.c \ bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \ bgp_nht.c bgp_updgrp.c bgp_updgrp_packet.c bgp_updgrp_adv.c bgp_bfd.c \ bgp_encap.c bgp_encap_tlv.c $(BGP_VNC_RFAPI_SRC) @@ -85,7 +86,8 @@ noinst_HEADERS = \ bgp_aspath.h bgp_attr.h bgp_community.h bgp_debug.h bgp_fsm.h \ bgp_network.h bgp_open.h bgp_packet.h bgp_regex.h bgp_route.h \ bgpd.h bgp_filter.h bgp_clist.h bgp_dump.h bgp_zebra.h \ - bgp_ecommunity.h bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \ + bgp_ecommunity.h bgp_lcommunity.h \ + bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \ bgp_advertise.h bgp_snmp.h bgp_vty.h bgp_mpath.h bgp_nht.h \ bgp_updgrp.h bgp_bfd.h bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h \ $(BGP_VNC_RFAPI_HD) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 4cf1f0daed..fc9440dddc 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -42,6 +42,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_debug.h" #include "bgpd/bgp_packet.h" #include "bgpd/bgp_ecommunity.h" +#include "bgpd/bgp_lcommunity.h" #include "bgpd/bgp_updgrp.h" #include "bgpd/bgp_encap_types.h" #if ENABLE_BGP_VNC @@ -76,6 +77,7 @@ static const struct message attr_str [] = #if ENABLE_BGP_VNC { BGP_ATTR_VNC, "VNC" }, #endif + { BGP_ATTR_LARGE_COMMUNITIES, "LARGE_COMMUNITY" } }; static const int attr_str_max = array_size(attr_str); @@ -670,6 +672,8 @@ attrhash_key_make (void *p) if (extra) { + if (extra->lcommunity) + MIX(lcommunity_hash_make (extra->lcommunity)); if (extra->ecommunity) MIX(ecommunity_hash_make (extra->ecommunity)); if (extra->cluster) @@ -718,6 +722,7 @@ attrhash_cmp (const void *p1, const void *p2) && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local) && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in) && ae1->ecommunity == ae2->ecommunity + && ae1->lcommunity == ae2->lcommunity && ae1->cluster == ae2->cluster && ae1->transit == ae2->transit && (ae1->encap_tunneltype == ae2->encap_tunneltype) @@ -836,6 +841,13 @@ bgp_attr_intern (struct attr *attr) attre->ecommunity->refcnt++; } + if (attre->lcommunity) + { + if (! attre->lcommunity->refcnt) + attre->lcommunity = lcommunity_intern (attre->lcommunity); + else + attre->lcommunity->refcnt++; + } if (attre->cluster) { if (! attre->cluster->refcnt) @@ -1026,6 +1038,10 @@ bgp_attr_unintern_sub (struct attr *attr) if (attr->extra->ecommunity) ecommunity_unintern (&attr->extra->ecommunity); UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)); + + if (attr->extra->lcommunity) + lcommunity_unintern (&attr->extra->lcommunity); + UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES)); if (attr->extra->cluster) cluster_unintern (attr->extra->cluster); @@ -1096,6 +1112,8 @@ bgp_attr_flush (struct attr *attr) if (attre->ecommunity && ! attre->ecommunity->refcnt) ecommunity_free (&attre->ecommunity); + if (attre->lcommunity && ! attre->lcommunity->refcnt) + lcommunity_free (&attre->lcommunity); if (attre->cluster && ! attre->cluster->refcnt) { cluster_free (attre->cluster); @@ -1254,6 +1272,7 @@ const u_int8_t attr_flags_values [] = { [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, + [BGP_ATTR_LARGE_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL }; static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1; @@ -2042,6 +2061,40 @@ bgp_mp_unreach_parse (struct bgp_attr_parser_args *args, return BGP_ATTR_PARSE_PROCEED; } +/* Large Community attribute. */ +static bgp_attr_parse_ret_t +bgp_attr_large_community (struct bgp_attr_parser_args *args) +{ + struct peer *const peer = args->peer; + struct attr *const attr = args->attr; + const bgp_size_t length = args->length; + + /* + * Large community follows new attribute format. + */ + if (length == 0) + { + if (attr->extra) + attr->extra->lcommunity = NULL; + /* Empty extcomm doesn't seem to be invalid per se */ + return BGP_ATTR_PARSE_PROCEED; + } + + (bgp_attr_extra_get (attr))->lcommunity = + lcommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length); + /* XXX: fix ecommunity_parse to use stream API */ + stream_forward_getp (peer->ibuf, length); + + if (attr->extra && !attr->extra->lcommunity) + return bgp_attr_malformed (args, + BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, + args->total); + + attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES); + + return BGP_ATTR_PARSE_PROCEED; +} + /* Extended Community attribute. */ static bgp_attr_parse_ret_t bgp_attr_ext_communities (struct bgp_attr_parser_args *args) @@ -2063,7 +2116,7 @@ bgp_attr_ext_communities (struct bgp_attr_parser_args *args) /* XXX: fix ecommunity_parse to use stream API */ stream_forward_getp (peer->ibuf, length); - if (!attr->extra->ecommunity) + if (attr->extra && !attr->extra->ecommunity) return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, args->total); @@ -2477,6 +2530,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, case BGP_ATTR_COMMUNITIES: ret = bgp_attr_community (&attr_args); break; + case BGP_ATTR_LARGE_COMMUNITIES: + ret = bgp_attr_large_community (&attr_args); + break; case BGP_ATTR_ORIGINATOR_ID: ret = bgp_attr_originator_id (&attr_args); break; @@ -3101,6 +3157,28 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, stream_put (s, attr->community->val, attr->community->size * 4); } + /* + * Large Community attribute. + */ + if (attr->extra && + CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY) + && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES))) + { + if (attr->extra->lcommunity->size * 12 > 255) + { + stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); + stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES); + stream_putw (s, attr->extra->lcommunity->size * 12); + } + else + { + stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); + stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES); + stream_putc (s, attr->extra->lcommunity->size * 12); + } + stream_put (s, attr->extra->lcommunity->val, attr->extra->lcommunity->size * 12); + } + /* Route Reflector. */ if (peer->sort == BGP_PEER_IBGP && from @@ -3333,6 +3411,7 @@ bgp_attr_init (void) attrhash_init (); community_init (); ecommunity_init (); + lcommunity_init (); cluster_init (); transit_init (); encap_init (); @@ -3345,6 +3424,7 @@ bgp_attr_finish (void) attrhash_finish (); community_finish (); ecommunity_finish (); + lcommunity_finish (); cluster_finish (); transit_finish (); encap_finish (); @@ -3448,6 +3528,25 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr, stream_put (s, attr->community->val, attr->community->size * 4); } + /* Large Community attribute. */ + if (attr->extra && attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES)) + { + if (attr->extra->lcommunity->size * 12 > 255) + { + stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); + stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES); + stream_putw (s, attr->extra->lcommunity->size * 12); + } + else + { + stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); + stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES); + stream_putc (s, attr->extra->lcommunity->size * 12); + } + + stream_put (s, attr->extra->lcommunity->val, attr->extra->lcommunity->size * 12); + } + /* Add a MP_NLRI attribute to dump the IPv6 next hop */ if (prefix != NULL && prefix->family == AF_INET6 && attr->extra && (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL || diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 6e639078d6..9c931051d8 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -92,6 +92,9 @@ struct attr_extra /* Extended Communities attribute. */ struct ecommunity *ecommunity; + + /* Large Communities attribute. */ + struct lcommunity *lcommunity; /* Route-Reflector Cluster attribute */ struct cluster_list *cluster; diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c index 9032b1e2f4..47192f0f03 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -29,6 +29,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgpd.h" #include "bgpd/bgp_community.h" #include "bgpd/bgp_ecommunity.h" +#include "bgpd/bgp_lcommunity.h" #include "bgpd/bgp_aspath.h" #include "bgpd/bgp_regex.h" #include "bgpd/bgp_clist.h" @@ -45,6 +46,8 @@ community_list_master_lookup (struct community_list_handler *ch, int master) return &ch->community_list; case EXTCOMMUNITY_LIST_MASTER: return &ch->extcommunity_list; + case LARGE_COMMUNITY_LIST_MASTER: + return &ch->lcommunity_list; } return NULL; } @@ -66,6 +69,10 @@ community_entry_free (struct community_entry *entry) if (entry->u.com) community_free (entry->u.com); break; + case LARGE_COMMUNITY_LIST_STANDARD: + if (entry->u.lcom) + lcommunity_free (&entry->u.lcom); + break; case EXTCOMMUNITY_LIST_STANDARD: /* In case of standard extcommunity-list, configuration string is made by ecommunity_ecom2str(). */ @@ -76,6 +83,7 @@ community_entry_free (struct community_entry *entry) break; case COMMUNITY_LIST_EXPANDED: case EXTCOMMUNITY_LIST_EXPANDED: + case LARGE_COMMUNITY_LIST_EXPANDED: if (entry->config) XFREE (MTYPE_COMMUNITY_LIST_CONFIG, entry->config); if (entry->reg) @@ -320,8 +328,13 @@ community_list_entry_lookup (struct community_list *list, const void *arg, if (entry->direct == direct && ecommunity_cmp (entry->u.ecom, arg)) return entry; break; + case LARGE_COMMUNITY_LIST_STANDARD: + if (entry->direct == direct && lcommunity_cmp (entry->u.lcom, arg)) + return entry; + break; case COMMUNITY_LIST_EXPANDED: case EXTCOMMUNITY_LIST_EXPANDED: + case LARGE_COMMUNITY_LIST_EXPANDED: if (entry->direct == direct && strcmp (entry->config, arg) == 0) return entry; break; @@ -447,6 +460,91 @@ community_regexp_match (struct community *com, regex_t * reg) return 0; } +static char * +lcommunity_str_get (struct lcommunity *lcom, int i) +{ + struct lcommunity_val lcomval; + u_int32_t globaladmin; + u_int32_t localdata1; + u_int32_t localdata2; + char *str; + u_char *ptr; + char *pnt; + + ptr = lcom->val; + ptr += (i * LCOMMUNITY_SIZE); + + memcpy (&lcomval, ptr, LCOMMUNITY_SIZE); + + /* Allocate memory. 48 bytes taken off bgp_lcommunity.c */ + str = pnt = XMALLOC (MTYPE_LCOMMUNITY_STR, 48); + + ptr = (u_char *)lcomval.val; + globaladmin = (*ptr++ << 24); + globaladmin |= (*ptr++ << 16); + globaladmin |= (*ptr++ << 8); + globaladmin |= (*ptr++); + + localdata1 = (*ptr++ << 24); + localdata1 |= (*ptr++ << 16); + localdata1 |= (*ptr++ << 8); + localdata1 |= (*ptr++); + + localdata2 = (*ptr++ << 24); + localdata2 |= (*ptr++ << 16); + localdata2 |= (*ptr++ << 8); + localdata2 |= (*ptr++); + + sprintf (pnt, "%u:%u:%u", globaladmin, localdata1, localdata2); + pnt += strlen (pnt); + *pnt = '\0'; + + return str; +} + +/* Internal function to perform regular expression match for + * * a single community. */ +static int +lcommunity_regexp_include (regex_t * reg, struct lcommunity *lcom, int i) +{ + const char *str; + + /* When there is no communities attribute it is treated as empty + * string. */ + if (lcom == NULL || lcom->size == 0) + str = ""; + else + str = lcommunity_str_get (lcom, i); + + /* Regular expression match. */ + if (regexec (reg, str, 0, NULL, 0) == 0) + return 1; + + /* No match. */ + return 0; +} + +static int +lcommunity_regexp_match (struct lcommunity *com, regex_t * reg) +{ + const char *str; + + /* When there is no communities attribute it is treated as empty + string. */ + if (com == NULL || com->size == 0) + str = ""; + else + str = lcommunity_str (com); + + /* Regular expression match. */ + if (regexec (reg, str, 0, NULL, 0) == 0) + return 1; + + /* No match. */ + return 0; +} + + static int ecommunity_regexp_match (struct ecommunity *ecom, regex_t * reg) { @@ -546,6 +644,30 @@ community_list_match (struct community *com, struct community_list *list) return 0; } +int +lcommunity_list_match (struct lcommunity *lcom, struct community_list *list) +{ + struct community_entry *entry; + + for (entry = list->head; entry; entry = entry->next) + { + if (entry->any) + return entry->direct == COMMUNITY_PERMIT ? 1 : 0; + + if (entry->style == LARGE_COMMUNITY_LIST_STANDARD) + { + if (lcommunity_match (lcom, entry->u.lcom)) + return entry->direct == COMMUNITY_PERMIT ? 1 : 0; + } + else if (entry->style == LARGE_COMMUNITY_LIST_EXPANDED) + { + if (lcommunity_regexp_match (lcom, entry->reg)) + return entry->direct == COMMUNITY_PERMIT ? 1 : 0; + } + } + return 0; +} + int ecommunity_list_match (struct ecommunity *ecom, struct community_list *list) { @@ -694,12 +816,17 @@ community_list_dup_check (struct community_list *list, if (community_cmp (entry->u.com, new->u.com)) return 1; break; + case LARGE_COMMUNITY_LIST_STANDARD: + if (lcommunity_cmp (entry->u.lcom, new->u.lcom)) + return 1; + break; case EXTCOMMUNITY_LIST_STANDARD: if (ecommunity_cmp (entry->u.ecom, new->u.ecom)) return 1; break; case COMMUNITY_LIST_EXPANDED: case EXTCOMMUNITY_LIST_EXPANDED: + case LARGE_COMMUNITY_LIST_EXPANDED: if (strcmp (entry->config, new->config) == 0) return 1; break; @@ -817,6 +944,185 @@ community_list_unset (struct community_list_handler *ch, return 0; } +/* Delete all permitted large communities in the list from com. */ +struct lcommunity * +lcommunity_list_match_delete (struct lcommunity *lcom, + struct community_list *list) +{ + struct community_entry *entry; + u_int32_t com_index_to_delete[lcom->size]; + u_char *ptr; + int delete_index = 0; + int i; + + /* Loop over each lcommunity value and evaluate each against the + * community-list. If we need to delete a community value add its index to + * com_index_to_delete. + */ + ptr = lcom->val; + for (i = 0; i < lcom->size; i++) + { + ptr += (i * LCOMMUNITY_SIZE); + for (entry = list->head; entry; entry = entry->next) + { + if (entry->any) + { + if (entry->direct == COMMUNITY_PERMIT) + { + com_index_to_delete[delete_index] = i; + delete_index++; + } + break; + } + + else if ((entry->style == LARGE_COMMUNITY_LIST_STANDARD) + && lcommunity_include (entry->u.lcom, ptr) ) + { + if (entry->direct == COMMUNITY_PERMIT) + { + com_index_to_delete[delete_index] = i; + delete_index++; + } + break; + } + + else if ((entry->style == LARGE_COMMUNITY_LIST_STANDARD) + && lcommunity_regexp_include (entry->reg, lcom, i)) + { + if (entry->direct == COMMUNITY_PERMIT) + { + com_index_to_delete[delete_index] = i; + delete_index++; + } + break; + } + } + } + + /* Delete all of the communities we flagged for deletion */ + ptr = lcom->val; + for (i = delete_index-1; i >= 0; i--) + { + ptr += (com_index_to_delete[i] * LCOMMUNITY_SIZE); + lcommunity_del_val (lcom, ptr); + } + + return lcom; +} + +/* Set lcommunity-list. */ +int +lcommunity_list_set (struct community_list_handler *ch, + const char *name, const char *str, int direct, int style) +{ + struct community_entry *entry = NULL; + struct community_list *list; + struct lcommunity *lcom = NULL; + regex_t *regex = NULL; + + /* Get community list. */ + list = community_list_get (ch, name, LARGE_COMMUNITY_LIST_MASTER); + + /* When community-list already has entry, new entry should have same + style. If you want to have mixed style community-list, you can + comment out this check. */ + if (!community_list_empty_p (list)) + { + struct community_entry *first; + + first = list->head; + + if (style != first->style) + { + return (first->style == COMMUNITY_LIST_STANDARD + ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT + : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT); + } + } + + if (str) + { + if (style == LARGE_COMMUNITY_LIST_STANDARD) + lcom = lcommunity_str2com (str); + else + regex = bgp_regcomp (str); + + if (! lcom && ! regex) + return COMMUNITY_LIST_ERR_MALFORMED_VAL; + } + + entry = community_entry_new (); + entry->direct = direct; + entry->style = style; + entry->any = (str ? 0 : 1); + entry->u.lcom = lcom; + entry->reg = regex; + if (lcom) + entry->config = lcommunity_lcom2str (lcom, LCOMMUNITY_FORMAT_COMMUNITY_LIST); + else if (regex) + entry->config = XSTRDUP (MTYPE_COMMUNITY_LIST_CONFIG, str); + else + entry->config = NULL; + + /* Do not put duplicated community entry. */ + if (community_list_dup_check (list, entry)) + community_entry_free (entry); + else + community_list_entry_add (list, entry); + + return 0; +} + +/* Unset community-list. When str is NULL, delete all of + community-list entry belongs to the specified name. */ +int +lcommunity_list_unset (struct community_list_handler *ch, + const char *name, const char *str, + int direct, int style) +{ + struct community_entry *entry = NULL; + struct community_list *list; + struct lcommunity *lcom = NULL; + regex_t *regex = NULL; + + /* Lookup community list. */ + list = community_list_lookup (ch, name, LARGE_COMMUNITY_LIST_MASTER); + if (list == NULL) + return COMMUNITY_LIST_ERR_CANT_FIND_LIST; + + /* Delete all of entry belongs to this community-list. */ + if (!str) + { + community_list_delete (list); + return 0; + } + + if (style == LARGE_COMMUNITY_LIST_STANDARD) + lcom = lcommunity_str2com (str); + else + regex = bgp_regcomp (str); + + if (! lcom && ! regex) + return COMMUNITY_LIST_ERR_MALFORMED_VAL; + + if (lcom) + entry = community_list_entry_lookup (list, lcom, direct); + else + entry = community_list_entry_lookup (list, str, direct); + + if (lcom) + lcommunity_free (&lcom); + if (regex) + bgp_regex_free (regex); + + if (!entry) + return COMMUNITY_LIST_ERR_CANT_FIND_LIST; + + community_list_entry_delete (list, entry, style); + + return 0; +} + /* Set extcommunity-list. */ int extcommunity_list_set (struct community_list_handler *ch, @@ -959,6 +1265,12 @@ community_list_terminate (struct community_list_handler *ch) while ((list = cm->str.head) != NULL) community_list_delete (list); + cm = &ch->lcommunity_list; + while ((list = cm->num.head) != NULL) + community_list_delete (list); + while ((list = cm->str.head) != NULL) + community_list_delete (list); + cm = &ch->extcommunity_list; while ((list = cm->num.head) != NULL) community_list_delete (list); diff --git a/bgpd/bgp_clist.h b/bgpd/bgp_clist.h index 277ab7226c..68e45c8f7b 100644 --- a/bgpd/bgp_clist.h +++ b/bgpd/bgp_clist.h @@ -24,6 +24,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA /* Master Community-list. */ #define COMMUNITY_LIST_MASTER 0 #define EXTCOMMUNITY_LIST_MASTER 1 +#define LARGE_COMMUNITY_LIST_MASTER 2 /* Community-list deny and permit. */ #define COMMUNITY_DENY 0 @@ -38,6 +39,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #define COMMUNITY_LIST_EXPANDED 1 /* Expanded community-list. */ #define EXTCOMMUNITY_LIST_STANDARD 2 /* Standard extcommunity-list. */ #define EXTCOMMUNITY_LIST_EXPANDED 3 /* Expanded extcommunity-list. */ +#define LARGE_COMMUNITY_LIST_STANDARD 4 /* Standard Large community-list. */ +#define LARGE_COMMUNITY_LIST_EXPANDED 5 /* Expanded Large community-list. */ /* Community-list. */ struct community_list @@ -80,6 +83,7 @@ struct community_entry { struct community *com; struct ecommunity *ecom; + struct lcommunity *lcom; } u; /* Configuration string. */ @@ -112,6 +116,9 @@ struct community_list_handler /* Exteded community-list. */ struct community_list_master extcommunity_list; + + /* Large community-list. */ + struct community_list_master lcommunity_list; }; /* Error code of community-list. */ @@ -139,6 +146,12 @@ extern int extcommunity_list_set (struct community_list_handler *ch, extern int extcommunity_list_unset (struct community_list_handler *ch, const char *name, const char *str, int direct, int style, int delete_all); +extern int lcommunity_list_set (struct community_list_handler *ch, + const char *name, const char *str, + int direct, int style); +extern int lcommunity_list_unset (struct community_list_handler *ch, + const char *name, const char *str, + int direct, int style); extern struct community_list_master * community_list_master_lookup (struct community_list_handler *, int); @@ -148,9 +161,12 @@ community_list_lookup (struct community_list_handler *, const char *, int); extern int community_list_match (struct community *, struct community_list *); extern int ecommunity_list_match (struct ecommunity *, struct community_list *); +extern int lcommunity_list_match (struct lcommunity *, struct community_list *); extern int community_list_exact_match (struct community *, struct community_list *); extern struct community * community_list_match_delete (struct community *, struct community_list *); - +extern struct lcommunity * +lcommunity_list_match_delete (struct lcommunity *lcom, + struct community_list *list); #endif /* _QUAGGA_BGP_CLIST_H */ diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index b65af9e1fa..6689883d94 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -29,6 +29,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgpd.h" #include "bgpd/bgp_ecommunity.h" +#include "bgpd/bgp_lcommunity.h" #include "bgpd/bgp_aspath.h" /* Hash of community attribute. */ diff --git a/bgpd/bgp_encap.c b/bgpd/bgp_encap.c index 75a348e3fe..418f2873c9 100644 --- a/bgpd/bgp_encap.c +++ b/bgpd/bgp_encap.c @@ -41,6 +41,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_route.h" #include "bgpd/bgp_attr.h" #include "bgpd/bgp_ecommunity.h" +#include "bgpd/bgp_lcommunity.h" #include "bgpd/bgp_mplsvpn.h" #include "bgpd/bgp_vty.h" #include "bgpd/bgp_encap.h" diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c new file mode 100644 index 0000000000..a4b6d96ed3 --- /dev/null +++ b/bgpd/bgp_lcommunity.c @@ -0,0 +1,563 @@ +/* BGP Large Communities Attribute + +Copyright (C) 2016 Keyur Patel + +This file is part of GNU Zebra. + +GNU Zebra 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. + +GNU Zebra 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 "hash.h" +#include "memory.h" +#include "prefix.h" +#include "command.h" +#include "filter.h" + +#include "bgpd/bgpd.h" +#include "bgpd/bgp_lcommunity.h" +#include "bgpd/bgp_aspath.h" + +/* Hash of community attribute. */ +static struct hash *lcomhash; + +/* Allocate a new lcommunities. */ +static struct lcommunity * +lcommunity_new (void) +{ + return (struct lcommunity *) XCALLOC (MTYPE_LCOMMUNITY, + sizeof (struct lcommunity)); +} + +/* Allocate lcommunities. */ +void +lcommunity_free (struct lcommunity **lcom) +{ + if ((*lcom)->val) + XFREE (MTYPE_LCOMMUNITY_VAL, (*lcom)->val); + if ((*lcom)->str) + XFREE (MTYPE_LCOMMUNITY_STR, (*lcom)->str); + XFREE (MTYPE_LCOMMUNITY, *lcom); + lcom = NULL; +} + +/* Add a new Large Communities value to Large Communities + Attribute structure. When the value is already exists in the + structure, we don't add the value. Newly added value is sorted by + numerical order. When the value is added to the structure return 1 + else return 0. */ +static int +lcommunity_add_val (struct lcommunity *lcom, struct lcommunity_val *lval) +{ + u_int8_t *p; + int ret; + int c; + + /* When this is fist value, just add it. */ + if (lcom->val == NULL) + { + lcom->size++; + lcom->val = XMALLOC (MTYPE_LCOMMUNITY_VAL, lcom_length (lcom)); + memcpy (lcom->val, lval->val, LCOMMUNITY_SIZE); + return 1; + } + + /* If the value already exists in the structure return 0. */ + c = 0; + for (p = lcom->val; c < lcom->size; p += LCOMMUNITY_SIZE, c++) + { + ret = memcmp (p, lval->val, LCOMMUNITY_SIZE); + if (ret == 0) + return 0; + if (ret > 0) + break; + } + + /* Add the value to the structure with numerical sorting. */ + lcom->size++; + lcom->val = XREALLOC (MTYPE_LCOMMUNITY_VAL, lcom->val, lcom_length (lcom)); + + memmove (lcom->val + (c + 1) * LCOMMUNITY_SIZE, + lcom->val + c * LCOMMUNITY_SIZE, + (lcom->size - 1 - c) * LCOMMUNITY_SIZE); + memcpy (lcom->val + c * LCOMMUNITY_SIZE, lval->val, LCOMMUNITY_SIZE); + + return 1; +} + +/* This function takes pointer to Large Communites strucutre then + create a new Large Communities structure by uniq and sort each + Large Communities value. */ +struct lcommunity * +lcommunity_uniq_sort (struct lcommunity *lcom) +{ + int i; + struct lcommunity *new; + struct lcommunity_val *lval; + + if (! lcom) + return NULL; + + new = lcommunity_new (); + + for (i = 0; i < lcom->size; i++) + { + lval = (struct lcommunity_val *) (lcom->val + (i * LCOMMUNITY_SIZE)); + lcommunity_add_val (new, lval); + } + return new; +} + +/* Parse Large Communites Attribute in BGP packet. */ +struct lcommunity * +lcommunity_parse (u_int8_t *pnt, u_short length) +{ + struct lcommunity tmp; + struct lcommunity *new; + + /* Length check. */ + if (length % LCOMMUNITY_SIZE) + return NULL; + + /* Prepare tmporary structure for making a new Large Communities + Attribute. */ + tmp.size = length / LCOMMUNITY_SIZE; + tmp.val = pnt; + + /* Create a new Large Communities Attribute by uniq and sort each + Large Communities value */ + new = lcommunity_uniq_sort (&tmp); + + return lcommunity_intern (new); +} + +/* Duplicate the Large Communities Attribute structure. */ +struct lcommunity * +lcommunity_dup (struct lcommunity *lcom) +{ + struct lcommunity *new; + + new = XCALLOC (MTYPE_LCOMMUNITY, sizeof (struct lcommunity)); + new->size = lcom->size; + if (new->size) + { + new->val = XMALLOC (MTYPE_LCOMMUNITY_VAL, lcom->size * LCOMMUNITY_SIZE); + memcpy (new->val, lcom->val, lcom->size * LCOMMUNITY_SIZE); + } + else + new->val = NULL; + return new; +} + +/* Retrun string representation of communities attribute. */ +char * +lcommunity_str (struct lcommunity *lcom) +{ + if (! lcom->str) + lcom->str = lcommunity_lcom2str (lcom, LCOMMUNITY_FORMAT_DISPLAY); + return lcom->str; +} + +/* Merge two Large Communities Attribute structure. */ +struct lcommunity * +lcommunity_merge (struct lcommunity *lcom1, struct lcommunity *lcom2) +{ + if (lcom1->val) + lcom1->val = XREALLOC (MTYPE_LCOMMUNITY_VAL, lcom1->val, + (lcom1->size + lcom2->size) * LCOMMUNITY_SIZE); + else + lcom1->val = XMALLOC (MTYPE_LCOMMUNITY_VAL, + (lcom1->size + lcom2->size) * LCOMMUNITY_SIZE); + + memcpy (lcom1->val + (lcom1->size * LCOMMUNITY_SIZE), + lcom2->val, lcom2->size * LCOMMUNITY_SIZE); + lcom1->size += lcom2->size; + + return lcom1; +} + +/* Intern Large Communities Attribute. */ +struct lcommunity * +lcommunity_intern (struct lcommunity *lcom) +{ + struct lcommunity *find; + + assert (lcom->refcnt == 0); + + find = (struct lcommunity *) hash_get (lcomhash, lcom, hash_alloc_intern); + + if (find != lcom) + lcommunity_free (&lcom); + + find->refcnt++; + + if (! find->str) + find->str = lcommunity_lcom2str (find, LCOMMUNITY_FORMAT_DISPLAY); + + return find; +} + +/* Unintern Large Communities Attribute. */ +void +lcommunity_unintern (struct lcommunity **lcom) +{ + struct lcommunity *ret; + + if ((*lcom)->refcnt) + (*lcom)->refcnt--; + + /* Pull off from hash. */ + if ((*lcom)->refcnt == 0) + { + /* Large community must be in the hash. */ + ret = (struct lcommunity *) hash_release (lcomhash, *lcom); + assert (ret != NULL); + + lcommunity_free (lcom); + } +} + +/* Utility function to make hash key. */ +unsigned int +lcommunity_hash_make (void *arg) +{ + const struct lcommunity *lcom = arg; + int size = lcom->size * LCOMMUNITY_SIZE; + u_int8_t *pnt = lcom->val; + unsigned int key = 0; + int c; + + for (c = 0; c < size; c += LCOMMUNITY_SIZE) + { + key += pnt[c]; + key += pnt[c + 1]; + key += pnt[c + 2]; + key += pnt[c + 3]; + key += pnt[c + 4]; + key += pnt[c + 5]; + key += pnt[c + 6]; + key += pnt[c + 7]; + key += pnt[c + 8]; + key += pnt[c + 9]; + key += pnt[c + 10]; + key += pnt[c + 11]; + } + + return key; +} + +/* Compare two Large Communities Attribute structure. */ +int +lcommunity_cmp (const void *arg1, const void *arg2) +{ + const struct lcommunity *lcom1 = arg1; + const struct lcommunity *lcom2 = arg2; + + return (lcom1->size == lcom2->size + && memcmp (lcom1->val, lcom2->val, lcom1->size * LCOMMUNITY_SIZE) == 0); +} + +/* Return communities hash. */ +struct hash * +lcommunity_hash (void) +{ + return lcomhash; +} + +/* Initialize Large Comminities related hash. */ +void +lcommunity_init (void) +{ + lcomhash = hash_create (lcommunity_hash_make, lcommunity_cmp); +} + +void +lcommunity_finish (void) +{ + hash_free (lcomhash); + lcomhash = NULL; +} + +/* Large Communities token enum. */ +enum lcommunity_token +{ + lcommunity_token_unknown = 0, + lcommunity_token_val, +}; + +/* Get next Large Communities token from the string. */ +static const char * +lcommunity_gettoken (const char *str, struct lcommunity_val *lval, + enum lcommunity_token *token) +{ + const char *p = str; + + /* Skip white space. */ + while (isspace ((int) *p)) + { + p++; + str++; + } + + /* Check the end of the line. */ + if (*p == '\0') + return NULL; + + /* Community value. */ + if (isdigit ((int) *p)) + { + int separator = 0; + int digit = 0; + u_int32_t globaladmin = 0; + u_int32_t localdata1 = 0; + u_int32_t localdata2 = 0; + + while (isdigit ((int) *p) || *p == ':') + { + if (*p == ':') + { + if (separator == 2) + { + *token = lcommunity_token_unknown; + return NULL; + } + else + { + separator++; + digit = 0; + if (separator == 1) { + globaladmin = localdata2; + } else { + localdata1 = localdata2; + } + localdata2 = 0; + } + } + else + { + digit = 1; + localdata2 *= 10; + localdata2 += (*p - '0'); + } + p++; + } + if (! digit) + { + *token = lcommunity_token_unknown; + return NULL; + } + + /* + * Copy the large comm. + */ + lval->val[0] = (globaladmin >> 24) & 0xff; + lval->val[1] = (globaladmin >> 16) & 0xff; + lval->val[2] = (globaladmin >> 8) & 0xff; + lval->val[3] = globaladmin & 0xff; + lval->val[4] = (localdata1 >> 24) & 0xff; + lval->val[5] = (localdata1 >> 16) & 0xff; + lval->val[6] = (localdata1 >> 8) & 0xff; + lval->val[7] = localdata1 & 0xff; + lval->val[8] = (localdata2 >> 24) & 0xff; + lval->val[9] = (localdata2 >> 16) & 0xff; + lval->val[10] = (localdata2 >> 8) & 0xff; + lval->val[11] = localdata2 & 0xff; + + *token = lcommunity_token_val; + return p; + } + *token = lcommunity_token_unknown; + return p; +} + +/* + Convert string to large community attribute. + When type is already known, please specify both str and type. + + When string includes keyword for each large community value. + Please specify keyword_included as non-zero value. +*/ +struct lcommunity * +lcommunity_str2com (const char *str) +{ + struct lcommunity *lcom = NULL; + enum lcommunity_token token = lcommunity_token_unknown; + struct lcommunity_val lval; + + while ((str = lcommunity_gettoken (str, &lval, &token))) + { + switch (token) + { + case lcommunity_token_val: + if (lcom == NULL) + lcom = lcommunity_new (); + lcommunity_add_val (lcom, &lval); + break; + case lcommunity_token_unknown: + default: + if (lcom) + lcommunity_free (&lcom); + return NULL; + } + } + return lcom; +} + +int +lcommunity_include (struct lcommunity *lcom, u_char *ptr) +{ + int i; + u_char *lcom_ptr; + + lcom_ptr = lcom->val; + for (i = 0; i < lcom->size; i++) { + lcom_ptr += (i * LCOMMUNITY_SIZE); + if (memcmp (ptr, lcom_ptr, LCOMMUNITY_SIZE) == 0) + return 1; + } + return 0; +} + +/* Convert large community attribute to string. + The large coms will be in 65535:65531:0 format. +*/ +char * +lcommunity_lcom2str (struct lcommunity *lcom, int format) +{ + int i; + u_int8_t *pnt; +#define LCOMMUNITY_STR_DEFAULT_LEN 40 + int str_size; + int str_pnt; + char *str_buf; + int len = 0; + int first = 1; + u_int32_t globaladmin, localdata1, localdata2; + + if (lcom->size == 0) + { + str_buf = XMALLOC (MTYPE_LCOMMUNITY_STR, 1); + str_buf[0] = '\0'; + return str_buf; + } + + /* Prepare buffer. */ + str_buf = XMALLOC (MTYPE_LCOMMUNITY_STR, LCOMMUNITY_STR_DEFAULT_LEN + 1); + str_size = LCOMMUNITY_STR_DEFAULT_LEN + 1; + str_pnt = 0; + + for (i = 0; i < lcom->size; i++) + { + /* Make it sure size is enough. */ + while (str_pnt + LCOMMUNITY_STR_DEFAULT_LEN >= str_size) + { + str_size *= 2; + str_buf = XREALLOC (MTYPE_LCOMMUNITY_STR, str_buf, str_size); + } + + /* Space between each value. */ + if (! first) + str_buf[str_pnt++] = ' '; + + pnt = lcom->val + (i * 12); + + globaladmin = (*pnt++ << 24); + globaladmin |= (*pnt++ << 16); + globaladmin |= (*pnt++ << 8); + globaladmin |= (*pnt++); + + localdata1 = (*pnt++ << 24); + localdata1 |= (*pnt++ << 16); + localdata1 |= (*pnt++ << 8); + localdata1 |= (*pnt++); + + localdata2 = (*pnt++ << 24); + localdata2 |= (*pnt++ << 16); + localdata2 |= (*pnt++ << 8); + localdata2 |= (*pnt++); + + len = sprintf( str_buf + str_pnt, "%u:%u:%u", globaladmin, + localdata1, localdata2); + str_pnt += len; + first = 0; + } + return str_buf; +} + +int +lcommunity_match (const struct lcommunity *lcom1, + const struct lcommunity *lcom2) +{ + int i = 0; + int j = 0; + + if (lcom1 == NULL && lcom2 == NULL) + return 1; + + if (lcom1 == NULL || lcom2 == NULL) + return 0; + + if (lcom1->size < lcom2->size) + return 0; + + /* Every community on com2 needs to be on com1 for this to match */ + while (i < lcom1->size && j < lcom2->size) + { + if (memcmp (lcom1->val + (i*12), lcom2->val + (j*12), LCOMMUNITY_SIZE) == 0) + j++; + i++; + } + + if (j == lcom2->size) + return 1; + else + return 0; +} + +/* Delete one lcommunity. */ +void +lcommunity_del_val (struct lcommunity *lcom, u_char *ptr) +{ + int i = 0; + int c = 0; + + if (! lcom->val) + return; + + while (i < lcom->size) + { + if (memcmp (lcom->val + i*LCOMMUNITY_SIZE, ptr, LCOMMUNITY_SIZE) == 0) + { + c = lcom->size -i -1; + + if (c > 0) + memmove (lcom->val + i*LCOMMUNITY_SIZE, lcom->val + (i + 1)*LCOMMUNITY_SIZE, c * LCOMMUNITY_SIZE); + + lcom->size--; + + if (lcom->size > 0) + lcom->val = XREALLOC (MTYPE_COMMUNITY_VAL, lcom->val, + lcom_length (lcom)); + else + { + XFREE (MTYPE_COMMUNITY_VAL, lcom->val); + lcom->val = NULL; + } + return; + } + i++; + } +} diff --git a/bgpd/bgp_lcommunity.h b/bgpd/bgp_lcommunity.h new file mode 100644 index 0000000000..7841b4b9a6 --- /dev/null +++ b/bgpd/bgp_lcommunity.h @@ -0,0 +1,75 @@ +/* BGP Large Communities Attribute. + +Copyright (C) 2016 Keyur Patel + +This file is part of GNU Zebra. + +GNU Zebra 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. + +GNU Zebra 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 _QUAGGA_BGP_LCOMMUNITY_H +#define _QUAGGA_BGP_LCOMMUNITY_H + +/* Extended communities attribute string format. */ +#define LCOMMUNITY_FORMAT_ROUTE_MAP 0 +#define LCOMMUNITY_FORMAT_COMMUNITY_LIST 1 +#define LCOMMUNITY_FORMAT_DISPLAY 2 + +/* Large Communities value is twelve octets long. */ +#define LCOMMUNITY_SIZE 12 + +/* Large Communities attribute. */ +struct lcommunity +{ + /* Reference counter. */ + unsigned long refcnt; + + /* Size of Extended Communities attribute. */ + int size; + + /* Extended Communities value. */ + u_int8_t *val; + + /* Human readable format string. */ + char *str; +}; + +/* Extended community value is eight octet. */ +struct lcommunity_val +{ + char val[LCOMMUNITY_SIZE]; +}; + +#define lcom_length(X) ((X)->size * LCOMMUNITY_SIZE) + +extern void lcommunity_init (void); +extern void lcommunity_finish (void); +extern void lcommunity_free (struct lcommunity **); +extern struct lcommunity *lcommunity_parse (u_int8_t *, u_short); +extern struct lcommunity *lcommunity_dup (struct lcommunity *); +extern struct lcommunity *lcommunity_merge (struct lcommunity *, struct lcommunity *); +extern struct lcommunity *lcommunity_uniq_sort (struct lcommunity *); +extern struct lcommunity *lcommunity_intern (struct lcommunity *); +extern int lcommunity_cmp (const void *, const void *); +extern void lcommunity_unintern (struct lcommunity **); +extern unsigned int lcommunity_hash_make (void *); +extern struct hash *lcommunity_hash (void); +extern struct lcommunity *lcommunity_str2com (const char *); +extern char *lcommunity_lcom2str (struct lcommunity *, int); +extern int lcommunity_match (const struct lcommunity *, const struct lcommunity *); +extern char *lcommunity_str (struct lcommunity *); +extern int lcommunity_include (struct lcommunity *lcom, u_char *ptr); +extern void lcommunity_del_val (struct lcommunity *lcom, u_char *ptr); +#endif /* _QUAGGA_BGP_LCOMMUNITY_H */ diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c index 72c0311c17..85e32645ee 100644 --- a/bgpd/bgp_memory.c +++ b/bgpd/bgp_memory.c @@ -111,3 +111,7 @@ DEFINE_MTYPE(BGPD, ENCAP_TLV, "ENCAP TLV") DEFINE_MTYPE(BGPD, BGP_TEA_OPTIONS, "BGP TEA Options") DEFINE_MTYPE(BGPD, BGP_TEA_OPTIONS_VALUE, "BGP TEA Options Value") + +DEFINE_MTYPE(BGPD, LCOMMUNITY, "Large Community") +DEFINE_MTYPE(BGPD, LCOMMUNITY_STR, "Large Community display string") +DEFINE_MTYPE(BGPD, LCOMMUNITY_VAL, "Large Community value") diff --git a/bgpd/bgp_memory.h b/bgpd/bgp_memory.h index a4ce8b891b..341fb235d0 100644 --- a/bgpd/bgp_memory.h +++ b/bgpd/bgp_memory.h @@ -108,4 +108,7 @@ DECLARE_MTYPE(ENCAP_TLV) DECLARE_MTYPE(BGP_TEA_OPTIONS) DECLARE_MTYPE(BGP_TEA_OPTIONS_VALUE) +DECLARE_MTYPE(LCOMMUNITY) +DECLARE_MTYPE(LCOMMUNITY_STR) +DECLARE_MTYPE(LCOMMUNITY_VAL) #endif /* _QUAGGA_BGP_MEMORY_H */ diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c index 1701c70441..f564ff1691 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -38,6 +38,7 @@ #include "bgpd/bgp_aspath.h" #include "bgpd/bgp_community.h" #include "bgpd/bgp_ecommunity.h" +#include "bgpd/bgp_lcommunity.h" #include "bgpd/bgp_mpath.h" /* @@ -662,6 +663,7 @@ bgp_info_mpath_aggregate_update (struct bgp_info *new_best, u_char origin; struct community *community, *commerge; struct ecommunity *ecomm, *ecommerge; + struct lcommunity *lcomm, *lcommerge; struct attr_extra *ae; struct attr attr = { 0 }; @@ -698,6 +700,7 @@ bgp_info_mpath_aggregate_update (struct bgp_info *new_best, community = attr.community ? community_dup (attr.community) : NULL; ae = attr.extra; ecomm = (ae && ae->ecommunity) ? ecommunity_dup (ae->ecommunity) : NULL; + lcomm = (ae && ae->lcommunity) ? lcommunity_dup (ae->lcommunity) : NULL; for (mpinfo = bgp_info_mpath_first (new_best); mpinfo; mpinfo = bgp_info_mpath_next (mpinfo)) @@ -733,6 +736,17 @@ bgp_info_mpath_aggregate_update (struct bgp_info *new_best, else ecomm = ecommunity_dup (ae->ecommunity); } + if (ae && ae->lcommunity) + { + if (lcomm) + { + lcommerge = lcommunity_merge (lcomm, ae->lcommunity); + lcomm = lcommunity_uniq_sort (lcommerge); + lcommunity_free (&lcommerge); + } + else + lcomm = lcommunity_dup (ae->lcommunity); + } } attr.aspath = aspath; diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 38470a3c7e..4c95f1b8f5 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -46,6 +46,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_aspath.h" #include "bgpd/bgp_community.h" #include "bgpd/bgp_ecommunity.h" +#include "bgpd/bgp_lcommunity.h" #include "bgpd/bgp_network.h" #include "bgpd/bgp_mplsvpn.h" #include "bgpd/bgp_encap.h" diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 26c500af1b..33b7bc1251 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1,5 +1,6 @@ /* BGP routing information Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro + Copyright (C) 2016 Job Snijders This file is part of GNU Zebra. @@ -46,6 +47,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_regex.h" #include "bgpd/bgp_community.h" #include "bgpd/bgp_ecommunity.h" +#include "bgpd/bgp_lcommunity.h" #include "bgpd/bgp_clist.h" #include "bgpd/bgp_packet.h" #include "bgpd/bgp_filter.h" @@ -7059,7 +7061,12 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, } } - /* Line 6 display Originator, Cluster-id */ + /* Line 6 display Large community */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) + vty_out (vty, " Large Community: %s%s", + attr->extra->lcommunity->str, VTY_NEWLINE); + + /* Line 7 display Originator, Cluster-id */ if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) { @@ -7115,7 +7122,7 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, if (binfo->extra && binfo->extra->damp_info) bgp_damp_info_vty (vty, binfo, json_path); - /* Line 7 display Addpath IDs */ + /* Line 8 display Addpath IDs */ if (binfo->addpath_rx_id || binfo->addpath_tx_id) { if (json_paths) @@ -7170,7 +7177,7 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, } } - /* Line 8 display Uptime */ + /* Line 9 display Uptime */ tbuf = time(NULL) - (bgp_clock() - binfo->uptime); if (json_paths) { @@ -7227,6 +7234,9 @@ enum bgp_show_type bgp_show_type_community_exact, bgp_show_type_community_list, bgp_show_type_community_list_exact, + bgp_show_type_lcommunity_all, + bgp_show_type_lcommunity, + bgp_show_type_lcommunity_list, bgp_show_type_flap_statistics, bgp_show_type_flap_neighbor, bgp_show_type_dampend_paths, @@ -7416,6 +7426,32 @@ bgp_show_table (struct vty *vty, struct bgp *bgp, struct bgp_table *table, if (! community_list_exact_match (ri->attr->community, list)) continue; } + if (type == bgp_show_type_community_all) + { + if (! ri->attr->community) + continue; + } + if (type == bgp_show_type_lcommunity) + { + struct lcommunity *lcom = output_arg; + + if (! ri->attr->extra || ! ri->attr->extra->lcommunity || + ! lcommunity_match (ri->attr->extra->lcommunity, lcom)) + continue; + } + if (type == bgp_show_type_lcommunity_list) + { + struct community_list *list = output_arg; + + if (! ri->attr->extra || + ! lcommunity_list_match (ri->attr->extra->lcommunity, list)) + continue; + } + if (type == bgp_show_type_lcommunity_all) + { + if (! ri->attr->extra || ! ri->attr->extra->lcommunity) + continue; + } if (type == bgp_show_type_dampend_paths || type == bgp_show_type_damp_neighbor) { @@ -7832,6 +7868,63 @@ bgp_show_route (struct vty *vty, const char *view_name, const char *ip_str, use_json); } +static int +bgp_show_lcommunity (struct vty *vty, struct bgp *bgp, int argc, + struct cmd_token **argv, afi_t afi, safi_t safi, u_char uj) +{ + struct lcommunity *lcom; + struct buffer *b; + int i; + char *str; + int first = 0; + + b = buffer_new (1024); + for (i = 0; i < argc; i++) + { + if (first) + buffer_putc (b, ' '); + else + { + if (strmatch (argv[i]->text, "")) + { + first = 1; + buffer_putstr (b, argv[i]->arg); + } + } + } + buffer_putc (b, '\0'); + + str = buffer_getstr (b); + buffer_free (b); + + lcom = lcommunity_str2com (str); + XFREE (MTYPE_TMP, str); + if (! lcom) + { + vty_out (vty, "%% Large-community malformed: %s", VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity, lcom, uj); +} + +static int +bgp_show_lcommunity_list (struct vty *vty, struct bgp *bgp, const char *lcom, + afi_t afi, safi_t safi, u_char uj) +{ + struct community_list *list; + + list = community_list_lookup (bgp_clist, lcom, LARGE_COMMUNITY_LIST_MASTER); + if (list == NULL) + { + vty_out (vty, "%% %s is not a valid large-community-list name%s", lcom, + VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity_list, list, uj); +} + /* BGP route print out function. */ DEFUN (show_ip_bgp_ipv4, show_ip_bgp_ipv4_cmd, @@ -7844,6 +7937,8 @@ DEFUN (show_ip_bgp_ipv4, |filter-list WORD\ |community [ [exact-match]]\ |community-list <(1-500)|WORD> [exact-match]\ + |large-community [...]\ + |large-community-list <(1-500)|WORD>\ |A.B.C.D/M longer-prefixes\ |X:X::X:X/M longer-prefixes>\ ] [json]", @@ -7878,6 +7973,14 @@ DEFUN (show_ip_bgp_ipv4, "community-list number\n" "community-list name\n" "Exact match of the communities\n" + "Display routes matching the large-communities\n" + "large-community number\n" + "large-community number\n" + "large-community number\n" + "large-community number\n" + "Display routes matching the large-community-list\n" + "large-community-list number\n" + "large-community-list name\n" "IPv4 prefix\n" "Display route and more specific routes\n" "IPv6 prefix\n" @@ -7967,6 +8070,17 @@ DEFUN (show_ip_bgp_ipv4, exact_match = 1; return bgp_show_community_list (vty, vrf, clist_number_or_name, exact_match, afi, safi); } + else if (strmatch(argv[idx]->text, "large-community")) + { + if (strmatch(argv[idx+1]->text, "")) + return bgp_show_lcommunity (vty, bgp, argc, argv, afi, safi, uj); + else + return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity_all, NULL, uj); + } + else if (strmatch(argv[idx]->text, "large-community-list")) + { + return bgp_show_lcommunity_list (vty, bgp, argv[idx+1]->arg, afi, safi, uj); + } /* prefix-longer */ else if (argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV6_TKN) return bgp_show_prefix_longer (vty, vrf, argv[idx + 1]->arg, afi, safi, bgp_show_type_prefix_longer); @@ -10527,6 +10641,7 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_ip_bgp_ipv4_cmd); install_element (VIEW_NODE, &show_ip_bgp_route_cmd); install_element (VIEW_NODE, &show_ip_bgp_regexp_cmd); + install_element (VIEW_NODE, &show_ip_bgp_instance_neighbor_advertised_route_cmd); install_element (VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd); install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd); @@ -10537,6 +10652,7 @@ bgp_route_init (void) /* BGP dampening clear commands */ install_element (ENABLE_NODE, &clear_ip_bgp_dampening_cmd); install_element (ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd); + install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd); install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd); diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 4f7f51fbbb..c4b3ddee36 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -52,6 +52,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_filter.h" #include "bgpd/bgp_mplsvpn.h" #include "bgpd/bgp_ecommunity.h" +#include "bgpd/bgp_lcommunity.h" #include "bgpd/bgp_vty.h" #include "bgpd/bgp_debug.h" @@ -84,6 +85,8 @@ o Cisco route-map as-path tag : Not yet automatic-tag : (This will not be implemented by bgpd) community : Done + large-community : Done + large-comm-list : Done comm-list : Not yet dampning : Not yet default : (This will not be implemented by bgpd) @@ -847,6 +850,78 @@ struct route_map_rule_cmd route_match_community_cmd = route_match_community_free }; +/* Match function for lcommunity match. */ +static route_map_result_t +route_match_lcommunity (void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + struct community_list *list; + struct bgp_info *bgp_info; + struct rmap_community *rcom; + + if (type == RMAP_BGP) + { + bgp_info = object; + rcom = rule; + + list = community_list_lookup (bgp_clist, rcom->name, + LARGE_COMMUNITY_LIST_MASTER); + if (! list) + return RMAP_NOMATCH; + + if (bgp_info->attr->extra && + lcommunity_list_match (bgp_info->attr->extra->lcommunity, list)) + return RMAP_MATCH; + + } + return RMAP_NOMATCH; +} + +/* Compile function for community match. */ +static void * +route_match_lcommunity_compile (const char *arg) +{ + struct rmap_community *rcom; + int len; + char *p; + + rcom = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_community)); + + p = strchr (arg, ' '); + if (p) + { + len = p - arg; + rcom->name = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1); + memcpy (rcom->name, arg, len); + } + else + { + rcom->name = XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + rcom->exact = 0; + } + return rcom; +} + +/* Compile function for community match. */ +static void +route_match_lcommunity_free (void *rule) +{ + struct rmap_community *rcom = rule; + + XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom->name); + XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom); +} + +/* Route map commands for community matching. */ +struct route_map_rule_cmd route_match_lcommunity_cmd = +{ + "large-community", + route_match_lcommunity, + route_match_lcommunity_compile, + route_match_lcommunity_free +}; + + /* Match function for extcommunity match. */ static route_map_result_t route_match_ecommunity (void *rule, struct prefix *prefix, @@ -1544,6 +1619,225 @@ struct route_map_rule_cmd route_set_community_cmd = route_set_community_free, }; +/* `set community COMMUNITY' */ +struct rmap_lcom_set +{ + struct lcommunity *lcom; + int additive; + int none; +}; + + +/* For lcommunity set mechanism. */ +static route_map_result_t +route_set_lcommunity (void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + struct rmap_lcom_set *rcs; + struct bgp_info *binfo; + struct attr *attr; + struct lcommunity *new = NULL; + struct lcommunity *old; + struct lcommunity *merge; + + if (type == RMAP_BGP) + { + rcs = rule; + binfo = object; + attr = binfo->attr; + old = (attr->extra) ? attr->extra->lcommunity : NULL; + + /* "none" case. */ + if (rcs->none) + { + attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES)); + if (attr->extra) { + attr->extra->lcommunity = NULL; + } + /* See the longer comment down below. */ + if (old && old->refcnt == 0) + lcommunity_free(&old); + return RMAP_OKAY; + } + + if (rcs->additive && old) + { + merge = lcommunity_merge (lcommunity_dup (old), rcs->lcom); + + /* HACK: if the old large-community is not intern'd, + * we should free it here, or all reference to it may be lost. + * Really need to cleanup attribute caching sometime. + */ + if (old->refcnt == 0) + lcommunity_free (&old); + new = lcommunity_uniq_sort (merge); + lcommunity_free (&merge); + } + else + new = lcommunity_dup (rcs->lcom); + + /* will be interned by caller if required */ + if (attr->extra) { + attr->extra->lcommunity = new; + } + attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES); + } + + return RMAP_OKAY; +} + +/* Compile function for set community. */ +static void * +route_set_lcommunity_compile (const char *arg) +{ + struct rmap_lcom_set *rcs; + struct lcommunity *lcom = NULL; + char *sp; + int additive = 0; + int none = 0; + + if (strcmp (arg, "none") == 0) + none = 1; + else + { + sp = strstr (arg, "additive"); + + if (sp && sp > arg) + { + /* "additive" keyworkd is included. */ + additive = 1; + *(sp - 1) = '\0'; + } + + lcom = lcommunity_str2com (arg); + + if (additive) + *(sp - 1) = ' '; + + if (! lcom) + return NULL; + } + + rcs = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_com_set)); + rcs->lcom = lcom; + rcs->additive = additive; + rcs->none = none; + + return rcs; +} + +/* Free function for set lcommunity. */ +static void +route_set_lcommunity_free (void *rule) +{ + struct rmap_lcom_set *rcs = rule; + + if (rcs->lcom) { + lcommunity_free (&rcs->lcom); + } + XFREE (MTYPE_ROUTE_MAP_COMPILED, rcs); +} + +/* Set community rule structure. */ +struct route_map_rule_cmd route_set_lcommunity_cmd = +{ + "large-community", + route_set_lcommunity, + route_set_lcommunity_compile, + route_set_lcommunity_free, +}; + +/* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */ + +/* For large community set mechanism. */ +static route_map_result_t +route_set_lcommunity_delete (void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + struct community_list *list; + struct lcommunity *merge; + struct lcommunity *new; + struct lcommunity *old; + struct bgp_info *binfo; + + if (type == RMAP_BGP) + { + if (! rule) + return RMAP_OKAY; + + binfo = object; + list = community_list_lookup (bgp_clist, rule, + LARGE_COMMUNITY_LIST_MASTER); + old = ((binfo->attr->extra) ? binfo->attr->extra->lcommunity : NULL); + + if (list && old) + { + merge = lcommunity_list_match_delete (lcommunity_dup (old), list); + new = lcommunity_uniq_sort (merge); + lcommunity_free (&merge); + + /* HACK: if the old community is not intern'd, + * we should free it here, or all reference to it may be lost. + * Really need to cleanup attribute caching sometime. + */ + if (old->refcnt == 0) + lcommunity_free (&old); + + if (new->size == 0) + { + binfo->attr->extra->lcommunity = NULL; + binfo->attr->flag &= ~ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES); + lcommunity_free (&new); + } + else + { + binfo->attr->extra->lcommunity = new; + binfo->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES); + } + } + } + + return RMAP_OKAY; +} + +/* Compile function for set lcommunity. */ +static void * +route_set_lcommunity_delete_compile (const char *arg) +{ + char *p; + char *str; + int len; + + p = strchr (arg, ' '); + if (p) + { + len = p - arg; + str = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1); + memcpy (str, arg, len); + } + else + str = NULL; + + return str; +} + +/* Free function for set lcommunity. */ +static void +route_set_lcommunity_delete_free (void *rule) +{ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + +/* Set lcommunity rule structure. */ +struct route_map_rule_cmd route_set_lcommunity_delete_cmd = +{ + "large-comm-list", + route_set_lcommunity_delete, + route_set_lcommunity_delete_compile, + route_set_lcommunity_delete_free, +}; + + /* `set comm-list (<1-99>|<100-500>|WORD) delete' */ /* For community set mechanism. */ @@ -3114,7 +3408,32 @@ DEFUN (no_match_community, RMAP_EVENT_CLIST_DELETED); } +DEFUN (match_lcommunity, + match_lcommunity_cmd, + "match large-community [(1-99)|(100-500)|WORD]", + MATCH_STR + "Match BGP large community list\n" + "Large Community-list number (standard)\n" + "Large Community-list number (expanded)\n" + "Large Community-list name\n") +{ + return bgp_route_match_add (vty, "large-community", argv[2]->arg, + RMAP_EVENT_LLIST_ADDED); +} +DEFUN (no_match_lcommunity, + no_match_lcommunity_cmd, + "no match large-community [(1-99)|(100-500)|WORD]", + NO_STR + MATCH_STR + "Match BGP large community list\n" + "Large Community-list number (standard)\n" + "Large Community-list number (expanded)\n" + "Large Community-list name\n") +{ + return bgp_route_match_delete (vty, "large-community", NULL, + RMAP_EVENT_LLIST_DELETED); +} DEFUN (match_ecommunity, match_ecommunity_cmd, @@ -3547,6 +3866,86 @@ DEFUN (no_set_community_delete, "comm-list", NULL); } +DEFUN (set_lcommunity, + set_lcommunity_cmd, + "set large-community AA:BB:CC...", + SET_STR + "BGP large community attribute\n" + "Large Community number in aa:bb:cc format or additive\n") +{ + int ret; + char *str; + + str = argv_concat (argv, argc, 2); + ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "large-community", str); + XFREE (MTYPE_TMP, str); + + return ret; +} + +DEFUN (set_lcommunity_none, + set_lcommunity_none_cmd, + "set large-community none", + SET_STR + "BGP large community attribute\n" + "No large community attribute\n") +{ + return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), + "large-community", "none"); +} + +DEFUN (no_set_lcommunity, + no_set_lcommunity_cmd, + "no set large-community ", + NO_STR + SET_STR + "BGP large community attribute\n" + "No community attribute\n" + "Large community\n" + "Large community in AA:BB:CC... format or additive\n") +{ + return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), + "large-community", NULL); +} + + +DEFUN (set_lcommunity_delete, + set_lcommunity_delete_cmd, + "set large-comm-list <(1-99)|(100-500)|WORD> delete", + SET_STR + "set BGP large community list (for deletion)\n" + "Large Community-list number (standard)\n" + "Large Communitly-list number (expanded)\n" + "Large Community-list name\n" + "Delete matching large communities\n") +{ + char *str; + + str = XCALLOC (MTYPE_TMP, strlen (argv[2]->arg) + strlen (" delete") + 1); + strcpy (str, argv[2]->arg); + strcpy (str + strlen (argv[2]->arg), " delete"); + + generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), + "large-comm-list", str); + + XFREE (MTYPE_TMP, str); + return CMD_SUCCESS; +} + +DEFUN (no_set_lcommunity_delete, + no_set_lcommunity_delete_cmd, + "no set large-comm-list [<(1-99|(100-500)|word)> delete]", + NO_STR + SET_STR + "set BGP large community list (for deletion)\n" + "Large Community-list number (standard)\n" + "Large Communitly-list number (expanded)\n" + "Large Community-list name\n" + "Delete matching large communities\n") +{ + return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), + "large-comm-list", NULL); +} DEFUN (set_ecommunity_rt, set_ecommunity_rt_cmd, @@ -4002,6 +4401,7 @@ bgp_route_map_init (void) route_map_install_match (&route_match_ip_route_source_prefix_list_cmd); route_map_install_match (&route_match_aspath_cmd); route_map_install_match (&route_match_community_cmd); + route_map_install_match (&route_match_lcommunity_cmd); route_map_install_match (&route_match_ecommunity_cmd); route_map_install_match (&route_match_local_pref_cmd); route_map_install_match (&route_match_metric_cmd); @@ -4021,6 +4421,8 @@ bgp_route_map_init (void) route_map_install_set (&route_set_aggregator_as_cmd); route_map_install_set (&route_set_community_cmd); route_map_install_set (&route_set_community_delete_cmd); + route_map_install_set (&route_set_lcommunity_cmd); + route_map_install_set (&route_set_lcommunity_delete_cmd); route_map_install_set (&route_set_vpnv4_nexthop_cmd); route_map_install_set (&route_set_originator_id_cmd); route_map_install_set (&route_set_ecommunity_rt_cmd); @@ -4042,6 +4444,8 @@ bgp_route_map_init (void) install_element (RMAP_NODE, &match_community_cmd); install_element (RMAP_NODE, &match_community_exact_cmd); install_element (RMAP_NODE, &no_match_community_cmd); + install_element (RMAP_NODE, &match_lcommunity_cmd); + install_element (RMAP_NODE, &no_match_lcommunity_cmd); install_element (RMAP_NODE, &match_ecommunity_cmd); install_element (RMAP_NODE, &no_match_ecommunity_cmd); install_element (RMAP_NODE, &match_origin_cmd); @@ -4071,6 +4475,11 @@ bgp_route_map_init (void) install_element (RMAP_NODE, &no_set_community_cmd); install_element (RMAP_NODE, &set_community_delete_cmd); install_element (RMAP_NODE, &no_set_community_delete_cmd); + install_element (RMAP_NODE, &set_lcommunity_cmd); + install_element (RMAP_NODE, &set_lcommunity_none_cmd); + install_element (RMAP_NODE, &no_set_lcommunity_cmd); + install_element (RMAP_NODE, &set_lcommunity_delete_cmd); + install_element (RMAP_NODE, &no_set_lcommunity_delete_cmd); install_element (RMAP_NODE, &set_ecommunity_rt_cmd); install_element (RMAP_NODE, &no_set_ecommunity_rt_cmd); install_element (RMAP_NODE, &set_ecommunity_soo_cmd); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 6d23af03e4..0797756f65 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -41,6 +41,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_aspath.h" #include "bgpd/bgp_community.h" #include "bgpd/bgp_ecommunity.h" +#include "bgpd/bgp_lcommunity.h" #include "bgpd/bgp_damp.h" #include "bgpd/bgp_debug.h" #include "bgpd/bgp_fsm.h" @@ -3748,13 +3749,15 @@ DEFUN (no_neighbor_send_community, /* neighbor send-community extended. */ DEFUN (neighbor_send_community_type, neighbor_send_community_type_cmd, - "neighbor send-community ", + "neighbor send-community ", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Send Community attribute to this neighbor\n" "Send Standard and Extended Community attributes\n" + "Send Standard, Large and Extended Community attributes\n" "Send Extended Community attributes\n" - "Send Standard Community attributes\n") + "Send Standard Community attributes\n" + "Send Large Community attributes\n") { int idx = 0; u_int32_t flag = 0; @@ -3765,25 +3768,35 @@ DEFUN (neighbor_send_community_type, SET_FLAG (flag, PEER_FLAG_SEND_COMMUNITY); else if (argv_find (argv, argc, "extended", &idx)) SET_FLAG (flag, PEER_FLAG_SEND_EXT_COMMUNITY); + else if (argv_find (argv, argc, "large", &idx)) + SET_FLAG (flag, PEER_FLAG_SEND_LARGE_COMMUNITY); + else if (argv_find (argv, argc, "both", &idx)) + { + SET_FLAG (flag, PEER_FLAG_SEND_COMMUNITY); + SET_FLAG (flag, PEER_FLAG_SEND_EXT_COMMUNITY); + } else - { - SET_FLAG (flag, PEER_FLAG_SEND_COMMUNITY); - SET_FLAG (flag, PEER_FLAG_SEND_EXT_COMMUNITY); - } + { + SET_FLAG (flag, PEER_FLAG_SEND_COMMUNITY); + SET_FLAG (flag, PEER_FLAG_SEND_EXT_COMMUNITY); + SET_FLAG (flag, PEER_FLAG_SEND_LARGE_COMMUNITY); + } return peer_af_flag_set_vty (vty, peer, bgp_node_afi (vty), bgp_node_safi (vty), flag); } DEFUN (no_neighbor_send_community_type, no_neighbor_send_community_type_cmd, - "no neighbor send-community ", + "no neighbor send-community ", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Send Community attribute to this neighbor\n" "Send Standard and Extended Community attributes\n" + "Send Standard, Large and Extended Community attributes\n" "Send Extended Community attributes\n" - "Send Standard Community attributes\n") + "Send Standard Community attributes\n" + "Send Large Community attributes\n") { int idx_peer = 2; int idx_type = 4; @@ -3795,11 +3808,21 @@ DEFUN (no_neighbor_send_community_type, return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), bgp_node_safi (vty), PEER_FLAG_SEND_EXT_COMMUNITY); + if (strncmp (argv[idx_type]->arg, "l", 1) == 0) + return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), + bgp_node_safi (vty), + PEER_FLAG_SEND_LARGE_COMMUNITY); + if (strncmp (argv[idx_type]->arg, "b", 1) == 0) + return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), + bgp_node_safi (vty), + PEER_FLAG_SEND_COMMUNITY | + PEER_FLAG_SEND_EXT_COMMUNITY); return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), bgp_node_safi (vty), (PEER_FLAG_SEND_COMMUNITY | - PEER_FLAG_SEND_EXT_COMMUNITY)); + PEER_FLAG_SEND_EXT_COMMUNITY| + PEER_FLAG_SEND_LARGE_COMMUNITY)); } /* neighbor soft-reconfig. */ @@ -6132,6 +6155,12 @@ DEFUN (show_bgp_memory, mtype_memstr (memstrbuf, sizeof (memstrbuf), count * sizeof (struct ecommunity)), VTY_NEWLINE); + if ((count = mtype_stats_alloc (MTYPE_LCOMMUNITY))) + vty_out (vty, "%ld BGP large-community entries, using %s of memory%s", + count, + mtype_memstr (memstrbuf, sizeof (memstrbuf), + count * sizeof (struct lcommunity)), + VTY_NEWLINE); if ((count = mtype_stats_alloc (MTYPE_CLUSTER))) vty_out (vty, "%ld Cluster lists, using %s of memory%s", count, @@ -7109,12 +7138,16 @@ bgp_show_peer_afi (struct vty *vty, struct peer *p, afi_t afi, safi_t safi, if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) vty_out (vty, " MED is propagated unchanged to this neighbor%s", VTY_NEWLINE); if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) - || CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)) + || CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY) + || CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY)) { vty_out (vty, " Community attribute sent to this neighbor"); if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) - && CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)) - vty_out (vty, "(both)%s", VTY_NEWLINE); + && CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY) + && CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY)) + vty_out (vty, "(all)%s", VTY_NEWLINE); + else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY)) + vty_out (vty, "(large)%s", VTY_NEWLINE); else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)) vty_out (vty, "(extended)%s", VTY_NEWLINE); else @@ -8637,6 +8670,36 @@ DEFUN (show_ip_bgp_community_info, return CMD_SUCCESS; } +static void +lcommunity_show_all_iterator (struct hash_backet *backet, struct vty *vty) +{ + struct lcommunity *lcom; + + lcom = (struct lcommunity *) backet->data; + vty_out (vty, "[%p] (%ld) %s%s", (void *)backet, lcom->refcnt, + lcommunity_str (lcom), VTY_NEWLINE); +} + +/* Show BGP's community internal data. */ +DEFUN (show_ip_bgp_lcommunity_info, + show_ip_bgp_lcommunity_info_cmd, + "show ip bgp large-community-info", + SHOW_STR + IP_STR + BGP_STR + "List all bgp large-community information\n") +{ + vty_out (vty, "Address Refcnt Large-community%s", VTY_NEWLINE); + + hash_iterate (lcommunity_hash (), + (void (*) (struct hash_backet *, void *)) + lcommunity_show_all_iterator, + vty); + + return CMD_SUCCESS; +} + + DEFUN (show_ip_bgp_attr_info, show_ip_bgp_attr_info_cmd, "show [ip] bgp attribute-info", @@ -10738,6 +10801,8 @@ bgp_vty_init (void) /* "show [ip] bgp community" commands. */ install_element (VIEW_NODE, &show_ip_bgp_community_info_cmd); + /* "show ip bgp large-community" commands. */ + install_element (VIEW_NODE, &show_ip_bgp_lcommunity_info_cmd); /* "show [ip] bgp attribute-info" commands. */ install_element (VIEW_NODE, &show_ip_bgp_attr_info_cmd); @@ -11070,6 +11135,324 @@ DEFUN (show_ip_community_list_arg, return CMD_SUCCESS; } +/* + * Large Community code. + */ +static int +lcommunity_list_set_vty (struct vty *vty, int argc, struct cmd_token **argv, + int style, int reject_all_digit_name) +{ + int ret; + int direct; + char *str; + int idx = 0; + char *cl_name; + + direct = argv_find (argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; + + /* All digit name check. */ + idx = 0; + argv_find (argv, argc, "WORD", &idx); + argv_find (argv, argc, "(1-99)", &idx); + argv_find (argv, argc, "(100-500)", &idx); + cl_name = argv[idx]->arg; + if (reject_all_digit_name && all_digit (cl_name)) + { + vty_out (vty, "%% Community name cannot have all digits%s", VTY_NEWLINE); + return CMD_WARNING; + } + + argv_find (argv, argc, "AA:BB:CC", &idx); + argv_find (argv, argc, "LINE", &idx); + /* Concat community string argument. */ + if (idx) + str = argv_concat (argv, argc, idx); + else + str = NULL; + + ret = lcommunity_list_set (bgp_clist, cl_name, str, direct, style); + + /* Free temporary community list string allocated by + argv_concat(). */ + if (str) + XFREE (MTYPE_TMP, str); + + if (ret < 0) + { + community_list_perror (vty, ret); + return CMD_WARNING; + } + return CMD_SUCCESS; +} + +static int +lcommunity_list_unset_vty (struct vty *vty, int argc, struct cmd_token **argv, + int style) +{ + int ret; + int direct = 0; + char *str = NULL; + int idx = 0; + + argv_find (argv, argc, "permit", &idx); + argv_find (argv, argc, "deny", &idx); + + if (idx) + { + /* Check the list direct. */ + if (strncmp (argv[idx]->arg, "p", 1) == 0) + direct = COMMUNITY_PERMIT; + else + direct = COMMUNITY_DENY; + + idx = 0; + argv_find (argv, argc, "LINE", &idx); + argv_find (argv, argc, "AA:AA:NN", &idx); + /* Concat community string argument. */ + str = argv_concat (argv, argc, idx); + } + + idx = 0; + argv_find (argv, argc, "(1-99)", &idx); + argv_find (argv, argc, "(100-500)", &idx); + argv_find (argv, argc, "WORD", &idx); + + /* Unset community list. */ + ret = lcommunity_list_unset (bgp_clist, argv[idx]->arg, str, direct, style); + + /* Free temporary community list string allocated by + argv_concat(). */ + if (str) + XFREE (MTYPE_TMP, str); + + if (ret < 0) + { + community_list_perror (vty, ret); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +/* "large-community-list" keyword help string. */ +#define LCOMMUNITY_LIST_STR "Add a large community list entry\n" +#define LCOMMUNITY_VAL_STR "large community in 'aa:bb:cc' format\n" + +DEFUN (ip_lcommunity_list_standard, + ip_lcommunity_list_standard_cmd, + "ip large-community-list (1-99) [AA:BB:CC...]", + IP_STR + LCOMMUNITY_LIST_STR + "Large Community list number (standard)\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + LCOMMUNITY_VAL_STR) +{ + return lcommunity_list_set_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD, 0); +} + +DEFUN (ip_lcommunity_list_expanded, + ip_lcommunity_list_expanded_cmd, + "ip large-community-list (100-500) LINE...", + IP_STR + LCOMMUNITY_LIST_STR + "Large Community list number (expanded)\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + "An ordered list as a regular-expression\n") +{ + return lcommunity_list_set_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_EXPANDED, 0); +} + +DEFUN (ip_lcommunity_list_name_standard, + ip_lcommunity_list_name_standard_cmd, + "ip large-community-list standard WORD [AA:BB.CC...]", + IP_STR + LCOMMUNITY_LIST_STR + "Specify standard large-community-list\n" + "Large Community list name\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + LCOMMUNITY_VAL_STR) +{ + return lcommunity_list_set_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD, 1); +} + +DEFUN (ip_lcommunity_list_name_expanded, + ip_lcommunity_list_name_expanded_cmd, + "ip large-community-list expanded WORD LINE...", + IP_STR + LCOMMUNITY_LIST_STR + "Specify expanded large-community-list\n" + "Large Community list name\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + "An ordered list as a regular-expression\n") +{ + return lcommunity_list_set_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_EXPANDED, 1); +} + +DEFUN (no_ip_lcommunity_list_standard_all, + no_ip_lcommunity_list_standard_all_cmd, + "no ip large-community-list <(1-99)|(100-500)|WORD>", + NO_STR + IP_STR + LCOMMUNITY_LIST_STR + "Large Community list number (standard)\n" + "Large Community list number (expanded)\n" + "Large Community list name\n") +{ + return lcommunity_list_unset_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD); +} + +DEFUN (no_ip_lcommunity_list_name_expanded_all, + no_ip_lcommunity_list_name_expanded_all_cmd, + "no ip large-community-list expanded WORD", + NO_STR + IP_STR + LCOMMUNITY_LIST_STR + "Specify expanded large-community-list\n" + "Large Community list name\n") +{ + return lcommunity_list_unset_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_EXPANDED); +} + +DEFUN (no_ip_lcommunity_list_standard, + no_ip_lcommunity_list_standard_cmd, + "no ip large-community-list (1-99) AA:AA:NN...", + NO_STR + IP_STR + LCOMMUNITY_LIST_STR + "Large Community list number (standard)\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + LCOMMUNITY_VAL_STR) +{ + return lcommunity_list_unset_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD); +} + +DEFUN (no_ip_lcommunity_list_expanded, + no_ip_lcommunity_list_expanded_cmd, + "no ip large-community-list (100-500) LINE...", + NO_STR + IP_STR + LCOMMUNITY_LIST_STR + "Large Community list number (expanded)\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + "An ordered list as a regular-expression\n") +{ + return lcommunity_list_unset_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_EXPANDED); +} + +DEFUN (no_ip_lcommunity_list_name_standard, + no_ip_lcommunity_list_name_standard_cmd, + "no ip large-community-list standard WORD AA:AA:NN...", + NO_STR + IP_STR + LCOMMUNITY_LIST_STR + "Specify standard large-community-list\n" + "Large Community list name\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + LCOMMUNITY_VAL_STR) +{ + return lcommunity_list_unset_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD); +} + +DEFUN (no_ip_lcommunity_list_name_expanded, + no_ip_lcommunity_list_name_expanded_cmd, + "no ip large-community-list expanded WORD LINE...", + NO_STR + IP_STR + LCOMMUNITY_LIST_STR + "Specify expanded large-community-list\n" + "Large community list name\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + "An ordered list as a regular-expression\n") +{ + return lcommunity_list_unset_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_EXPANDED); +} + +static void +lcommunity_list_show (struct vty *vty, struct community_list *list) +{ + struct community_entry *entry; + + for (entry = list->head; entry; entry = entry->next) + { + if (entry == list->head) + { + if (all_digit (list->name)) + vty_out (vty, "Large community %s list %s%s", + entry->style == EXTCOMMUNITY_LIST_STANDARD ? + "standard" : "(expanded) access", + list->name, VTY_NEWLINE); + else + vty_out (vty, "Named large community %s list %s%s", + entry->style == EXTCOMMUNITY_LIST_STANDARD ? + "standard" : "expanded", + list->name, VTY_NEWLINE); + } + if (entry->any) + vty_out (vty, " %s%s", + community_direct_str (entry->direct), VTY_NEWLINE); + else + vty_out (vty, " %s %s%s", + community_direct_str (entry->direct), + entry->style == EXTCOMMUNITY_LIST_STANDARD ? + entry->u.ecom->str : entry->config, + VTY_NEWLINE); + } +} + +DEFUN (show_ip_lcommunity_list, + show_ip_lcommunity_list_cmd, + "show ip large-community-list", + SHOW_STR + IP_STR + "List large-community list\n") +{ + struct community_list *list; + struct community_list_master *cm; + + cm = community_list_master_lookup (bgp_clist, LARGE_COMMUNITY_LIST_MASTER); + if (! cm) + return CMD_SUCCESS; + + for (list = cm->num.head; list; list = list->next) + lcommunity_list_show (vty, list); + + for (list = cm->str.head; list; list = list->next) + lcommunity_list_show (vty, list); + + return CMD_SUCCESS; +} + +DEFUN (show_ip_lcommunity_list_arg, + show_ip_lcommunity_list_arg_cmd, + "show ip large-community-list <(1-500)|WORD>", + SHOW_STR + IP_STR + "List large-community list\n" + "large-community-list number\n" + "large-community-list name\n") +{ + struct community_list *list; + + list = community_list_lookup (bgp_clist, argv[3]->arg, LARGE_COMMUNITY_LIST_MASTER); + if (! list) + { + vty_out (vty, "%% Can't find extcommunity-list%s", VTY_NEWLINE); + return CMD_WARNING; + } + + lcommunity_list_show (vty, list); + + return CMD_SUCCESS; +} + /* "extcommunity-list" keyword help string. */ #define EXTCOMMUNITY_LIST_STR "Add a extended community list entry\n" #define EXTCOMMUNITY_VAL_STR "Extended community attribute in 'rt aa:nn_or_IPaddr:nn' OR 'soo aa:nn_or_IPaddr:nn' format\n" @@ -11379,6 +11762,30 @@ community_list_config_write (struct vty *vty) community_list_config_str (entry), VTY_NEWLINE); write++; } + + + /* lcommunity-list. */ + cm = community_list_master_lookup (bgp_clist, LARGE_COMMUNITY_LIST_MASTER); + + for (list = cm->num.head; list; list = list->next) + for (entry = list->head; entry; entry = entry->next) + { + vty_out (vty, "ip large-community-list %s %s %s%s", + list->name, community_direct_str (entry->direct), + community_list_config_str (entry), VTY_NEWLINE); + write++; + } + for (list = cm->str.head; list; list = list->next) + for (entry = list->head; entry; entry = entry->next) + { + vty_out (vty, "ip large-community-list %s %s %s %s%s", + entry->style == LARGE_COMMUNITY_LIST_STANDARD + ? "standard" : "expanded", + list->name, community_direct_str (entry->direct), + community_list_config_str (entry), VTY_NEWLINE); + write++; + } + return write; } @@ -11409,4 +11816,18 @@ community_list_vty (void) install_element (CONFIG_NODE, &no_ip_extcommunity_list_expanded_all_cmd); install_element (VIEW_NODE, &show_ip_extcommunity_list_cmd); install_element (VIEW_NODE, &show_ip_extcommunity_list_arg_cmd); + + /* Large Community List */ + install_element (CONFIG_NODE, &ip_lcommunity_list_standard_cmd); + install_element (CONFIG_NODE, &ip_lcommunity_list_expanded_cmd); + install_element (CONFIG_NODE, &ip_lcommunity_list_name_standard_cmd); + install_element (CONFIG_NODE, &ip_lcommunity_list_name_expanded_cmd); + install_element (CONFIG_NODE, &no_ip_lcommunity_list_standard_all_cmd); + install_element (CONFIG_NODE, &no_ip_lcommunity_list_name_expanded_all_cmd); + install_element (CONFIG_NODE, &no_ip_lcommunity_list_standard_cmd); + install_element (CONFIG_NODE, &no_ip_lcommunity_list_expanded_cmd); + install_element (CONFIG_NODE, &no_ip_lcommunity_list_name_standard_cmd); + install_element (CONFIG_NODE, &no_ip_lcommunity_list_name_expanded_cmd); + install_element (VIEW_NODE, &show_ip_lcommunity_list_cmd); + install_element (VIEW_NODE, &show_ip_lcommunity_list_arg_cmd); } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 5457822f3b..968eebd299 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -902,6 +902,7 @@ peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi) { SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY); SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY); + SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY); } /* Clear neighbor default_originate_rmap */ @@ -1206,6 +1207,7 @@ peer_new (struct bgp *bgp) { SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY); SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY); + SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY); } peer->orf_plist[afi][safi] = NULL; } @@ -3702,6 +3704,7 @@ static const struct peer_flag_action peer_af_flag_action_list[] = { { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out }, { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out }, + { PEER_FLAG_SEND_LARGE_COMMUNITY, 1, peer_change_reset_out }, { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out }, { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset }, { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset }, @@ -6982,10 +6985,17 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, if (bgp_option_check (BGP_OPT_CONFIG_CISCO)) { if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) - && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) + && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY) + && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY)) { afi_header_vty_out (vty, afi, safi, write, - " neighbor %s send-community both%s", + " neighbor %s send-community all%s", + addr, VTY_NEWLINE); + } + else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY)) + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s send-community large%s", addr, VTY_NEWLINE); } else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) @@ -7006,10 +7016,19 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) && (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)) && !peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY) && - (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))) + (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) && + !peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY) && + (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY))) { afi_header_vty_out (vty, afi, safi, write, - " no neighbor %s send-community both%s", + " no neighbor %s send-community all%s", + addr, VTY_NEWLINE); + } + else if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY) && + (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY))) + { + afi_header_vty_out (vty, afi, safi, write, + " no neighbor %s send-community large%s", addr, VTY_NEWLINE); } else if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY) && diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 2718805130..814bb506c8 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -705,6 +705,7 @@ struct peer #define PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS (1 << 23) /* addpath-tx-bestpath-per-AS */ #define PEER_FLAG_WEIGHT (1 << 24) /* weight */ #define PEER_FLAG_ALLOWAS_IN_ORIGIN (1 << 25) /* allowas-in origin */ +#define PEER_FLAG_SEND_LARGE_COMMUNITY (1 << 26) /* Send large Communities */ /* MD5 password */ char *password; @@ -963,6 +964,7 @@ struct bgp_nlri #define BGP_ATTR_AS4_AGGREGATOR 18 #define BGP_ATTR_AS_PATHLIMIT 21 #define BGP_ATTR_ENCAP 23 +#define BGP_ATTR_LARGE_COMMUNITIES 32 #if ENABLE_BGP_VNC #define BGP_ATTR_VNC 255 #endif diff --git a/lib/routemap.c b/lib/routemap.c index 74bae1fd76..70f3069a36 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -710,6 +710,7 @@ enum route_map_dep_type ROUTE_MAP_DEP_RMAP = 1, ROUTE_MAP_DEP_CLIST, ROUTE_MAP_DEP_ECLIST, + ROUTE_MAP_DEP_LCLIST, ROUTE_MAP_DEP_PLIST, ROUTE_MAP_DEP_ASPATH, ROUTE_MAP_DEP_FILTER, @@ -1819,6 +1820,7 @@ route_map_dep_update (struct hash *dephash, const char *dep_name, case RMAP_EVENT_CLIST_ADDED: case RMAP_EVENT_ECLIST_ADDED: case RMAP_EVENT_ASLIST_ADDED: + case RMAP_EVENT_LLIST_ADDED: case RMAP_EVENT_CALL_ADDED: case RMAP_EVENT_FILTER_ADDED: if (rmap_debug) @@ -1840,6 +1842,7 @@ route_map_dep_update (struct hash *dephash, const char *dep_name, case RMAP_EVENT_CLIST_DELETED: case RMAP_EVENT_ECLIST_DELETED: case RMAP_EVENT_ASLIST_DELETED: + case RMAP_EVENT_LLIST_DELETED: case RMAP_EVENT_CALL_DELETED: case RMAP_EVENT_FILTER_DELETED: if (rmap_debug) @@ -1902,6 +1905,10 @@ route_map_get_dep_hash (route_map_event_t event) case RMAP_EVENT_ASLIST_DELETED: upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_ASPATH]; break; + case RMAP_EVENT_LLIST_ADDED: + case RMAP_EVENT_LLIST_DELETED: + upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_LCLIST]; + break; case RMAP_EVENT_CALL_ADDED: case RMAP_EVENT_CALL_DELETED: upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_RMAP]; diff --git a/lib/routemap.h b/lib/routemap.h index b52f7289b0..b378c64eae 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -84,6 +84,8 @@ typedef enum RMAP_EVENT_CLIST_DELETED, RMAP_EVENT_ECLIST_ADDED, RMAP_EVENT_ECLIST_DELETED, + RMAP_EVENT_LLIST_ADDED, + RMAP_EVENT_LLIST_DELETED, RMAP_EVENT_ASLIST_ADDED, RMAP_EVENT_ASLIST_DELETED, RMAP_EVENT_FILTER_ADDED, From fcd6282c55a4186a0c0e9dd57ca37992d1d0b025 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 19 Jan 2017 08:49:12 -0500 Subject: [PATCH 383/444] 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 384/444] 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 385/444] 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 386/444] 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 387/444] 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 From 52951b630a4f85db81f598d2bc759c6387ff2801 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 20 Jan 2017 10:43:08 -0500 Subject: [PATCH 388/444] bgpd: Fix cli for large-communities The original commit for large communities broke 'show ip bgp' and 'show bgp ipv4 unicast' and their ilk. This commit fixes this as well as some vtysh parse errors identified. Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 120 ++++++++++++++++++++++++++++++++++++-------- bgpd/bgp_routemap.c | 24 ++++++--- bgpd/bgp_vty.c | 32 +++++++++++- 3 files changed, 146 insertions(+), 30 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 33b7bc1251..330e7ed52e 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -7925,6 +7925,101 @@ bgp_show_lcommunity_list (struct vty *vty, struct bgp *bgp, const char *lcom, return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity_list, list, uj); } +DEFUN (show_ip_bgp_large_community_list, + show_ip_bgp_large_community_list_cmd, + "show [ip] bgp [ WORD] [ []] large-community-list <(1-500)|WORD> [json]", + SHOW_STR + IP_STR + BGP_STR + BGP_INSTANCE_HELP_STR + "Address Family\n" + "Address Family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display routes matching the large-community-list\n" + "large-community-list number\n" + "large-community-list name\n" + JSON_STR) +{ + char *vrf = NULL; + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; + int idx = 0; + + if (argv_find (argv, argc, "ip", &idx)) + afi = AFI_IP; + if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) + vrf = argv[++idx]->arg; + if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx)) + { + afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; + if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx)) + safi = bgp_vty_safi_from_arg (argv[idx]->text); + } + + int uj = use_json (argc, argv); + + struct bgp *bgp = bgp_lookup_by_name (vrf); + if (bgp == NULL) + { + vty_out (vty, "Can't find BGP instance %s%s", vrf, VTY_NEWLINE); + return CMD_WARNING; + } + + argv_find (argv, argc, "large-community-list", &idx); + return bgp_show_lcommunity_list (vty, bgp, argv[idx+1]->arg, afi, safi, uj); +} +DEFUN (show_ip_bgp_large_community, + show_ip_bgp_large_community_cmd, + "show [ip] bgp [ WORD] [ []] large-community [AA:BB:CC] [json]", + SHOW_STR + IP_STR + BGP_STR + BGP_INSTANCE_HELP_STR + "Address Family\n" + "Address Family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Display routes matching the large-communities\n" + "List of large-community numbers\n" + JSON_STR) +{ + char *vrf = NULL; + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; + int idx = 0; + + if (argv_find (argv, argc, "ip", &idx)) + afi = AFI_IP; + if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) + vrf = argv[++idx]->arg; + if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx)) + { + afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; + if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx)) + safi = bgp_vty_safi_from_arg (argv[idx]->text); + } + + int uj = use_json (argc, argv); + + struct bgp *bgp = bgp_lookup_by_name (vrf); + if (bgp == NULL) + { + vty_out (vty, "Can't find BGP instance %s%s", vrf, VTY_NEWLINE); + return CMD_WARNING; + } + + argv_find (argv, argc, "large-community", &idx); + if (strmatch(argv[idx+1]->text, "AA:BB:CC")) + return bgp_show_lcommunity (vty, bgp, argc, argv, afi, safi, uj); + else + return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity_all, NULL, uj); +} + /* BGP route print out function. */ DEFUN (show_ip_bgp_ipv4, show_ip_bgp_ipv4_cmd, @@ -7937,8 +8032,6 @@ DEFUN (show_ip_bgp_ipv4, |filter-list WORD\ |community [ [exact-match]]\ |community-list <(1-500)|WORD> [exact-match]\ - |large-community [...]\ - |large-community-list <(1-500)|WORD>\ |A.B.C.D/M longer-prefixes\ |X:X::X:X/M longer-prefixes>\ ] [json]", @@ -7973,14 +8066,6 @@ DEFUN (show_ip_bgp_ipv4, "community-list number\n" "community-list name\n" "Exact match of the communities\n" - "Display routes matching the large-communities\n" - "large-community number\n" - "large-community number\n" - "large-community number\n" - "large-community number\n" - "Display routes matching the large-community-list\n" - "large-community-list number\n" - "large-community-list name\n" "IPv4 prefix\n" "Display route and more specific routes\n" "IPv6 prefix\n" @@ -8070,17 +8155,6 @@ DEFUN (show_ip_bgp_ipv4, exact_match = 1; return bgp_show_community_list (vty, vrf, clist_number_or_name, exact_match, afi, safi); } - else if (strmatch(argv[idx]->text, "large-community")) - { - if (strmatch(argv[idx+1]->text, "")) - return bgp_show_lcommunity (vty, bgp, argc, argv, afi, safi, uj); - else - return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity_all, NULL, uj); - } - else if (strmatch(argv[idx]->text, "large-community-list")) - { - return bgp_show_lcommunity_list (vty, bgp, argv[idx+1]->arg, afi, safi, uj); - } /* prefix-longer */ else if (argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV6_TKN) return bgp_show_prefix_longer (vty, vrf, argv[idx + 1]->arg, afi, safi, bgp_show_type_prefix_longer); @@ -10720,6 +10794,10 @@ bgp_route_init (void) /* IPv4 Multicast Mode */ install_element (BGP_IPV4M_NODE, &bgp_damp_set_cmd); install_element (BGP_IPV4M_NODE, &bgp_damp_unset_cmd); + + /* Large Communities */ + install_element (VIEW_NODE, &show_ip_bgp_large_community_list_cmd); + install_element (VIEW_NODE, &show_ip_bgp_large_community_cmd); } void diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index c4b3ddee36..693a807c89 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -3410,7 +3410,7 @@ DEFUN (no_match_community, DEFUN (match_lcommunity, match_lcommunity_cmd, - "match large-community [(1-99)|(100-500)|WORD]", + "match large-community [<(1-99)|(100-500)|WORD>]", MATCH_STR "Match BGP large community list\n" "Large Community-list number (standard)\n" @@ -3423,7 +3423,7 @@ DEFUN (match_lcommunity, DEFUN (no_match_lcommunity, no_match_lcommunity_cmd, - "no match large-community [(1-99)|(100-500)|WORD]", + "no match large-community [<(1-99)|(100-500)|WORD>]", NO_STR MATCH_STR "Match BGP large community list\n" @@ -3896,18 +3896,27 @@ DEFUN (set_lcommunity_none, DEFUN (no_set_lcommunity, no_set_lcommunity_cmd, - "no set large-community ", + "no set large-community none", NO_STR SET_STR "BGP large community attribute\n" - "No community attribute\n" - "Large community\n" - "Large community in AA:BB:CC... format or additive\n") + "No community attribute\n") { return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), "large-community", NULL); } +DEFUN (no_set_lcommunity1, + no_set_lcommunity1_cmd, + "no set large-community AA:BB:CC...", + NO_STR + SET_STR + "BGP large community attribute\n" + "Large community in AA:BB:CC... format or additive\n") +{ + return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), + "large-community", NULL); +} DEFUN (set_lcommunity_delete, set_lcommunity_delete_cmd, @@ -3934,7 +3943,7 @@ DEFUN (set_lcommunity_delete, DEFUN (no_set_lcommunity_delete, no_set_lcommunity_delete_cmd, - "no set large-comm-list [<(1-99|(100-500)|word)> delete]", + "no set large-comm-list <(1-99|(100-500)|WORD)> [delete]", NO_STR SET_STR "set BGP large community list (for deletion)\n" @@ -4478,6 +4487,7 @@ bgp_route_map_init (void) install_element (RMAP_NODE, &set_lcommunity_cmd); install_element (RMAP_NODE, &set_lcommunity_none_cmd); install_element (RMAP_NODE, &no_set_lcommunity_cmd); + install_element (RMAP_NODE, &no_set_lcommunity1_cmd); install_element (RMAP_NODE, &set_lcommunity_delete_cmd); install_element (RMAP_NODE, &no_set_lcommunity_delete_cmd); install_element (RMAP_NODE, &set_ecommunity_rt_cmd); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 0797756f65..b3eaaaf111 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -11240,7 +11240,20 @@ lcommunity_list_unset_vty (struct vty *vty, int argc, struct cmd_token **argv, DEFUN (ip_lcommunity_list_standard, ip_lcommunity_list_standard_cmd, - "ip large-community-list (1-99) [AA:BB:CC...]", + "ip large-community-list (1-99) ", + IP_STR + LCOMMUNITY_LIST_STR + "Large Community list number (standard)\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + LCOMMUNITY_VAL_STR) +{ + return lcommunity_list_set_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD, 0); +} + +DEFUN (ip_lcommunity_list_standard1, + ip_lcommunity_list_standard1_cmd, + "ip large-community-list (1-99) AA:BB:CC...", IP_STR LCOMMUNITY_LIST_STR "Large Community list number (standard)\n" @@ -11266,7 +11279,20 @@ DEFUN (ip_lcommunity_list_expanded, DEFUN (ip_lcommunity_list_name_standard, ip_lcommunity_list_name_standard_cmd, - "ip large-community-list standard WORD [AA:BB.CC...]", + "ip large-community-list standard WORD ", + IP_STR + LCOMMUNITY_LIST_STR + "Specify standard large-community-list\n" + "Large Community list name\n" + "Specify large community to reject\n" + "Specify large community to accept\n") +{ + return lcommunity_list_set_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD, 1); +} + +DEFUN (ip_lcommunity_list_name_standard1, + ip_lcommunity_list_name_standard1_cmd, + "ip large-community-list standard WORD AA:BB:CC...", IP_STR LCOMMUNITY_LIST_STR "Specify standard large-community-list\n" @@ -11819,8 +11845,10 @@ community_list_vty (void) /* Large Community List */ install_element (CONFIG_NODE, &ip_lcommunity_list_standard_cmd); + install_element (CONFIG_NODE, &ip_lcommunity_list_standard1_cmd); install_element (CONFIG_NODE, &ip_lcommunity_list_expanded_cmd); install_element (CONFIG_NODE, &ip_lcommunity_list_name_standard_cmd); + install_element (CONFIG_NODE, &ip_lcommunity_list_name_standard1_cmd); install_element (CONFIG_NODE, &ip_lcommunity_list_name_expanded_cmd); install_element (CONFIG_NODE, &no_ip_lcommunity_list_standard_all_cmd); install_element (CONFIG_NODE, &no_ip_lcommunity_list_name_expanded_all_cmd); From cedb5a712431fcb6b1c2eb80d01dc3e0b9ea19f9 Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Sun, 15 Jan 2017 16:43:20 -0500 Subject: [PATCH 389/444] bgpd rfapi: fix issue where advertised prefixes were not being disambiguated by RD Signed-off-by: Lou Berger --- bgpd/rfapi/rfapi.c | 2 +- bgpd/rfapi/rfapi_ap.c | 60 +++++++++++++++++--------------------- bgpd/rfapi/rfapi_ap.h | 1 + bgpd/rfapi/rfapi_private.h | 19 ------------ bgpd/rfapi/rfapi_rib.c | 18 +++++++++++- bgpd/rfapi/rfapi_rib.h | 33 +++++++++++++++++++++ bgpd/rfapi/rfapi_vty.c | 27 +++++++++-------- 7 files changed, 92 insertions(+), 68 deletions(-) diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c index 61da18a308..6353f7dacf 100644 --- a/bgpd/rfapi/rfapi.c +++ b/bgpd/rfapi/rfapi.c @@ -2777,7 +2777,7 @@ rfapi_register ( NULL, action == RFAPI_REGISTER_KILL); - if (0 == rfapiApDelete (bgp, rfd, &p, pfx_mac, &adv_tunnel)) + if (0 == rfapiApDelete (bgp, rfd, &p, pfx_mac, &prd, &adv_tunnel)) { if (adv_tunnel) rfapiTunnelRouteAnnounce (bgp, rfd, &rfd->max_prefix_lifetime); diff --git a/bgpd/rfapi/rfapi_ap.c b/bgpd/rfapi/rfapi_ap.c index 4b8eb9511b..4c415504fa 100644 --- a/bgpd/rfapi/rfapi_ap.c +++ b/bgpd/rfapi/rfapi_ap.c @@ -103,12 +103,11 @@ sl_adb_lifetime_cmp (void *adb1, void *adb2) return 0; } - void rfapiApInit (struct rfapi_advertised_prefixes *ap) { - ap->ipN_by_prefix = skiplist_new (0, vnc_prefix_cmp, NULL); - ap->ip0_by_ether = skiplist_new (0, vnc_prefix_cmp, NULL); + ap->ipN_by_prefix = skiplist_new (0, rfapi_rib_key_cmp, NULL); + ap->ip0_by_ether = skiplist_new (0, rfapi_rib_key_cmp, NULL); ap->by_lifetime = skiplist_new (0, sl_adb_lifetime_cmp, NULL); } @@ -192,7 +191,7 @@ rfapiApReadvertiseAll (struct bgp *bgp, struct rfapi_descriptor *rfd) * TBD this is not quite right. When pfx_ip is 0/32 or 0/128, * we need to substitute the VN address as the prefix */ - add_vnc_route (rfd, bgp, SAFI_MPLS_VPN, &adb->prefix_ip, &prd, /* RD to use (0 for ENCAP) */ + add_vnc_route (rfd, bgp, SAFI_MPLS_VPN, &adb->u.s.prefix_ip, &prd, /* RD to use (0 for ENCAP) */ &rfd->vn_addr, /* nexthop */ &local_pref, &adb->lifetime, NULL, NULL, /* struct rfapi_un_option */ NULL, /* struct rfapi_vn_option */ @@ -221,11 +220,11 @@ rfapiApWithdrawAll (struct bgp *bgp, struct rfapi_descriptor *rfd) struct prefix pfx_vn_buf; struct prefix *pfx_ip; - if (!(RFAPI_0_PREFIX (&adb->prefix_ip) && - RFAPI_HOST_PREFIX (&adb->prefix_ip))) + if (!(RFAPI_0_PREFIX (&adb->u.s.prefix_ip) && + RFAPI_HOST_PREFIX (&adb->u.s.prefix_ip))) { - pfx_ip = &adb->prefix_ip; + pfx_ip = &adb->u.s.prefix_ip; } else @@ -247,7 +246,7 @@ rfapiApWithdrawAll (struct bgp *bgp, struct rfapi_descriptor *rfd) } } - del_vnc_route (rfd, rfd->peer, bgp, SAFI_MPLS_VPN, pfx_ip ? pfx_ip : &pfx_vn_buf, &adb->prd, /* RD to use (0 for ENCAP) */ + del_vnc_route (rfd, rfd->peer, bgp, SAFI_MPLS_VPN, pfx_ip ? pfx_ip : &pfx_vn_buf, &adb->u.s.prd, /* RD to use (0 for ENCAP) */ ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, NULL, 0); } } @@ -404,19 +403,19 @@ rfapiApAdjustLifetimeStats ( { void *cursor; - struct prefix *prefix; - struct rfapi_adb *adb; + struct rfapi_rib_key rk; + struct rfapi_adb *adb; int rc; vnc_zlog_debug_verbose ("%s: walking to find new min/max", __func__); cursor = NULL; for (rc = skiplist_next (rfd->advertised.ipN_by_prefix, - (void **) &prefix, (void **) &adb, + (void **) &rk, (void **) &adb, &cursor); !rc; rc = skiplist_next (rfd->advertised.ipN_by_prefix, - (void **) &prefix, (void **) &adb, &cursor)) + (void **) &rk, (void **) &adb, &cursor)) { uint32_t lt = adb->lifetime; @@ -428,10 +427,10 @@ rfapiApAdjustLifetimeStats ( } cursor = NULL; for (rc = skiplist_next (rfd->advertised.ip0_by_ether, - (void **) &prefix, (void **) &adb, + (void **) &rk, (void **) &adb, &cursor); !rc; rc = - skiplist_next (rfd->advertised.ip0_by_ether, (void **) &prefix, + skiplist_next (rfd->advertised.ip0_by_ether, (void **) &rk, (void **) &adb, &cursor)) { @@ -483,14 +482,15 @@ rfapiApAdd ( struct rfapi_adb *adb; uint32_t old_lifetime = 0; int use_ip0 = 0; + struct rfapi_rib_key rk; + rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk); if (RFAPI_0_PREFIX (pfx_ip) && RFAPI_HOST_PREFIX (pfx_ip)) { use_ip0 = 1; assert (pfx_eth); - rc = - skiplist_search (rfd->advertised.ip0_by_ether, pfx_eth, + skiplist_search (rfd->advertised.ip0_by_ether, &rk, (void **) &adb); } @@ -499,7 +499,7 @@ rfapiApAdd ( /* find prefix in advertised prefixes list */ rc = - skiplist_search (rfd->advertised.ipN_by_prefix, pfx_ip, + skiplist_search (rfd->advertised.ipN_by_prefix, &rk, (void **) &adb); } @@ -510,19 +510,17 @@ rfapiApAdd ( adb = XCALLOC (MTYPE_RFAPI_ADB, sizeof (struct rfapi_adb)); assert (adb); adb->lifetime = lifetime; - adb->prefix_ip = *pfx_ip; - if (pfx_eth) - adb->prefix_eth = *pfx_eth; + adb->u.key = rk; if (use_ip0) { assert (pfx_eth); - skiplist_insert (rfd->advertised.ip0_by_ether, &adb->prefix_eth, + skiplist_insert (rfd->advertised.ip0_by_ether, &adb->u.key, adb); } else { - skiplist_insert (rfd->advertised.ipN_by_prefix, &adb->prefix_ip, + skiplist_insert (rfd->advertised.ipN_by_prefix, &adb->u.key, adb); } @@ -537,19 +535,12 @@ rfapiApAdd ( adb->lifetime = lifetime; assert (!skiplist_insert (rfd->advertised.by_lifetime, adb, adb)); } - - if (!use_ip0 && pfx_eth && prefix_cmp (&adb->prefix_eth, pfx_eth)) - { - /* mac address changed */ - adb->prefix_eth = *pfx_eth; - } } adb->cost = cost; if (l2o) adb->l2o = *l2o; else memset (&adb->l2o, 0, sizeof (struct rfapi_l2address_option)); - adb->prd = *prd; if (rfapiApAdjustLifetimeStats (rfd, (rc ? NULL : &old_lifetime), &lifetime)) @@ -568,16 +559,19 @@ rfapiApDelete ( struct rfapi_descriptor *rfd, struct prefix *pfx_ip, struct prefix *pfx_eth, + struct prefix_rd *prd, int *advertise_tunnel) /* out */ { int rc; struct rfapi_adb *adb; uint32_t old_lifetime; int use_ip0 = 0; + struct rfapi_rib_key rk; if (advertise_tunnel) *advertise_tunnel = 0; + rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk); /* find prefix in advertised prefixes list */ if (RFAPI_0_PREFIX (pfx_ip) && RFAPI_HOST_PREFIX (pfx_ip)) { @@ -585,7 +579,7 @@ rfapiApDelete ( assert (pfx_eth); rc = - skiplist_search (rfd->advertised.ip0_by_ether, pfx_eth, + skiplist_search (rfd->advertised.ip0_by_ether, &rk, (void **) &adb); } @@ -594,7 +588,7 @@ rfapiApDelete ( /* find prefix in advertised prefixes list */ rc = - skiplist_search (rfd->advertised.ipN_by_prefix, pfx_ip, + skiplist_search (rfd->advertised.ipN_by_prefix, &rk, (void **) &adb); } @@ -607,11 +601,11 @@ rfapiApDelete ( if (use_ip0) { - rc = skiplist_delete (rfd->advertised.ip0_by_ether, pfx_eth, NULL); + rc = skiplist_delete (rfd->advertised.ip0_by_ether, &rk, NULL); } else { - rc = skiplist_delete (rfd->advertised.ipN_by_prefix, pfx_ip, NULL); + rc = skiplist_delete (rfd->advertised.ipN_by_prefix, &rk, NULL); } assert (!rc); diff --git a/bgpd/rfapi/rfapi_ap.h b/bgpd/rfapi/rfapi_ap.h index f2805f49cb..8a59f05274 100644 --- a/bgpd/rfapi/rfapi_ap.h +++ b/bgpd/rfapi/rfapi_ap.h @@ -93,6 +93,7 @@ rfapiApDelete ( struct rfapi_descriptor *rfd, struct prefix *pfx_ip, struct prefix *pfx_eth, + struct prefix_rd *prd, int *advertise_tunnel); /* out */ diff --git a/bgpd/rfapi/rfapi_private.h b/bgpd/rfapi/rfapi_private.h index 33390c4f55..00f90e35fc 100644 --- a/bgpd/rfapi/rfapi_private.h +++ b/bgpd/rfapi/rfapi_private.h @@ -34,21 +34,6 @@ #include "rfapi.h" -/* - * RFAPI Advertisement Data Block - * - * Holds NVE prefix advertisement information - */ -struct rfapi_adb -{ - struct prefix prefix_ip; - struct prefix prefix_eth; /* now redundant with l2o */ - struct prefix_rd prd; - uint32_t lifetime; - uint8_t cost; - struct rfapi_l2address_option l2o; -}; - /* * Lists of rfapi_adb. Each rfapi_adb is referenced twice: * @@ -62,7 +47,6 @@ struct rfapi_advertised_prefixes struct skiplist *by_lifetime; /* all */ }; - struct rfapi_descriptor { struct route_node *un_node; /* backref to un table */ @@ -378,9 +362,6 @@ rfp_cost_to_localpref (uint8_t cost); extern int rfapi_set_autord_from_vn (struct prefix_rd *rd, struct rfapi_ip_addr *vn); -extern void -rfapiAdbFree (struct rfapi_adb *adb); - extern struct rfapi_nexthop * rfapi_nexthop_new (struct rfapi_nexthop *copyme); diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c index 6aae35e635..3a4a159215 100644 --- a/bgpd/rfapi/rfapi_rib.c +++ b/bgpd/rfapi/rfapi_rib.c @@ -405,10 +405,26 @@ rfapiRibStartTimer ( assert (ri->timer); } +extern void +rfapi_rib_key_init (struct prefix *prefix, /* may be NULL */ + struct prefix_rd *rd, /* may be NULL */ + struct prefix *aux, /* may be NULL */ + struct rfapi_rib_key *rk) + +{ + memset((void *)rk, 0, sizeof(struct rfapi_rib_key)); + if (prefix) + rk->vn = *prefix; + if (rd) + rk->rd = *rd; + if (aux) + rk->aux_prefix = *aux; +} + /* * Compares two s */ -static int +int rfapi_rib_key_cmp (void *k1, void *k2) { struct rfapi_rib_key *a = (struct rfapi_rib_key *) k1; diff --git a/bgpd/rfapi/rfapi_rib.h b/bgpd/rfapi/rfapi_rib.h index 2a111946f7..74331a28d0 100644 --- a/bgpd/rfapi/rfapi_rib.h +++ b/bgpd/rfapi/rfapi_rib.h @@ -45,6 +45,27 @@ struct rfapi_rib_key */ struct prefix aux_prefix; }; +#include "rfapi.h" + +/* + * RFAPI Advertisement Data Block + * + * Holds NVE prefix advertisement information + */ +struct rfapi_adb +{ + union { + struct { + struct prefix prefix_ip; + struct prefix_rd prd; + struct prefix prefix_eth; + } s; /* mainly for legacy use */ + struct rfapi_rib_key key; + } u; + uint32_t lifetime; + uint8_t cost; + struct rfapi_l2address_option l2o; +}; struct rfapi_info { @@ -151,4 +172,16 @@ rfapiRibCheckCounts ( #define RFAPI_RIB_CHECK_COUNTS(checkstats, offset) #endif +extern void +rfapi_rib_key_init (struct prefix *prefix, /* may be NULL */ + struct prefix_rd *rd, /* may be NULL */ + struct prefix *aux, /* may be NULL */ + struct rfapi_rib_key *rk); + +extern int +rfapi_rib_key_cmp (void *k1, void *k2); + +extern void +rfapiAdbFree (struct rfapi_adb *adb); + #endif /* QUAGGA_HGP_RFAPI_RIB_H */ diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index 3e179b7f72..ed3155307d 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -1846,14 +1846,14 @@ rfapiPrintDescriptor (struct vty *vty, struct rfapi_descriptor *rfd) { /* group like family prefixes together in output */ - if (family != adb->prefix_ip.family) + if (family != adb->u.s.prefix_ip.family) continue; - prefix2str (&adb->prefix_ip, buf, BUFSIZ); + prefix2str (&adb->u.s.prefix_ip, buf, BUFSIZ); buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ vty_out (vty, " Adv Pfx: %s%s", buf, HVTY_NEWLINE); - rfapiPrintAdvertisedInfo (vty, rfd, SAFI_MPLS_VPN, &adb->prefix_ip); + rfapiPrintAdvertisedInfo (vty, rfd, SAFI_MPLS_VPN, &adb->u.s.prefix_ip); } } for (rc = @@ -1864,14 +1864,14 @@ rfapiPrintDescriptor (struct vty *vty, struct rfapi_descriptor *rfd) &cursor)) { - prefix2str (&adb->prefix_eth, buf, BUFSIZ); + prefix2str (&adb->u.s.prefix_eth, buf, BUFSIZ); buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ vty_out (vty, " Adv Pfx: %s%s", buf, HVTY_NEWLINE); /* TBD update the following function to print ethernet info */ /* Also need to pass/use rd */ - rfapiPrintAdvertisedInfo (vty, rfd, SAFI_MPLS_VPN, &adb->prefix_ip); + rfapiPrintAdvertisedInfo (vty, rfd, SAFI_MPLS_VPN, &adb->u.s.prefix_ip); } vty_out (vty, "%s", HVTY_NEWLINE); } @@ -3375,7 +3375,7 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) if (pPrefix) { - if (!prefix_same (pPrefix, &adb->prefix_ip)) + if (!prefix_same (pPrefix, &adb->u.s.prefix_ip)) { #if DEBUG_L2_EXTRA vnc_zlog_debug_verbose ("%s: adb=%p, prefix doesn't match, skipping", @@ -3388,7 +3388,7 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) { if (memcmp (cda->l2o.o.macaddr.octet, - adb->prefix_eth.u.prefix_eth.octet, ETHER_ADDR_LEN)) + adb->u.s.prefix_eth.u.prefix_eth.octet, ETHER_ADDR_LEN)) { #if DEBUG_L2_EXTRA vnc_zlog_debug_verbose ("%s: adb=%p, macaddr doesn't match, skipping", @@ -3430,24 +3430,23 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) this_advertisement_prefix_count = 1; - rfapiQprefix2Rprefix (&adb->prefix_ip, &rp); + rfapiQprefix2Rprefix (&adb->u.s.prefix_ip, &rp); /* if mac addr present in advert, make l2o vn option */ - if (adb->prefix_eth.family == AF_ETHERNET) + if (adb->u.s.prefix_eth.family == AF_ETHERNET) { - memset (&vn1, 0, sizeof (vn1)); memset (&vn2, 0, sizeof (vn2)); vn1.type = RFAPI_VN_OPTION_TYPE_L2ADDR; - vn1.v.l2addr.macaddr = adb->prefix_eth.u.prefix_eth; + vn1.v.l2addr.macaddr = adb->u.s.prefix_eth.u.prefix_eth; /* * use saved RD value instead of trying to invert * complex L2-style RD computation in rfapi_register() */ vn2.type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD; - vn2.v.internal_rd = adb->prd; + vn2.v.internal_rd = adb->u.s.prd; vn1.next = &vn2; @@ -3499,7 +3498,7 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) if (CHECK_FLAG (cda->l2o.flags, RFAPI_L2O_MACADDR)) { if (memcmp (cda->l2o.o.macaddr.octet, - adb->prefix_eth.u.prefix_eth.octet, + adb->u.s.prefix_eth.u.prefix_eth.octet, ETHER_ADDR_LEN)) { @@ -3526,7 +3525,7 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) struct rfapi_vn_option vn; - rfapiQprefix2Rprefix (&adb->prefix_ip, &rp); + rfapiQprefix2Rprefix (&adb->u.s.prefix_ip, &rp); memset (&vn, 0, sizeof (vn)); vn.type = RFAPI_VN_OPTION_TYPE_L2ADDR; From 5ff06872e924383e2139b63e9f6e8344b183c283 Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Thu, 12 Jan 2017 08:30:17 -0500 Subject: [PATCH 390/444] bgpd: add vrf-policy config using existing vnc code add add/clear vrf prefix + Modified for FRR master parser Signed-off-by: Lou Berger --- bgpd/bgp_mplsvpn.h | 8 +- bgpd/rfapi/bgp_rfapi_cfg.c | 778 +++++++++++++++++++++++++++++++++++-- bgpd/rfapi/bgp_rfapi_cfg.h | 23 +- bgpd/rfapi/rfapi.c | 97 +++-- bgpd/rfapi/rfapi_import.c | 13 +- bgpd/rfapi/rfapi_import.h | 2 + bgpd/rfapi/rfapi_private.h | 14 + bgpd/rfapi/rfapi_rib.c | 6 +- bgpd/rfapi/rfapi_vty.c | 623 ++++++++++++++++++++++++----- lib/command.c | 3 + lib/command.h | 1 + lib/vty.c | 1 + vtysh/vtysh.c | 39 ++ 13 files changed, 1430 insertions(+), 178 deletions(-) diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index 336b736169..234cf9baa2 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -30,6 +30,10 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #define RD_ADDRSTRLEN 28 +#ifdef MPLS_LABEL_MAX +# undef MPLS_LABEL_MAX +#endif + typedef enum { MPLS_LABEL_IPV4_EXPLICIT_NULL = 0, /* [RFC3032] */ MPLS_LABEL_ROUTER_ALERT = 1, /* [RFC3032] */ @@ -45,7 +49,9 @@ typedef enum { MPLS_LABEL_UNASSIGNED11 = 11, MPLS_LABEL_GAL = 13, /* [RFC5586] */ MPLS_LABEL_OAM_ALERT = 14, /* [RFC3429] */ - MPLS_LABEL_EXTENSION = 15 /* [RFC7274] */ + MPLS_LABEL_EXTENSION = 15, /* [RFC7274] */ + MPLS_LABEL_MAX = 1048575, + MPLS_LABEL_ILLEGAL = 0xFFFFFFFF /* for internal use only */ } mpls_special_label_t; #define MPLS_LABEL_IS_SPECIAL(label) \ diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c index ab9a24e831..a2b0be3cc6 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.c +++ b/bgpd/rfapi/bgp_rfapi_cfg.c @@ -561,8 +561,9 @@ DEFUN (vnc_defaults_responselifetime, return CMD_SUCCESS; } -static struct rfapi_nve_group_cfg * -rfapi_group_lookup_byname (struct bgp *bgp, const char *name) +struct rfapi_nve_group_cfg * +bgp_rfapi_cfg_match_byname (struct bgp *bgp, const char *name, + rfapi_group_cfg_type_t type) /* _MAX = any */ { struct rfapi_nve_group_cfg *rfg; struct listnode *node, *nnode; @@ -570,18 +571,29 @@ rfapi_group_lookup_byname (struct bgp *bgp, const char *name) for (ALL_LIST_ELEMENTS (bgp->rfapi_cfg->nve_groups_sequential, node, nnode, rfg)) { - if (!strcmp (rfg->name, name)) + if ((type == RFAPI_GROUP_CFG_MAX || type == rfg->type) && + !strcmp (rfg->name, name)) return rfg; } return NULL; } static struct rfapi_nve_group_cfg * -rfapi_group_new () +rfapi_group_new (struct bgp *bgp, + rfapi_group_cfg_type_t type, + const char *name) { struct rfapi_nve_group_cfg *rfg; rfg = XCALLOC (MTYPE_RFAPI_GROUP_CFG, sizeof (struct rfapi_nve_group_cfg)); + if (rfg) + { + rfg->type = type; + rfg->name = strdup (name); + /* add to tail of list */ + listnode_add (bgp->rfapi_cfg->nve_groups_sequential, rfg); + } + rfg->label = MPLS_LABEL_ILLEGAL; QOBJ_REG (rfg, rfapi_nve_group_cfg); return rfg; @@ -1033,7 +1045,8 @@ DEFUN (vnc_redistribute_nvegroup, * OK if nve group doesn't exist yet; we'll set the pointer * when the group is defined later */ - bgp->rfapi_cfg->rfg_redist = rfapi_group_lookup_byname (bgp, argv[3]->arg); + bgp->rfapi_cfg->rfg_redist = bgp_rfapi_cfg_match_byname (bgp, argv[3]->arg, + RFAPI_GROUP_CFG_NVE); if (bgp->rfapi_cfg->rfg_redist_name) free (bgp->rfapi_cfg->rfg_redist_name); bgp->rfapi_cfg->rfg_redist_name = strdup (argv[3]->arg); @@ -1622,7 +1635,7 @@ DEFUN (vnc_export_nvegroup, return CMD_WARNING; } - rfg_new = rfapi_group_lookup_byname (bgp, argv[5]->arg); + rfg_new = bgp_rfapi_cfg_match_byname (bgp, argv[5]->arg, RFAPI_GROUP_CFG_NVE); if (argv[2]->arg[0] == 'b') { @@ -2417,20 +2430,17 @@ DEFUN (vnc_nve_group, struct rfapi_rfg_name *rfgn; /* Search for name */ - rfg = rfapi_group_lookup_byname (bgp, argv[2]->arg); + rfg = bgp_rfapi_cfg_match_byname (bgp, argv[2]->arg, RFAPI_GROUP_CFG_NVE); if (!rfg) { - rfg = rfapi_group_new (); + rfg = rfapi_group_new (bgp, RFAPI_GROUP_CFG_NVE, argv[2]->arg); if (!rfg) { /* Error out of memory */ vty_out (vty, "Can't allocate memory for NVE group%s", VTY_NEWLINE); return CMD_WARNING; } - rfg->name = strdup (argv[2]->arg); - /* add to tail of list */ - listnode_add (bgp->rfapi_cfg->nve_groups_sequential, rfg); /* Copy defaults from struct rfapi_cfg */ rfg->rd = bgp->rfapi_cfg->default_rd; @@ -2629,7 +2639,8 @@ static int bgp_rfapi_delete_named_nve_group ( struct vty *vty, /* NULL = no output */ struct bgp *bgp, - const char *rfg_name) /* NULL = any */ + const char *rfg_name, /* NULL = any */ + rfapi_group_cfg_type_t type) /* _MAX = any */ { struct rfapi_nve_group_cfg *rfg = NULL; struct listnode *node, *nnode; @@ -2638,7 +2649,7 @@ bgp_rfapi_delete_named_nve_group ( /* Search for name */ if (rfg_name) { - rfg = rfapi_group_lookup_byname (bgp, rfg_name); + rfg = bgp_rfapi_cfg_match_byname (bgp, rfg_name, type); if (!rfg) { if (vty) @@ -2665,7 +2676,8 @@ bgp_rfapi_delete_named_nve_group ( for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_direct_bgp_l, node, rfgn)) { - if (rfg_name == NULL || !strcmp (rfgn->name, rfg_name)) + if (rfg_name == NULL || + (type == RFAPI_GROUP_CFG_NVE && !strcmp (rfgn->name, rfg_name))) { rfgn->rfg = NULL; /* remove exported routes from this group */ @@ -2680,7 +2692,8 @@ bgp_rfapi_delete_named_nve_group ( for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_zebra_l, node, rfgn)) { - if (rfg_name == NULL || !strcmp (rfgn->name, rfg_name)) + if (rfg_name == NULL || + (type == RFAPI_GROUP_CFG_NVE && !strcmp (rfgn->name, rfg_name))) { rfgn->rfg = NULL; /* remove exported routes from this group */ @@ -2707,7 +2720,7 @@ DEFUN (vnc_no_nve_group, { VTY_DECLVAR_CONTEXT(bgp, bgp); - return bgp_rfapi_delete_named_nve_group (vty, bgp, argv[3]->arg); + return bgp_rfapi_delete_named_nve_group (vty, bgp, argv[3]->arg, RFAPI_GROUP_CFG_NVE); } DEFUN (vnc_nve_group_prefix, @@ -3237,6 +3250,492 @@ static struct cmd_node bgp_vnc_nve_group_node = { 1 }; +/*------------------------------------------------------------------------- + * VNC nve-group + * Note there are two types of NVEs, one for VPNs one for RFP NVEs + *-----------------------------------------------------------------------*/ + +DEFUN (vnc_vrf_policy, + vnc_vrf_policy_cmd, + "vrf-policy NAME", + "Configure a VRF policy group\n" + "VRF name\n") +{ + struct rfapi_nve_group_cfg *rfg; + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + /* Search for name */ + rfg = bgp_rfapi_cfg_match_byname (bgp, argv[1]->arg, RFAPI_GROUP_CFG_VRF); + + if (!rfg) + { + rfg = rfapi_group_new (bgp, RFAPI_GROUP_CFG_VRF, argv[1]->arg); + if (!rfg) + { + /* Error out of memory */ + vty_out (vty, "Can't allocate memory for NVE group%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + /* + * XXX subsequent calls will need to make sure this item is still + * in the linked list and has the same name + */ + VTY_PUSH_CONTEXT_SUB (BGP_VRF_POLICY_NODE, rfg); + + return CMD_SUCCESS; +} + +DEFUN (vnc_no_vrf_policy, + vnc_no_vrf_policy_cmd, + "no vrf-policy NAME", + NO_STR + "Remove a VRF policy group\n" + "VRF name\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + return bgp_rfapi_delete_named_nve_group (vty, bgp, argv[2]->arg, RFAPI_GROUP_CFG_VRF); +} + +DEFUN (vnc_vrf_policy_label, + vnc_vrf_policy_label_cmd, + "label (0-1048575)", + "Default label value for VRF\n" + "Label Value <0-1048575>\n") +{ + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + + uint32_t label; + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + /* make sure it's still in list */ + if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) + { + /* Not in list anymore */ + vty_out (vty, "Current NVE group no longer exists%s", VTY_NEWLINE); + return CMD_WARNING; + } + + VTY_GET_INTEGER_RANGE ("Label value", label, argv[1]->arg, 0, MPLS_LABEL_MAX); + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_prechange (bgp); + } + + rfg->label = label; + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_postchange (bgp); + } + return CMD_SUCCESS; +} + +DEFUN (vnc_vrf_policy_no_label, + vnc_vrf_policy_no_label_cmd, + "no label", + "Remove VRF default label\n") +{ + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + + /* make sure it's still in list */ + if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) + { + /* Not in list anymore */ + vty_out (vty, "Current VRF group no longer exists%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_prechange (bgp); + } + + rfg->label = MPLS_LABEL_ILLEGAL; + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_postchange (bgp); + } + return CMD_SUCCESS; +} + +DEFUN (vnc_vrf_policy_nexthop, + vnc_vrf_policy_nexthop_cmd, + "nexthop ", + "Specify next hop to use for VRF advertised prefixes\n" + "IPv4 prefix\n" + "IPv6 prefix\n" + "Use configured router-id (default)") +{ + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + struct prefix p; + + VTY_DECLVAR_CONTEXT(bgp, bgp); + + /* make sure it's still in list */ + if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) + { + /* Not in list anymore */ + vty_out (vty, "Current VRF no longer exists%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_prechange (bgp); + } + + if (!str2prefix (argv[1]->arg, &p) && p.family) + { + //vty_out (vty, "Nexthop set to self%s", VTY_NEWLINE); + SET_FLAG (rfg->flags, RFAPI_RFG_VPN_NH_SELF); + memset(&rfg->vn_prefix, 0, sizeof(struct prefix)); + } + else + { + UNSET_FLAG (rfg->flags, RFAPI_RFG_VPN_NH_SELF); + rfg->vn_prefix = p; + } + + /* TBD handle router-id/ nexthop changes when have advertised prefixes */ + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_postchange (bgp); + } + + return CMD_SUCCESS; +} + +/* The RT code should be refactored/simplified with above... */ +DEFUN (vnc_vrf_policy_rt_import, + vnc_vrf_policy_rt_import_cmd, + "rt import RTLIST...", + "Specify route targets\n" + "Import filter\n" + "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") +{ + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + int rc; + struct listnode *node; + struct rfapi_rfg_name *rfgn; + int is_export_bgp = 0; + int is_export_zebra = 0; + + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + /* make sure it's still in list */ + if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) + { + /* Not in list anymore */ + vty_out (vty, "Current NVE group no longer exists%s", VTY_NEWLINE); + return CMD_WARNING; + } + + rc = set_ecom_list (vty, argc-2, argv+2, &rfg->rt_import_list); + if (rc != CMD_SUCCESS) + return rc; + + for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_direct_bgp_l, + node, rfgn)) + { + + if (rfgn->rfg == rfg) + { + is_export_bgp = 1; + break; + } + } + + if (is_export_bgp) + vnc_direct_bgp_del_group (bgp, rfg); + + for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_zebra_l, node, rfgn)) + { + + if (rfgn->rfg == rfg) + { + is_export_zebra = 1; + break; + } + } + + if (is_export_zebra) + vnc_zebra_del_group (bgp, rfg); + + /* + * stop referencing old import table, now reference new one + */ + if (rfg->rfapi_import_table) + rfapiImportTableRefDelByIt (bgp, rfg->rfapi_import_table); + rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list); + + if (is_export_bgp) + vnc_direct_bgp_add_group (bgp, rfg); + + if (is_export_zebra) + vnc_zebra_add_group (bgp, rfg); + + return CMD_SUCCESS; +} + +DEFUN (vnc_vrf_policy_rt_export, + vnc_vrf_policy_rt_export_cmd, + "rt export RTLIST...", + "Specify route targets\n" + "Export filter\n" + "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") +{ + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + int rc; + + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + /* make sure it's still in list */ + if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) + { + /* Not in list anymore */ + vty_out (vty, "Current NVE group no longer exists%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_prechange (bgp); + } + + rc = set_ecom_list (vty, argc-2, argv+2, &rfg->rt_export_list); + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_postchange (bgp); + } + + return rc; +} + +DEFUN (vnc_vrf_policy_rt_both, + vnc_vrf_policy_rt_both_cmd, + "rt both RTLIST...", + "Specify route targets\n" + "Export+import filters\n" + "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") +{ + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + int rc; + int is_export_bgp = 0; + int is_export_zebra = 0; + struct listnode *node; + struct rfapi_rfg_name *rfgn; + + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + /* make sure it's still in list */ + if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) + { + /* Not in list anymore */ + vty_out (vty, "Current NVE group no longer exists%s", VTY_NEWLINE); + return CMD_WARNING; + } + + rc = set_ecom_list (vty, argc-2, argv+2, &rfg->rt_import_list); + if (rc != CMD_SUCCESS) + return rc; + + for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_direct_bgp_l, + node, rfgn)) + { + + if (rfgn->rfg == rfg) + { + is_export_bgp = 1; + break; + } + } + + if (is_export_bgp) + vnc_direct_bgp_del_group (bgp, rfg); + + for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_zebra_l, node, rfgn)) + { + + if (rfgn->rfg == rfg) + { + is_export_zebra = 1; + break; + } + } + + if (is_export_zebra) + { + vnc_zlog_debug_verbose ("%s: is_export_zebra", __func__); + vnc_zebra_del_group (bgp, rfg); + } + + /* + * stop referencing old import table, now reference new one + */ + if (rfg->rfapi_import_table) + rfapiImportTableRefDelByIt (bgp, rfg->rfapi_import_table); + rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list); + + if (is_export_bgp) + vnc_direct_bgp_add_group (bgp, rfg); + + if (is_export_zebra) + vnc_zebra_add_group (bgp, rfg); + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_prechange (bgp); + } + + rc = set_ecom_list (vty, argc-2, argv+2, &rfg->rt_export_list); + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_postchange (bgp); + } + + return rc; + +} + +DEFUN (vnc_vrf_policy_rd, + vnc_vrf_policy_rd_cmd, + "rd ASN:nn_or_IP-address:nn", + "Specify default VRF route distinguisher\n" + "Route Distinguisher (: | : | auto:nh: )\n") +{ + int ret; + struct prefix_rd prd; + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + /* make sure it's still in list */ + if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) + { + /* Not in list anymore */ + vty_out (vty, "Current NVE group no longer exists%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (!strncmp (argv[1]->arg, "auto:nh:", 8)) + { + /* + * use AF_UNIX to designate automatically-assigned RD + * auto:vn:nn where nn is a 2-octet quantity + */ + char *end = NULL; + uint32_t value32 = strtoul (argv[1]->arg + 8, &end, 10); + uint16_t value = value32 & 0xffff; + + if (!*(argv[1]->arg + 5) || *end) + { + vty_out (vty, "%% Malformed rd%s", VTY_NEWLINE); + return CMD_WARNING; + } + if (value32 > 0xffff) + { + vty_out (vty, "%% Malformed rd (must be less than %u%s", + 0x0ffff, VTY_NEWLINE); + return CMD_WARNING; + } + + memset (&prd, 0, sizeof (prd)); + prd.family = AF_UNIX; + prd.prefixlen = 64; + prd.val[0] = (RD_TYPE_IP >> 8) & 0x0ff; + prd.val[1] = RD_TYPE_IP & 0x0ff; + prd.val[6] = (value >> 8) & 0x0ff; + prd.val[7] = value & 0x0ff; + + } + else + { + + ret = str2prefix_rd (argv[1]->arg, &prd); + if (!ret) + { + vty_out (vty, "%% Malformed rd%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_prechange (bgp); + } + + rfg->rd = prd; + + if (bgp->rfapi_cfg->rfg_redist == rfg) + { + vnc_redistribute_postchange (bgp); + } + return CMD_SUCCESS; +} + +DEFUN (exit_vrf_policy, + exit_vrf_policy_cmd, + "exit-vrf-policy", + "Exit VRF policy configuration mode\n") +{ + if (vty->node == BGP_VRF_POLICY_NODE) + { + vty->node = BGP_NODE; + } + return CMD_SUCCESS; +} + +static struct cmd_node bgp_vrf_policy_node = { + BGP_VRF_POLICY_NODE, + "%s(config-router-vrf-policy)# ", + 1 +}; + /*------------------------------------------------------------------------- * vnc-l2-group *-----------------------------------------------------------------------*/ @@ -3247,11 +3746,17 @@ DEFUN (vnc_l2_group, "vnc l2-group NAME", VNC_CONFIG_STR "Configure a L2 group\n" "Group name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); struct rfapi_l2_group_cfg *rfg; + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } /* Search for name */ - rfg = rfapi_l2_group_lookup_byname (bgp, argv[2]->arg); + rfg = rfapi_l2_group_lookup_byname (bgp, argv[1]->arg); if (!rfg) { @@ -3262,7 +3767,7 @@ DEFUN (vnc_l2_group, vty_out (vty, "Can't allocate memory for L2 group%s", VTY_NEWLINE); return CMD_WARNING; } - rfg->name = strdup (argv[2]->arg); + rfg->name = strdup (argv[1]->arg); /* add to tail of list */ listnode_add (bgp->rfapi_cfg->l2_groups, rfg); } @@ -3336,18 +3841,29 @@ DEFUN (vnc_no_l2_group, { VTY_DECLVAR_CONTEXT(bgp, bgp); + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } return bgp_rfapi_delete_named_l2_group (vty, bgp, argv[3]->arg); } DEFUN (vnc_l2_group_lni, vnc_l2_group_lni_cmd, - "logical-network-id (0-4294967295)", + "logical-network-id <0-4294967295>", "Specify Logical Network ID associated with group\n" "value\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); VTY_DECLVAR_CONTEXT_SUB(rfapi_l2_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } /* make sure it's still in list */ if (!listnode_lookup (bgp->rfapi_cfg->l2_groups, rfg)) @@ -3364,14 +3880,20 @@ DEFUN (vnc_l2_group_lni, DEFUN (vnc_l2_group_labels, vnc_l2_group_labels_cmd, - "labels LABELLIST...", + "labels .LABELLIST", "Specify label values associated with group\n" "Space separated list of label values <0-1048575>\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); VTY_DECLVAR_CONTEXT_SUB(rfapi_l2_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); struct list *ll; + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + /* make sure it's still in list */ if (!listnode_lookup (bgp->rfapi_cfg->l2_groups, rfg)) { @@ -3386,13 +3908,12 @@ DEFUN (vnc_l2_group_labels, ll = list_new (); rfg->labels = ll; } - - argc -= 1; - argv += 1; + argc--; + argv++; for (; argc; --argc, ++argv) { uint32_t label; - VTY_GET_INTEGER_RANGE ("Label value", label, argv[0]->arg, 0, 1048575); + VTY_GET_INTEGER_RANGE ("Label value", label, argv[0]->arg, 0, MPLS_LABEL_MAX); if (!listnode_lookup (ll, (void *) (uintptr_t) label)) listnode_add (ll, (void *) (uintptr_t) label); } @@ -3402,16 +3923,22 @@ DEFUN (vnc_l2_group_labels, DEFUN (vnc_l2_group_no_labels, vnc_l2_group_no_labels_cmd, - "no labels LABELLIST...", + "no labels .LABELLIST", NO_STR "Remove label values associated with L2 group\n" "Specify label values associated with L2 group\n" "Space separated list of label values <0-1048575>\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); VTY_DECLVAR_CONTEXT_SUB(rfapi_l2_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); struct list *ll; + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + /* make sure it's still in list */ if (!listnode_lookup (bgp->rfapi_cfg->l2_groups, rfg)) { @@ -3427,12 +3954,12 @@ DEFUN (vnc_l2_group_no_labels, return CMD_WARNING; } - argc -= 2; - argv += 2; + argc-=2; + argv+=2; for (; argc; --argc, ++argv) { uint32_t label; - VTY_GET_INTEGER_RANGE ("Label value", label, argv[0]->arg, 0, 1048575); + VTY_GET_INTEGER_RANGE ("Label value", label, argv[0]->arg, 0, MPLS_LABEL_MAX); listnode_delete (ll, (void *) (uintptr_t) label); } @@ -3448,8 +3975,8 @@ DEFUN (vnc_l2_group_rt, "Import filters\n" "A route target\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); VTY_DECLVAR_CONTEXT_SUB(rfapi_l2_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); int rc = CMD_SUCCESS; int do_import = 0; int do_export = 0; @@ -3467,10 +3994,8 @@ DEFUN (vnc_l2_group_rt, default: vty_out (vty, "Unknown option, %s%s", argv[1]->arg, VTY_NEWLINE); return CMD_ERR_NO_MATCH; - } - if (argc < 3) - return CMD_ERR_INCOMPLETE; + } if (!bgp) { vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); @@ -3486,9 +4011,9 @@ DEFUN (vnc_l2_group_rt, } if (do_import) - rc = set_ecom_list (vty, argc - 2, argv + 2, &rfg->rt_import_list); + rc = set_ecom_list (vty, argc-2, argv+2, &rfg->rt_import_list); if (rc == CMD_SUCCESS && do_export) - rc = set_ecom_list (vty, argc - 2, argv + 2, &rfg->rt_export_list); + rc = set_ecom_list (vty, argc-2, argv+2, &rfg->rt_export_list); return rc; } @@ -3571,7 +4096,9 @@ bgp_rfapi_cfg_init (void) install_node (&bgp_vnc_defaults_node, NULL); install_node (&bgp_vnc_nve_group_node, NULL); + install_node (&bgp_vrf_policy_node, NULL); install_node (&bgp_vnc_l2_group_node, NULL); + install_default (BGP_VRF_POLICY_NODE); install_default (BGP_VNC_DEFAULTS_NODE); install_default (BGP_VNC_NVE_GROUP_NODE); install_default (BGP_VNC_L2_GROUP_NODE); @@ -3582,6 +4109,8 @@ bgp_rfapi_cfg_init (void) install_element (BGP_NODE, &vnc_defaults_cmd); install_element (BGP_NODE, &vnc_nve_group_cmd); install_element (BGP_NODE, &vnc_no_nve_group_cmd); + install_element (BGP_NODE, &vnc_vrf_policy_cmd); + install_element (BGP_NODE, &vnc_no_vrf_policy_cmd); install_element (BGP_NODE, &vnc_l2_group_cmd); install_element (BGP_NODE, &vnc_no_l2_group_cmd); install_element (BGP_NODE, &vnc_advertise_un_method_cmd); @@ -3645,6 +4174,16 @@ bgp_rfapi_cfg_init (void) &vnc_nve_group_export_no_routemap_cmd); install_element (BGP_VNC_NVE_GROUP_NODE, &exit_vnc_cmd); + install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_label_cmd); + install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_no_label_cmd); + //Hide per Jan 17 discussion + //install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_nexthop_cmd); + install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_rt_import_cmd); + install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_rt_export_cmd); + install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_rt_both_cmd); + install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_rd_cmd); + install_element (BGP_VRF_POLICY_NODE, &exit_vrf_policy_cmd); + install_element (BGP_VNC_L2_GROUP_NODE, &vnc_l2_group_lni_cmd); install_element (BGP_VNC_L2_GROUP_NODE, &vnc_l2_group_labels_cmd); install_element (BGP_VNC_L2_GROUP_NODE, &vnc_l2_group_no_labels_cmd); @@ -3713,7 +4252,7 @@ bgp_rfapi_cfg_destroy (struct bgp *bgp, struct rfapi_cfg *h) if (h == NULL) return; - bgp_rfapi_delete_named_nve_group (NULL, bgp, NULL); + bgp_rfapi_delete_named_nve_group (NULL, bgp, NULL, RFAPI_GROUP_CFG_MAX); bgp_rfapi_delete_named_l2_group (NULL, bgp, NULL); if (h->l2_groups != NULL) list_delete (h->l2_groups); @@ -3741,6 +4280,166 @@ bgp_rfapi_cfg_write (struct vty *vty, struct bgp *bgp) afi_t afi; int type; + vty_out (vty, "!%s", VTY_NEWLINE); + for (ALL_LIST_ELEMENTS (hc->nve_groups_sequential, node, nnode, rfg)) + if (rfg->type == RFAPI_GROUP_CFG_VRF) + { + ++write; + vty_out (vty, " vrf-policy %s%s", rfg->name, VTY_NEWLINE); + if (rfg->label <= MPLS_LABEL_MAX) + { + vty_out (vty, " label %u%s", rfg->label, VTY_NEWLINE); + + } + if (CHECK_FLAG (rfg->flags, RFAPI_RFG_VPN_NH_SELF)) + { + vty_out (vty, " nexthop self%s", VTY_NEWLINE); + + } + else + { + if (rfg->vn_prefix.family) + { + char buf[BUFSIZ]; + buf[0] = buf[BUFSIZ - 1] = 0; + inet_ntop(rfg->vn_prefix.family, &rfg->vn_prefix.u.prefix, buf, sizeof(buf)); + if (!buf[0] || buf[BUFSIZ - 1]) + { + //vty_out (vty, "nexthop self%s", VTY_NEWLINE); + } + else + { + vty_out (vty, " nexthop %s%s", buf, VTY_NEWLINE); + } + } + } + + if (rfg->rd.prefixlen) + { + char buf[BUFSIZ]; + buf[0] = buf[BUFSIZ - 1] = 0; + + if (AF_UNIX == rfg->rd.family) + { + + uint16_t value = 0; + + value = ((rfg->rd.val[6] << 8) & 0x0ff00) | + (rfg->rd.val[7] & 0x0ff); + + vty_out (vty, " rd auto:nh:%d%s", value, VTY_NEWLINE); + + } + else + { + + if (!prefix_rd2str (&rfg->rd, buf, BUFSIZ) || + !buf[0] || buf[BUFSIZ - 1]) + { + + vty_out (vty, "!Error: Can't convert rd%s", VTY_NEWLINE); + } + else + { + vty_out (vty, " rd %s%s", buf, VTY_NEWLINE); + } + } + } + + if (rfg->rt_import_list && rfg->rt_export_list && + ecommunity_cmp (rfg->rt_import_list, rfg->rt_export_list)) + { + char *b = ecommunity_ecom2str (rfg->rt_import_list, + ECOMMUNITY_FORMAT_ROUTE_MAP); + vty_out (vty, " rt both %s%s", b, VTY_NEWLINE); + XFREE (MTYPE_ECOMMUNITY_STR, b); + } + else + { + if (rfg->rt_import_list) + { + char *b = ecommunity_ecom2str (rfg->rt_import_list, + ECOMMUNITY_FORMAT_ROUTE_MAP); + vty_out (vty, " rt import %s%s", b, VTY_NEWLINE); + XFREE (MTYPE_ECOMMUNITY_STR, b); + } + if (rfg->rt_export_list) + { + char *b = ecommunity_ecom2str (rfg->rt_export_list, + ECOMMUNITY_FORMAT_ROUTE_MAP); + vty_out (vty, " rt export %s%s", b, VTY_NEWLINE); + XFREE (MTYPE_ECOMMUNITY_STR, b); + } + } + + /* + * route filtering: prefix-lists and route-maps + */ + for (afi = AFI_IP; afi < AFI_MAX; ++afi) + { + + const char *afistr = (afi == AFI_IP) ? "ipv4" : "ipv6"; + + if (rfg->plist_export_bgp_name[afi]) + { + vty_out (vty, " export bgp %s prefix-list %s%s", + afistr, rfg->plist_export_bgp_name[afi], + VTY_NEWLINE); + } + if (rfg->plist_export_zebra_name[afi]) + { + vty_out (vty, " export zebra %s prefix-list %s%s", + afistr, rfg->plist_export_zebra_name[afi], + VTY_NEWLINE); + } + /* + * currently we only support redist plists for bgp-direct. + * If we later add plist support for redistributing other + * protocols, we'll need to loop over protocols here + */ + if (rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]) + { + vty_out (vty, " redistribute bgp-direct %s prefix-list %s%s", + afistr, + rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi], + VTY_NEWLINE); + } + if (rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT_EXT][afi]) + { + vty_out (vty, + " redistribute bgp-direct-to-nve-groups %s prefix-list %s%s", + afistr, + rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT_EXT] + [afi], VTY_NEWLINE); + } + } + + if (rfg->routemap_export_bgp_name) + { + vty_out (vty, " export bgp route-map %s%s", + rfg->routemap_export_bgp_name, VTY_NEWLINE); + } + if (rfg->routemap_export_zebra_name) + { + vty_out (vty, " export zebra route-map %s%s", + rfg->routemap_export_zebra_name, VTY_NEWLINE); + } + if (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]) + { + vty_out (vty, " redistribute bgp-direct route-map %s%s", + rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT], + VTY_NEWLINE); + } + if (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT_EXT]) + { + vty_out (vty, + " redistribute bgp-direct-to-nve-groups route-map %s%s", + rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT_EXT], + VTY_NEWLINE); + } + vty_out (vty, " exit-vrf-policy%s", VTY_NEWLINE); + vty_out (vty, "!%s", VTY_NEWLINE); + } if (hc->flags & BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP) { vty_out (vty, " vnc advertise-un-method encap-safi%s", VTY_NEWLINE); @@ -3902,6 +4601,7 @@ bgp_rfapi_cfg_write (struct vty *vty, struct bgp *bgp) } for (ALL_LIST_ELEMENTS (hc->nve_groups_sequential, node, nnode, rfg)) + if (rfg->type == RFAPI_GROUP_CFG_NVE) { ++write; vty_out (vty, " vnc nve-group %s%s", rfg->name, VTY_NEWLINE); diff --git a/bgpd/rfapi/bgp_rfapi_cfg.h b/bgpd/rfapi/bgp_rfapi_cfg.h index 897b4be764..8f93d69f6b 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.h +++ b/bgpd/rfapi/bgp_rfapi_cfg.h @@ -41,12 +41,21 @@ struct rfapi_l2_group_cfg }; DECLARE_QOBJ_TYPE(rfapi_l2_group_cfg) +typedef enum +{ + RFAPI_GROUP_CFG_NVE = 1, + RFAPI_GROUP_CFG_VRF, + RFAPI_GROUP_CFG_L2, + RFAPI_GROUP_CFG_MAX +} rfapi_group_cfg_type_t; + struct rfapi_nve_group_cfg { struct route_node *vn_node; /* backref */ struct route_node *un_node; /* backref */ - char *name; + rfapi_group_cfg_type_t type; /* NVE|VPN */ + char *name; /* unique by type! */ struct prefix vn_prefix; struct prefix un_prefix; @@ -54,8 +63,9 @@ struct rfapi_nve_group_cfg uint8_t l2rd; /* 0 = VN addr LSB */ uint32_t response_lifetime; uint32_t flags; -#define RFAPI_RFG_RESPONSE_LIFETIME 0x1 +#define RFAPI_RFG_RESPONSE_LIFETIME 0x01 /* bits */ #define RFAPI_RFG_L2RD 0x02 +#define RFAPI_RFG_VPN_NH_SELF 0x04 struct ecommunity *rt_import_list; struct ecommunity *rt_export_list; struct rfapi_import_table *rfapi_import_table; @@ -99,6 +109,9 @@ struct rfapi_nve_group_cfg char *routemap_redist_name[ZEBRA_ROUTE_MAX]; struct route_map *routemap_redist[ZEBRA_ROUTE_MAX]; + /* for VRF type groups */ + uint32_t label; + struct rfapi_descriptor *rfd; QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(rfapi_nve_group_cfg) @@ -288,6 +301,12 @@ bgp_rfapi_cfg_match_group ( struct prefix *vn, struct prefix *un); +struct rfapi_nve_group_cfg * +bgp_rfapi_cfg_match_byname ( + struct bgp *bgp, + const char *name, + rfapi_group_cfg_type_t type); /* _MAX = any */ + extern void vnc_prefix_list_update (struct bgp *bgp); diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c index 6353f7dacf..c195d09ce7 100644 --- a/bgpd/rfapi/rfapi.c +++ b/bgpd/rfapi/rfapi.c @@ -335,6 +335,9 @@ is_valid_rfd (struct rfapi_descriptor *rfd) if (!rfd || rfd->bgp == NULL) return 0; + if (CHECK_FLAG(rfd->flags, RFAPI_HD_FLAG_IS_VRF)) /* assume VRF/internal are valid */ + return 1; + if (rfapi_find_handle (rfd->bgp, &rfd->vn_addr, &rfd->un_addr, &hh)) return 0; @@ -357,6 +360,9 @@ rfapi_check (void *handle) if (!rfd || rfd->bgp == NULL) return EINVAL; + if (CHECK_FLAG(rfd->flags, RFAPI_HD_FLAG_IS_VRF)) /* assume VRF/internal are valid */ + return 0; + if ((rc = rfapi_find_handle (rfd->bgp, &rfd->vn_addr, &rfd->un_addr, &hh))) return rc; @@ -1347,7 +1353,6 @@ rfapi_rfp_set_cb_methods (void *rfp_start_val, /*********************************************************************** * NVE Sessions ***********************************************************************/ - /* * Caller must supply an already-allocated rfd with the "caller" * fields already set (vn_addr, un_addr, callback, cookie) @@ -1474,6 +1479,57 @@ rfapi_open_inner ( return 0; } +/* moved from rfapi_register */ +int +rfapi_init_and_open( + struct bgp *bgp, + struct rfapi_descriptor *rfd, + struct rfapi_nve_group_cfg *rfg) +{ + struct rfapi *h = bgp->rfapi; + char buf_vn[BUFSIZ]; + char buf_un[BUFSIZ]; + afi_t afi_vn, afi_un; + struct prefix pfx_un; + struct route_node *rn; + + + rfapi_time (&rfd->open_time); + + if (rfg->type == RFAPI_GROUP_CFG_VRF) + SET_FLAG(rfd->flags, RFAPI_HD_FLAG_IS_VRF); + + rfapiRfapiIpAddr2Str (&rfd->vn_addr, buf_vn, BUFSIZ); + rfapiRfapiIpAddr2Str (&rfd->un_addr, buf_un, BUFSIZ); + + vnc_zlog_debug_verbose ("%s: new RFD with VN=%s UN=%s cookie=%p", + __func__, buf_vn, buf_un, rfd->cookie); + + if (rfg->type != RFAPI_GROUP_CFG_VRF) /* unclear if needed for VRF */ + { + listnode_add (&h->descriptors, rfd); + if (h->descriptors.count > h->stat.max_descriptors) + { + h->stat.max_descriptors = h->descriptors.count; + } + + /* + * attach to UN radix tree + */ + afi_vn = family2afi (rfd->vn_addr.addr_family); + afi_un = family2afi (rfd->un_addr.addr_family); + assert (afi_vn && afi_un); + assert (!rfapiRaddr2Qprefix (&rfd->un_addr, &pfx_un)); + + rn = route_node_get (&(h->un[afi_un]), &pfx_un); + assert (rn); + rfd->next = rn->info; + rn->info = rfd; + rfd->un_node = rn; + } + return rfapi_open_inner (rfd, bgp, h, rfg); +} + struct rfapi_vn_option * rfapiVnOptionsDup (struct rfapi_vn_option *orig) { @@ -1991,14 +2047,10 @@ rfapi_open ( struct prefix pfx_vn; struct prefix pfx_un; - struct route_node *rn; int rc; rfapi_handle hh = NULL; int reusing_provisional = 0; - afi_t afi_vn; - afi_t afi_un; - { char buf[2][INET_ADDRSTRLEN]; vnc_zlog_debug_verbose ("%s: VN=%s UN=%s", __func__, @@ -2129,40 +2181,7 @@ rfapi_open ( if (!reusing_provisional) { - rfapi_time (&rfd->open_time); - - { - char buf_vn[BUFSIZ]; - char buf_un[BUFSIZ]; - - rfapiRfapiIpAddr2Str (vn, buf_vn, BUFSIZ); - rfapiRfapiIpAddr2Str (un, buf_un, BUFSIZ); - - vnc_zlog_debug_verbose ("%s: new HD with VN=%s UN=%s cookie=%p", - __func__, buf_vn, buf_un, userdata); - } - - listnode_add (&h->descriptors, rfd); - if (h->descriptors.count > h->stat.max_descriptors) - { - h->stat.max_descriptors = h->descriptors.count; - } - - /* - * attach to UN radix tree - */ - afi_vn = family2afi (rfd->vn_addr.addr_family); - afi_un = family2afi (rfd->un_addr.addr_family); - assert (afi_vn && afi_un); - assert (!rfapiRaddr2Qprefix (&rfd->un_addr, &pfx_un)); - - rn = route_node_get (&(h->un[afi_un]), &pfx_un); - assert (rn); - rfd->next = rn->info; - rn->info = rfd; - rfd->un_node = rn; - - rc = rfapi_open_inner (rfd, bgp, h, rfg); + rc = rfapi_init_and_open(bgp, rfd, rfg); /* * This can fail only if the VN address is IPv6 and the group * specified auto-assignment of RDs, which only works for v4, diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index 26325b5816..5ba98e55d0 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -4943,6 +4943,7 @@ rfapiDeleteRemotePrefixesIt ( * un if set, tunnel must match this prefix * vn if set, nexthop prefix must match this prefix * p if set, prefix must match this prefix + * it if set, only look in this import table * * output * pARcount number of active routes deleted @@ -4958,6 +4959,7 @@ rfapiDeleteRemotePrefixes ( struct prefix *un, struct prefix *vn, struct prefix *p, + struct rfapi_import_table *arg_it, int delete_active, int delete_holddown, uint32_t *pARcount, @@ -4995,7 +4997,11 @@ rfapiDeleteRemotePrefixes ( * for the afi/safi combination */ - for (it = h->imports; it; it = it->next) + if (arg_it) + it = arg_it; + else + it = h->imports; + for (; it; ) { vnc_zlog_debug_verbose @@ -5016,6 +5022,11 @@ rfapiDeleteRemotePrefixes ( &deleted_holddown_nve_count, uniq_active_nves, uniq_holddown_nves); + + if (arg_it) + it = NULL; + else + it = it->next; } /* diff --git a/bgpd/rfapi/rfapi_import.h b/bgpd/rfapi/rfapi_import.h index 3cf55462a1..51afa0002f 100644 --- a/bgpd/rfapi/rfapi_import.h +++ b/bgpd/rfapi/rfapi_import.h @@ -223,6 +223,7 @@ extern int rfapiEcommunityGetEthernetTag ( * un if set, tunnel must match this prefix * vn if set, nexthop prefix must match this prefix * p if set, prefix must match this prefix + * it if set, only look in this import table * * output * pARcount number of active routes deleted @@ -238,6 +239,7 @@ rfapiDeleteRemotePrefixes ( struct prefix *un, struct prefix *vn, struct prefix *p, + struct rfapi_import_table *it, int delete_active, int delete_holddown, uint32_t *pARcount, /* active routes */ diff --git a/bgpd/rfapi/rfapi_private.h b/bgpd/rfapi/rfapi_private.h index 00f90e35fc..ed83ef1e1f 100644 --- a/bgpd/rfapi/rfapi_private.h +++ b/bgpd/rfapi/rfapi_private.h @@ -135,6 +135,7 @@ struct rfapi_descriptor #define RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_ETHER 0x00000004 #define RFAPI_HD_FLAG_PROVISIONAL 0x00000008 #define RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY 0x00000010 +#define RFAPI_HD_FLAG_IS_VRF 0x00000012 }; #define RFAPI_QUEUED_FLAG(afi) ( \ @@ -433,4 +434,17 @@ DECLARE_MTYPE(RFAPI_L2ADDR_OPT) DECLARE_MTYPE(RFAPI_AP) DECLARE_MTYPE(RFAPI_MONITOR_ETH) + +/* + * Caller must supply an already-allocated rfd with the "caller" + * fields already set (vn_addr, un_addr, callback, cookie) + * The advertised_prefixes[] array elements should be NULL to + * have this function set them to newly-allocated radix trees. + */ +extern int +rfapi_init_and_open( + struct bgp *bgp, + struct rfapi_descriptor *rfd, + struct rfapi_nve_group_cfg *rfg); + #endif /* _QUAGGA_BGP_RFAPI_PRIVATE_H */ diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c index 3a4a159215..8e5d47415f 100644 --- a/bgpd/rfapi/rfapi_rib.c +++ b/bgpd/rfapi/rfapi_rib.c @@ -514,9 +514,13 @@ rfapi_info_cmp (struct rfapi_info *a, struct rfapi_info *b) void rfapiRibClear (struct rfapi_descriptor *rfd) { - struct bgp *bgp = bgp_get_default (); + struct bgp *bgp; afi_t afi; + if (rfd->bgp) + bgp = rfd->bgp; + else + bgp = bgp_get_default (); #if DEBUG_L2_EXTRA vnc_zlog_debug_verbose ("%s: rfd=%p", __func__, rfd); #endif diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index ed3155307d..f8142ed299 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -3004,9 +3004,12 @@ struct rfapi_local_reg_delete_arg /* * match parameters */ + struct bgp *bgp; struct rfapi_ip_addr un_address; /* AF==0: wildcard */ struct rfapi_ip_addr vn_address; /* AF==0: wildcard */ struct prefix prefix; /* AF==0: wildcard */ + struct prefix_rd rd; /* plen!=64: wildcard */ + struct rfapi_nve_group_cfg *rfg; /* NULL: wildcard */ struct rfapi_l2address_option_match l2o; @@ -3106,22 +3109,26 @@ nve_addr_cmp (void *k1, void *k2) static int parse_deleter_args ( - struct vty *vty, - struct cmd_token *carg_prefix, - struct cmd_token *carg_vn, - struct cmd_token *carg_un, - struct cmd_token *carg_l2addr, - struct cmd_token *carg_vni, - struct rfapi_local_reg_delete_arg *rcdarg) + struct vty *vty, + struct bgp *bgp, + const char *arg_prefix, + const char *arg_vn, + const char *arg_un, + const char *arg_l2addr, + const char *arg_vni, + const char *arg_rd, + struct rfapi_nve_group_cfg *arg_rfg, + struct rfapi_local_reg_delete_arg *rcdarg) { - const char *arg_prefix = carg_prefix ? carg_prefix->arg : NULL; - const char *arg_vn = carg_vn ? carg_vn->arg : NULL; - const char *arg_un = carg_un ? carg_un->arg : NULL; - const char *arg_l2addr = carg_l2addr ? carg_l2addr->arg : NULL; - const char *arg_vni = carg_vni ? carg_vni->arg : NULL; int rc = CMD_WARNING; - memset (rcdarg, 0, sizeof (struct rfapi_local_reg_delete_arg)); + memset (rcdarg, 0, sizeof (struct rfapi_local_reg_delete_arg)); + + rcdarg->vty = vty; + if (bgp == NULL) + bgp = bgp_get_default(); + rcdarg->bgp = bgp; + rcdarg->rfg = arg_rfg; /* may be NULL */ if (arg_vn && strcmp (arg_vn, "*")) { @@ -3167,7 +3174,41 @@ parse_deleter_args ( rcdarg->l2o.flags |= RFAPI_L2O_LNI; } } - return 0; + if (arg_rd) + { + if (!str2prefix_rd (arg_rd, &rcdarg->rd)) + { + vty_out (vty, "Malformed RD \"%s\"%s", + arg_rd, VTY_NEWLINE); + return rc; + } + } + + return CMD_SUCCESS; +} + +static int +parse_deleter_tokens ( + struct vty *vty, + struct bgp *bgp, + struct cmd_token *carg_prefix, + struct cmd_token *carg_vn, + struct cmd_token *carg_un, + struct cmd_token *carg_l2addr, + struct cmd_token *carg_vni, + struct cmd_token *carg_rd, + struct rfapi_nve_group_cfg *arg_rfg, + struct rfapi_local_reg_delete_arg *rcdarg) +{ + const char *arg_prefix = carg_prefix ? carg_prefix->arg : NULL; + const char *arg_vn = carg_vn ? carg_vn->arg : NULL; + const char *arg_un = carg_un ? carg_un->arg : NULL; + const char *arg_l2addr = carg_l2addr ? carg_l2addr->arg : NULL; + const char *arg_vni = carg_vni ? carg_vni->arg : NULL; + const char *arg_rd = carg_rd ? carg_rd->arg : NULL; + return parse_deleter_args (vty, bgp,arg_prefix, arg_vn, arg_un, + arg_l2addr, arg_vni, arg_rd, + arg_rfg, rcdarg); } static void @@ -3271,51 +3312,37 @@ clear_vnc_responses (struct rfapi_local_reg_delete_arg *cda) * TBD need to count deleted prefixes and nves? * * ENXIO BGP or VNC not configured - */ + */ static int -rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) +rfapiDeleteLocalPrefixesByRFD (struct rfapi_local_reg_delete_arg *cda, + struct rfapi_descriptor *rfd) { - struct rfapi_ip_addr *pUn; /* NULL = wildcard */ - struct rfapi_ip_addr *pVn; /* NULL = wildcard */ - struct prefix *pPrefix; /* NULL = wildcard */ + struct rfapi_ip_addr *pUn; /* NULL = wildcard */ + struct rfapi_ip_addr *pVn; /* NULL = wildcard */ + struct prefix *pPrefix; /* NULL = wildcard */ + struct prefix_rd *pPrd; /* NULL = wildcard */ - struct rfapi *h; - struct listnode *node; - struct rfapi_descriptor *rfd; struct rfapi_ip_prefix rprefix; - struct bgp *bgp_default = bgp_get_default (); struct rfapi_next_hop_entry *head = NULL; struct rfapi_next_hop_entry *tail = NULL; - struct rfapi_cfg *rfapi_cfg; #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: entry", __func__); + vnc_zlog_debug_verbose ("%s: entry", __func__); #endif - if (!bgp_default) - return ENXIO; - - pUn = (cda->un_address.addr_family ? &cda->un_address : NULL); - pVn = (cda->vn_address.addr_family ? &cda->vn_address : NULL); - pPrefix = (cda->prefix.family ? &cda->prefix : NULL); - - h = bgp_default->rfapi; - rfapi_cfg = bgp_default->rfapi_cfg; - - if (!h || !rfapi_cfg) - return ENXIO; + pUn = (cda->un_address.addr_family ? &cda->un_address : NULL); + pVn = (cda->vn_address.addr_family ? &cda->vn_address : NULL); + pPrefix = (cda->prefix.family ? &cda->prefix : NULL); + pPrd = (cda->rd.prefixlen == 64 ? &cda->rd : NULL); if (pPrefix) { rfapiQprefix2Rprefix (pPrefix, &rprefix); } -#if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: starting descriptor loop", __func__); -#endif - - for (ALL_LIST_ELEMENTS_RO (&h->descriptors, node, rfd)) + do /* to preserve old code structure */ { + struct rfapi *h=cda->bgp->rfapi;; struct rfapi_adb *adb; int rc; int deleted_from_this_nve; @@ -3380,6 +3407,17 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) #if DEBUG_L2_EXTRA vnc_zlog_debug_verbose ("%s: adb=%p, prefix doesn't match, skipping", __func__, adb); +#endif + continue; + } + } + if (pPrd) + { + if (memcmp(pPrd->val, adb->u.s.prd.val, 8) != 0) + { +#if DEBUG_L2_EXTRA + vnc_zlog_debug_verbose ("%s: adb=%p, RD doesn't match, skipping", + __func__, adb); #endif continue; } @@ -3422,47 +3460,43 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) for (ALL_LIST_ELEMENTS_RO (adb_delete_list, node, adb)) { - - struct rfapi_vn_option vn1; - struct rfapi_vn_option vn2; - struct rfapi_vn_option *pVn; int this_advertisement_prefix_count; + struct rfapi_vn_option optary[3]; + struct rfapi_vn_option *opt = NULL; + int cur_opt = 0; this_advertisement_prefix_count = 1; rfapiQprefix2Rprefix (&adb->u.s.prefix_ip, &rp); + memset (optary, 0, sizeof (optary)); + /* if mac addr present in advert, make l2o vn option */ if (adb->u.s.prefix_eth.family == AF_ETHERNET) { - memset (&vn1, 0, sizeof (vn1)); - memset (&vn2, 0, sizeof (vn2)); - - vn1.type = RFAPI_VN_OPTION_TYPE_L2ADDR; - vn1.v.l2addr.macaddr = adb->u.s.prefix_eth.u.prefix_eth; - - /* - * use saved RD value instead of trying to invert - * complex L2-style RD computation in rfapi_register() - */ - vn2.type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD; - vn2.v.internal_rd = adb->u.s.prd; - - vn1.next = &vn2; - - pVn = &vn1; + if (opt != NULL) + opt->next = &optary[cur_opt]; + opt = &optary[cur_opt++]; + opt->type = RFAPI_VN_OPTION_TYPE_L2ADDR; + opt->v.l2addr.macaddr = adb->u.s.prefix_eth.u.prefix_eth; ++this_advertisement_prefix_count; } - else - { - pVn = NULL; - } + /* + * use saved RD value instead of trying to invert + * complex RD computation in rfapi_register() + */ + if (opt != NULL) + opt->next = &optary[cur_opt]; + opt = &optary[cur_opt++]; + opt->type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD; + opt->v.internal_rd = adb->u.s.prd; #if DEBUG_L2_EXTRA vnc_zlog_debug_verbose ("%s: ipN killing reg from adb %p ", __func__, adb); #endif - rc = rfapi_register (rfd, &rp, 0, NULL, pVn, RFAPI_REGISTER_KILL); + rc = rfapi_register (rfd, &rp, 0, NULL, + (cur_opt ? optary : NULL), RFAPI_REGISTER_KILL); if (!rc) { cda->pfx_count += this_advertisement_prefix_count; @@ -3588,11 +3622,44 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) skiplist_insert (cda->nves, hap, hap); } } - } + } while (0); /* to preserve old code structure */ return 0; } +static int +rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) +{ + int rc = 0; + + if (cda->rfg) + { + if (cda->rfg->rfd) /* if not open, nothing to delete */ + rc = rfapiDeleteLocalPrefixesByRFD (cda, cda->rfg->rfd); + } + else + { + struct bgp *bgp = cda->bgp; + struct rfapi *h; + struct rfapi_cfg *rfapi_cfg; + + struct listnode *node; + struct rfapi_descriptor *rfd; + if (!bgp) + return ENXIO; + h = bgp->rfapi; + rfapi_cfg = bgp->rfapi_cfg; + if (!h || !rfapi_cfg) + return ENXIO; + vnc_zlog_debug_verbose ("%s: starting descriptor loop", __func__); + for (ALL_LIST_ELEMENTS_RO (&h->descriptors, node, rfd)) + { + rc = rfapiDeleteLocalPrefixesByRFD (cda, rfd); + } + } + return rc; +} + /* * clear_vnc_prefix * @@ -3608,6 +3675,8 @@ clear_vnc_prefix (struct rfapi_local_reg_delete_arg *cda) struct prefix *pVN = NULL; struct prefix *pPrefix = NULL; + struct rfapi_import_table *it = NULL; + /* * Delete matching remote prefixes in holddown */ @@ -3625,7 +3694,11 @@ clear_vnc_prefix (struct rfapi_local_reg_delete_arg *cda) { pPrefix = &cda->prefix; } - rfapiDeleteRemotePrefixes (pUN, pVN, pPrefix, + if (cda->rfg) + { + it = cda->rfg->rfapi_import_table; + } + rfapiDeleteRemotePrefixes (pUN, pVN, pPrefix, it, 0, 1, &cda->remote_active_pfx_count, &cda->remote_active_nve_count, &cda->remote_holddown_pfx_count, @@ -3710,7 +3783,7 @@ DEFUN (clear_vnc_nve_all, struct rfapi_local_reg_delete_arg cda; int rc; - if ((rc = parse_deleter_args (vty, NULL, NULL, NULL, NULL, NULL, &cda))) + if ((rc = parse_deleter_args (vty, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; @@ -3743,7 +3816,7 @@ DEFUN (clear_vnc_nve_vn_un, int rc; if ((rc = - parse_deleter_args (vty, NULL, argv[4], argv[6], NULL, NULL, &cda))) + parse_deleter_tokens (vty, NULL, NULL, argv[4], argv[6], NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; @@ -3776,7 +3849,7 @@ DEFUN (clear_vnc_nve_un_vn, int rc; if ((rc = - parse_deleter_args (vty, NULL, argv[6], argv[4], NULL, NULL, &cda))) + parse_deleter_tokens (vty, NULL, NULL, argv[6], argv[4], NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; @@ -3804,7 +3877,7 @@ DEFUN (clear_vnc_nve_vn, struct rfapi_local_reg_delete_arg cda; int rc; - if ((rc = parse_deleter_args (vty, NULL, argv[4], NULL, NULL, NULL, &cda))) + if ((rc = parse_deleter_tokens (vty, NULL, NULL, argv[4], NULL, NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; @@ -3831,7 +3904,7 @@ DEFUN (clear_vnc_nve_un, struct rfapi_local_reg_delete_arg cda; int rc; - if ((rc = parse_deleter_args (vty, NULL, NULL, argv[6], NULL, NULL, &cda))) + if ((rc = parse_deleter_tokens (vty, NULL, NULL, NULL, argv[6], NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; @@ -3874,7 +3947,7 @@ DEFUN (clear_vnc_prefix_vn_un, int rc; if ((rc = - parse_deleter_args (vty, argv[3], argv[5], argv[7], NULL, NULL, &cda))) + parse_deleter_tokens (vty, NULL, argv[3], argv[5], argv[7], NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -3904,7 +3977,7 @@ DEFUN (clear_vnc_prefix_un_vn, int rc; if ((rc = - parse_deleter_args (vty, argv[3], argv[7], argv[5], NULL, NULL, &cda))) + parse_deleter_tokens (vty, NULL, argv[3], argv[7], argv[5], NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -3930,7 +4003,7 @@ DEFUN (clear_vnc_prefix_un, int rc; if ((rc = - parse_deleter_args (vty, argv[3], NULL, argv[5], NULL, NULL, &cda))) + parse_deleter_tokens (vty, NULL, argv[3], NULL, argv[5], NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -3956,7 +4029,7 @@ DEFUN (clear_vnc_prefix_vn, int rc; if ((rc = - parse_deleter_args (vty, argv[3], argv[5], NULL, NULL, NULL, &cda))) + parse_deleter_tokens (vty, NULL, argv[3], argv[5], NULL, NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -3978,7 +4051,7 @@ DEFUN (clear_vnc_prefix_all, struct rfapi_local_reg_delete_arg cda; int rc; - if ((rc = parse_deleter_args (vty, argv[3], NULL, NULL, NULL, NULL, &cda))) + if ((rc = parse_deleter_tokens (vty, NULL, argv[3], NULL, NULL, NULL, NULL, NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4020,8 +4093,8 @@ DEFUN (clear_vnc_mac_vn_un, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, NULL, argv[7], argv[9], argv[3], argv[5], - &cda))) + parse_deleter_tokens (vty, NULL, NULL, argv[7], argv[9], argv[3], argv[5], + NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4054,8 +4127,8 @@ DEFUN (clear_vnc_mac_un_vn, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, NULL, argv[9], argv[7], argv[3], argv[5], - &cda))) + parse_deleter_tokens (vty, NULL, NULL, argv[9], argv[7], argv[3], argv[5], + NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4084,7 +4157,7 @@ DEFUN (clear_vnc_mac_un, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, NULL, NULL, argv[7], argv[3], argv[5], &cda))) + parse_deleter_tokens (vty, NULL, NULL, NULL, argv[7], argv[3], argv[5], NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4113,7 +4186,7 @@ DEFUN (clear_vnc_mac_vn, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, NULL, argv[7], NULL, argv[3], argv[5], &cda))) + parse_deleter_tokens (vty, NULL, NULL, argv[7], NULL, argv[3], argv[5], NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4139,7 +4212,7 @@ DEFUN (clear_vnc_mac_all, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, NULL, NULL, NULL, argv[3], argv[5], &cda))) + parse_deleter_tokens (vty, NULL, NULL, NULL, NULL, argv[3], argv[5], NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4180,8 +4253,8 @@ DEFUN (clear_vnc_mac_vn_un_prefix, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, argv[11], argv[7], argv[9], argv[3], argv[5], - &cda))) + parse_deleter_tokens (vty, NULL, argv[11], argv[7], argv[9], argv[3], argv[5], + NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4222,8 +4295,8 @@ DEFUN (clear_vnc_mac_un_vn_prefix, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, argv[11], argv[9], argv[7], argv[3], argv[5], - &cda))) + parse_deleter_tokens (vty, NULL, argv[11], argv[9], argv[7], argv[3], argv[5], + NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4256,8 +4329,8 @@ DEFUN (clear_vnc_mac_un_prefix, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, argv[9], NULL, argv[7], argv[3], argv[5], - &cda))) + parse_deleter_tokens (vty, NULL, argv[9], NULL, argv[7], argv[3], argv[5], + NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4290,8 +4363,8 @@ DEFUN (clear_vnc_mac_vn_prefix, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, argv[9], argv[7], NULL, argv[3], argv[5], - &cda))) + parse_deleter_tokens (vty, NULL, argv[9], argv[7], NULL, argv[3], argv[5], + NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4320,7 +4393,7 @@ DEFUN (clear_vnc_mac_all_prefix, /* pfx vn un L2 VNI */ if ((rc = - parse_deleter_args (vty, argv[7], NULL, NULL, argv[3], argv[5], &cda))) + parse_deleter_tokens (vty, NULL, argv[7], NULL, NULL, argv[3], argv[5], NULL, NULL, &cda))) return rc; cda.vty = vty; clear_vnc_prefix (&cda); @@ -4928,6 +5001,361 @@ notcfg: return CMD_WARNING; } +/************************************************************************ + * Add prefix with vrf + * + * add [vrf ] prefix + * [rd ] [label ] [local-preference <0-4294967295>] + ************************************************************************/ +static int +vnc_add_vrf_prefix (struct vty *vty, + const char *arg_vrf, + const char *arg_prefix, + const char *arg_rd, /* optional */ + const char *arg_label, /* optional */ + const char *arg_pref) /* optional */ +{ + struct bgp *bgp; + struct rfapi_nve_group_cfg *rfg; + struct prefix pfx; + struct rfapi_ip_prefix rpfx; + uint32_t pref = 0; + struct rfapi_vn_option optary[3]; + struct rfapi_vn_option *opt = NULL; + int cur_opt = 0; + + bgp = bgp_get_default (); /* assume main instance for now */ + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + if (!bgp->rfapi || !bgp->rfapi_cfg) + { + vty_out (vty, "VRF support not configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + rfg = bgp_rfapi_cfg_match_byname (bgp, arg_vrf, RFAPI_GROUP_CFG_VRF); + /* arg checks */ + if (!rfg) + { + vty_out (vty, "VRF \"%s\" appears not to be configured.%s", + arg_vrf, VTY_NEWLINE); + return CMD_WARNING; + } + if (!rfg->rt_export_list || !rfg->rfapi_import_table) + { + vty_out (vty, "VRF \"%s\" is missing RT import/export RT configuration.%s", + arg_vrf, VTY_NEWLINE); + return CMD_WARNING; + } + if (!rfg->rd.family && !arg_rd) + { + vty_out (vty, "VRF \"%s\" isn't configured with an RD, so RD must be provided.%s", + arg_vrf, VTY_NEWLINE); + return CMD_WARNING; + } + if (rfg->label > MPLS_LABEL_MAX && !arg_label) + { + vty_out (vty, "VRF \"%s\" isn't configured with a default labels, so a label must be provided.%s", + arg_vrf, VTY_NEWLINE); + return CMD_WARNING; + } + if (!str2prefix (arg_prefix, &pfx)) + { + vty_out (vty, "Malformed prefix \"%s\"%s", + arg_prefix, VTY_NEWLINE); + return CMD_WARNING; + } + rfapiQprefix2Rprefix (&pfx, &rpfx); + memset (optary, 0, sizeof (optary)); + if (arg_rd) + { + if (opt != NULL) + opt->next = &optary[cur_opt]; + opt = &optary[cur_opt++]; + opt->type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD; + if (!str2prefix_rd (arg_rd, &opt->v.internal_rd)) + { + vty_out (vty, "Malformed RD \"%s\"%s", + arg_rd, VTY_NEWLINE); + return CMD_WARNING; + } + } + if (rfg->label <= MPLS_LABEL_MAX || arg_label) + { + struct rfapi_l2address_option *l2o; + if (opt != NULL) + opt->next = &optary[cur_opt]; + opt = &optary[cur_opt++]; + opt->type = RFAPI_VN_OPTION_TYPE_L2ADDR; + l2o = &opt->v.l2addr; + if (arg_label) + { + int32_t label; + VTY_GET_INTEGER_RANGE ("Label value", label, arg_label, 0, MPLS_LABEL_MAX); + l2o->label = label; + } + else + l2o->label = rfg->label; + } + if (arg_pref) + { + char *endptr = NULL; + pref = strtoul (arg_pref, &endptr, 10); + if (*endptr != '\0') + { + vty_out (vty, "%% Invalid local-preference value \"%s\"%s", arg_pref, VTY_NEWLINE); + return CMD_WARNING; + } + } + rpfx.cost = 255 - (pref & 255) ; + if (rfg->rfd == NULL) /* need new rfapi_handle */ + { + /* based on rfapi_open */ + struct rfapi_descriptor *rfd; + rfd = XCALLOC (MTYPE_RFAPI_DESC, sizeof (struct rfapi_descriptor)); + rfd->bgp = bgp; + rfg->rfd = rfd; + /* leave most fields empty as will get from (dynamic) config when needed */ + rfd->default_tunneltype_option.type = BGP_ENCAP_TYPE_MPLS; + rfd->cookie = rfg; + if (rfg->vn_prefix.family && + !CHECK_FLAG(rfg->flags, RFAPI_RFG_VPN_NH_SELF)) + { + rfapiQprefix2Raddr(&rfg->vn_prefix, &rfd->vn_addr); + } + else + { + memset(&rfd->vn_addr, 0, sizeof(struct rfapi_ip_addr)); + rfd->vn_addr.addr_family = AF_INET; + rfd->vn_addr.addr.v4 = bgp->router_id; + } + rfd->un_addr = rfd->vn_addr; /* sigh, need something in UN for lookups */ + vnc_zlog_debug_verbose ("%s: Opening RFD for VRF %s", + __func__, rfg->name); + rfapi_init_and_open(bgp, rfd, rfg); + } + + if (!rfapi_register (rfg->rfd, &rpfx, RFAPI_INFINITE_LIFETIME, NULL, + (cur_opt ? optary : NULL), RFAPI_REGISTER_ADD)) + { + struct rfapi_next_hop_entry *head = NULL; + struct rfapi_next_hop_entry *tail = NULL; + struct rfapi_vn_option *vn_opt_new; + + vnc_zlog_debug_verbose ("%s: rfapi_register succeeded", __func__); + + if (bgp->rfapi->rfp_methods.local_cb) + { + struct rfapi_descriptor *r = (struct rfapi_descriptor *) rfg->rfd; + vn_opt_new = rfapi_vn_options_dup (opt); + + rfapiAddDeleteLocalRfpPrefix (&r->un_addr, &r->vn_addr, &rpfx, + 1, RFAPI_INFINITE_LIFETIME, + vn_opt_new, &head, &tail); + if (head) + { + bgp->rfapi->flags |= RFAPI_INCALLBACK; + (*bgp->rfapi->rfp_methods.local_cb) (head, r->cookie); + bgp->rfapi->flags &= ~RFAPI_INCALLBACK; + } + head = tail = NULL; + } + vnc_zlog_debug_verbose ("%s completed, count=%d/%d", __func__, + rfg->rfapi_import_table->local_count[AFI_IP], + rfg->rfapi_import_table->local_count[AFI_IP6]); + return CMD_SUCCESS; + } + + vnc_zlog_debug_verbose ("%s: rfapi_register failed", __func__); + vty_out (vty, "Add failed.%s", VTY_NEWLINE); + return CMD_WARNING; +} + +DEFUN (add_vrf_prefix_rd_label_pref, + add_vrf_prefix_rd_label_pref_cmd, + "add vrf NAME prefix [rd ASN:nn_or_IP-address] [label (0-1048575)] [preference (0-4294967295)]", + "Add\n" + "To a VRF\n" + "VRF name\n" + "Add/modify prefix related information\n" + "IPv4 prefix\n" + "IPv6 prefix\n" + "Override configured VRF Route Distinguisher\n" + ": or :\n" + "Override configured VRF label" + "Label Value <0-1048575>\n" + "Set advertised local preference\n" + "local preference (higher=more preferred)\n") +{ + char *arg_vrf = argv[2]->arg; + char *arg_prefix = argv[4]->arg; + char *arg_rd = NULL; /* optional */ + char *arg_label = NULL; /* optional */ + char *arg_pref = NULL; /* optional */ + int pargc = 5; + argc--; /* don't parse argument */ + while (pargc < argc) + { + switch (argv[pargc++]->arg[0]) + { + case 'r': + arg_rd = argv[pargc]->arg; + break; + case 'l': + arg_label = argv[pargc]->arg; + break; + case 'p': + arg_pref = argv[pargc]->arg; + break; + default: + break; + } + pargc ++; + } + + return vnc_add_vrf_prefix (vty, arg_vrf, arg_prefix, arg_rd, arg_label, arg_pref); +} + +/************************************************************************ + * del prefix with vrf + * + * clear [vrf ] prefix [rd ] + ************************************************************************/ +static int +rfapi_cfg_group_it_count(struct rfapi_nve_group_cfg *rfg) +{ + int count = 0; + afi_t afi = AFI_MAX; + while (afi-- > 0) + { + count += rfg->rfapi_import_table->local_count[afi]; + } + return count; +} + +static void +clear_vnc_vrf_closer (struct rfapi_nve_group_cfg *rfg) +{ + struct rfapi_descriptor *rfd = rfg->rfd; + afi_t afi; + + if (rfd == NULL) + return; + /* check if IT is empty */ + for (afi = 0; + afi < AFI_MAX && rfg->rfapi_import_table->local_count[afi] == 0; + afi++); + + if (afi == AFI_MAX) + { + vnc_zlog_debug_verbose ("%s: closing RFD for VRF %s", + __func__, rfg->name); + rfg->rfd = NULL; + rfapi_close(rfd); + } + else + { + vnc_zlog_debug_verbose ("%s: VRF %s afi=%d count=%d", + __func__, rfg->name, afi, + rfg->rfapi_import_table->local_count[afi]); + } +} + +static int +vnc_clear_vrf (struct vty *vty, + struct bgp *bgp, + const char *arg_vrf, + const char *arg_prefix, /* NULL = all */ + const char *arg_rd) /* optional */ +{ + struct rfapi_nve_group_cfg *rfg; + struct rfapi_local_reg_delete_arg cda; + int rc; + int start_count; + + if (bgp == NULL) + bgp = bgp_get_default (); /* assume main instance for now */ + if (!bgp) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + if (!bgp->rfapi || !bgp->rfapi_cfg) + { + vty_out (vty, "VRF support not configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + rfg = bgp_rfapi_cfg_match_byname (bgp, arg_vrf, RFAPI_GROUP_CFG_VRF); + /* arg checks */ + if (!rfg) + { + vty_out (vty, "VRF \"%s\" appears not to be configured.%s", + arg_vrf, VTY_NEWLINE); + return CMD_WARNING; + } + rc = parse_deleter_args (vty, bgp, arg_prefix, NULL, NULL, NULL, NULL, + arg_rd, rfg, &cda); + if (rc != CMD_SUCCESS) /* parse error */ + return rc; + + start_count = rfapi_cfg_group_it_count(rfg); + clear_vnc_prefix (&cda); + clear_vnc_vrf_closer (rfg); + vty_out (vty, "Cleared %u out of %d prefixes.%s", + cda.pfx_count, start_count, VTY_NEWLINE); + return CMD_SUCCESS; +} + +DEFUN (clear_vrf_prefix_rd, + clear_vrf_prefix_rd_cmd, + "clear vrf NAME [prefix ] [rd ASN:nn_or_IP-address]", + "Clear stored data\n" + "From a VRF\n" + "VRF name\n" + "Prefix related information\n" + "IPv4 prefix\n" + "IPv6 prefix\n" + "Specific VRF Route Distinguisher\n" + ": or :\n") +{ + char *arg_vrf = argv[2]->arg; + char *arg_prefix = NULL; /* optional */ + char *arg_rd = NULL; /* optional */ + int pargc = 3; + argc--; /* don't check parameter */ + while (pargc < argc) + { + switch (argv[pargc++]->arg[0]) + { + case 'r': + arg_rd = argv[pargc]->arg; + break; + case 'p': + arg_prefix = argv[pargc]->arg; + break; + default: + break; + } + pargc ++; + } + return vnc_clear_vrf (vty, NULL, arg_vrf, arg_prefix, arg_rd); +} + +DEFUN (clear_vrf_all, + clear_vrf_all_cmd, + "clear vrf NAME all", + "Clear stored data\n" + "From a VRF\n" + "VRF name\n" + "All prefixes\n") +{ + char *arg_vrf = argv[2]->arg; + return vnc_clear_vrf (vty, NULL, arg_vrf, NULL, NULL); +} + void rfapi_vty_init () { install_element (ENABLE_NODE, &add_vnc_prefix_cost_life_lnh_cmd); @@ -4951,6 +5379,8 @@ void rfapi_vty_init () install_element (ENABLE_NODE, &add_vnc_mac_vni_life_cmd); install_element (ENABLE_NODE, &add_vnc_mac_vni_cmd); + install_element (ENABLE_NODE, &add_vrf_prefix_rd_label_pref_cmd); + install_element (ENABLE_NODE, &clear_vnc_nve_all_cmd); install_element (ENABLE_NODE, &clear_vnc_nve_vn_un_cmd); install_element (ENABLE_NODE, &clear_vnc_nve_un_vn_cmd); @@ -4975,6 +5405,9 @@ void rfapi_vty_init () install_element (ENABLE_NODE, &clear_vnc_mac_vn_prefix_cmd); install_element (ENABLE_NODE, &clear_vnc_mac_all_prefix_cmd); + install_element (ENABLE_NODE, &clear_vrf_prefix_rd_cmd); + install_element (ENABLE_NODE, &clear_vrf_all_cmd); + install_element (ENABLE_NODE, &vnc_clear_counters_cmd); install_element (VIEW_NODE, &vnc_show_summary_cmd); diff --git a/lib/command.c b/lib/command.c index 6294e994e7..4ac1d1abe5 100644 --- a/lib/command.c +++ b/lib/command.c @@ -741,6 +741,7 @@ node_parent ( enum node_type node ) case BGP_VPNV6_NODE: case BGP_ENCAP_NODE: case BGP_ENCAPV6_NODE: + case BGP_VRF_POLICY_NODE: case BGP_VNC_DEFAULTS_NODE: case BGP_VNC_NVE_GROUP_NODE: case BGP_VNC_L2_GROUP_NODE: @@ -1106,6 +1107,7 @@ cmd_exit (struct vty *vty) case BGP_VPNV6_NODE: case BGP_ENCAP_NODE: case BGP_ENCAPV6_NODE: + case BGP_VRF_POLICY_NODE: case BGP_VNC_DEFAULTS_NODE: case BGP_VNC_NVE_GROUP_NODE: case BGP_VNC_L2_GROUP_NODE: @@ -1169,6 +1171,7 @@ DEFUN (config_end, case BGP_NODE: case BGP_ENCAP_NODE: case BGP_ENCAPV6_NODE: + case BGP_VRF_POLICY_NODE: case BGP_VNC_DEFAULTS_NODE: case BGP_VNC_NVE_GROUP_NODE: case BGP_VNC_L2_GROUP_NODE: diff --git a/lib/command.h b/lib/command.h index 1e1698fc7d..bc68cc0c84 100644 --- a/lib/command.h +++ b/lib/command.h @@ -99,6 +99,7 @@ enum node_type BGP_IPV6M_NODE, /* BGP IPv6 multicast address family. */ BGP_ENCAP_NODE, /* BGP ENCAP SAFI */ BGP_ENCAPV6_NODE, /* BGP ENCAP SAFI */ + BGP_VRF_POLICY_NODE, /* BGP VRF policy */ BGP_VNC_DEFAULTS_NODE, /* BGP VNC nve defaults */ BGP_VNC_NVE_GROUP_NODE, /* BGP VNC nve group */ BGP_VNC_L2_GROUP_NODE, /* BGP VNC L2 group */ diff --git a/lib/vty.c b/lib/vty.c index a435706d1f..9413d003ef 100644 --- a/lib/vty.c +++ b/lib/vty.c @@ -742,6 +742,7 @@ vty_end_config (struct vty *vty) case BGP_VPNV6_NODE: case BGP_ENCAP_NODE: case BGP_ENCAPV6_NODE: + case BGP_VRF_POLICY_NODE: case BGP_VNC_DEFAULTS_NODE: case BGP_VNC_NVE_GROUP_NODE: case BGP_VNC_L2_GROUP_NODE: diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 50677b5685..51b5091c57 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -312,6 +312,10 @@ vtysh_execute_func (const char *line, int pager) { vtysh_execute("exit-address-family"); } + else if (saved_node == BGP_VRF_POLICY_NODE && (tried == 1)) + { + vtysh_execute("exit-vrf-policy"); + } else if ((saved_node == BGP_VNC_DEFAULTS_NODE || saved_node == BGP_VNC_NVE_GROUP_NODE || saved_node == BGP_VNC_L2_GROUP_NODE) && (tried == 1)) @@ -963,6 +967,11 @@ static struct cmd_node bgp_vnc_nve_group_node = "%s(config-router-vnc-nve-group)# " }; +static struct cmd_node bgp_vrf_policy_node = { + BGP_VRF_POLICY_NODE, + "%s(config-router-vrf-policy)# " +}; + static struct cmd_node bgp_vnc_l2_group_node = { BGP_VNC_L2_GROUP_NODE, @@ -1209,6 +1218,17 @@ DEFUNSH (VTYSH_BGPD, return CMD_SUCCESS; } +DEFUNSH (VTYSH_BGPD, + vnc_vrf_policy, + vnc_vrf_policy_cmd, + "vrf-policy NAME", + "Configure a VRF policy group\n" + "Group name\n") +{ + vty->node = BGP_VRF_POLICY_NODE; + return CMD_SUCCESS; +} + DEFUNSH (VTYSH_BGPD, vnc_l2_group, vnc_l2_group_cmd, @@ -1481,6 +1501,7 @@ vtysh_exit (struct vty *vty) case BGP_IPV4M_NODE: case BGP_IPV6_NODE: case BGP_IPV6M_NODE: + case BGP_VRF_POLICY_NODE: case BGP_VNC_DEFAULTS_NODE: case BGP_VNC_NVE_GROUP_NODE: case BGP_VNC_L2_GROUP_NODE: @@ -1560,6 +1581,17 @@ DEFUNSH (VTYSH_BGPD, return CMD_SUCCESS; } +DEFUNSH (VTYSH_BGPD, + exit_vrf_policy, + exit_vrf_policy_cmd, + "exit-vrf-policy", + "Exit from VRF configuration mode\n") +{ + if (vty->node == BGP_VRF_POLICY_NODE) + vty->node = BGP_NODE; + return CMD_SUCCESS; +} + DEFUNSH (VTYSH_RIPD, vtysh_exit_ripd, vtysh_exit_ripd_cmd, @@ -3042,6 +3074,7 @@ vtysh_init_vty (void) install_node (&bgp_ipv4m_node, NULL); install_node (&bgp_ipv6_node, NULL); install_node (&bgp_ipv6m_node, NULL); + install_node (&bgp_vrf_policy_node, NULL); install_node (&bgp_vnc_defaults_node, NULL); install_node (&bgp_vnc_nve_group_node, NULL); install_node (&bgp_vnc_l2_group_node, NULL); @@ -3079,6 +3112,7 @@ vtysh_init_vty (void) vtysh_install_default (BGP_IPV6_NODE); vtysh_install_default (BGP_IPV6M_NODE); #if ENABLE_BGP_VNC + vtysh_install_default (BGP_VRF_POLICY_NODE); vtysh_install_default (BGP_VNC_DEFAULTS_NODE); vtysh_install_default (BGP_VNC_NVE_GROUP_NODE); vtysh_install_default (BGP_VNC_L2_GROUP_NODE); @@ -3150,6 +3184,8 @@ vtysh_init_vty (void) install_element (BGP_IPV6M_NODE, &vtysh_exit_bgpd_cmd); install_element (BGP_IPV6M_NODE, &vtysh_quit_bgpd_cmd); #if defined (ENABLE_BGP_VNC) + install_element (BGP_VRF_POLICY_NODE, &vtysh_exit_bgpd_cmd); + install_element (BGP_VRF_POLICY_NODE, &vtysh_quit_bgpd_cmd); install_element (BGP_VNC_DEFAULTS_NODE, &vtysh_exit_bgpd_cmd); install_element (BGP_VNC_DEFAULTS_NODE, &vtysh_quit_bgpd_cmd); install_element (BGP_VNC_NVE_GROUP_NODE, &vtysh_exit_bgpd_cmd); @@ -3191,6 +3227,7 @@ vtysh_init_vty (void) install_element (BGP_ENCAPV6_NODE, &vtysh_end_all_cmd); install_element (BGP_IPV6_NODE, &vtysh_end_all_cmd); install_element (BGP_IPV6M_NODE, &vtysh_end_all_cmd); + install_element (BGP_VRF_POLICY_NODE, &vtysh_end_all_cmd); install_element (BGP_VNC_DEFAULTS_NODE, &vtysh_end_all_cmd); install_element (BGP_VNC_NVE_GROUP_NODE, &vtysh_end_all_cmd); install_element (BGP_VNC_L2_GROUP_NODE, &vtysh_end_all_cmd); @@ -3239,6 +3276,7 @@ vtysh_init_vty (void) install_element (BGP_NODE, &address_family_encapv4_cmd); install_element (BGP_NODE, &address_family_encapv6_cmd); #if defined(ENABLE_BGP_VNC) + install_element (BGP_NODE, &vnc_vrf_policy_cmd); install_element (BGP_NODE, &vnc_defaults_cmd); install_element (BGP_NODE, &vnc_nve_group_cmd); install_element (BGP_NODE, &vnc_l2_group_cmd); @@ -3256,6 +3294,7 @@ vtysh_init_vty (void) install_element (BGP_IPV6_NODE, &exit_address_family_cmd); install_element (BGP_IPV6M_NODE, &exit_address_family_cmd); + install_element (BGP_VRF_POLICY_NODE, &exit_vrf_policy_cmd); install_element (BGP_VNC_DEFAULTS_NODE, &exit_vnc_config_cmd); install_element (BGP_VNC_NVE_GROUP_NODE, &exit_vnc_config_cmd); install_element (BGP_VNC_L2_GROUP_NODE, &exit_vnc_config_cmd); From ffc50094a6afe5ff4625f952be2873815f1b0944 Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Sat, 14 Jan 2017 12:09:12 -0500 Subject: [PATCH 391/444] bgpd rfapi: add NVE/VRF name to show vnc registrations Signed-off-by: Lou Berger --- bgpd/rfapi/bgp_rfapi_cfg.c | 10 +++++----- bgpd/rfapi/rfapi_backend.h | 9 --------- bgpd/rfapi/rfapi_import.c | 4 +++- bgpd/rfapi/rfapi_import.h | 6 ++++++ bgpd/rfapi/rfapi_vty.c | 17 ++++++++++++----- 5 files changed, 26 insertions(+), 20 deletions(-) diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c index a2b0be3cc6..10b365c1c8 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.c +++ b/bgpd/rfapi/bgp_rfapi_cfg.c @@ -2463,7 +2463,7 @@ DEFUN (vnc_nve_group, rfg->rt_import_list = ecommunity_dup (bgp->rfapi_cfg->default_rt_import_list); rfg->rfapi_import_table = - rfapiImportTableRefAdd (bgp, rfg->rt_import_list); + rfapiImportTableRefAdd (bgp, rfg->rt_import_list, rfg); } /* @@ -2903,7 +2903,7 @@ DEFUN (vnc_nve_group_rt_import, */ if (rfg->rfapi_import_table) rfapiImportTableRefDelByIt (bgp, rfg->rfapi_import_table); - rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list); + rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list, rfg); if (is_export_bgp) vnc_direct_bgp_add_group (bgp, rfg); @@ -3010,7 +3010,7 @@ DEFUN (vnc_nve_group_rt_both, */ if (rfg->rfapi_import_table) rfapiImportTableRefDelByIt (bgp, rfg->rfapi_import_table); - rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list); + rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list, rfg); if (is_export_bgp) vnc_direct_bgp_add_group (bgp, rfg); @@ -3494,7 +3494,7 @@ DEFUN (vnc_vrf_policy_rt_import, */ if (rfg->rfapi_import_table) rfapiImportTableRefDelByIt (bgp, rfg->rfapi_import_table); - rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list); + rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list, rfg); if (is_export_bgp) vnc_direct_bgp_add_group (bgp, rfg); @@ -3613,7 +3613,7 @@ DEFUN (vnc_vrf_policy_rt_both, */ if (rfg->rfapi_import_table) rfapiImportTableRefDelByIt (bgp, rfg->rfapi_import_table); - rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list); + rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list, rfg); if (is_export_bgp) vnc_direct_bgp_add_group (bgp, rfg); diff --git a/bgpd/rfapi/rfapi_backend.h b/bgpd/rfapi/rfapi_backend.h index 788ec73751..9e5b0dc5cb 100644 --- a/bgpd/rfapi/rfapi_backend.h +++ b/bgpd/rfapi/rfapi_backend.h @@ -36,15 +36,6 @@ extern void rfapi_delete (struct bgp *); struct rfapi *bgp_rfapi_new (struct bgp *bgp); void bgp_rfapi_destroy (struct bgp *bgp, struct rfapi *h); -struct rfapi_import_table *rfapiImportTableRefAdd (struct bgp *bgp, - struct ecommunity - *rt_import_list); - -void -rfapiImportTableRefDelByIt (struct bgp *bgp, - struct rfapi_import_table *it_target); - - extern void rfapiProcessUpdate (struct peer *peer, void *rfd, diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index 5ba98e55d0..235992d5bf 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -4644,7 +4644,8 @@ bgp_rfapi_destroy (struct bgp *bgp, struct rfapi *h) } struct rfapi_import_table * -rfapiImportTableRefAdd (struct bgp *bgp, struct ecommunity *rt_import_list) +rfapiImportTableRefAdd (struct bgp *bgp, struct ecommunity *rt_import_list, + struct rfapi_nve_group_cfg *rfg) { struct rfapi *h; struct rfapi_import_table *it; @@ -4670,6 +4671,7 @@ rfapiImportTableRefAdd (struct bgp *bgp, struct ecommunity *rt_import_list) h->imports = it; it->rt_import_list = ecommunity_dup (rt_import_list); + it->rfg = rfg; it->monitor_exterior_orphans = skiplist_new (0, NULL, (void (*)(void *)) prefix_free); diff --git a/bgpd/rfapi/rfapi_import.h b/bgpd/rfapi/rfapi_import.h index 51afa0002f..3ba76539dd 100644 --- a/bgpd/rfapi/rfapi_import.h +++ b/bgpd/rfapi/rfapi_import.h @@ -38,6 +38,7 @@ struct rfapi_import_table { struct rfapi_import_table *next; + struct rfapi_nve_group_cfg *rfg; struct ecommunity *rt_import_list; /* copied from nve grp */ int refcount; /* nve grps and nves */ uint32_t l2_logical_net_id; /* L2 only: EVPN Eth Seg Id */ @@ -90,6 +91,11 @@ rfapiShowImportTable ( struct route_table *rt, int isvpn); +extern struct rfapi_import_table * +rfapiImportTableRefAdd ( + struct bgp *bgp, + struct ecommunity *rt_import_list, + struct rfapi_nve_group_cfg *rfg); extern void rfapiImportTableRefDelByIt ( diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index f8142ed299..7fbfae2951 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -1446,17 +1446,24 @@ rfapiShowRemoteRegistrationsIt ( if (pLni) { - fp (out, "%s[%s] L2VPN Network 0x%x (%u) RT={%s}%s", - HVTY_NEWLINE, type, *pLni, (*pLni & 0xfff), s, - HVTY_NEWLINE); + fp (out, "%s[%s] L2VPN Network 0x%x (%u) RT={%s}", + HVTY_NEWLINE, type, *pLni, (*pLni & 0xfff), s); } else { - fp (out, "%s[%s] Prefix RT={%s}%s", - HVTY_NEWLINE, type, s, HVTY_NEWLINE); + fp (out, "%s[%s] Prefix RT={%s}", + HVTY_NEWLINE, type, s); } XFREE (MTYPE_ECOMMUNITY_STR, s); + if (it->rfg && it->rfg->name) + { + fp (out, " %s \"%s\"", + (it->rfg->type == RFAPI_GROUP_CFG_VRF ? + "VRF" : "NVE group"), + it->rfg->name); + } + fp (out, "%s", HVTY_NEWLINE); if (show_expiring) { #if RFAPI_REGISTRATIONS_REPORT_AGE From ce8080dbd8e7db3d8d761142e151e3b8018c49ba Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Sun, 22 Jan 2017 20:51:12 -0500 Subject: [PATCH 392/444] bgpd: disambiguate differet forms of show bgp ipv4 vpn address-family ipv4&6 vpn Signed-off-by: Lou Berger --- bgpd/bgp_mplsvpn.c | 8 ++++---- bgpd/bgp_vty.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index bfbddb6c30..ae0f0ab1dc 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -969,7 +969,7 @@ bgp_show_mpls_vpn (struct vty *vty, afi_t afi, struct prefix_rd *prd, DEFUN (show_bgp_ip_vpn_rd, show_bgp_ip_vpn_rd_cmd, - "show [ip] bgp "BGP_AFI_CMD_STR" vpn [rd ASN:nn_or_IP-address:nn] [json]", + "show bgp "BGP_AFI_CMD_STR" vpn all [rd ASN:nn_or_IP-address:nn] [json]", SHOW_STR IP_STR BGP_STR @@ -979,7 +979,7 @@ DEFUN (show_bgp_ip_vpn_rd, "VPN Route Distinguisher\n" JSON_STR) { - int idx_ext_community = 5; + int idx_rd = 5; int ret; struct prefix_rd prd; afi_t afi; @@ -987,9 +987,9 @@ DEFUN (show_bgp_ip_vpn_rd, if (argv_find_and_parse_afi (argv, argc, &idx, &afi)) { - if (argv[idx_ext_community]->arg) + if (argc >= 7 && argv[idx_rd]->arg) { - ret = str2prefix_rd (argv[idx_ext_community]->arg, &prd); + ret = str2prefix_rd (argv[idx_rd]->arg, &prd); if (! ret) { vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index fd6718e2ac..eba4ebf1d1 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -5586,7 +5586,6 @@ DEFUN (address_family_vpnv6, vty->node = BGP_VPNV6_NODE; return CMD_SUCCESS; } -#endif /* KEEP_OLD_VPN_COMMANDS */ DEFUN (address_family_ipv4_vpn, address_family_ipv4_vpn_cmd, @@ -5609,6 +5608,7 @@ DEFUN (address_family_ipv6_vpn, vty->node = BGP_VPNV6_NODE; return CMD_SUCCESS; } +#endif /* KEEP_OLD_VPN_COMMANDS */ DEFUN (address_family_encap, address_family_encap_cmd, @@ -10711,9 +10711,9 @@ bgp_vty_init (void) #ifdef KEEP_OLD_VPN_COMMANDS install_element (BGP_NODE, &address_family_vpnv4_cmd); install_element (BGP_NODE, &address_family_vpnv6_cmd); -#endif /* KEEP_OLD_VPN_COMMANDS */ install_element (BGP_NODE, &address_family_ipv4_vpn_cmd); install_element (BGP_NODE, &address_family_ipv6_vpn_cmd); +#endif /* KEEP_OLD_VPN_COMMANDS */ install_element (BGP_NODE, &address_family_encap_cmd); install_element (BGP_NODE, &address_family_encapv6_cmd); From 7790a2d69ee8439dbed951e77703458bb472dd4f Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 23 Jan 2017 16:54:51 +0100 Subject: [PATCH 393/444] lib: time: add new monotime() helpers This adds monotime() to retrieve monotonic clock time, as well as monotime_since() and monotime_until() for relative monotonic time. Signed-off-by: David Lamparter --- lib/Makefile.am | 3 ++- lib/monotime.h | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 lib/monotime.h diff --git a/lib/Makefile.am b/lib/Makefile.am index f2c076c475..5dd38ee45a 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -46,7 +46,8 @@ pkginclude_HEADERS = \ 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 wheel.h \ - event_counter.h + event_counter.h \ + monotime.h noinst_HEADERS = \ plist_int.h diff --git a/lib/monotime.h b/lib/monotime.h new file mode 100644 index 0000000000..10d3bb604d --- /dev/null +++ b/lib/monotime.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017 David Lamparter, for NetDEF, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _FRR_MONOTIME_H +#define _FRR_MONOTIME_H + +#include +#include +#include + +#ifndef TIMESPEC_TO_TIMEVAL +/* should be in sys/time.h on BSD & Linux libcs */ +#define TIMESPEC_TO_TIMEVAL(tv, ts) do { \ + (tv)->tv_sec = (ts)->tv_sec; \ + (tv)->tv_usec = (ts)->tv_nsec / 1000; \ + } while (0) +#endif + +static inline time_t monotime(struct timeval *tvo) +{ + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + if (tvo) { + TIMESPEC_TO_TIMEVAL(tvo, &ts); + } + return ts.tv_sec; +} + +/* the following two return microseconds, not time_t! + * + * also, they're negative forms of each other, but having both makes the + * code more readable + */ +static inline int64_t monotime_since(const struct timeval *ref, + struct timeval *out) +{ + struct timeval tv; + monotime(&tv); + timersub(&tv, ref, &tv); + if (out) + *out = tv; + return (int64_t)tv.tv_sec * 1000000LL + tv.tv_usec; +} + +static inline int64_t monotime_until(const struct timeval *ref, + struct timeval *out) +{ + struct timeval tv; + monotime(&tv); + timersub(ref, &tv, &tv); + if (out) + *out = tv; + return (int64_t)tv.tv_sec * 1000000LL + tv.tv_usec; +} + +#endif /* _FRR_MONOTIME_H */ From cbf3e3eb3a6452b898b4a082b81e8ec4f9dddb26 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 17 Jan 2017 22:05:56 +0100 Subject: [PATCH 394/444] ospfd: time: replace local helpers with monotime This ditches tv_add, tv_sub, tv_cmp, etc. in favour of monotime{,_since,_until}() which actually makes the code much more readable in some locations. Signed-off-by: David Lamparter --- ospfd/ospf_dump.c | 5 +-- ospfd/ospf_flood.c | 5 +-- ospfd/ospf_lsa.c | 87 +++++++-------------------------------------- ospfd/ospf_lsa.h | 6 ---- ospfd/ospf_packet.c | 37 +++++++++---------- ospfd/ospf_spf.c | 10 +++--- ospfd/ospf_vty.c | 70 ++++++++++++++---------------------- 7 files changed, 66 insertions(+), 154 deletions(-) diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index 4e9797184d..6e9e59f9b7 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -22,6 +22,7 @@ #include +#include "monotime.h" #include "linklist.h" #include "thread.h" #include "prefix.h" @@ -317,8 +318,8 @@ ospf_timer_dump (struct thread *t, char *buf, size_t size) struct timeval result; if (!t) return "inactive"; - - result = tv_sub (t->u.sands, recent_relative_time()); + + monotime_until (&t->u.sands, &result); return ospf_timeval_dump (&result, buf, size); } diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index 7f83ddeaae..32dd8e8a91 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -22,6 +22,7 @@ #include +#include "monotime.h" #include "linklist.h" #include "prefix.h" #include "if.h" @@ -277,8 +278,8 @@ ospf_flood (struct ospf *ospf, struct ospf_neighbor *nbr, "while local one is initial instance."); ; /* Accept this LSA for quick LSDB resynchronization. */ } - else if (tv_cmp (tv_sub (recent_relative_time (), current->tv_recv), - msec2tv (ospf->min_ls_arrival)) < 0) + else if (monotime_since (¤t->tv_recv, NULL) + < ospf->min_ls_arrival * 1000LL) { if (IS_DEBUG_OSPF_EVENT) zlog_debug ("LSA[Flooding]: LSA is received recently."); diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 916d4d01c9..94575d5944 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -22,6 +22,7 @@ #include +#include "monotime.h" #include "linklist.h" #include "prefix.h" #include "if.h" @@ -62,40 +63,6 @@ get_metric (u_char *metric) } -struct timeval -tv_adjust (struct timeval a) -{ - while (a.tv_usec >= 1000000) - { - a.tv_usec -= 1000000; - a.tv_sec++; - } - - while (a.tv_usec < 0) - { - a.tv_usec += 1000000; - a.tv_sec--; - } - - return a; -} - -int -tv_ceil (struct timeval a) -{ - a = tv_adjust (a); - - return (a.tv_usec ? a.tv_sec + 1 : a.tv_sec); -} - -int -tv_floor (struct timeval a) -{ - a = tv_adjust (a); - - return a.tv_sec; -} - struct timeval int2tv (int a) { @@ -115,50 +82,22 @@ msec2tv (int a) ret.tv_sec = a/1000; ret.tv_usec = (a%1000) * 1000; - return tv_adjust (ret); -} - -struct timeval -tv_add (struct timeval a, struct timeval b) -{ - struct timeval ret; - - ret.tv_sec = a.tv_sec + b.tv_sec; - ret.tv_usec = a.tv_usec + b.tv_usec; - - return tv_adjust (ret); -} - -struct timeval -tv_sub (struct timeval a, struct timeval b) -{ - struct timeval ret; - - ret.tv_sec = a.tv_sec - b.tv_sec; - ret.tv_usec = a.tv_usec - b.tv_usec; - - return tv_adjust (ret); -} - -int -tv_cmp (struct timeval a, struct timeval b) -{ - return (a.tv_sec == b.tv_sec ? - a.tv_usec - b.tv_usec : a.tv_sec - b.tv_sec); + return ret; } int ospf_lsa_refresh_delay (struct ospf_lsa *lsa) { - struct timeval delta, now; + struct timeval delta; int delay = 0; - quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); - delta = tv_sub (now, lsa->tv_orig); - - if (tv_cmp (delta, msec2tv (OSPF_MIN_LS_INTERVAL)) < 0) + if (monotime_since (&lsa->tv_orig, &delta) < OSPF_MIN_LS_INTERVAL * 1000LL) { - delay = tv_ceil (tv_sub (msec2tv (OSPF_MIN_LS_INTERVAL), delta)); + struct timeval minv = msec2tv (OSPF_MIN_LS_INTERVAL); + timersub (&minv, &delta, &minv); + + /* TBD: remove padding to full sec, return timeval instead */ + delay = minv.tv_sec + !!minv.tv_usec; if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) zlog_debug ("LSA[Type%d:%s]: Refresh timer delay %d seconds", @@ -174,12 +113,10 @@ ospf_lsa_refresh_delay (struct ospf_lsa *lsa) int get_age (struct ospf_lsa *lsa) { - int age; + struct timeval rel; - age = ntohs (lsa->data->ls_age) - + tv_floor (tv_sub (recent_relative_time (), lsa->tv_recv)); - - return age; + monotime_since (&lsa->tv_recv, &rel); + return ntohs (lsa->data->ls_age) + rel.tv_sec; } diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index 28ecc9d4d6..8b9a0d4c49 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -227,14 +227,8 @@ struct as_external_lsa /* Prototypes. */ /* XXX: Eek, time functions, similar are in lib/thread.c */ -extern struct timeval tv_adjust (struct timeval); -extern int tv_ceil (struct timeval); -extern int tv_floor (struct timeval); extern struct timeval int2tv (int); extern struct timeval msec2tv (int); -extern struct timeval tv_add (struct timeval, struct timeval); -extern struct timeval tv_sub (struct timeval, struct timeval); -extern int tv_cmp (struct timeval, struct timeval); extern int get_age (struct ospf_lsa *); extern u_int16_t ospf_lsa_checksum (struct lsa_header *); diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index f7d1d0fa7d..2aa761d46f 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -22,6 +22,7 @@ #include +#include "monotime.h" #include "thread.h" #include "memory.h" #include "linklist.h" @@ -521,16 +522,18 @@ ospf_ls_upd_timer (struct thread *thread) struct ospf_lsa *lsa; if ((lsa = rn->info) != NULL) - /* Don't retransmit an LSA if we received it within - the last RxmtInterval seconds - this is to allow the - neighbour a chance to acknowledge the LSA as it may - have ben just received before the retransmit timer - fired. This is a small tweak to what is in the RFC, - but it will cut out out a lot of retransmit traffic - - MAG */ - if (tv_cmp (tv_sub (recent_relative_time (), lsa->tv_recv), - int2tv (retransmit_interval)) >= 0) - listnode_add (update, rn->info); + { + /* Don't retransmit an LSA if we received it within + the last RxmtInterval seconds - this is to allow the + neighbour a chance to acknowledge the LSA as it may + have ben just received before the retransmit timer + fired. This is a small tweak to what is in the RFC, + but it will cut out out a lot of retransmit traffic + - MAG */ + if (monotime_since (&lsa->tv_recv, NULL) + >= retransmit_interval * 1000000LL) + listnode_add (update, rn->info); + } } } @@ -1469,10 +1472,8 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, } else { - struct timeval t, now; - quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); - t = tv_sub (now, nbr->last_send_ts); - if (tv_cmp (t, int2tv (nbr->v_inactivity)) < 0) + if (monotime_since (&nbr->last_send_ts, NULL) + < nbr->v_inactivity * 1000000LL) { /* In states Loading and Full the slave must resend its last Database Description packet in response to @@ -2074,12 +2075,8 @@ ospf_ls_upd (struct ospf *ospf, struct ip *iph, struct ospf_header *ospfh, recent) LSA instance. */ else { - struct timeval now; - - quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); - - if (tv_cmp (tv_sub (now, current->tv_orig), - msec2tv (ospf->min_ls_arrival)) >= 0) + if (monotime_since (¤t->tv_orig, NULL) + >= ospf->min_ls_arrival * 1000LL) /* Trap NSSA type later.*/ ospf_ls_upd_send_lsa (nbr, current, OSPF_SEND_PACKET_DIRECT); DISCARD_LSA (lsa, 8); diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c index 5dfd41dd1e..dcbb0151fd 100644 --- a/ospfd/ospf_spf.c +++ b/ospfd/ospf_spf.c @@ -20,6 +20,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include +#include "monotime.h" #include "thread.h" #include "memory.h" #include "hash.h" @@ -1421,7 +1422,6 @@ void ospf_spf_calculate_schedule (struct ospf *ospf, ospf_spf_reason_t reason) { unsigned long delay, elapsed, ht; - struct timeval result; if (IS_DEBUG_OSPF_EVENT) zlog_debug ("SPF: calculation timer scheduled"); @@ -1440,11 +1440,9 @@ ospf_spf_calculate_schedule (struct ospf *ospf, ospf_spf_reason_t reason) (void *)ospf->t_spf_calc); return; } - - /* XXX Monotic timers: we only care about relative time here. */ - result = tv_sub (recent_relative_time (), ospf->ts_spf); - - elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000); + + elapsed = monotime_since (&ospf->ts_spf, NULL) / 1000; + ht = ospf->spf_holdtime * ospf->spf_hold_multiplier; if (ht > ospf->spf_max_holdtime) diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index ce12974d40..2a627f9221 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -23,6 +23,7 @@ #include #include +#include "monotime.h" #include "memory.h" #include "thread.h" #include "prefix.h" @@ -2809,10 +2810,8 @@ show_ip_ospf_area (struct vty *vty, struct ospf_area *area, json_object *json_ar json_object_boolean_true_add(json_area, "indefiniteActiveAdmin"); if (area->t_stub_router) { - struct timeval result; - unsigned long time_store = 0; - result = tv_sub (area->t_stub_router->u.sands, recent_relative_time()); - time_store = (1000 * result.tv_sec) + (result.tv_usec / 1000); + long time_store; + time_store = monotime_until(&area->t_stub_router->u.sands, NULL) / 1000LL; json_object_int_add(json_area, "activeStartupRemainderMsecs", time_store); } } @@ -2971,9 +2970,8 @@ show_ip_ospf_common (struct vty *vty, struct ospf *ospf, u_char use_json) { if (use_json) { - unsigned long time_store = 0; - result = tv_sub (ospf->t_deferred_shutdown->u.sands, recent_relative_time()); - time_store = (1000 * result.tv_sec) + (result.tv_usec / 1000); + long time_store; + time_store = monotime_until(&ospf->t_deferred_shutdown->u.sands, NULL) / 1000LL; json_object_int_add(json, "deferredShutdownMsecs", time_store); } else @@ -3066,11 +3064,9 @@ show_ip_ospf_common (struct vty *vty, struct ospf *ospf, u_char use_json) { if (ospf->ts_spf.tv_sec || ospf->ts_spf.tv_usec) { - unsigned long time_store = 0; + long time_store = 0; - result = tv_sub (recent_relative_time(), ospf->ts_spf); - result = tv_sub (result, recent_relative_time()); - time_store = (1000 * result.tv_sec) + (result.tv_usec / 1000); + time_store = monotime_since(&ospf->ts_spf, NULL) / 1000LL; json_object_int_add(json, "spfLastExecutedMsecs", time_store); time_store = (1000 * ospf->ts_spf_duration.tv_sec) + (ospf->ts_spf_duration.tv_usec / 1000); @@ -3084,7 +3080,7 @@ show_ip_ospf_common (struct vty *vty, struct ospf *ospf, u_char use_json) vty_out (vty, " SPF algorithm "); if (ospf->ts_spf.tv_sec || ospf->ts_spf.tv_usec) { - result = tv_sub (recent_relative_time(), ospf->ts_spf); + monotime_since(&ospf->ts_spf, &result); vty_out (vty, "last executed %s ago%s", ospf_timeval_dump (&result, timebuf, sizeof (timebuf)), VTY_NEWLINE); @@ -3098,13 +3094,10 @@ show_ip_ospf_common (struct vty *vty, struct ospf *ospf, u_char use_json) if (use_json) { - struct timeval temp_time; - unsigned long time_store = 0; - if (ospf->t_spf_calc) { - temp_time = tv_sub (ospf->t_spf_calc->u.sands, recent_relative_time()); - time_store = (1000 * temp_time.tv_sec) + (temp_time.tv_usec / 1000); + long time_store; + time_store = monotime_until(&ospf->t_spf_calc->u.sands, NULL) / 1000LL; json_object_int_add(json, "spfTimerDueInMsecs", time_store); } @@ -3509,16 +3502,9 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf, struct interface char timebuf[OSPF_TIME_DUMP_SIZE]; if (use_json) { - struct timeval result; - unsigned long time_store = 0; - if (oi->t_hello) - result = tv_sub (oi->t_hello->u.sands, recent_relative_time()); - else - { - result.tv_sec = 0; - result.tv_usec = 0; - } - time_store = (1000 * result.tv_sec) + (result.tv_usec / 1000); + long time_store = 0; + if (oi->t_hello) + time_store = monotime_until(&oi->t_hello->u.sands, NULL) / 1000LL; json_object_int_add(json_interface_sub, "timerHelloInMsecs", time_store); } else @@ -3708,11 +3694,9 @@ show_ip_ospf_neighbor_sub (struct vty *vty, struct ospf_interface *oi, json_obje json_neighbor = json_object_new_object(); ospf_nbr_state_message (nbr, msgbuf, 16); - struct timeval result; - unsigned long time_store = 0; + long time_store; - result = tv_sub (nbr->t_inactivity->u.sands, recent_relative_time()); - time_store = (1000 * result.tv_sec) + (result.tv_usec / 1000); + time_store = monotime_until(&nbr->t_inactivity->u.sands, NULL) / 1000LL; json_object_int_add (json_neighbor, "priority", nbr->priority); json_object_string_add (json_neighbor, "state", msgbuf); @@ -4093,9 +4077,8 @@ show_ip_ospf_nbr_nbma_detail_sub (struct vty *vty, struct ospf_interface *oi, st /* Show poll-interval timer. */ if (use_json) { - struct timeval res = tv_sub (nbr_nbma->t_poll->u.sands, recent_relative_time ()); - unsigned long time_store = 0; - time_store = (1000 * res.tv_sec) + (res.tv_usec / 1000); + long time_store; + time_store = monotime_until(&nbr_nbma->t_poll->u.sands, NULL) / 1000LL; json_object_int_add(json_sub, "pollIntervalTimerDueMsec", time_store); } else @@ -4170,11 +4153,12 @@ show_ip_ospf_neighbor_detail_sub (struct vty *vty, struct ospf_interface *oi, if (nbr->ts_last_progress.tv_sec || nbr->ts_last_progress.tv_usec) { - struct timeval res = tv_sub (recent_relative_time (), nbr->ts_last_progress); + struct timeval res; + long time_store; + + time_store = monotime_since(&nbr->ts_last_progress, &res) / 1000LL; if (use_json) { - unsigned long time_store = 0; - time_store = (1000 * res.tv_sec) + (res.tv_usec / 1000); json_object_int_add(json_sub, "lastPrgrsvChangeMsec", time_store); } else @@ -4189,11 +4173,12 @@ show_ip_ospf_neighbor_detail_sub (struct vty *vty, struct ospf_interface *oi, if (nbr->ts_last_regress.tv_sec || nbr->ts_last_regress.tv_usec) { - struct timeval res = tv_sub (recent_relative_time (), nbr->ts_last_regress); + struct timeval res; + long time_store; + + time_store = monotime_since(&nbr->ts_last_regress, &res) / 1000LL; if (use_json) { - unsigned long time_store = 0; - time_store = (1000 * res.tv_sec) + (res.tv_usec / 1000); json_object_int_add(json_sub, "lastRegressiveChangeMsec", time_store); if (nbr->last_regress_str) json_object_string_add(json_sub, "lastRegressiveChangeReason", nbr->last_regress_str); @@ -4234,9 +4219,8 @@ show_ip_ospf_neighbor_detail_sub (struct vty *vty, struct ospf_interface *oi, { if (nbr->t_inactivity) { - struct timeval res = tv_sub (nbr->t_inactivity->u.sands, recent_relative_time ()); - unsigned long time_store = 0; - time_store = (1000 * res.tv_sec) + (res.tv_usec / 1000); + long time_store; + time_store = monotime_until(&nbr->t_inactivity->u.sands, NULL) / 1000LL; json_object_int_add(json_sub, "routerDeadIntervalTimerDueMsec", time_store); } else From 95ac0ac5ff4146b28c13ba7d821909948b285a5d Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 23 Jan 2017 16:54:56 +0100 Subject: [PATCH 395/444] ospf6d: time: remove unused/duplicate helpers timersub() & timerclear() are in sys/time.h; timerstring_local() is unused. Signed-off-by: David Lamparter --- ospf6d/ospf6d.h | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/ospf6d/ospf6d.h b/ospf6d/ospf6d.h index b41e8ff001..f0bc022749 100644 --- a/ospf6d/ospf6d.h +++ b/ospf6d/ospf6d.h @@ -58,21 +58,6 @@ extern struct thread_master *master; #define OSPF6_NEIGHBOR(x) ((struct ospf6_neighbor *) (x)) /* operation on timeval structure */ -#ifndef timerclear -#define timerclear(a) (a)->tv_sec = (tvp)->tv_usec = 0 -#endif /*timerclear*/ -#ifndef timersub -#define timersub(a, b, res) \ - do { \ - (res)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ - (res)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ - if ((res)->tv_usec < 0) \ - { \ - (res)->tv_sec--; \ - (res)->tv_usec += 1000000; \ - } \ - } while (0) -#endif /*timersub*/ #define timerstring(tv, buf, size) \ do { \ if ((tv)->tv_sec / 60 / 60 / 24) \ @@ -87,15 +72,6 @@ extern struct thread_master *master; (tv)->tv_sec / 60LL % 60, \ (tv)->tv_sec % 60LL); \ } while (0) -#define timerstring_local(tv, buf, size) \ - do { \ - int ret; \ - struct tm *tm; \ - tm = localtime (&(tv)->tv_sec); \ - ret = strftime (buf, size, "%Y/%m/%d %H:%M:%S", tm); \ - if (ret == 0) \ - zlog_warn ("strftime error"); \ - } while (0) #define threadtimer_string(now, t, buf, size) \ do { \ From 6ced0e7f10d850d51f21200f5d3243cc1b90c453 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 17 Jan 2017 22:46:07 +0100 Subject: [PATCH 396/444] lib: time: remove recent_relative_time() Replace with monotime() [which is not cached]. Signed-off-by: David Lamparter --- bgpd/bgp_packet.c | 13 ++----------- lib/thread.c | 7 ------- lib/thread.h | 2 -- ospf6d/ospf6_area.c | 2 +- ospf6d/ospf6_neighbor.c | 8 +++----- ospf6d/ospf6_spf.c | 7 +------ ospfd/ospf_flood.c | 4 ++-- ospfd/ospf_lsa.c | 2 +- ospfd/ospf_nsm.c | 4 ++-- 9 files changed, 12 insertions(+), 37 deletions(-) diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 38470a3c7e..b4f5cc1e8e 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -2153,15 +2153,6 @@ bgp_marker_all_one (struct stream *s, int length) return 1; } -/* Recent thread time. - On same clock base as bgp_clock (MONOTONIC) - but can be time of last context switch to bgp_read thread. */ -static time_t -bgp_recent_clock (void) -{ - return recent_relative_time().tv_sec; -} - /* Starting point of packet process function. */ int bgp_read (struct thread *thread) @@ -2288,14 +2279,14 @@ bgp_read (struct thread *thread) bgp_open_receive (peer, size); /* XXX return value ignored! */ break; case BGP_MSG_UPDATE: - peer->readtime = bgp_recent_clock (); + peer->readtime = monotime (NULL); bgp_update_receive (peer, size); break; case BGP_MSG_NOTIFY: bgp_notify_receive (peer, size); break; case BGP_MSG_KEEPALIVE: - peer->readtime = bgp_recent_clock (); + peer->readtime = monotime (NULL); bgp_keepalive_receive (peer, size); break; case BGP_MSG_ROUTE_REFRESH_NEW: diff --git a/lib/thread.c b/lib/thread.c index 64eaae45b9..711dd3b730 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -179,13 +179,6 @@ quagga_monotime (void) return tv.tv_sec; } -/* Public export of recent_relative_time by value */ -struct timeval -recent_relative_time (void) -{ - return relative_time; -} - static unsigned int cpu_record_hash_key (struct cpu_thread_history *a) { diff --git a/lib/thread.h b/lib/thread.h index c22bb4828d..a28768e50b 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -262,8 +262,6 @@ extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before, be used instead of calling gettimeofday if a recent value is sufficient. This is guaranteed to be refreshed before a thread is called. */ extern struct timeval recent_time; -/* Similar to recent_time, but a monotonically increasing time value */ -extern struct timeval recent_relative_time (void); /* only for use in logging functions! */ extern struct thread *thread_current; diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index d9cf97a713..198526a0eb 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -388,7 +388,7 @@ ospf6_area_show (struct vty *vty, struct ospf6_area *oa) if (oa->ts_spf.tv_sec || oa->ts_spf.tv_usec) { - result = timeval_elapsed (recent_relative_time (), oa->ts_spf); + result = monotime_since(&oa->ts_spf, NULL); if (result/TIMER_SECOND_MICRO > 0) { vty_out (vty, "SPF last executed %ld.%lds ago%s", diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index e9bb2493ff..f8a0d7a317 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -633,7 +633,7 @@ ospf6_neighbor_show (struct vty *vty, struct ospf6_neighbor *on) { char router_id[16]; char duration[16]; - struct timeval now, res; + struct timeval res; char nstate[16]; char deadtime[16]; long h, m, s; @@ -645,13 +645,11 @@ ospf6_neighbor_show (struct vty *vty, struct ospf6_neighbor *on) } #endif /*HAVE_GETNAMEINFO*/ - quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); - /* Dead time */ h = m = s = 0; if (on->inactivity_timer) { - s = on->inactivity_timer->u.sands.tv_sec - recent_relative_time().tv_sec; + s = monotime_until(&on->inactivity_timer->u.sands, NULL) / 1000000LL; h = s / 3600; s -= h * 3600; m = s / 60; @@ -673,7 +671,7 @@ ospf6_neighbor_show (struct vty *vty, struct ospf6_neighbor *on) } /* Duration */ - timersub (&now, &on->last_changed, &res); + monotime_since(&on->last_changed, &res); timerstring (&res, duration, sizeof (duration)); /* diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c index 04519e7d46..9014446374 100644 --- a/ospf6d/ospf6_spf.c +++ b/ospf6d/ospf6_spf.c @@ -670,7 +670,6 @@ void ospf6_spf_schedule (struct ospf6 *ospf6, unsigned int reason) { unsigned long delay, elapsed, ht; - struct timeval now, result; ospf6_set_spf_reason(ospf6, reason); @@ -694,11 +693,7 @@ ospf6_spf_schedule (struct ospf6 *ospf6, unsigned int reason) return; } - /* XXX Monotic timers: we only care about relative time here. */ - now = recent_relative_time (); - timersub (&now, &ospf6->ts_spf, &result); - - elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000); + elapsed = monotime_since(&ospf6->ts_spf, NULL) / 1000LL; ht = ospf6->spf_holdtime * ospf6->spf_hold_multiplier; if (ht > ospf6->spf_max_holdtime) diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index 32dd8e8a91..417a7aa8d2 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -970,7 +970,7 @@ ospf_lsa_flush_area (struct ospf_lsa *lsa, struct ospf_area *area) more time for the ACK to be received and avoid retransmissions */ lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); - lsa->tv_recv = recent_relative_time (); + monotime(&lsa->tv_recv); lsa->tv_orig = lsa->tv_recv; ospf_flood_through_area (area, NULL, lsa); ospf_lsa_maxage (area->ospf, lsa); @@ -983,7 +983,7 @@ ospf_lsa_flush_as (struct ospf *ospf, struct ospf_lsa *lsa) more time for the ACK to be received and avoid retransmissions */ lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); - lsa->tv_recv = recent_relative_time (); + monotime(&lsa->tv_recv); lsa->tv_orig = lsa->tv_recv; ospf_flood_through_as (ospf, NULL, lsa); ospf_lsa_maxage (ospf, lsa); diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 94575d5944..d4811c5b21 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -165,7 +165,7 @@ ospf_lsa_new () new->flags = 0; new->lock = 1; new->retransmit_counter = 0; - new->tv_recv = recent_relative_time (); + monotime(&new->tv_recv); new->tv_orig = new->tv_recv; new->refresh_list = -1; diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index 17cc1f66c2..ccb82bf8fe 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -630,10 +630,10 @@ nsm_notice_state_change (struct ospf_neighbor *nbr, int next_state, int event) /* Advance in NSM */ if (next_state > nbr->state) - nbr->ts_last_progress = recent_relative_time (); + monotime(&nbr->ts_last_progress); else /* regression in NSM */ { - nbr->ts_last_regress = recent_relative_time (); + monotime(&nbr->ts_last_regress); nbr->last_regress_str = ospf_nsm_event_str [event]; } From 3dad49ca9499dcb917691e10ebc1685dda74cf72 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 17 Jan 2017 22:48:33 +0100 Subject: [PATCH 397/444] lib: time: remove recent_time This isn't even used anywhere. Signed-off-by: David Lamparter --- lib/log.c | 1 - lib/thread.c | 28 ---------------------------- 2 files changed, 29 deletions(-) diff --git a/lib/log.c b/lib/log.c index d48534dc18..4ab8338653 100644 --- a/lib/log.c +++ b/lib/log.c @@ -118,7 +118,6 @@ quagga_timestamp(int timestamp_precision, char *buf, size_t buflen) } cache; struct timeval clock; - /* would it be sufficient to use global 'recent_time' here? I fear not... */ gettimeofday(&clock, NULL); /* first, we update the cache if the time has changed */ diff --git a/lib/thread.c b/lib/thread.c index 711dd3b730..518a69918d 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -41,8 +41,6 @@ DEFINE_MTYPE_STATIC(LIB, THREAD_STATS, "Thread stats") #include #endif -/* Recent absolute time of day */ -struct timeval recent_time; /* Relative time, since startup */ static struct timeval relative_time; @@ -97,24 +95,6 @@ timeval_elapsed (struct timeval a, struct timeval b) + (a.tv_usec - b.tv_usec)); } -/* gettimeofday wrapper, to keep recent_time updated */ -static int -quagga_gettimeofday (struct timeval *tv) -{ - int ret; - - assert (tv); - - if (!(ret = gettimeofday (&recent_time, NULL))) - { - /* avoid copy if user passed recent_time pointer.. */ - if (tv != &recent_time) - *tv = recent_time; - return 0; - } - return ret; -} - static int quagga_get_relative (struct timeval *tv) { @@ -1418,14 +1398,6 @@ thread_getrusage (RUSAGE_T *r) quagga_get_relative (NULL); getrusage(RUSAGE_SELF, &(r->cpu)); r->real = relative_time; - -#ifdef HAVE_CLOCK_MONOTONIC - /* quagga_get_relative() only updates recent_time if gettimeofday - * based, not when using CLOCK_MONOTONIC. As we export recent_time - * and guarantee to update it before threads are run... - */ - quagga_gettimeofday(&recent_time); -#endif /* HAVE_CLOCK_MONOTONIC */ } struct thread *thread_current = NULL; From d9d5c3e8bf8e9bec894ad97a09b0bf435799de1a Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 17 Jan 2017 22:57:57 +0100 Subject: [PATCH 398/444] lib: time: remove local time helpers Signed-off-by: David Lamparter --- lib/thread.c | 65 ++++++++-------------------------------------------- 1 file changed, 9 insertions(+), 56 deletions(-) diff --git a/lib/thread.c b/lib/thread.c index 518a69918d..acec80a636 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -46,48 +46,6 @@ static struct timeval relative_time; static struct hash *cpu_record = NULL; -/* Adjust so that tv_usec is in the range [0,TIMER_SECOND_MICRO). - And change negative values to 0. */ -static struct timeval -timeval_adjust (struct timeval a) -{ - while (a.tv_usec >= TIMER_SECOND_MICRO) - { - a.tv_usec -= TIMER_SECOND_MICRO; - a.tv_sec++; - } - - while (a.tv_usec < 0) - { - a.tv_usec += TIMER_SECOND_MICRO; - a.tv_sec--; - } - - if (a.tv_sec < 0) - /* Change negative timeouts to 0. */ - a.tv_sec = a.tv_usec = 0; - - return a; -} - -static struct timeval -timeval_subtract (struct timeval a, struct timeval b) -{ - struct timeval ret; - - ret.tv_usec = a.tv_usec - b.tv_usec; - ret.tv_sec = a.tv_sec - b.tv_sec; - - return timeval_adjust (ret); -} - -static long -timeval_cmp (struct timeval a, struct timeval b) -{ - return (a.tv_sec == b.tv_sec - ? a.tv_usec - b.tv_usec : a.tv_sec - b.tv_sec); -} - unsigned long timeval_elapsed (struct timeval a, struct timeval b) { @@ -410,11 +368,9 @@ thread_timer_cmp(void *a, void *b) struct thread *thread_a = a; struct thread *thread_b = b; - long cmp = timeval_cmp(thread_a->u.sands, thread_b->u.sands); - - if (cmp < 0) + if (timercmp (&thread_a->u.sands, &thread_b->u.sands, <)) return -1; - if (cmp > 0) + if (timercmp (&thread_a->u.sands, &thread_b->u.sands, >)) return 1; return 0; } @@ -658,9 +614,9 @@ thread_timer_remain_second (struct thread *thread) struct timeval thread_timer_remain(struct thread *thread) { - quagga_get_relative(NULL); - - return timeval_subtract(thread->u.sands, relative_time); + struct timeval remain; + monotime_until(&thread->u.sands, &remain); + return remain; } /* Get new thread. */ @@ -860,7 +816,6 @@ funcname_thread_add_timer_timeval (struct thread_master *m, { struct thread *thread; struct pqueue *queue; - struct timeval alarm_time; assert (m != NULL); @@ -872,9 +827,7 @@ funcname_thread_add_timer_timeval (struct thread_master *m, /* Do we need jitter here? */ quagga_get_relative (NULL); - alarm_time.tv_sec = relative_time.tv_sec + time_relative->tv_sec; - alarm_time.tv_usec = relative_time.tv_usec + time_relative->tv_usec; - thread->u.sands = timeval_adjust(alarm_time); + timeradd (&relative_time, time_relative, &thread->u.sands); pqueue_enqueue(thread, queue); return thread; @@ -1110,7 +1063,7 @@ thread_timer_wait (struct pqueue *queue, struct timeval *timer_val) if (queue->size) { struct thread *next_timer = queue->array[0]; - *timer_val = timeval_subtract (next_timer->u.sands, relative_time); + timersub (&next_timer->u.sands, &relative_time, timer_val); return timer_val; } return NULL; @@ -1238,7 +1191,7 @@ thread_timer_process (struct pqueue *queue, struct timeval *timenow) while (queue->size) { thread = queue->array[0]; - if (timeval_cmp (*timenow, thread->u.sands) < 0) + if (timercmp (timenow, &thread->u.sands, <)) return ready; pqueue_dequeue(queue); thread->type = THREAD_READY; @@ -1317,7 +1270,7 @@ thread_fetch (struct thread_master *m, struct thread *fetch) timer_wait_bg = thread_timer_wait (m->background, &timer_val_bg); if (timer_wait_bg && - (!timer_wait || (timeval_cmp (*timer_wait, *timer_wait_bg) > 0))) + (!timer_wait || (timercmp (timer_wait, timer_wait_bg, >)))) timer_wait = timer_wait_bg; } From afe4c21720ed9956ba4034a64508f38d3cedc17e Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 17 Jan 2017 23:07:59 +0100 Subject: [PATCH 399/444] *: remove quagga_gettime() return value checks The next patch will bulk-replace these, and monotime() has time_t as return value, not an error indicator. Signed-off-by: David Lamparter --- ospf6d/ospf6_lsa.c | 8 ++------ ospf6d/ospf6_message.c | 5 +---- zebra/zebra_fpm.c | 20 +++----------------- 3 files changed, 6 insertions(+), 27 deletions(-) diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c index 06962ec069..92ee9662b7 100644 --- a/ospf6d/ospf6_lsa.c +++ b/ospf6d/ospf6_lsa.c @@ -207,9 +207,7 @@ ospf6_lsa_age_set (struct ospf6_lsa *lsa) assert (lsa && lsa->header); - if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &now) < 0) - zlog_warn ("LSA: quagga_gettime failed, may fail LSA AGEs: %s", - safe_strerror (errno)); + quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); lsa->birth.tv_sec = now.tv_sec - ntohs (lsa->header->age); lsa->birth.tv_usec = now.tv_usec; @@ -230,9 +228,7 @@ ospf6_lsa_age_current (struct ospf6_lsa *lsa) assert (lsa->header); /* current time */ - if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &now) < 0) - zlog_warn ("LSA: quagga_gettime failed, may fail LSA AGEs: %s", - safe_strerror (errno)); + quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); if (ntohs (lsa->header->age) >= OSPF_LSA_MAXAGE) { diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c index e9a25d37e5..229c1ef557 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -1817,10 +1817,7 @@ ospf6_dbdesc_send (struct thread *thread) if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT) && (on->dbdesc_seqnum == 0)) { - struct timeval tv; - if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0) - tv.tv_sec = 1; - on->dbdesc_seqnum = tv.tv_sec; + on->dbdesc_seqnum = quagga_monotime (); } dbdesc->options[0] = on->ospf6_if->area->options[0]; diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index 8b337152b4..d44c75383b 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -296,20 +296,6 @@ zfpm_state_to_str (zfpm_state_t state) } } -/* - * zfpm_get_time - */ -static time_t -zfpm_get_time (void) -{ - struct timeval tv; - - if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0) - zlog_warn ("FPM: quagga_gettime failed!!"); - - return tv.tv_sec; -} - /* * zfpm_get_elapsed_time * @@ -320,7 +306,7 @@ zfpm_get_elapsed_time (time_t reference) { time_t now; - now = zfpm_get_time (); + now = quagga_monotime (); if (now < reference) { @@ -1177,7 +1163,7 @@ zfpm_connect_cb (struct thread *t) */ zfpm_g->connect_calls++; zfpm_g->stats.connect_calls++; - zfpm_g->last_connect_call_time = zfpm_get_time (); + zfpm_g->last_connect_call_time = quagga_monotime (); ret = connect (sock, (struct sockaddr *) &serv, sizeof (serv)); if (ret >= 0) @@ -1531,7 +1517,7 @@ zfpm_clear_stats (struct vty *vty) zfpm_stop_stats_timer (); zfpm_start_stats_timer (); - zfpm_g->last_stats_clear_time = zfpm_get_time(); + zfpm_g->last_stats_clear_time = quagga_monotime(); vty_out (vty, "Cleared FPM stats%s", VTY_NEWLINE); } From cf672a865428b5e55844b6d2e01ca9d3bd4afe6b Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 18 Jan 2017 01:30:43 +0100 Subject: [PATCH 400/444] *: use monotime() This is largely a bulk-replace made with coccinelle. Signed-off-by: David Lamparter --- bgpd/bgpd.c | 2 +- isisd/isis_spf.c | 4 ++-- lib/bfd.c | 2 +- lib/thread.c | 24 ------------------------ lib/thread.h | 8 +------- ospf6d/ospf6_abr.c | 2 +- ospf6d/ospf6_bfd.c | 2 +- ospf6d/ospf6_flood.c | 6 +++--- ospf6d/ospf6_interface.c | 2 +- ospf6d/ospf6_intra.c | 4 ++-- ospf6d/ospf6_lsa.c | 6 +++--- ospf6d/ospf6_message.c | 2 +- ospf6d/ospf6_neighbor.c | 8 ++++---- ospf6d/ospf6_route.c | 6 +++--- ospf6d/ospf6_spf.c | 4 ++-- ospf6d/ospf6_top.c | 4 ++-- ospfd/ospf_ase.c | 4 ++-- ospfd/ospf_bfd.c | 2 +- ospfd/ospf_lsa.c | 8 ++++---- ospfd/ospf_packet.c | 2 +- ospfd/ospf_spf.c | 22 +++++++++++----------- ospfd/ospfd.c | 6 +++--- tests/test-timer-performance.c | 6 +++--- zebra/zebra_fpm.c | 6 +++--- zebra/zebra_rnh.c | 2 +- zebra/zserv.c | 14 +++++++------- 26 files changed, 64 insertions(+), 94 deletions(-) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 5457822f3b..3cd1ac65c0 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -348,7 +348,7 @@ time_t bgp_clock (void) { struct timeval tv; - quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv); + monotime(&tv); return tv.tv_sec; } diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 086f5b23da..c1fb062e55 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -1149,7 +1149,7 @@ isis_run_spf (struct isis_area *area, int level, int family, u_char *sysid) unsigned long long start_time, end_time; /* Get time that can't roll backwards. */ - quagga_gettime(QUAGGA_CLK_MONOTONIC, &time_now); + monotime(&time_now); start_time = time_now.tv_sec; start_time = (start_time * 1000000) + time_now.tv_usec; @@ -1243,7 +1243,7 @@ out: spftree->pending = 0; spftree->runcount++; spftree->last_run_timestamp = time (NULL); - quagga_gettime(QUAGGA_CLK_MONOTONIC, &time_now); + monotime(&time_now); end_time = time_now.tv_sec; end_time = (end_time * 1000000) + time_now.tv_usec; spftree->last_run_duration = end_time - start_time; diff --git a/lib/bfd.c b/lib/bfd.c index 5db08fea60..a5edaea217 100644 --- a/lib/bfd.c +++ b/lib/bfd.c @@ -362,7 +362,7 @@ bfd_last_update (time_t last_update, char *buf, size_t len) } /* Get current time. */ - quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv); + monotime(&tv); curr = tv.tv_sec; diff = curr - last_update; tm = gmtime (&diff); diff --git a/lib/thread.c b/lib/thread.c index acec80a636..cb7676f0e2 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -93,30 +93,6 @@ quagga_get_relative (struct timeval *tv) return ret; } -/* Exported Quagga timestamp function. - * Modelled on POSIX clock_gettime. - */ -int -quagga_gettime (enum quagga_clkid clkid, struct timeval *tv) -{ - switch (clkid) - { - case QUAGGA_CLK_MONOTONIC: - return quagga_get_relative (tv); - default: - errno = EINVAL; - return -1; - } -} - -time_t -quagga_monotime (void) -{ - struct timeval tv; - quagga_get_relative(&tv); - return tv.tv_sec; -} - static unsigned int cpu_record_hash_key (struct cpu_thread_history *a) { diff --git a/lib/thread.h b/lib/thread.h index a28768e50b..348e4e155a 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -23,6 +23,7 @@ #define _ZEBRA_THREAD_H #include +#include "monotime.h" struct rusage_t { @@ -247,13 +248,6 @@ extern void thread_set_yield_time (struct thread *, unsigned long); extern void thread_getrusage (RUSAGE_T *); extern void thread_cmd_init (void); -/* replacements for the system gettimeofday(), clock_gettime() and - * time() functions, providing support for non-decrementing clock on - * all systems, and fully monotonic on /some/ systems. - */ -extern int quagga_gettime (enum quagga_clkid, struct timeval *); -extern time_t quagga_monotime (void); - /* Returns elapsed real (wall clock) time. */ extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before, unsigned long *cpu_time_elapsed); diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index f75a35fa50..2e31535d24 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -433,7 +433,7 @@ ospf6_abr_originate_summary_to_area (struct ospf6_route *route, else { summary->type = route->type; - quagga_gettime (QUAGGA_CLK_MONOTONIC, &summary->changed); + monotime(&summary->changed); } summary->path.router_bits = route->path.router_bits; diff --git a/ospf6d/ospf6_bfd.c b/ospf6d/ospf6_bfd.c index 28126918b5..fed5021208 100644 --- a/ospf6d/ospf6_bfd.c +++ b/ospf6d/ospf6_bfd.c @@ -245,7 +245,7 @@ ospf6_bfd_interface_dest_update (int command, struct zclient *zclient, old_status = bfd_info->status; bfd_info->status = status; - quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv); + monotime(&tv); bfd_info->last_update = tv.tv_sec; if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c index 14c16c0241..6ac93d8984 100644 --- a/ospf6d/ospf6_flood.c +++ b/ospf6d/ospf6_flood.c @@ -224,7 +224,7 @@ ospf6_install_lsa (struct ospf6_lsa *lsa) ospf6_flood_clear (old); } - quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); + monotime(&now); if (! OSPF6_LSA_IS_MAXAGE (lsa)) lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa, OSPF_LSA_MAXAGE + lsa->birth.tv_sec - now.tv_sec); @@ -862,7 +862,7 @@ ospf6_receive_lsa (struct ospf6_neighbor *from, if (old) { struct timeval now, res; - quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); + monotime(&now); timersub (&now, &old->installed, &res); time_delta_ms = (res.tv_sec * 1000) + (int)(res.tv_usec/1000); if (time_delta_ms < from->ospf6_if->area->ospf6->lsa_minarrival) @@ -875,7 +875,7 @@ ospf6_receive_lsa (struct ospf6_neighbor *from, } } - quagga_gettime (QUAGGA_CLK_MONOTONIC, &new->received); + monotime(&new->received); if (is_debug) zlog_debug ("Install, Flood, Possibly acknowledge the received LSA"); diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 0ed8d30a8b..c458098099 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -961,7 +961,7 @@ ospf6_interface_show (struct vty *vty, struct interface *ifp) vty_out (vty, " Number of I/F scoped LSAs is %u%s", oi->lsdb->count, VNL); - quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); + monotime(&now); timerclear (&res); if (oi->thread_send_lsupdate) diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index 586bd77f75..d93406fb68 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -1485,11 +1485,11 @@ ospf6_brouter_debug_print (struct ospf6_route *brouter) ospf6_linkstate_prefix2str (&brouter->prefix, destination, sizeof (destination)); - quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); + monotime(&now); timersub (&now, &brouter->installed, &res); timerstring (&res, installed, sizeof (installed)); - quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); + monotime(&now); timersub (&now, &brouter->changed, &res); timerstring (&res, changed, sizeof (changed)); diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c index 92ee9662b7..bea153c928 100644 --- a/ospf6d/ospf6_lsa.c +++ b/ospf6d/ospf6_lsa.c @@ -207,7 +207,7 @@ ospf6_lsa_age_set (struct ospf6_lsa *lsa) assert (lsa && lsa->header); - quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); + monotime(&now); lsa->birth.tv_sec = now.tv_sec - ntohs (lsa->header->age); lsa->birth.tv_usec = now.tv_usec; @@ -228,7 +228,7 @@ ospf6_lsa_age_current (struct ospf6_lsa *lsa) assert (lsa->header); /* current time */ - quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); + monotime(&now); if (ntohs (lsa->header->age) >= OSPF_LSA_MAXAGE) { @@ -509,7 +509,7 @@ ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) inet_ntop (AF_INET, &lsa->header->adv_router, adv_router, sizeof (adv_router)); - quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); + monotime(&now); timersub (&now, &lsa->installed, &res); timerstring (&res, duration, sizeof (duration)); diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c index 229c1ef557..578b39a641 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -1817,7 +1817,7 @@ ospf6_dbdesc_send (struct thread *thread) if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT) && (on->dbdesc_seqnum == 0)) { - on->dbdesc_seqnum = quagga_monotime (); + on->dbdesc_seqnum = monotime(NULL); } dbdesc->options[0] = on->ospf6_if->area->options[0]; diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index f8a0d7a317..ec79a1552b 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -97,7 +97,7 @@ ospf6_neighbor_create (u_int32_t router_id, struct ospf6_interface *oi) on->ospf6_if = oi; on->state = OSPF6_NEIGHBOR_DOWN; on->state_change = 0; - quagga_gettime (QUAGGA_CLK_MONOTONIC, &on->last_changed); + monotime(&on->last_changed); on->router_id = router_id; on->summary_list = ospf6_lsdb_create (on); @@ -163,7 +163,7 @@ ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on, int e return; on->state_change++; - quagga_gettime (QUAGGA_CLK_MONOTONIC, &on->last_changed); + monotime(&on->last_changed); /* log */ if (IS_OSPF6_DEBUG_NEIGHBOR (STATE)) @@ -705,7 +705,7 @@ ospf6_neighbor_show_drchoice (struct vty *vty, struct ospf6_neighbor *on) inet_ntop (AF_INET, &on->drouter, drouter, sizeof (drouter)); inet_ntop (AF_INET, &on->bdrouter, bdrouter, sizeof (bdrouter)); - quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); + monotime(&now); timersub (&now, &on->last_changed, &res); timerstring (&res, duration, sizeof (duration)); @@ -729,7 +729,7 @@ ospf6_neighbor_show_detail (struct vty *vty, struct ospf6_neighbor *on) inet_ntop (AF_INET, &on->drouter, drouter, sizeof (drouter)); inet_ntop (AF_INET, &on->bdrouter, bdrouter, sizeof (bdrouter)); - quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); + monotime(&now); timersub (&now, &on->last_changed, &res); timerstring (&res, duration, sizeof (duration)); diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index 2f416e2689..29956c61a0 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -600,7 +600,7 @@ ospf6_route_add (struct ospf6_route *route, else if (IS_OSPF6_DEBUG_ROUTE (TABLE)) zlog_debug ("%s: route add: %s", ospf6_route_table_name (table), buf); - quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); + monotime(&now); node = route_node_get (table->table, &route->prefix); route->rnode = node; @@ -1020,7 +1020,7 @@ ospf6_route_show (struct vty *vty, struct ospf6_route *route) struct listnode *node; struct ospf6_nexthop *nh; - quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); + monotime(&now); timersub (&now, &route->changed, &res); timerstring (&res, duration, sizeof (duration)); @@ -1068,7 +1068,7 @@ ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route) struct listnode *node; struct ospf6_nexthop *nh; - quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); + monotime(&now); /* destination */ if (route->type == OSPF6_DEST_TYPE_LINKSTATE) diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c index 9014446374..333ce5588e 100644 --- a/ospf6d/ospf6_spf.c +++ b/ospf6d/ospf6_spf.c @@ -603,7 +603,7 @@ ospf6_spf_calculation_thread (struct thread *t) ospf6->t_spf_calc = NULL; /* execute SPF calculation */ - quagga_gettime (QUAGGA_CLK_MONOTONIC, &start); + monotime(&start); if (ospf6_is_router_abr (ospf6)) ospf6_abr_range_reset_cost (ospf6); @@ -644,7 +644,7 @@ ospf6_spf_calculation_thread (struct thread *t) if (ospf6_is_router_abr (ospf6)) ospf6_abr_defaults_to_stub (ospf6); - quagga_gettime (QUAGGA_CLK_MONOTONIC, &end); + monotime(&end); timersub (&end, &start, &runtime); ospf6->ts_spf_duration = runtime; diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 6da9680fe2..92111c73fc 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -124,7 +124,7 @@ ospf6_create (void) o = XCALLOC (MTYPE_OSPF6_TOP, sizeof (struct ospf6)); /* initialize */ - quagga_gettime (QUAGGA_CLK_MONOTONIC, &o->starttime); + monotime(&o->starttime); o->area_list = list_new (); o->area_list->cmp = ospf6_area_cmp; o->lsdb = ospf6_lsdb_create (o); @@ -891,7 +891,7 @@ ospf6_show (struct vty *vty, struct ospf6 *o) router_id, VNL); /* running time */ - quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); + monotime(&now); timersub (&now, &o->starttime, &running); timerstring (&running, duration, sizeof (duration)); vty_out (vty, " Running %s%s", duration, VNL); diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c index fe40b10171..b063f317e2 100644 --- a/ospfd/ospf_ase.c +++ b/ospfd/ospf_ase.c @@ -649,7 +649,7 @@ ospf_ase_calculate_timer (struct thread *t) { ospf->ase_calc = 0; - quagga_gettime(QUAGGA_CLK_MONOTONIC, &start_time); + monotime(&start_time); /* Calculate external route for each AS-external-LSA */ LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) @@ -681,7 +681,7 @@ ospf_ase_calculate_timer (struct thread *t) ospf->old_external_route = ospf->new_external_route; ospf->new_external_route = route_table_init (); - quagga_gettime(QUAGGA_CLK_MONOTONIC, &stop_time); + monotime(&stop_time); zlog_info ("SPF Processing Time(usecs): External Routes: %lld\n", (stop_time.tv_sec - start_time.tv_sec)*1000000LL+ diff --git a/ospfd/ospf_bfd.c b/ospfd/ospf_bfd.c index b4d50a6b9f..74bc38220b 100644 --- a/ospfd/ospf_bfd.c +++ b/ospfd/ospf_bfd.c @@ -249,7 +249,7 @@ ospf_bfd_interface_dest_update (int command, struct zclient *zclient, old_status = bfd_info->status; bfd_info->status = status; - quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv); + monotime(&tv); bfd_info->last_update = tv.tv_sec; if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index d4811c5b21..cf9943893a 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -3638,8 +3638,8 @@ ospf_refresher_register_lsa (struct ospf *ospf, struct ospf_lsa *lsa) */ delay = (random() % (max_delay - min_delay)) + min_delay; - current_index = ospf->lsa_refresh_queue.index + (quagga_monotime () - - ospf->lsa_refresher_started)/OSPF_LSA_REFRESHER_GRANULARITY; + current_index = ospf->lsa_refresh_queue.index + (monotime(NULL) + - ospf->lsa_refresher_started)/OSPF_LSA_REFRESHER_GRANULARITY; index = (current_index + delay/OSPF_LSA_REFRESHER_GRANULARITY) % (OSPF_LSA_REFRESHER_SLOTS); @@ -3702,7 +3702,7 @@ ospf_lsa_refresh_walker (struct thread *t) modulus. */ ospf->lsa_refresh_queue.index = ((unsigned long)(ospf->lsa_refresh_queue.index + - (quagga_monotime () - ospf->lsa_refresher_started) + (monotime(NULL) - ospf->lsa_refresher_started) / OSPF_LSA_REFRESHER_GRANULARITY)) % OSPF_LSA_REFRESHER_SLOTS; @@ -3743,7 +3743,7 @@ ospf_lsa_refresh_walker (struct thread *t) ospf->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker, ospf, ospf->lsa_refresh_interval); - ospf->lsa_refresher_started = quagga_monotime (); + ospf->lsa_refresher_started = monotime(NULL); for (ALL_LIST_ELEMENTS (lsa_to_refresh, node, nnode, lsa)) { diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 2aa761d46f..bf78336ad5 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -3574,7 +3574,7 @@ ospf_db_desc_send (struct ospf_neighbor *nbr) if (nbr->last_send) ospf_packet_free (nbr->last_send); nbr->last_send = ospf_packet_dup (op); - quagga_gettime (QUAGGA_CLK_MONOTONIC, &nbr->last_send_ts); + monotime(&nbr->last_send_ts); } /* Re-send Database Description. */ diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c index dcbb0151fd..2b00ff3d74 100644 --- a/ospfd/ospf_spf.c +++ b/ospfd/ospf_spf.c @@ -1280,7 +1280,7 @@ ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table, /* Increment SPF Calculation Counter. */ area->spf_calculation++; - quagga_gettime (QUAGGA_CLK_MONOTONIC, &area->ospf->ts_spf); + monotime(&area->ospf->ts_spf); area->ts_spf = area->ospf->ts_spf; if (IS_DEBUG_OSPF_EVENT) @@ -1312,7 +1312,7 @@ ospf_spf_calculate_timer (struct thread *thread) ospf->t_spf_calc = NULL; - quagga_gettime (QUAGGA_CLK_MONOTONIC, &spf_start_time); + monotime(&spf_start_time); /* Allocate new table tree. */ new_table = route_table_init (); new_rtrs = route_table_init (); @@ -1339,7 +1339,7 @@ ospf_spf_calculate_timer (struct thread *thread) areas_processed++; } - quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time); + monotime(&stop_time); spf_time = timeval_elapsed (stop_time, spf_start_time); ospf_vl_shut_unapproved (ospf); @@ -1348,14 +1348,14 @@ ospf_spf_calculate_timer (struct thread *thread) ospf_ia_routing (ospf, new_table, new_rtrs); - quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time); + monotime(&stop_time); ia_time = timeval_elapsed (stop_time, start_time); - quagga_gettime (QUAGGA_CLK_MONOTONIC, &start_time); + monotime(&start_time); ospf_prune_unreachable_networks (new_table); ospf_prune_unreachable_routers (new_rtrs); - quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time); + monotime(&stop_time); prune_time = timeval_elapsed (stop_time, start_time); /* AS-external-LSA calculation should not be performed here. */ @@ -1366,12 +1366,12 @@ ospf_spf_calculate_timer (struct thread *thread) ospf_ase_calculate_timer_add (ospf); - quagga_gettime (QUAGGA_CLK_MONOTONIC, &start_time); + monotime(&start_time); /* Update routing table. */ ospf_route_install (ospf, new_table); - quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time); + monotime(&stop_time); rt_time = timeval_elapsed (stop_time, start_time); /* Update ABR/ASBR routing table */ if (ospf->old_rtrs) @@ -1384,14 +1384,14 @@ ospf_spf_calculate_timer (struct thread *thread) ospf->old_rtrs = ospf->new_rtrs; ospf->new_rtrs = new_rtrs; - quagga_gettime (QUAGGA_CLK_MONOTONIC, &start_time); + monotime(&start_time); if (IS_OSPF_ABR (ospf)) ospf_abr_task (ospf); - quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time); + monotime(&stop_time); abr_time = timeval_elapsed (stop_time, start_time); - quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time); + monotime(&stop_time); total_spf_time = timeval_elapsed (stop_time, spf_start_time); ospf->ts_spf_duration.tv_sec = total_spf_time/1000000; ospf->ts_spf_duration.tv_usec = total_spf_time % 1000000; diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index b7542c2a8b..0398bc21b8 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -273,7 +273,7 @@ ospf_new (u_short instance) new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT; new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker, new, new->lsa_refresh_interval); - new->lsa_refresher_started = quagga_monotime (); + new->lsa_refresher_started = monotime(NULL); if ((new->fd = ospf_sock_init()) < 0) { @@ -1583,7 +1583,7 @@ ospf_timers_refresh_set (struct ospf *ospf, int interval) return 1; time_left = ospf->lsa_refresh_interval - - (quagga_monotime () - ospf->lsa_refresher_started); + (monotime(NULL) - ospf->lsa_refresher_started); if (time_left > interval) { @@ -1602,7 +1602,7 @@ ospf_timers_refresh_unset (struct ospf *ospf) int time_left; time_left = ospf->lsa_refresh_interval - - (quagga_monotime () - ospf->lsa_refresher_started); + (monotime(NULL) - ospf->lsa_refresher_started); if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT) { diff --git a/tests/test-timer-performance.c b/tests/test-timer-performance.c index ee45ede6ac..a7d09beecc 100644 --- a/tests/test-timer-performance.c +++ b/tests/test-timer-performance.c @@ -61,7 +61,7 @@ int main(int argc, char **argv) for (i = 0; i < SCHEDULE_TIMERS; i++) thread_cancel(timers[i]); - quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv_start); + monotime(&tv_start); for (i = 0; i < SCHEDULE_TIMERS; i++) { @@ -72,7 +72,7 @@ int main(int argc, char **argv) NULL, interval_msec); } - quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv_lap); + monotime(&tv_lap); for (i = 0; i < REMOVE_TIMERS; i++) { @@ -84,7 +84,7 @@ int main(int argc, char **argv) timers[index] = NULL; } - quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv_stop); + monotime(&tv_stop); t_schedule = 1000 * (tv_lap.tv_sec - tv_start.tv_sec); t_schedule += (tv_lap.tv_usec - tv_start.tv_usec) / 1000; diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index d44c75383b..1b2ae29eaa 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -306,7 +306,7 @@ zfpm_get_elapsed_time (time_t reference) { time_t now; - now = quagga_monotime (); + now = monotime(NULL); if (now < reference) { @@ -1163,7 +1163,7 @@ zfpm_connect_cb (struct thread *t) */ zfpm_g->connect_calls++; zfpm_g->stats.connect_calls++; - zfpm_g->last_connect_call_time = quagga_monotime (); + zfpm_g->last_connect_call_time = monotime(NULL); ret = connect (sock, (struct sockaddr *) &serv, sizeof (serv)); if (ret >= 0) @@ -1517,7 +1517,7 @@ zfpm_clear_stats (struct vty *vty) zfpm_stop_stats_timer (); zfpm_start_stats_timer (); - zfpm_g->last_stats_clear_time = quagga_monotime(); + zfpm_g->last_stats_clear_time = monotime(NULL); vty_out (vty, "Cleared FPM stats%s", VTY_NEWLINE); } diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 315d4832dd..182cfe552d 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -922,7 +922,7 @@ send_client (struct rnh *rnh, struct zserv *client, rnh_type_t type, vrf_id_t vr } stream_putw_at (s, 0, stream_get_endp (s)); - client->nh_last_upd_time = quagga_monotime(); + client->nh_last_upd_time = monotime(NULL); client->last_write_cmd = cmd; return zebra_server_send_message(client); } diff --git a/zebra/zserv.c b/zebra/zserv.c index 6a15b9a251..dbf4262bd8 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -100,7 +100,7 @@ zserv_flush_data(struct thread *thread) break; } - client->last_write_time = quagga_monotime(); + client->last_write_time = monotime(NULL); return 0; } @@ -134,7 +134,7 @@ zebra_server_send_message(struct zserv *client) break; } - client->last_write_time = quagga_monotime(); + client->last_write_time = monotime(NULL); return 0; } @@ -826,7 +826,7 @@ zserv_rnh_register (struct zserv *client, int sock, u_short length, s = client->ibuf; - client->nh_reg_time = quagga_monotime(); + client->nh_reg_time = monotime(NULL); while (l < length) { @@ -914,7 +914,7 @@ zserv_rnh_unregister (struct zserv *client, int sock, u_short length, rnh = zebra_lookup_rnh(&p, zvrf_id (zvrf), type); if (rnh) { - client->nh_dereg_time = quagga_monotime(); + client->nh_dereg_time = monotime(NULL); zebra_remove_rnh_client(rnh, client, type); } } @@ -1826,7 +1826,7 @@ zebra_client_create (int sock) /* Set table number. */ client->rtm_table = zebrad.rtm_table_default; - client->connect_time = quagga_monotime(); + client->connect_time = monotime(NULL); /* Initialize flags */ for (afi = AFI_IP; afi < AFI_MAX; afi++) for (i = 0; i < ZEBRA_ROUTE_MAX; i++) @@ -1952,7 +1952,7 @@ zebra_client_read (struct thread *thread) zlog_debug ("zebra message received [%s] %d in VRF %u", zserv_command_string (command), length, vrf_id); - client->last_read_time = quagga_monotime(); + client->last_read_time = monotime(NULL); client->last_read_cmd = command; zvrf = zebra_vrf_lookup_by_id (vrf_id); @@ -2263,7 +2263,7 @@ zserv_time_buf(time_t *time1, char *buf, int buflen) return (buf); } - now = quagga_monotime(); + now = monotime(NULL); now -= *time1; tm = gmtime(&now); From 816c2194ca4198767c766d729636fd4af6afedf0 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 23 Jan 2017 18:16:03 +0100 Subject: [PATCH 401/444] ospfd: simplify SPF time consumption calculations monotime_since() does exactly the same thing. ... and timeval_elapsed is now private to lib/thread.c Signed-off-by: David Lamparter --- lib/thread.c | 2 +- lib/thread.h | 1 - ospfd/ospf_spf.c | 30 +++++++++--------------------- 3 files changed, 10 insertions(+), 23 deletions(-) diff --git a/lib/thread.c b/lib/thread.c index cb7676f0e2..fe4f5c11c9 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -46,7 +46,7 @@ static struct timeval relative_time; static struct hash *cpu_record = NULL; -unsigned long +static unsigned long timeval_elapsed (struct timeval a, struct timeval b) { return (((a.tv_sec - b.tv_sec) * TIMER_SECOND_MICRO) diff --git a/lib/thread.h b/lib/thread.h index 348e4e155a..a0801e1ecd 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -240,7 +240,6 @@ extern void thread_call (struct thread *); extern unsigned long thread_timer_remain_second (struct thread *); extern struct timeval thread_timer_remain(struct thread*); extern int thread_should_yield (struct thread *); -extern unsigned long timeval_elapsed (struct timeval a, struct timeval b); /* set yield time for thread */ extern void thread_set_yield_time (struct thread *, unsigned long); diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c index 2b00ff3d74..077d0e68ad 100644 --- a/ospfd/ospf_spf.c +++ b/ospfd/ospf_spf.c @@ -1301,7 +1301,7 @@ ospf_spf_calculate_timer (struct thread *thread) struct route_table *new_table, *new_rtrs; struct ospf_area *area; struct listnode *node, *nnode; - struct timeval start_time, stop_time, spf_start_time; + struct timeval start_time, spf_start_time; int areas_processed = 0; unsigned long ia_time, prune_time, rt_time; unsigned long abr_time, total_spf_time, spf_time; @@ -1339,24 +1339,19 @@ ospf_spf_calculate_timer (struct thread *thread) areas_processed++; } - monotime(&stop_time); - spf_time = timeval_elapsed (stop_time, spf_start_time); + spf_time = monotime_since(&spf_start_time, NULL); ospf_vl_shut_unapproved (ospf); - start_time = stop_time; /* saving a call */ - + monotime(&start_time); ospf_ia_routing (ospf, new_table, new_rtrs); - - monotime(&stop_time); - ia_time = timeval_elapsed (stop_time, start_time); + ia_time = monotime_since(&start_time, NULL); monotime(&start_time); ospf_prune_unreachable_networks (new_table); ospf_prune_unreachable_routers (new_rtrs); + prune_time = monotime_since(&start_time, NULL); - monotime(&stop_time); - prune_time = timeval_elapsed (stop_time, start_time); /* AS-external-LSA calculation should not be performed here. */ /* If new Router Route is installed, @@ -1366,13 +1361,11 @@ ospf_spf_calculate_timer (struct thread *thread) ospf_ase_calculate_timer_add (ospf); - monotime(&start_time); - /* Update routing table. */ + monotime(&start_time); ospf_route_install (ospf, new_table); + rt_time = monotime_since(&start_time, NULL); - monotime(&stop_time); - rt_time = timeval_elapsed (stop_time, start_time); /* Update ABR/ASBR routing table */ if (ospf->old_rtrs) { @@ -1387,14 +1380,9 @@ ospf_spf_calculate_timer (struct thread *thread) monotime(&start_time); if (IS_OSPF_ABR (ospf)) ospf_abr_task (ospf); + abr_time = monotime_since(&start_time, NULL); - monotime(&stop_time); - abr_time = timeval_elapsed (stop_time, start_time); - - monotime(&stop_time); - total_spf_time = timeval_elapsed (stop_time, spf_start_time); - ospf->ts_spf_duration.tv_sec = total_spf_time/1000000; - ospf->ts_spf_duration.tv_usec = total_spf_time % 1000000; + total_spf_time = monotime_since(&spf_start_time, &ospf->ts_spf_duration); ospf_get_spf_reason_str (rbuf); From 4b185cb399650082b317809ed7ec18207fef9f5a Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 23 Jan 2017 18:45:43 +0100 Subject: [PATCH 402/444] lib: time: clean out thread.c Remove quagga_get_relative(), replace with monotime(). Signed-off-by: David Lamparter --- lib/thread.c | 72 ++++++++-------------------------------------------- 1 file changed, 11 insertions(+), 61 deletions(-) diff --git a/lib/thread.c b/lib/thread.c index fe4f5c11c9..406eddc9e6 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -42,8 +42,6 @@ DEFINE_MTYPE_STATIC(LIB, THREAD_STATS, "Thread stats") #endif /* Relative time, since startup */ -static struct timeval relative_time; - static struct hash *cpu_record = NULL; static unsigned long @@ -53,46 +51,6 @@ timeval_elapsed (struct timeval a, struct timeval b) + (a.tv_usec - b.tv_usec)); } -static int -quagga_get_relative (struct timeval *tv) -{ - int ret; - -#ifdef HAVE_CLOCK_MONOTONIC - { - struct timespec tp; - if (!(ret = clock_gettime (CLOCK_MONOTONIC, &tp))) - { - relative_time.tv_sec = tp.tv_sec; - relative_time.tv_usec = tp.tv_nsec / 1000; - } - } -#elif defined(__APPLE__) - { - uint64_t ticks; - uint64_t useconds; - static mach_timebase_info_data_t timebase_info; - - ticks = mach_absolute_time(); - if (timebase_info.denom == 0) - mach_timebase_info(&timebase_info); - - useconds = ticks * timebase_info.numer / timebase_info.denom / 1000; - relative_time.tv_sec = useconds / 1000000; - relative_time.tv_usec = useconds % 1000000; - - return 0; - } -#else /* !HAVE_CLOCK_MONOTONIC && !__APPLE__ */ -#error no monotonic clock on this system -#endif /* HAVE_CLOCK_MONOTONIC */ - - if (tv) - *tv = relative_time; - - return ret; -} - static unsigned int cpu_record_hash_key (struct cpu_thread_history *a) { @@ -576,12 +534,8 @@ thread_master_free (struct thread_master *m) unsigned long thread_timer_remain_second (struct thread *thread) { - quagga_get_relative (NULL); - - if (thread->u.sands.tv_sec - relative_time.tv_sec > 0) - return thread->u.sands.tv_sec - relative_time.tv_sec; - else - return 0; + int64_t remain = monotime_until(&thread->u.sands, NULL) / 1000000LL; + return remain < 0 ? 0 : remain; } #define debugargdef const char *funcname, const char *schedfrom, int fromln @@ -801,9 +755,8 @@ funcname_thread_add_timer_timeval (struct thread_master *m, queue = ((type == THREAD_TIMER) ? m->timer : m->background); thread = thread_get (m, type, func, arg, debugargpass); - /* Do we need jitter here? */ - quagga_get_relative (NULL); - timeradd (&relative_time, time_relative, &thread->u.sands); + monotime(&thread->u.sands); + timeradd(&thread->u.sands, time_relative, &thread->u.sands); pqueue_enqueue(thread, queue); return thread; @@ -1039,7 +992,7 @@ thread_timer_wait (struct pqueue *queue, struct timeval *timer_val) if (queue->size) { struct thread *next_timer = queue->array[0]; - timersub (&next_timer->u.sands, &relative_time, timer_val); + monotime_until(&next_timer->u.sands, timer_val); return timer_val; } return NULL; @@ -1205,6 +1158,7 @@ thread_fetch (struct thread_master *m, struct thread *fetch) thread_fd_set readfd; thread_fd_set writefd; thread_fd_set exceptfd; + struct timeval now; struct timeval timer_val = { .tv_sec = 0, .tv_usec = 0 }; struct timeval timer_val_bg; struct timeval *timer_wait = &timer_val; @@ -1241,7 +1195,6 @@ thread_fetch (struct thread_master *m, struct thread *fetch) /* Calculate select wait timer if nothing else to do */ if (m->ready.count == 0) { - quagga_get_relative (NULL); timer_wait = thread_timer_wait (m->timer, &timer_val); timer_wait_bg = thread_timer_wait (m->background, &timer_val_bg); @@ -1264,8 +1217,8 @@ thread_fetch (struct thread_master *m, struct thread *fetch) /* Check foreground timers. Historically, they have had higher priority than I/O threads, so let's push them onto the ready list in front of the I/O threads. */ - quagga_get_relative (NULL); - thread_timer_process (m->timer, &relative_time); + monotime(&now); + thread_timer_process (m->timer, &now); /* Got IO, process it */ if (num > 0) @@ -1281,7 +1234,7 @@ thread_fetch (struct thread_master *m, struct thread *fetch) #endif /* Background timer/events, lowest priority */ - thread_timer_process (m->background, &relative_time); + thread_timer_process (m->background, &now); if ((thread = thread_trim_head (&m->ready)) != NULL) return thread_run (m, thread, fetch); @@ -1310,9 +1263,7 @@ thread_consumed_time (RUSAGE_T *now, RUSAGE_T *start, unsigned long *cputime) int thread_should_yield (struct thread *thread) { - quagga_get_relative (NULL); - return (timeval_elapsed(relative_time, thread->real) > - thread->yield); + return monotime_since(&thread->real, NULL) > (int64_t)thread->yield; } void @@ -1324,9 +1275,8 @@ thread_set_yield_time (struct thread *thread, unsigned long yield_time) void thread_getrusage (RUSAGE_T *r) { - quagga_get_relative (NULL); + monotime(&r->real); getrusage(RUSAGE_SELF, &(r->cpu)); - r->real = relative_time; } struct thread *thread_current = NULL; From e0e2a99068b47824ec563eb24c2ee617499da491 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 23 Jan 2017 18:51:19 +0100 Subject: [PATCH 403/444] lib: cope with negative timeout in thread.c Since time is no longer cached, if we schedule something with zero timeout, it will automatically be negative by the time we reach the event loop. Signed-off-by: David Lamparter --- lib/thread.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/thread.c b/lib/thread.c index 406eddc9e6..de7066bb82 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -1203,6 +1203,12 @@ thread_fetch (struct thread_master *m, struct thread *fetch) timer_wait = timer_wait_bg; } + if (timer_wait && timer_wait->tv_sec < 0) + { + timerclear(&timer_val); + timer_wait = &timer_val; + } + num = fd_select (m, FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait); /* Signals should get quick treatment */ From 61617d382e018adf7b148bf4d18d6a0fb1fb8645 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 23 Jan 2017 21:49:21 +0100 Subject: [PATCH 404/444] lib: parser: free Mr. T Mr. T was abducted by the parser and held hostage for ransom. Murdock was called, flew in and replaced him with a Tab character. Signed-off-by: David Lamparter --- lib/command_lex.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/command_lex.l b/lib/command_lex.l index d767926263..e245fc4976 100644 --- a/lib/command_lex.l +++ b/lib/command_lex.l @@ -47,7 +47,7 @@ RANGE \({NUMBER}[ ]?\-[ ]?{NUMBER}\) %option bison-bridge %% -[ /t] /* ignore whitespace */; +[ \t] /* ignore whitespace */; {WORD} {yylval->string = XSTRDUP(MTYPE_TMP, yytext); return WORD;} {IPV4} {yylval->string = XSTRDUP(MTYPE_TMP, yytext); return IPV4;} {IPV4_PREFIX} {yylval->string = XSTRDUP(MTYPE_TMP, yytext); return IPV4_PREFIX;} From 0bf5b1cbe3812e748d459fa4c4fb6596e072e7bd Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 16 Dec 2016 22:30:36 +0100 Subject: [PATCH 405/444] lib: parser: simplify OPTION_TKN & SELECTOR_TKN These are functionally identical as "fork" tokens. Signed-off-by: David Lamparter --- lib/command.c | 2 +- lib/command.h | 7 +++--- lib/command_match.c | 36 +++++++++++++--------------- lib/command_parse.y | 17 +++++++------ lib/grammar_sandbox.c | 5 ++-- lib/grammar_sandbox.h | 56 ------------------------------------------- tools/permutations.c | 2 +- 7 files changed, 33 insertions(+), 92 deletions(-) delete mode 100644 lib/grammar_sandbox.h diff --git a/lib/command.c b/lib/command.c index 6294e994e7..cb1f54fbbd 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1268,7 +1268,7 @@ permute (struct graph_node *start, struct vty *vty) for (ALL_LIST_ELEMENTS_RO (position,ln,gnn)) { struct cmd_token *tt = gnn->data; - if (tt->type < SELECTOR_TKN) + if (tt->type < SPECIAL_TKN) vty_out (vty, " %s", tt->text); } if (gn == start) diff --git a/lib/command.h b/lib/command.h index 1e1698fc7d..dd940f0d57 100644 --- a/lib/command.h +++ b/lib/command.h @@ -176,11 +176,12 @@ enum cmd_token_type IPV6_PREFIX_TKN, // IPV6 network prefixes /* plumbing types */ - SELECTOR_TKN, // marks beginning of selector - OPTION_TKN, // marks beginning of option - NUL_TKN, // dummy token + FORK_TKN, // marks subgraph beginning + JOIN_TKN, // marks subgraph end START_TKN, // first token in line END_TKN, // last token in line + + SPECIAL_TKN = FORK_TKN, }; /* Command attributes */ diff --git a/lib/command_match.c b/lib/command_match.c index d228563240..c3eec53bbc 100644 --- a/lib/command_match.c +++ b/lib/command_match.c @@ -459,7 +459,7 @@ command_complete (struct graph *graph, /** * Adds all children that are reachable by one parser hop to the given list. - * NUL_TKN, SELECTOR_TKN, and OPTION_TKN nodes are treated as transparent. + * special tokens except END_TKN are treated as transparent. * * @param[in] list to add the nexthops to * @param[in] node to start calculating nexthops from @@ -490,26 +490,24 @@ add_nexthops (struct list *list, struct graph_node *node, if (j != stackpos) continue; } - switch (token->type) + if (token->type >= SPECIAL_TKN && token->type != END_TKN) { - case OPTION_TKN: - case SELECTOR_TKN: - case NUL_TKN: - added += add_nexthops (list, child, stack, stackpos); - break; - default: - if (stack) - { - nextstack = XMALLOC (MTYPE_CMD_MATCHSTACK, - (stackpos + 1) * sizeof(struct graph_node *)); - nextstack[0] = child; - memcpy(nextstack + 1, stack, stackpos * sizeof(struct graph_node *)); + added += add_nexthops (list, child, stack, stackpos); + } + else + { + if (stack) + { + nextstack = XMALLOC (MTYPE_CMD_MATCHSTACK, + (stackpos + 1) * sizeof(struct graph_node *)); + nextstack[0] = child; + memcpy(nextstack + 1, stack, stackpos * sizeof(struct graph_node *)); - listnode_add (list, nextstack); - } - else - listnode_add (list, child); - added++; + listnode_add (list, nextstack); + } + else + listnode_add (list, child); + added++; } } diff --git a/lib/command_parse.y b/lib/command_parse.y index c920e11380..478ba0537c 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -274,8 +274,8 @@ placeholder_token: selector: '<' selector_seq_seq '>' { $$ = malloc (sizeof (struct subgraph)); - $$->start = new_token_node (ctx, SELECTOR_TKN, NULL, NULL); - $$->end = new_token_node (ctx, NUL_TKN, NULL, NULL); + $$->start = new_token_node (ctx, FORK_TKN, NULL, NULL); + $$->end = new_token_node (ctx, JOIN_TKN, NULL, NULL); for (unsigned int i = 0; i < vector_active ($2->start->to); i++) { struct graph_node *sn = vector_slot ($2->start->to, i), @@ -329,8 +329,8 @@ selector_seq_seq: selector: '{' selector_seq_seq '}' { $$ = malloc (sizeof (struct subgraph)); - $$->start = new_token_node (ctx, SELECTOR_TKN, NULL, NULL); - $$->end = new_token_node (ctx, NUL_TKN, NULL, NULL); + $$->start = new_token_node (ctx, FORK_TKN, NULL, NULL); + $$->end = new_token_node (ctx, JOIN_TKN, NULL, NULL); graph_add_edge ($$->start, $$->end); for (unsigned int i = 0; i < vector_active ($2->start->to); i++) { @@ -377,8 +377,8 @@ option: '[' option_token_seq ']' { // make a new option $$ = malloc (sizeof (struct subgraph)); - $$->start = new_token_node (ctx, OPTION_TKN, NULL, NULL); - $$->end = new_token_node (ctx, NUL_TKN, NULL, NULL); + $$->start = new_token_node (ctx, FORK_TKN, NULL, NULL); + $$->end = new_token_node (ctx, JOIN_TKN, NULL, NULL); // add a path through the sequence to the end graph_add_edge ($$->start, $2->start); graph_add_edge ($2->end, $$->end); @@ -575,8 +575,7 @@ cmp_token (struct cmd_token *first, struct cmd_token *second) * cases; ultimately this forks the graph, but the matcher can handle * this regardless */ - case SELECTOR_TKN: - case OPTION_TKN: + case FORK_TKN: return 0; /* end nodes are always considered equal, since each node may only @@ -584,7 +583,7 @@ cmp_token (struct cmd_token *first, struct cmd_token *second) */ case START_TKN: case END_TKN: - case NUL_TKN: + case JOIN_TKN: default: break; } diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c index 0239ca44ac..b5ac36c41f 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -275,9 +275,8 @@ struct message tokennames[] = { item(IPV6_PREFIX_TKN), // IPV6 network prefixes /* plumbing types */ - item(SELECTOR_TKN), // marks beginning of selector - item(OPTION_TKN), // marks beginning of option - item(NUL_TKN), // dummy token + item(FORK_TKN), + item(JOIN_TKN), item(START_TKN), // first token in line item(END_TKN), // last token in line { 0, NULL } diff --git a/lib/grammar_sandbox.h b/lib/grammar_sandbox.h deleted file mode 100644 index 5da0b05d09..0000000000 --- a/lib/grammar_sandbox.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef _GRAMMAR_SANDBOX_H -#define _GRAMMAR_SANDBOX_H - -/** - * Houses functionality for testing shim as well as code that should go into - * command.h and command.c during integration. - */ -#include "memory.h" - -#define CMD_CR_TEXT "" - -void -grammar_sandbox_init (void); - -/** - * Types for tokens. - * - * The type determines what kind of data the token can match (in the - * matching use case) or hold (in the argv use case). - */ -enum cmd_token_type_t -{ - WORD_TKN, // words - NUMBER_TKN, // integral numbers - VARIABLE_TKN, // almost anything - RANGE_TKN, // integer range - IPV4_TKN, // IPV4 addresses - IPV4_PREFIX_TKN, // IPV4 network prefixes - IPV6_TKN, // IPV6 prefixes - IPV6_PREFIX_TKN, // IPV6 network prefixes - - /* plumbing types */ - SELECTOR_TKN, // marks beginning of selector - OPTION_TKN, // marks beginning of option - NUL_TKN, // dummy token - START_TKN, // first token in line - END_TKN, // last token in line -}; - -/** - * Token struct. - */ -struct cmd_token_t -{ - enum cmd_token_type_t type; // token type - - char *text; // token text - char *desc; // token description - - long long value; // for numeric types - long long min, max; // for ranges - - char *arg; // user input that matches this token -}; - -#endif /* _GRAMMAR_SANDBOX_H */ diff --git a/tools/permutations.c b/tools/permutations.c index 8db51ee037..0ca980b259 100644 --- a/tools/permutations.c +++ b/tools/permutations.c @@ -70,7 +70,7 @@ permute (struct graph_node *start) for (ALL_LIST_ELEMENTS_RO (position,ln,gnn)) { struct cmd_token *tt = gnn->data; - if (tt->type < SELECTOR_TKN) + if (tt->type < SPECIAL_TKN) fprintf (stdout, "%s ", tt->text); } fprintf (stdout, "\n"); From ab037159286a3241244a6b3e7d1033e3940aa944 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 16 Dec 2016 22:34:35 +0100 Subject: [PATCH 406/444] lib: parser: track matching FORK_TKN & JOIN_TKN This associates pairs of FORK and JOIN tokens, so the merge function can identify where a subgraph begins and ends. Signed-off-by: David Lamparter --- lib/command.h | 2 ++ lib/command_parse.y | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/lib/command.h b/lib/command.h index dd940f0d57..b71142fdce 100644 --- a/lib/command.h +++ b/lib/command.h @@ -203,6 +203,8 @@ struct cmd_token char *desc; // token description long long min, max; // for ranges char *arg; // user input that matches this token + + struct graph_node *forkjoin; // paired FORK/JOIN for JOIN/FORK }; /* Structure of command element. */ diff --git a/lib/command_parse.y b/lib/command_parse.y index 478ba0537c..af6497d128 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -276,6 +276,8 @@ selector: '<' selector_seq_seq '>' $$ = malloc (sizeof (struct subgraph)); $$->start = new_token_node (ctx, FORK_TKN, NULL, NULL); $$->end = new_token_node (ctx, JOIN_TKN, NULL, NULL); + ((struct cmd_token *)$$->start->data)->forkjoin = $$->end; + ((struct cmd_token *)$$->end->data)->forkjoin = $$->start; for (unsigned int i = 0; i < vector_active ($2->start->to); i++) { struct graph_node *sn = vector_slot ($2->start->to, i), @@ -331,6 +333,8 @@ selector: '{' selector_seq_seq '}' $$ = malloc (sizeof (struct subgraph)); $$->start = new_token_node (ctx, FORK_TKN, NULL, NULL); $$->end = new_token_node (ctx, JOIN_TKN, NULL, NULL); + ((struct cmd_token *)$$->start->data)->forkjoin = $$->end; + ((struct cmd_token *)$$->end->data)->forkjoin = $$->start; graph_add_edge ($$->start, $$->end); for (unsigned int i = 0; i < vector_active ($2->start->to); i++) { @@ -379,6 +383,8 @@ option: '[' option_token_seq ']' $$ = malloc (sizeof (struct subgraph)); $$->start = new_token_node (ctx, FORK_TKN, NULL, NULL); $$->end = new_token_node (ctx, JOIN_TKN, NULL, NULL); + ((struct cmd_token *)$$->start->data)->forkjoin = $$->end; + ((struct cmd_token *)$$->end->data)->forkjoin = $$->start; // add a path through the sequence to the end graph_add_edge ($$->start, $2->start); graph_add_edge ($2->end, $$->end); From 2020b1c8a88fc4f0c0dd788261deb06ee0c670a7 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 17 Dec 2016 05:14:49 +0100 Subject: [PATCH 407/444] lib: parser: keep subgraph pointers on stack There's no need to malloc() these, we can just keep them on the stack. The entire struct will get copied around, but replacing a 2-pointer copy with a 1-pointer copy + malloc + free overhead is not quite efficient. Signed-off-by: David Lamparter --- lib/command_parse.y | 150 +++++++++++++++++++------------------------- 1 file changed, 64 insertions(+), 86 deletions(-) diff --git a/lib/command_parse.y b/lib/command_parse.y index af6497d128..0d3c52a6e0 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -50,13 +50,18 @@ #define YYSTYPE CMD_YYSTYPE struct parser_ctx; + + /* subgraph semantic value */ + struct subgraph { + struct graph_node *start, *end; + }; } %union { long long number; char *string; struct graph_node *node; - struct subgraph *subgraph; + struct subgraph subgraph; } %code provides { @@ -109,11 +114,6 @@ void cmd_yyerror (struct parser_ctx *ctx, char const *msg); - /* subgraph semantic value */ - struct subgraph { - struct graph_node *start, *end; - }; - /* helper functions for parser */ static char * doc_next (struct parser_ctx *ctx); @@ -204,9 +204,8 @@ cmd_token: } | compound_token { - graph_add_edge (ctx->currnode, $1->start); - ctx->currnode = $1->end; - free ($1); + graph_add_edge (ctx->currnode, $1.start); + ctx->currnode = $1.end; } ; @@ -273,104 +272,89 @@ placeholder_token: /* productions */ selector: '<' selector_seq_seq '>' { - $$ = malloc (sizeof (struct subgraph)); - $$->start = new_token_node (ctx, FORK_TKN, NULL, NULL); - $$->end = new_token_node (ctx, JOIN_TKN, NULL, NULL); - ((struct cmd_token *)$$->start->data)->forkjoin = $$->end; - ((struct cmd_token *)$$->end->data)->forkjoin = $$->start; - for (unsigned int i = 0; i < vector_active ($2->start->to); i++) + $$.start = new_token_node (ctx, FORK_TKN, NULL, NULL); + $$.end = new_token_node (ctx, JOIN_TKN, NULL, NULL); + ((struct cmd_token *)$$.start->data)->forkjoin = $$.end; + ((struct cmd_token *)$$.end->data)->forkjoin = $$.start; + for (unsigned int i = 0; i < vector_active ($2.start->to); i++) { - struct graph_node *sn = vector_slot ($2->start->to, i), - *en = vector_slot ($2->end->from, i); - graph_add_edge ($$->start, sn); - graph_add_edge (en, $$->end); + struct graph_node *sn = vector_slot ($2.start->to, i), + *en = vector_slot ($2.end->from, i); + graph_add_edge ($$.start, sn); + graph_add_edge (en, $$.end); } - graph_delete_node (ctx->graph, $2->start); - graph_delete_node (ctx->graph, $2->end); - free ($2); + graph_delete_node (ctx->graph, $2.start); + graph_delete_node (ctx->graph, $2.end); }; selector_seq_seq: selector_seq_seq '|' selector_token_seq { - $$ = malloc (sizeof (struct subgraph)); - $$->start = graph_new_node (ctx->graph, NULL, NULL); - $$->end = graph_new_node (ctx->graph, NULL, NULL); + $$.start = graph_new_node (ctx->graph, NULL, NULL); + $$.end = graph_new_node (ctx->graph, NULL, NULL); // link in last sequence - graph_add_edge ($$->start, $3->start); - graph_add_edge ($3->end, $$->end); + graph_add_edge ($$.start, $3.start); + graph_add_edge ($3.end, $$.end); - for (unsigned int i = 0; i < vector_active ($1->start->to); i++) + for (unsigned int i = 0; i < vector_active ($1.start->to); i++) { - struct graph_node *sn = vector_slot ($1->start->to, i), - *en = vector_slot ($1->end->from, i); - graph_add_edge ($$->start, sn); - graph_add_edge (en, $$->end); + struct graph_node *sn = vector_slot ($1.start->to, i), + *en = vector_slot ($1.end->from, i); + graph_add_edge ($$.start, sn); + graph_add_edge (en, $$.end); } - graph_delete_node (ctx->graph, $1->start); - graph_delete_node (ctx->graph, $1->end); - free ($1); - free ($3); + graph_delete_node (ctx->graph, $1.start); + graph_delete_node (ctx->graph, $1.end); } | selector_token_seq '|' selector_token_seq { - $$ = malloc (sizeof (struct subgraph)); - $$->start = graph_new_node (ctx->graph, NULL, NULL); - $$->end = graph_new_node (ctx->graph, NULL, NULL); - graph_add_edge ($$->start, $1->start); - graph_add_edge ($1->end, $$->end); - graph_add_edge ($$->start, $3->start); - graph_add_edge ($3->end, $$->end); - free ($1); - free ($3); + $$.start = graph_new_node (ctx->graph, NULL, NULL); + $$.end = graph_new_node (ctx->graph, NULL, NULL); + graph_add_edge ($$.start, $1.start); + graph_add_edge ($1.end, $$.end); + graph_add_edge ($$.start, $3.start); + graph_add_edge ($3.end, $$.end); } ; /* {keyword} productions */ selector: '{' selector_seq_seq '}' { - $$ = malloc (sizeof (struct subgraph)); - $$->start = new_token_node (ctx, FORK_TKN, NULL, NULL); - $$->end = new_token_node (ctx, JOIN_TKN, NULL, NULL); - ((struct cmd_token *)$$->start->data)->forkjoin = $$->end; - ((struct cmd_token *)$$->end->data)->forkjoin = $$->start; - graph_add_edge ($$->start, $$->end); - for (unsigned int i = 0; i < vector_active ($2->start->to); i++) + $$.start = new_token_node (ctx, FORK_TKN, NULL, NULL); + $$.end = new_token_node (ctx, JOIN_TKN, NULL, NULL); + ((struct cmd_token *)$$.start->data)->forkjoin = $$.end; + ((struct cmd_token *)$$.end->data)->forkjoin = $$.start; + graph_add_edge ($$.start, $$.end); + for (unsigned int i = 0; i < vector_active ($2.start->to); i++) { - struct graph_node *sn = vector_slot ($2->start->to, i), - *en = vector_slot ($2->end->from, i); - graph_add_edge ($$->start, sn); - graph_add_edge (en, $$->start); + struct graph_node *sn = vector_slot ($2.start->to, i), + *en = vector_slot ($2.end->from, i); + graph_add_edge ($$.start, sn); + graph_add_edge (en, $$.start); } - graph_delete_node (ctx->graph, $2->start); - graph_delete_node (ctx->graph, $2->end); - free ($2); + graph_delete_node (ctx->graph, $2.start); + graph_delete_node (ctx->graph, $2.end); }; selector_token_seq: simple_token { - $$ = malloc (sizeof (struct subgraph)); - $$->start = $$->end = $1; + $$.start = $$.end = $1; } | selector_token_seq selector_token { - $$ = malloc (sizeof (struct subgraph)); - graph_add_edge ($1->end, $2->start); - $$->start = $1->start; - $$->end = $2->end; - free ($1); - free ($2); + graph_add_edge ($1.end, $2.start); + $$.start = $1.start; + $$.end = $2.end; } ; selector_token: simple_token { - $$ = malloc (sizeof (struct subgraph)); - $$->start = $$->end = $1; + $$.start = $$.end = $1; } | option | selector @@ -380,17 +364,15 @@ selector_token: option: '[' option_token_seq ']' { // make a new option - $$ = malloc (sizeof (struct subgraph)); - $$->start = new_token_node (ctx, FORK_TKN, NULL, NULL); - $$->end = new_token_node (ctx, JOIN_TKN, NULL, NULL); - ((struct cmd_token *)$$->start->data)->forkjoin = $$->end; - ((struct cmd_token *)$$->end->data)->forkjoin = $$->start; + $$.start = new_token_node (ctx, FORK_TKN, NULL, NULL); + $$.end = new_token_node (ctx, JOIN_TKN, NULL, NULL); + ((struct cmd_token *)$$.start->data)->forkjoin = $$.end; + ((struct cmd_token *)$$.end->data)->forkjoin = $$.start; // add a path through the sequence to the end - graph_add_edge ($$->start, $2->start); - graph_add_edge ($2->end, $$->end); + graph_add_edge ($$.start, $2.start); + graph_add_edge ($2.end, $$.end); // add a path directly from the start to the end - graph_add_edge ($$->start, $$->end); - free ($2); + graph_add_edge ($$.start, $$.end); } ; @@ -398,20 +380,16 @@ option_token_seq: option_token | option_token_seq option_token { - $$ = malloc (sizeof (struct subgraph)); - graph_add_edge ($1->end, $2->start); - $$->start = $1->start; - $$->end = $2->end; - free ($1); - free ($2); + graph_add_edge ($1.end, $2.start); + $$.start = $1.start; + $$.end = $2.end; } ; option_token: simple_token { - $$ = malloc (sizeof (struct subgraph)); - $$->start = $$->end = $1; + $$.start = $$.end = $1; } | compound_token ; From 663982cda7188c03472975ef412e57152744eaa5 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 17 Dec 2016 05:25:36 +0100 Subject: [PATCH 408/444] lib: parser: unify subgraphs & simplify even more This cuts a large piece of complexity from the parser by making the sequences between | the same, no matter whether it's <> () or []. This causes some changes in behaviour: - [foo|bar] is now accepted - is now accepted (yes it's stupid) - {a|b} is now means "at least one of these, in any order"; to allow zero use [{a|b}] instead. Signed-off-by: David Lamparter --- lib/command_parse.y | 117 +++++++++---------------------------------- tests/testcli.refout | 8 +-- 2 files changed, 26 insertions(+), 99 deletions(-) diff --git a/lib/command_parse.y b/lib/command_parse.y index 0d3c52a6e0..db4709172c 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -99,14 +99,10 @@ %type literal_token %type placeholder_token %type simple_token -%type option -%type option_token -%type option_token_seq %type selector %type selector_token %type selector_token_seq %type selector_seq_seq -%type compound_token %code { @@ -202,7 +198,7 @@ cmd_token: if ((ctx->currnode = add_edge_dedup (ctx->currnode, $1)) != $1) graph_delete_node (ctx->graph, $1); } -| compound_token +| selector { graph_add_edge (ctx->currnode, $1.start); ctx->currnode = $1.end; @@ -214,11 +210,6 @@ simple_token: | placeholder_token ; -compound_token: - selector -| option -; - literal_token: WORD { $$ = new_token_node (ctx, WORD_TKN, strdup($1), doc_next(ctx)); @@ -272,126 +263,66 @@ placeholder_token: /* productions */ selector: '<' selector_seq_seq '>' { - $$.start = new_token_node (ctx, FORK_TKN, NULL, NULL); - $$.end = new_token_node (ctx, JOIN_TKN, NULL, NULL); - ((struct cmd_token *)$$.start->data)->forkjoin = $$.end; - ((struct cmd_token *)$$.end->data)->forkjoin = $$.start; - for (unsigned int i = 0; i < vector_active ($2.start->to); i++) - { - struct graph_node *sn = vector_slot ($2.start->to, i), - *en = vector_slot ($2.end->from, i); - graph_add_edge ($$.start, sn); - graph_add_edge (en, $$.end); - } - graph_delete_node (ctx->graph, $2.start); - graph_delete_node (ctx->graph, $2.end); + $$ = $2; }; selector_seq_seq: selector_seq_seq '|' selector_token_seq { - $$.start = graph_new_node (ctx->graph, NULL, NULL); - $$.end = graph_new_node (ctx->graph, NULL, NULL); - - // link in last sequence + $$ = $1; graph_add_edge ($$.start, $3.start); graph_add_edge ($3.end, $$.end); - - for (unsigned int i = 0; i < vector_active ($1.start->to); i++) - { - struct graph_node *sn = vector_slot ($1.start->to, i), - *en = vector_slot ($1.end->from, i); - graph_add_edge ($$.start, sn); - graph_add_edge (en, $$.end); - } - graph_delete_node (ctx->graph, $1.start); - graph_delete_node (ctx->graph, $1.end); } -| selector_token_seq '|' selector_token_seq +| selector_token_seq { - $$.start = graph_new_node (ctx->graph, NULL, NULL); - $$.end = graph_new_node (ctx->graph, NULL, NULL); + $$.start = new_token_node (ctx, FORK_TKN, NULL, NULL); + $$.end = new_token_node (ctx, JOIN_TKN, NULL, NULL); + ((struct cmd_token *)$$.start->data)->forkjoin = $$.end; + ((struct cmd_token *)$$.end->data)->forkjoin = $$.start; + graph_add_edge ($$.start, $1.start); graph_add_edge ($1.end, $$.end); - graph_add_edge ($$.start, $3.start); - graph_add_edge ($3.end, $$.end); } ; /* {keyword} productions */ selector: '{' selector_seq_seq '}' { - $$.start = new_token_node (ctx, FORK_TKN, NULL, NULL); - $$.end = new_token_node (ctx, JOIN_TKN, NULL, NULL); - ((struct cmd_token *)$$.start->data)->forkjoin = $$.end; - ((struct cmd_token *)$$.end->data)->forkjoin = $$.start; - graph_add_edge ($$.start, $$.end); - for (unsigned int i = 0; i < vector_active ($2.start->to); i++) - { - struct graph_node *sn = vector_slot ($2.start->to, i), - *en = vector_slot ($2.end->from, i); - graph_add_edge ($$.start, sn); - graph_add_edge (en, $$.start); - } - graph_delete_node (ctx->graph, $2.start); - graph_delete_node (ctx->graph, $2.end); + $$ = $2; + graph_add_edge ($$.end, $$.start); + /* there is intentionally no start->end link, for two reasons: + * 1) this allows "at least 1 of" semantics, which are otherwise impossible + * 2) this would add a start->end->start loop in the graph that the current + * loop-avoidal fails to handle + * just use [{a|b}] if neccessary, that will work perfectly fine, and reason + * #1 is good enough to keep it this way. */ }; -selector_token_seq: - simple_token -{ - $$.start = $$.end = $1; -} -| selector_token_seq selector_token -{ - graph_add_edge ($1.end, $2.start); - $$.start = $1.start; - $$.end = $2.end; -} -; - selector_token: simple_token { $$.start = $$.end = $1; } -| option | selector ; -/* [option] productions */ -option: '[' option_token_seq ']' -{ - // make a new option - $$.start = new_token_node (ctx, FORK_TKN, NULL, NULL); - $$.end = new_token_node (ctx, JOIN_TKN, NULL, NULL); - ((struct cmd_token *)$$.start->data)->forkjoin = $$.end; - ((struct cmd_token *)$$.end->data)->forkjoin = $$.start; - // add a path through the sequence to the end - graph_add_edge ($$.start, $2.start); - graph_add_edge ($2.end, $$.end); - // add a path directly from the start to the end - graph_add_edge ($$.start, $$.end); -} -; - -option_token_seq: - option_token -| option_token_seq option_token +selector_token_seq: + selector_token_seq selector_token { graph_add_edge ($1.end, $2.start); $$.start = $1.start; $$.end = $2.end; } +| selector_token ; -option_token: - simple_token +/* [option] productions */ +selector: '[' selector_seq_seq ']' { - $$.start = $$.end = $1; + $$ = $2; + graph_add_edge ($$.start, $$.end); } -| compound_token ; %% diff --git a/tests/testcli.refout b/tests/testcli.refout index 088cbdfec4..8b438baee2 100644 --- a/tests/testcli.refout +++ b/tests/testcli.refout @@ -188,15 +188,11 @@ test# pat c c x % [NONE] Unknown command: pat c c x test# test# pat d -cmd8 with 2 args. -[00]: pat -[01]: d +% Command incomplete. test# pat d bar baz foo test# pat d -cmd8 with 2 args. -[00]: pat -[01]: d +% Command incomplete. test# pat d foo 1.2.3.4 cmd8 with 4 args. [00]: pat From 8bb647a8302be446e4ea4d05b98f3c656cb647d7 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 17 Dec 2016 07:32:58 +0100 Subject: [PATCH 409/444] lib: parser: add error location reporting flex+bison have nice capabilities to track the location that is currently being processed; let's enable these and get better warnings for broken CLI specs. Signed-off-by: David Lamparter --- lib/command_lex.l | 12 ++++++++++- lib/command_parse.y | 52 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/lib/command_lex.l b/lib/command_lex.l index e245fc4976..703596b43d 100644 --- a/lib/command_lex.l +++ b/lib/command_lex.l @@ -24,6 +24,11 @@ %{ #include "command_parse.h" + +#define YY_USER_ACTION yylloc->last_column += yyleng; +#define LOC_STEP \ + yylloc->first_column = yylloc->last_column; \ + yylloc->first_line = yylloc->last_line; %} WORD (\-|\+)?[a-z0-9\*][-+_a-zA-Z0-9\*]* @@ -45,9 +50,14 @@ RANGE \({NUMBER}[ ]?\-[ ]?{NUMBER}\) %option prefix="cmd_yy" %option reentrant %option bison-bridge +%option bison-locations %% -[ \t] /* ignore whitespace */; +%{ + LOC_STEP; +%} + +[ \t]+ LOC_STEP /* ignore whitespace */; {WORD} {yylval->string = XSTRDUP(MTYPE_TMP, yytext); return WORD;} {IPV4} {yylval->string = XSTRDUP(MTYPE_TMP, yytext); return IPV4;} {IPV4_PREFIX} {yylval->string = XSTRDUP(MTYPE_TMP, yytext); return IPV4_PREFIX;} diff --git a/lib/command_parse.y b/lib/command_parse.y index db4709172c..cbc7ce9754 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -27,6 +27,8 @@ #define YYDEBUG 1 %} +%locations +%define parse.error verbose %define api.pure full /* define api.prefix {cmd_yy} */ @@ -49,6 +51,7 @@ #include "graph.h" #define YYSTYPE CMD_YYSTYPE + #define YYLTYPE CMD_YYLTYPE struct parser_ctx; /* subgraph semantic value */ @@ -108,7 +111,7 @@ /* bison declarations */ void - cmd_yyerror (struct parser_ctx *ctx, char const *msg); + cmd_yyerror (CMD_YYLTYPE *locp, struct parser_ctx *ctx, char const *msg); /* helper functions for parser */ static char * @@ -130,7 +133,7 @@ char *doc); static void - terminate_graph (struct parser_ctx *ctx, + terminate_graph (CMD_YYLTYPE *locp, struct parser_ctx *ctx, struct graph_node *); static void @@ -169,7 +172,7 @@ start: cmd_token_seq { // tack on the command element - terminate_graph (ctx, ctx->currnode); + terminate_graph (&@1, ctx, ctx->currnode); } | cmd_token_seq placeholder_token '.' '.' '.' { @@ -183,7 +186,7 @@ start: add_edge_dedup (ctx->currnode, ctx->currnode); // tack on the command element - terminate_graph (ctx, ctx->currnode); + terminate_graph (&@1, ctx, ctx->currnode); } ; @@ -255,7 +258,7 @@ placeholder_token: token->max = strtoll (yylval.string, &yylval.string, 10); // validate range - if (token->min > token->max) cmd_yyerror (ctx, "Invalid range."); + if (token->min > token->max) cmd_yyerror (&@1, ctx, "Invalid range."); free ($1); } @@ -352,11 +355,39 @@ command_parse_format (struct graph *graph, struct cmd_element *cmd) /* parser helper functions */ void -yyerror (struct parser_ctx *ctx, char const *msg) +yyerror (CMD_YYLTYPE *loc, struct parser_ctx *ctx, char const *msg) { + char *tmpstr = strdup(ctx->el->string); + char *line, *eol; + char spacing[256]; + int lineno = 0; + zlog_err ("%s: FATAL parse error: %s", __func__, msg); - zlog_err ("while parsing this command definition: \n\t%s\n", ctx->el->string); - //exit(EXIT_FAILURE); + zlog_err ("%s: %d:%d-%d of this command definition:", __func__, loc->first_line, loc->first_column, loc->last_column); + + line = tmpstr; + do { + lineno++; + eol = strchr(line, '\n'); + if (eol) + *eol++ = '\0'; + + zlog_err ("%s: | %s", __func__, line); + if (lineno == loc->first_line && lineno == loc->last_line + && loc->first_column < (int)sizeof(spacing) - 1 + && loc->last_column < (int)sizeof(spacing) - 1) { + + int len = loc->last_column - loc->first_column; + if (len == 0) + len = 1; + + memset(spacing, ' ', loc->first_column - 1); + memset(spacing + loc->first_column - 1, '^', len); + spacing[loc->first_column - 1 + len] = '\0'; + zlog_err ("%s: | %s", __func__, spacing); + } + } while ((line = eol)); + free(tmpstr); } static void @@ -371,7 +402,8 @@ cleanup (struct parser_ctx *ctx) } static void -terminate_graph (struct parser_ctx *ctx, struct graph_node *finalnode) +terminate_graph (CMD_YYLTYPE *locp, struct parser_ctx *ctx, + struct graph_node *finalnode) { // end of graph should look like this // * -> finalnode -> END_TKN -> cmd_element @@ -385,7 +417,7 @@ terminate_graph (struct parser_ctx *ctx, struct graph_node *finalnode) graph_new_node (ctx->graph, element, NULL); if (node_adjacent (finalnode, end_token_node)) - cmd_yyerror (ctx, "Duplicate command."); + cmd_yyerror (locp, ctx, "Duplicate command."); graph_add_edge (finalnode, end_token_node); graph_add_edge (end_token_node, end_element_node); From 818a5168a1c141beaa63fe887d195123a23a012e Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 5 Dec 2016 23:03:57 +0100 Subject: [PATCH 410/444] grammar_sandbox: add .dot file writing capability Writing a .dot graphviz file is very useful to get a graphical representation of the command graph. This code is intended solely for testing & development, it uses some fixed-size array and may unexpectedly crash. Signed-off-by: David Lamparter --- lib/grammar_sandbox.c | 112 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c index b5ac36c41f..98c75ca6e3 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -45,6 +45,10 @@ void grammar_sandbox_init (void); void pretty_print_graph (struct vty *vty, struct graph_node *, int, int, struct graph_node **, size_t); +static void +pretty_print_dot (FILE *ofd, unsigned opts, struct graph_node *start, + struct graph_node **stack, size_t stackpos, + struct graph_node **visited, size_t *visitpos); void init_cmdgraph (struct vty *, struct graph **); vector @@ -240,6 +244,36 @@ DEFUN (grammar_test_show, return CMD_SUCCESS; } +DEFUN (grammar_test_dot, + grammar_test_dot_cmd, + "grammar dotfile OUTNAME", + GRAMMAR_STR + "print current graph for dot\n" + ".dot filename\n") +{ + struct graph_node *stack[MAXDEPTH]; + struct graph_node *visited[MAXDEPTH*MAXDEPTH]; + size_t vpos = 0; + + if (!nodegraph) { + vty_out(vty, "nodegraph uninitialized\r\n"); + return CMD_SUCCESS; + } + FILE *ofd = fopen(argv[2]->arg, "w"); + if (!ofd) { + vty_out(vty, "%s: %s\r\n", argv[2]->arg, strerror(errno)); + return CMD_SUCCESS; + } + + fprintf(ofd, "digraph {\n graph [ rankdir = LR ];\n node [ fontname = \"Fira Mono\", fontsize = 9 ];\n\n"); + pretty_print_dot (ofd, 0, + vector_slot (nodegraph->nodes, 0), + stack, 0, visited, &vpos); + fprintf(ofd, "}\n"); + fclose(ofd); + return CMD_SUCCESS; +} + DEFUN (grammar_init_graph, grammar_init_graph_cmd, "grammar init", @@ -258,6 +292,7 @@ void grammar_sandbox_init(void) { // install all enable elements install_element (ENABLE_NODE, &grammar_test_cmd); install_element (ENABLE_NODE, &grammar_test_show_cmd); + install_element (ENABLE_NODE, &grammar_test_dot_cmd); install_element (ENABLE_NODE, &grammar_test_match_cmd); install_element (ENABLE_NODE, &grammar_test_complete_cmd); install_element (ENABLE_NODE, &grammar_test_doc_cmd); @@ -345,6 +380,83 @@ pretty_print_graph (struct vty *vty, struct graph_node *start, int level, vty_out(vty, "%s", VTY_NEWLINE); } +static void +pretty_print_dot (FILE *ofd, unsigned opts, struct graph_node *start, + struct graph_node **stack, size_t stackpos, + struct graph_node **visited, size_t *visitpos) +{ + // print this node + char tokennum[32]; + struct cmd_token *tok = start->data; + const char *color; + + for (size_t i = 0; i < (*visitpos); i++) + if (visited[i] == start) + return; + visited[(*visitpos)++] = start; + if ((*visitpos) == MAXDEPTH*MAXDEPTH) + return; + + snprintf(tokennum, sizeof(tokennum), "%d?", tok->type); + fprintf(ofd, " n%016llx [ shape=box, label=<", (unsigned long long)start); + + fprintf(ofd, "%s", LOOKUP_DEF(tokennames, tok->type, tokennum)); + if (tok->attr == CMD_ATTR_DEPRECATED) + fprintf(ofd, " (d)"); + else if (tok->attr == CMD_ATTR_HIDDEN) + fprintf(ofd, " (h)"); + if (tok->text) { + if (tok->type == WORD_TKN) + fprintf(ofd, "
\"%s\"", tok->text); + else + fprintf(ofd, "
%s", tok->text); + } +/* if (desc) + fprintf(ofd, " ?'%s'", tok->desc); */ + switch (tok->type) { + case START_TKN: color = "#ccffcc"; break; + case FORK_TKN: color = "#aaddff"; break; + case JOIN_TKN: color = "#ddaaff"; break; + case WORD_TKN: color = "#ffffff"; break; + default: color = "#ffffff"; break; + } + fprintf(ofd, ">, style = filled, fillcolor = \"%s\" ];\n", color); + + if (stackpos == MAXDEPTH) + return; + stack[stackpos++] = start; + + for (unsigned int i = 0; i < vector_active (start->to); i++) + { + struct graph_node *adj = vector_slot (start->to, i); + // if this node is a vararg, just print * + if (adj == start) { + fprintf(ofd, " n%016llx -> n%016llx;\n", + (unsigned long long)start, + (unsigned long long)start); + } else if (((struct cmd_token *)adj->data)->type == END_TKN) { + //struct cmd_token *et = adj->data; + fprintf(ofd, " n%016llx -> end%016llx;\n", + (unsigned long long)start, + (unsigned long long)adj); + fprintf(ofd, " end%016llx [ shape=box, label=, style = filled, fillcolor = \"#ffddaa\" ];\n", + (unsigned long long)adj); + } else { + fprintf(ofd, " n%016llx -> n%016llx;\n", + (unsigned long long)start, + (unsigned long long)adj); + size_t k; + for (k = 0; k < stackpos; k++) + if (stack[k] == adj) + break; + if (k == stackpos) { + pretty_print_dot (ofd, opts, adj, stack, stackpos, visited, visitpos); + } + } + } +} + + /** stuff that should go in command.c + command.h */ void init_cmdgraph (struct vty *vty, struct graph **graph) From af2567b646a9bdf22c3f47caeedc8f2de1dac81c Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 16 Dec 2016 08:11:37 +0100 Subject: [PATCH 411/444] grammar_sandbox: add into daemons if DEV_BUILD Also adds "grammar access " to test/dump an existing command node (e.g. BGP_NODE). Signed-off-by: David Lamparter --- lib/Makefile.am | 3 +- lib/command.c | 6 +- lib/command.h | 4 ++ lib/grammar_sandbox.c | 123 ++++++++++--------------------------- lib/grammar_sandbox_main.c | 64 +++++++++++++++++++ 5 files changed, 109 insertions(+), 91 deletions(-) create mode 100644 lib/grammar_sandbox_main.c diff --git a/lib/Makefile.am b/lib/Makefile.am index f2c076c475..b048720673 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -26,6 +26,7 @@ libzebra_la_SOURCES = \ imsg-buffer.c imsg.c skiplist.c \ qobj.c wheel.c \ event_counter.c \ + grammar_sandbox.c \ strlcpy.c \ strlcat.c @@ -53,7 +54,7 @@ noinst_HEADERS = \ noinst_PROGRAMS = grammar_sandbox -grammar_sandbox_SOURCES = grammar_sandbox.c +grammar_sandbox_SOURCES = grammar_sandbox_main.c grammar_sandbox_LDADD = libzebra.la EXTRA_DIST = \ diff --git a/lib/command.c b/lib/command.c index cb1f54fbbd..6fad28ce6c 100644 --- a/lib/command.c +++ b/lib/command.c @@ -523,7 +523,7 @@ compare_completions (const void *fst, const void *snd) * @param completions linked list of cmd_token * @return deduplicated and sorted vector with */ -static vector +vector completions_to_vec (struct list *completions) { vector comps = vector_init (VECTOR_MIN_SIZE); @@ -2398,6 +2398,10 @@ cmd_init (int terminal) vrf_install_commands (); } srandom(time(NULL)); + +#ifdef DEV_BUILD + grammar_sandbox_init(); +#endif } struct cmd_token * diff --git a/lib/command.h b/lib/command.h index b71142fdce..3da77d3af3 100644 --- a/lib/command.h +++ b/lib/command.h @@ -422,6 +422,9 @@ extern void cmd_terminate (void); extern void cmd_exit (struct vty *vty); extern int cmd_list_cmds (struct vty *vty, int do_permute); +/* NOT safe for general use; call this only if DEV_BUILD! */ +extern void grammar_sandbox_init (void); + /* memory management for cmd_token */ struct cmd_token * new_cmd_token (enum cmd_token_type, u_char attr, char *, char *); @@ -430,6 +433,7 @@ del_cmd_token (struct cmd_token *); struct cmd_token * copy_cmd_token (struct cmd_token *); +extern vector completions_to_vec (struct list *completions); extern void command_parse_format (struct graph *graph, struct cmd_element *cmd); /* Export typical functions. */ diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c index 98c75ca6e3..f92c78de55 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -3,11 +3,6 @@ * * This unit defines a number of commands in the old engine that can * be used to test and interact with the new engine. - * - * This shim should be removed upon integration. It is currently hooked in - * vtysh/vtysh.c. It has no header, vtysh.c merely includes this entire unit - * since it clutters up the makefiles less and this is only a temporary shim. - * * -- * Copyright (C) 2016 Cumulus Networks, Inc. * @@ -51,13 +46,9 @@ pretty_print_dot (FILE *ofd, unsigned opts, struct graph_node *start, struct graph_node **visited, size_t *visitpos); void init_cmdgraph (struct vty *, struct graph **); -vector -completions_to_vec (struct list *); -int -compare_completions (const void *, const void *); /** shim interface commands **/ -struct graph *nodegraph; +struct graph *nodegraph = NULL, *nodegraph_free = NULL; DEFUN (grammar_test, grammar_test_cmd, @@ -280,11 +271,41 @@ DEFUN (grammar_init_graph, GRAMMAR_STR "(re)initialize graph\n") { - graph_delete_graph (nodegraph); + if (nodegraph_free) + graph_delete_graph (nodegraph_free); + nodegraph_free = NULL; + init_cmdgraph (vty, &nodegraph); return CMD_SUCCESS; } +extern vector cmdvec; + +DEFUN (grammar_access, + grammar_access_cmd, + "grammar access (0-65535)", + GRAMMAR_STR + "access node graph\n" + "node number\n") +{ + if (nodegraph_free) + graph_delete_graph (nodegraph_free); + nodegraph_free = NULL; + + struct cmd_node *cnode; + + cnode = vector_slot (cmdvec, atoi (argv[2]->arg)); + if (!cnode) + { + vty_out (vty, "%% no such node%s", VTY_NEWLINE); + return CMD_WARNING; + } + + vty_out (vty, "node %d%s", (int)cnode->node, VTY_NEWLINE); + nodegraph = cnode->cmdgraph; + return CMD_SUCCESS; +} + /* this is called in vtysh.c to set up the testing shim */ void grammar_sandbox_init(void) { init_cmdgraph (NULL, &nodegraph); @@ -297,6 +318,7 @@ void grammar_sandbox_init(void) { install_element (ENABLE_NODE, &grammar_test_complete_cmd); install_element (ENABLE_NODE, &grammar_test_doc_cmd); install_element (ENABLE_NODE, &grammar_init_graph_cmd); + install_element (ENABLE_NODE, &grammar_access_cmd); } #define item(x) { x, #x } @@ -463,86 +485,9 @@ init_cmdgraph (struct vty *vty, struct graph **graph) { // initialize graph, add start noe *graph = graph_new (); + nodegraph_free = *graph; struct cmd_token *token = new_cmd_token (START_TKN, 0, NULL, NULL); graph_new_node (*graph, token, (void (*)(void *)) &del_cmd_token); if (vty) vty_out (vty, "initialized graph%s", VTY_NEWLINE); } - -int -compare_completions (const void *fst, const void *snd) -{ - struct cmd_token *first = *(struct cmd_token **) fst, - *secnd = *(struct cmd_token **) snd; - return strcmp (first->text, secnd->text); -} - -vector -completions_to_vec (struct list *completions) -{ - vector comps = vector_init (VECTOR_MIN_SIZE); - - struct listnode *ln; - struct cmd_token *token; - unsigned int i, exists; - for (ALL_LIST_ELEMENTS_RO(completions,ln,token)) - { - // linear search for token in completions vector - exists = 0; - for (i = 0; i < vector_active (comps) && !exists; i++) - { - struct cmd_token *curr = vector_slot (comps, i); - exists = !strcmp (curr->text, token->text) && - !strcmp (curr->desc, token->desc); - } - - if (!exists) - vector_set (comps, copy_cmd_token (token)); - } - - // sort completions - qsort (comps->index, - vector_active (comps), - sizeof (void *), - &compare_completions); - - return comps; -} - -static void vty_do_exit(void) -{ - printf ("\nend.\n"); - exit (0); -} - -struct thread_master *master; - -int main(int argc, char **argv) -{ - struct thread thread; - - master = thread_master_create (); - - zlog_default = openzlog ("grammar_sandbox", ZLOG_NONE, 0, - LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); - zlog_set_level (NULL, ZLOG_DEST_SYSLOG, ZLOG_DISABLED); - zlog_set_level (NULL, ZLOG_DEST_STDOUT, LOG_DEBUG); - zlog_set_level (NULL, ZLOG_DEST_MONITOR, ZLOG_DISABLED); - - /* Library inits. */ - cmd_init (1); - host.name = strdup ("test"); - - vty_init (master); - memory_init (); - grammar_sandbox_init(); - - vty_stdio (vty_do_exit); - - /* Fetch next active thread. */ - while (thread_fetch (master, &thread)) - thread_call (&thread); - - /* Not reached. */ - exit (0); -} diff --git a/lib/grammar_sandbox_main.c b/lib/grammar_sandbox_main.c new file mode 100644 index 0000000000..5deef406c1 --- /dev/null +++ b/lib/grammar_sandbox_main.c @@ -0,0 +1,64 @@ +/* + * Testing shim and API examples for the new CLI backend. + * + * Minimal main() to run grammar_sandbox standalone. + * [split off grammar_sandbox.c 2017-01-23] + * -- + * Copyright (C) 2016 Cumulus Networks, Inc. + * Copyright (C) 2017 David Lamparter for NetDEF, Inc. + * + * This file is part of FreeRangeRouting (FRR). + * + * FRR 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. + * + * FRR 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 FRR; see the file COPYING. If not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "command.h" +#include "memory_vty.h" + +static void vty_do_exit(void) +{ + printf ("\nend.\n"); + exit (0); +} + +struct thread_master *master; + +int main(int argc, char **argv) +{ + struct thread thread; + + master = thread_master_create (); + + zlog_default = openzlog ("grammar_sandbox", ZLOG_NONE, 0, + LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, ZLOG_DISABLED); + zlog_set_level (NULL, ZLOG_DEST_STDOUT, LOG_DEBUG); + zlog_set_level (NULL, ZLOG_DEST_MONITOR, ZLOG_DISABLED); + + /* Library inits. */ + cmd_init (1); + host.name = strdup ("test"); + + vty_init (master); + memory_init (); + + vty_stdio (vty_do_exit); + + /* Fetch next active thread. */ + while (thread_fetch (master, &thread)) + thread_call (&thread); + + /* Not reached. */ + exit (0); +} From 24d812a9e3547dfd035e6b50d93a1c0ada6e1c43 Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Mon, 23 Jan 2017 15:39:04 -0500 Subject: [PATCH 412/444] bgpd: restore show bgp neighbors command --- bgpd/bgp_route.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 6faf474286..33e565d427 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -9441,7 +9441,7 @@ peer_adj_routes (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, DEFUN (show_ip_bgp_instance_neighbor_advertised_route, show_ip_bgp_instance_neighbor_advertised_route_cmd, - "show [ip] bgp [ WORD] []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] neighbors [ [route-map WORD]] [json]", + "show [ip] bgp [ WORD] []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] neighbors [route-map WORD] [json]", SHOW_STR IP_STR BGP_STR From 39cea8220a9bcc51d97a7832760591e117cdde7a Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 23 Jan 2017 23:17:35 +0100 Subject: [PATCH 413/444] lib: time: add TIMEVAL_TO_TIMESPEC Should be in system headers, but not specified by any standard. Not currently used anywhere yet. Signed-off-by: David Lamparter --- lib/monotime.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/monotime.h b/lib/monotime.h index 10d3bb604d..0fd4940431 100644 --- a/lib/monotime.h +++ b/lib/monotime.h @@ -28,6 +28,13 @@ (tv)->tv_usec = (ts)->tv_nsec / 1000; \ } while (0) #endif +#ifndef TIMEVAL_TO_TIMESPEC +/* should be in sys/time.h on BSD & Linux libcs */ +#define TIMEVAL_TO_TIMESPEC(tv, ts) do { \ + (ts)->tv_sec = (tv)->tv_sec; \ + (ts)->tv_nsec = (tv)->tv_usec * 1000; \ + } while (0) +#endif static inline time_t monotime(struct timeval *tvo) { From 05dbb7df2f2dfbb476f79b0e7a85a3f506f36255 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 23 Jan 2017 23:26:23 +0100 Subject: [PATCH 414/444] build: support bison < 3.0 for parse.error=verbose *sigh* Signed-off-by: David Lamparter --- configure.ac | 3 +++ lib/Makefile.am | 2 +- lib/command_parse.y | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 6ce5d0cc2c..550ac4f926 100755 --- a/configure.ac +++ b/configure.ac @@ -1459,6 +1459,7 @@ case "x${quagga_ac_bison_version}" in x2.7*) BISON_OPENBRACE='"' BISON_CLOSEBRACE='"' + BISON_VERBOSE='' AC_MSG_RESULT([$quagga_ac_bison_version - 2.7 or older]) ;; x2.*|x1.*) @@ -1474,11 +1475,13 @@ case "x${quagga_ac_bison_version}" in *) BISON_OPENBRACE='{' BISON_CLOSEBRACE='}' + BISON_VERBOSE='-Dparse.error=verbose' AC_MSG_RESULT([$quagga_ac_bison_version - 3.0 or newer]) ;; esac AC_SUBST(BISON_OPENBRACE) AC_SUBST(BISON_CLOSEBRACE) +AC_SUBST(BISON_VERBOSE) if $quagga_ac_bison_missing; then YACC="$SHELL $missing_dir/missing bison -y" diff --git a/lib/Makefile.am b/lib/Makefile.am index b048720673..08d9dccb9d 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -3,7 +3,7 @@ AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib AM_CFLAGS = $(WERROR) DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" -AM_YFLAGS = -d -Dapi.prefix=@BISON_OPENBRACE@cmd_yy@BISON_CLOSEBRACE@ +AM_YFLAGS = -d -Dapi.prefix=@BISON_OPENBRACE@cmd_yy@BISON_CLOSEBRACE@ @BISON_VERBOSE@ command_lex.h: command_lex.c @if test ! -f $@; then rm -f command_lex.c; else :; fi diff --git a/lib/command_parse.y b/lib/command_parse.y index cbc7ce9754..dd8e6fb596 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -28,7 +28,7 @@ %} %locations -%define parse.error verbose +/* define parse.error verbose */ %define api.pure full /* define api.prefix {cmd_yy} */ From 14152706b42699d5665cd5291637730841e41b94 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 24 Jan 2017 02:51:00 +0100 Subject: [PATCH 415/444] lib: parser: guard yylloc yylloc seems to be NULL on parser init for some flex+bison combinations... Signed-off-by: David Lamparter --- lib/command_lex.l | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/command_lex.l b/lib/command_lex.l index 703596b43d..2a241abbec 100644 --- a/lib/command_lex.l +++ b/lib/command_lex.l @@ -26,9 +26,10 @@ #include "command_parse.h" #define YY_USER_ACTION yylloc->last_column += yyleng; -#define LOC_STEP \ +#define LOC_STEP do { if (yylloc) { \ yylloc->first_column = yylloc->last_column; \ - yylloc->first_line = yylloc->last_line; + yylloc->first_line = yylloc->last_line; \ + } } while(0) %} WORD (\-|\+)?[a-z0-9\*][-+_a-zA-Z0-9\*]* From b285cf4b74312d94e8c21647205b905926af7dd8 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 23 Jan 2017 23:40:07 +0100 Subject: [PATCH 416/444] grammar_sandbox: detab Signed-off-by: David Lamparter --- lib/grammar_sandbox.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c index f92c78de55..315bd4d59c 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -42,8 +42,8 @@ void pretty_print_graph (struct vty *vty, struct graph_node *, int, int, struct graph_node **, size_t); static void pretty_print_dot (FILE *ofd, unsigned opts, struct graph_node *start, - struct graph_node **stack, size_t stackpos, - struct graph_node **visited, size_t *visitpos); + struct graph_node **stack, size_t stackpos, + struct graph_node **visited, size_t *visitpos); void init_cmdgraph (struct vty *, struct graph **); @@ -258,8 +258,8 @@ DEFUN (grammar_test_dot, fprintf(ofd, "digraph {\n graph [ rankdir = LR ];\n node [ fontname = \"Fira Mono\", fontsize = 9 ];\n\n"); pretty_print_dot (ofd, 0, - vector_slot (nodegraph->nodes, 0), - stack, 0, visited, &vpos); + vector_slot (nodegraph->nodes, 0), + stack, 0, visited, &vpos); fprintf(ofd, "}\n"); fclose(ofd); return CMD_SUCCESS; @@ -348,7 +348,7 @@ size_t tokennames_max = array_size(tokennames); */ void pretty_print_graph (struct vty *vty, struct graph_node *start, int level, - int desc, struct graph_node **stack, size_t stackpos) + int desc, struct graph_node **stack, size_t stackpos) { // print this node char tokennum[32]; @@ -404,8 +404,8 @@ pretty_print_graph (struct vty *vty, struct graph_node *start, int level, static void pretty_print_dot (FILE *ofd, unsigned opts, struct graph_node *start, - struct graph_node **stack, size_t stackpos, - struct graph_node **visited, size_t *visitpos) + struct graph_node **stack, size_t stackpos, + struct graph_node **visited, size_t *visitpos) { // print this node char tokennum[32]; @@ -454,19 +454,19 @@ pretty_print_dot (FILE *ofd, unsigned opts, struct graph_node *start, // if this node is a vararg, just print * if (adj == start) { fprintf(ofd, " n%016llx -> n%016llx;\n", - (unsigned long long)start, - (unsigned long long)start); + (unsigned long long)start, + (unsigned long long)start); } else if (((struct cmd_token *)adj->data)->type == END_TKN) { - //struct cmd_token *et = adj->data; + //struct cmd_token *et = adj->data; fprintf(ofd, " n%016llx -> end%016llx;\n", - (unsigned long long)start, - (unsigned long long)adj); - fprintf(ofd, " end%016llx [ shape=box, label=, style = filled, fillcolor = \"#ffddaa\" ];\n", - (unsigned long long)adj); + (unsigned long long)start, + (unsigned long long)adj); + fprintf(ofd, " end%016llx [ shape=box, label=, style = filled, fillcolor = \"#ffddaa\" ];\n", + (unsigned long long)adj); } else { fprintf(ofd, " n%016llx -> n%016llx;\n", - (unsigned long long)start, - (unsigned long long)adj); + (unsigned long long)start, + (unsigned long long)adj); size_t k; for (k = 0; k < stackpos; k++) if (stack[k] == adj) From 8fd8881c2951f166ca55095e0c01a9820a714e08 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 23 Jan 2017 23:32:01 +0100 Subject: [PATCH 417/444] zebra: fpm: fix --enable-dev-build I guess no one uses --enable-dev-build... Signed-off-by: David Lamparter --- zebra/zebra_fpm_dt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zebra/zebra_fpm_dt.c b/zebra/zebra_fpm_dt.c index bd171c89b2..715e250a66 100644 --- a/zebra/zebra_fpm_dt.c +++ b/zebra/zebra_fpm_dt.c @@ -42,6 +42,8 @@ #include "vrf.h" #include "zebra/rib.h" +#include "zebra/zserv.h" +#include "zebra/zebra_vrf.h" #include "zebra_fpm_private.h" From ece35fdcb7803f655be804d1143e361fcc6e81a3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 21 Jan 2017 07:07:46 -0500 Subject: [PATCH 418/444] lib: Add VRF_ALL define Allow the specification of a VRF_ALL to be used for CLI. Signed-off-by: Donald Sharp --- lib/vrf.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/vrf.h b/lib/vrf.h index 96c716a7b8..f8bb07ef48 100644 --- a/lib/vrf.h +++ b/lib/vrf.h @@ -34,6 +34,7 @@ /* The default VRF ID */ #define VRF_DEFAULT 0 #define VRF_UNKNOWN UINT16_MAX +#define VRF_ALL UINT16_MAX - 1 /* Pending: May need to refine this. */ #ifndef IFLA_VRF_MAX From 9dd6d53149ab54c5960eb1b5f4d4248cbbc41853 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 22 Jan 2017 11:01:09 -0500 Subject: [PATCH 419/444] bgpd: Fix function used only within KEEP_OLD_VPN_COMMANDS The show_adj_route_vpn function is only currently used in conjunction with the KEEP_OLD_VPN_COMMANDS #define. Add this function to that define for the moment. Signed-off-by: Donald Sharp --- bgpd/bgp_mplsvpn.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index bfbddb6c30..dd25fdfaf4 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -566,6 +566,7 @@ DEFUN (no_vpnv6_network, return bgp_static_unset_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg); } +#if defined(KEEP_OLD_VPN_COMMANDS) static int show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd, u_char use_json, afi_t afi) { @@ -732,6 +733,7 @@ show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd, u } return CMD_SUCCESS; } +#endif enum bgp_show_type { From 3289141f01cda126e9896401e1f74fae2913343a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 22 Jan 2017 11:05:04 -0500 Subject: [PATCH 420/444] bgpd: Remove unused function bgp_parse_safi The bgp_parse_safi function is never called remove it. Especially as that later commits will properly handle what this function was trying to do. Signed-off-by: Donald Sharp --- bgpd/bgp_vty.c | 12 +----------- bgpd/bgp_vty.h | 3 --- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 2e001b3a9d..ef400380da 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -167,17 +167,7 @@ bgp_vty_safi_from_arg(const char *safi_str) } int -bgp_parse_safi(const char *str, safi_t *safi) -{ - *safi = bgp_vty_safi_from_arg(str); - if (*safi != SAFI_MAX) - return 0; - else - return -1; -} - -int -argv_find_and_parse_safi(struct cmd_token **argv, int argc, int *index, safi_t *safi) +argv_find_and_parse_safi (struct cmd_token **argv, int argc, int *index, safi_t *safi) { int ret = 0; if (argv_find (argv, argc, "unicast", index)) diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h index 40c1723218..3f2f573414 100644 --- a/bgpd/bgp_vty.h +++ b/bgpd/bgp_vty.h @@ -51,9 +51,6 @@ peer_and_group_lookup_vty (struct vty *vty, const char *peer_str); extern int bgp_parse_afi(const char *str, afi_t *afi); -extern int -bgp_parse_safi(const char *str, safi_t *safi); - extern afi_t bgp_vty_afi_from_arg(const char *afi_str); From 9fa4d336caa23066f4fa886434d2857798023945 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 22 Jan 2017 13:13:48 -0500 Subject: [PATCH 421/444] bgpd: Fix vpn commands cli The parser was incorrect for the 'set ... vpn nexthop ...' commands. Signed-off-by: Donald Sharp --- bgpd/bgp_routemap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 50524baa01..373a8e5d97 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -3992,7 +3992,7 @@ DEFUN (no_set_vpn_nexthop, DEFUN (set_ipx_vpn_nexthop, set_ipx_vpn_nexthop_cmd, - "set vpn next-hop [A.B.C.D|X:X::X:X]", + "set vpn next-hop []", SET_STR "IPv4 information\n" "IPv6 information\n" @@ -4019,7 +4019,7 @@ DEFUN (set_ipx_vpn_nexthop, DEFUN (no_set_ipx_vpn_nexthop, no_set_ipx_vpn_nexthop_cmd, - "no set vpn next-hop [A.B.C.D|X:X::X:X]", + "no set vpn next-hop []", NO_STR SET_STR "IPv4 information\n" From af462945f1a46f80c857e30b72e53ad3610817ee Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 23 Jan 2017 19:48:24 -0500 Subject: [PATCH 422/444] bgpd: Start cleanup of 'show [ip] bgp ...' commands Create bgp_vty_find_and_parse_afi_safi_vrf that will parse the `show [ip] bgp [ WORD] [ []]' part of a command and to return the correct spot we are in the command. Cleanup 'dampening parameters' part of this command. Consolidate the creation of the bgp data structure to be a bit cleaner. Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 216 +++++++++++++---------------------------------- bgpd/bgp_vty.c | 34 ++++++++ bgpd/bgp_vty.h | 3 + 3 files changed, 94 insertions(+), 159 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 6faf474286..53c0cd822a 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -7235,30 +7235,30 @@ enum bgp_show_type }; static int -bgp_show_prefix_list (struct vty *vty, const char *name, +bgp_show_prefix_list (struct vty *vty, struct bgp *bgp, const char *prefix_list_str, afi_t afi, safi_t safi, enum bgp_show_type type); static int -bgp_show_filter_list (struct vty *vty, const char *name, +bgp_show_filter_list (struct vty *vty, struct bgp *bgp, const char *filter, afi_t afi, safi_t safi, enum bgp_show_type type); static int -bgp_show_route_map (struct vty *vty, const char *name, +bgp_show_route_map (struct vty *vty, struct bgp *bgp, const char *rmap_str, afi_t afi, safi_t safi, enum bgp_show_type type); static int -bgp_show_community_list (struct vty *vty, const char *name, +bgp_show_community_list (struct vty *vty, struct bgp *bgp, const char *com, int exact, afi_t afi, safi_t safi); static int -bgp_show_prefix_longer (struct vty *vty, const char *name, +bgp_show_prefix_longer (struct vty *vty, struct bgp *bgp, const char *prefix, afi_t afi, safi_t safi, enum bgp_show_type type); static int bgp_show_regexp (struct vty *vty, const char *regstr, afi_t afi, safi_t safi, enum bgp_show_type type); static int -bgp_show_community (struct vty *vty, const char *view_name, int argc, +bgp_show_community (struct vty *vty, struct bgp *bgp, int argc, struct cmd_token **argv, int exact, afi_t afi, safi_t safi); static int @@ -7834,8 +7834,8 @@ bgp_show_route (struct vty *vty, const char *view_name, const char *ip_str, } /* BGP route print out function. */ -DEFUN (show_ip_bgp_ipv4, - show_ip_bgp_ipv4_cmd, +DEFUN (show_ip_bgp, + show_ip_bgp_cmd, "show [ip] bgp [ WORD] [ []]\ [<\ cidr-only\ @@ -7862,7 +7862,7 @@ DEFUN (show_ip_bgp_ipv4, "Display detailed information about dampening\n" "Display flap statistics of routes\n" "Display paths suppressed due to dampening\n" - "Display dampening parameters\n" + "Display detail of configured dampening parameters\n" "Display routes matching the route-map\n" "A route-map to match on\n" "Display routes conforming to the prefix-list\n" @@ -7885,67 +7885,58 @@ DEFUN (show_ip_bgp_ipv4, "Display route and more specific routes\n" JSON_STR) { - char *vrf = NULL; + vrf_id_t vrf = VRF_DEFAULT; afi_t afi = AFI_IP6; safi_t safi = SAFI_UNICAST; int exact_match = 0; enum bgp_show_type sh_type = bgp_show_type_normal; - + struct bgp *bgp = NULL; int idx = 0; - if (argv_find (argv, argc, "ip", &idx)) - afi = AFI_IP; - if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) - vrf = argv[++idx]->arg; - if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx)) - { - afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; - if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx)) - safi = bgp_vty_safi_from_arg (argv[idx]->text); - } - else if (argv_find (argv, argc, "encap", &idx) || argv_find (argv, argc, "vpnv4", &idx)) - { - afi = AFI_IP; - safi = strmatch (argv[idx]->text, "encap") ? SAFI_ENCAP : SAFI_MPLS_VPN; - // advance idx if necessary - argv_find (argv, argc, "unicast", &idx); - } - + idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); + if (!idx) + { + vty_out (vty, "View/Vrf Specified: %s is unknown", argv[5]->arg); + return CMD_WARNING; + } int uj = use_json (argc, argv); if (uj) argc--; - struct bgp *bgp = bgp_lookup_by_name (vrf); - if (bgp == NULL) - { - vty_out (vty, "Can't find BGP instance %s%s", vrf, VTY_NEWLINE); - return CMD_WARNING; - } + if (vrf != VRF_ALL) + { + bgp = bgp_lookup_by_vrf_id (vrf); + if (bgp == NULL) + { + vty_out (vty, "Can't find BGP instance %s%s", argv[5]->arg, VTY_NEWLINE); + return CMD_WARNING; + } + } + else + bgp = NULL; - if (++idx < argc) - { - if (strmatch(argv[idx]->text, "cidr-only")) - return bgp_show (vty, bgp, afi, safi, bgp_show_type_cidr_only, NULL, uj); + if (argv_find(argv, argc, "cidr-only", &idx)) + return bgp_show (vty, bgp, afi, safi, bgp_show_type_cidr_only, NULL, uj); - else if (strmatch(argv[idx]->text, "dampening")) + if (argv_find(argv, argc, "dampening", &idx)) { if (argv_find (argv, argc, "dampened-paths", &idx)) return bgp_show (vty, bgp, afi, safi, bgp_show_type_dampend_paths, NULL, uj); else if (argv_find (argv, argc, "flap-statistics", &idx)) return bgp_show (vty, bgp, afi, safi, bgp_show_type_flap_statistics, NULL, uj); else if (argv_find (argv, argc, "parameters", &idx)) - return bgp_show_dampening_parameters (vty, AFI_IP, SAFI_UNICAST); + return bgp_show_dampening_parameters (vty, afi, safi); } - else if (strmatch(argv[idx]->text, "prefix-list")) - return bgp_show_prefix_list (vty, vrf, argv[idx + 1]->arg, afi, safi, bgp_show_type_prefix_list); + if (argv_find(argv, argc, "prefix-list", &idx)) + return bgp_show_prefix_list (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_prefix_list); - else if (strmatch(argv[idx]->text, "filter-list")) - return bgp_show_filter_list (vty, vrf, argv[idx + 1]->arg, afi, safi, bgp_show_type_filter_list); + if (argv_find(argv, argc, "filter-list", &idx)) + return bgp_show_filter_list (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_filter_list); - else if (strmatch(argv[idx]->text, "route-map")) - return bgp_show_route_map (vty, vrf, argv[idx + 1]->arg, afi, safi, bgp_show_type_route_map); + if (argv_find(argv, argc, "route-map", &idx)) + return bgp_show_route_map (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_route_map); - else if (strmatch(argv[idx]->text, "community")) + if (argv_find(argv, argc, "community", &idx)) { /* show a specific community */ if (argv[idx + 1]->type == VARIABLE_TKN || @@ -7955,23 +7946,22 @@ DEFUN (show_ip_bgp_ipv4, { if (strmatch(argv[idx + 2]->text, "exact_match")) exact_match = 1; - return bgp_show_community (vty, vrf, argc, argv, exact_match, afi, safi); + return bgp_show_community (vty, bgp, argc, argv, exact_match, afi, safi); } /* show all communities */ else return bgp_show (vty, bgp, afi, safi, bgp_show_type_community_all, NULL, uj); } - else if (strmatch(argv[idx]->text, "community-list")) - { - const char *clist_number_or_name = argv[++idx]->arg; - if (++idx < argc && strmatch (argv[idx]->arg, "exact-match")) - exact_match = 1; - return bgp_show_community_list (vty, vrf, clist_number_or_name, exact_match, afi, safi); - } - /* prefix-longer */ - else if (argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV6_TKN) - return bgp_show_prefix_longer (vty, vrf, argv[idx + 1]->arg, afi, safi, bgp_show_type_prefix_longer); - } + if (argv_find(argv, argc, "community-list", &idx)) + { + const char *clist_number_or_name = argv[++idx]->arg; + if (++idx < argc && strmatch (argv[idx]->arg, "exact-match")) + exact_match = 1; + return bgp_show_community_list (vty, bgp, clist_number_or_name, exact_match, afi, safi); + } + /* prefix-longer */ + if (argv_find(argv, argc, "A.B.C.D/M", &idx) || argv_find(argv, argc, "X:X::X:X/M", &idx)) + return bgp_show_prefix_longer (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_prefix_longer); return bgp_show (vty, bgp, afi, safi, sh_type, NULL, uj); } @@ -8185,18 +8175,11 @@ bgp_show_regexp (struct vty *vty, const char *regstr, afi_t afi, } static int -bgp_show_prefix_list (struct vty *vty, const char *name, +bgp_show_prefix_list (struct vty *vty, struct bgp *bgp, const char *prefix_list_str, afi_t afi, safi_t safi, enum bgp_show_type type) { struct prefix_list *plist; - struct bgp *bgp = NULL; - - if (name && !(bgp = bgp_lookup_by_name(name))) - { - vty_out (vty, "%% No such BGP instance exists%s", VTY_NEWLINE); - return CMD_WARNING; - } plist = prefix_list_lookup (afi, prefix_list_str); if (plist == NULL) @@ -8210,18 +8193,11 @@ bgp_show_prefix_list (struct vty *vty, const char *name, } static int -bgp_show_filter_list (struct vty *vty, const char *name, +bgp_show_filter_list (struct vty *vty, struct bgp *bgp, const char *filter, afi_t afi, safi_t safi, enum bgp_show_type type) { struct as_list *as_list; - struct bgp *bgp = NULL; - - if (name && !(bgp = bgp_lookup_by_name(name))) - { - vty_out (vty, "%% No such BGP instance exists%s", VTY_NEWLINE); - return CMD_WARNING; - } as_list = as_list_lookup (filter); if (as_list == NULL) @@ -8233,53 +8209,12 @@ bgp_show_filter_list (struct vty *vty, const char *name, return bgp_show (vty, bgp, afi, safi, type, as_list, 0); } -DEFUN (show_ip_bgp_dampening_info, - show_ip_bgp_dampening_params_cmd, - "show [ip] bgp dampening parameters", - SHOW_STR - IP_STR - BGP_STR - "Display detailed information about dampening\n" - "Display detail of configured dampening parameters\n") -{ - return bgp_show_dampening_parameters (vty, AFI_IP, SAFI_UNICAST); -} - - -DEFUN (show_ip_bgp_ipv4_dampening_parameters, - show_ip_bgp_ipv4_dampening_parameters_cmd, - "show [ip] bgp ipv4 dampening parameters", - SHOW_STR - IP_STR - BGP_STR - "Address Family\n" - "Address Family modifier\n" - "Address Family modifier\n" - "Display detailed information about dampening\n" - "Display detail of configured dampening parameters\n") -{ - int idx_safi = 4; - if (strncmp(argv[idx_safi]->arg, "m", 1) == 0) - return bgp_show_dampening_parameters (vty, AFI_IP, SAFI_MULTICAST); - - return bgp_show_dampening_parameters (vty, AFI_IP, SAFI_UNICAST); -} - static int -bgp_show_route_map (struct vty *vty, const char *name, +bgp_show_route_map (struct vty *vty, struct bgp *bgp, const char *rmap_str, afi_t afi, safi_t safi, enum bgp_show_type type) { struct route_map *rmap; - struct bgp *bgp = NULL; - - if (name && !(bgp = bgp_lookup_by_name(name))) - { - - - vty_out (vty, "%% No such BGP instance exists%s", VTY_NEWLINE); - return CMD_WARNING; - } rmap = route_map_lookup_by_name (rmap_str); if (! rmap) @@ -8293,36 +8228,15 @@ bgp_show_route_map (struct vty *vty, const char *name, } static int -bgp_show_community (struct vty *vty, const char *view_name, int argc, +bgp_show_community (struct vty *vty, struct bgp *bgp, int argc, struct cmd_token **argv, int exact, afi_t afi, safi_t safi) { struct community *com; struct buffer *b; - struct bgp *bgp; int i; char *str; int first = 0; - /* BGP structure lookup */ - if (view_name) - { - bgp = bgp_lookup_by_name (view_name); - if (bgp == NULL) - { - vty_out (vty, "Can't find BGP instance %s%s", view_name, VTY_NEWLINE); - return CMD_WARNING; - } - } - else - { - bgp = bgp_get_default (); - if (bgp == NULL) - { - vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); - return CMD_WARNING; - } - } - b = buffer_new (1024); for (i = 0; i < argc; i++) { @@ -8356,18 +8270,11 @@ bgp_show_community (struct vty *vty, const char *view_name, int argc, } static int -bgp_show_community_list (struct vty *vty, const char *name, +bgp_show_community_list (struct vty *vty, struct bgp *bgp, const char *com, int exact, afi_t afi, safi_t safi) { struct community_list *list; - struct bgp *bgp = NULL; - - if (name && !(bgp = bgp_lookup_by_name(name))) - { - vty_out (vty, "%% No such BGP instance exists%s", VTY_NEWLINE); - return CMD_WARNING; - } list = community_list_lookup (bgp_clist, com, COMMUNITY_LIST_MASTER); if (list == NULL) @@ -8383,19 +8290,12 @@ bgp_show_community_list (struct vty *vty, const char *name, } static int -bgp_show_prefix_longer (struct vty *vty, const char *name, +bgp_show_prefix_longer (struct vty *vty, struct bgp *bgp, const char *prefix, afi_t afi, safi_t safi, enum bgp_show_type type) { int ret; struct prefix *p; - struct bgp *bgp = NULL; - - if (name && !(bgp = bgp_lookup_by_name(name))) - { - vty_out (vty, "%% No such BGP instance exists%s", VTY_NEWLINE); - return CMD_WARNING; - } p = prefix_new(); @@ -10527,14 +10427,12 @@ bgp_route_init (void) install_element (BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd); install_element (VIEW_NODE, &show_ip_bgp_instance_all_cmd); - install_element (VIEW_NODE, &show_ip_bgp_ipv4_cmd); + install_element (VIEW_NODE, &show_ip_bgp_cmd); install_element (VIEW_NODE, &show_ip_bgp_route_cmd); install_element (VIEW_NODE, &show_ip_bgp_regexp_cmd); install_element (VIEW_NODE, &show_ip_bgp_instance_neighbor_advertised_route_cmd); install_element (VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd); install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd); - install_element (VIEW_NODE, &show_ip_bgp_dampening_params_cmd); - install_element (VIEW_NODE, &show_ip_bgp_ipv4_dampening_parameters_cmd); #ifdef KEEP_OLD_VPN_COMMANDS install_element (VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd); #endif /* KEEP_OLD_VPN_COMMANDS */ diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index ef400380da..7f4bd49d29 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -197,6 +197,40 @@ argv_find_and_parse_safi (struct cmd_token **argv, int argc, int *index, safi_t return ret; } +int +bgp_vty_find_and_parse_afi_safi_vrf (struct vty *vty, struct cmd_token **argv, int argc, int idx, + afi_t *afi, safi_t *safi, vrf_id_t *vrf) +{ + char *vrf_name = NULL; + + if (argv_find (argv, argc, "ip", &idx)) + *afi = AFI_IP; + + if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) + { + vrf_name = argv[idx + 1]->arg; + idx += 2; + } + + if (argv_find_and_parse_afi (argv, argc, &idx, afi)) + argv_find_and_parse_safi (argv, argc, &idx, safi); + + if (vrf_name) + { + if (strmatch(vrf_name, "all")) + *vrf = VRF_ALL; + else + *vrf = vrf_name_to_id (vrf_name); + } + + if (*vrf == VRF_UNKNOWN) + { + vty_out (vty, "View/Vrf specified is unknown: %s", vrf_name); + return 0; + } + return idx + 1; +} + static int peer_address_self_check (struct bgp *bgp, union sockunion *su) { diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h index 3f2f573414..cfc4f6cdfb 100644 --- a/bgpd/bgp_vty.h +++ b/bgpd/bgp_vty.h @@ -63,4 +63,7 @@ argv_find_and_parse_afi(struct cmd_token **argv, int argc, int *index, afi_t *af extern int argv_find_and_parse_safi(struct cmd_token **argv, int argc, int *index, safi_t *safi); +extern int +bgp_vty_find_and_parse_afi_safi_vrf (struct vty *vty, struct cmd_token **argv, int argc, int idx, + afi_t *afi, safi_t *safi, vrf_id_t *vrf); #endif /* _QUAGGA_BGP_VTY_H */ From c41247f50e8136d8f32bcc2ec83e0b87985b4c10 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 23 Jan 2017 19:58:56 -0500 Subject: [PATCH 423/444] bgpd: Cleanup 'show .... ' Cleanup the bgp bestpath or multipath show commands. Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 68 ++++++++++++++++-------------------------------- 1 file changed, 22 insertions(+), 46 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 53c0cd822a..25fd988009 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -7801,33 +7801,11 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp, /* Display specified route of Main RIB */ static int -bgp_show_route (struct vty *vty, const char *view_name, const char *ip_str, +bgp_show_route (struct vty *vty, struct bgp *bgp, const char *ip_str, afi_t afi, safi_t safi, struct prefix_rd *prd, int prefix_check, enum bgp_path_type pathtype, u_char use_json) { - struct bgp *bgp; - - /* BGP structure lookup. */ - if (view_name) - { - bgp = bgp_lookup_by_name (view_name); - if (bgp == NULL) - { - vty_out (vty, "Can't find BGP instance %s%s", view_name, VTY_NEWLINE); - return CMD_WARNING; - } - } - else - { - bgp = bgp_get_default (); - if (bgp == NULL) - { - vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); - return CMD_WARNING; - } - } - return bgp_show_route_in_table (vty, bgp, bgp->rib[afi][safi], ip_str, afi, safi, prd, prefix_check, pathtype, use_json); @@ -7992,34 +7970,32 @@ DEFUN (show_ip_bgp_route, afi_t afi = AFI_IP6; safi_t safi = SAFI_UNICAST; - char *vrf = NULL; + vrf_id_t vrf = VRF_DEFAULT;; char *prefix = NULL; - + struct bgp *bgp = NULL; enum bgp_path_type path_type; u_char uj = use_json(argc, argv); int idx = 0; - /* show [ip] bgp */ - if (argv_find (argv, argc, "ip", &idx)) - afi = AFI_IP; - /* [ WORD] */ - if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) - vrf = argv[++idx]->arg; - /* []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] */ - if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx)) - { - afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; - if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx)) - safi = strmatch (argv[idx]->text, "unicast") ? SAFI_UNICAST : SAFI_MULTICAST; - } - else if (argv_find (argv, argc, "encap", &idx) || argv_find (argv, argc, "vpnv4", &idx)) - { - afi = AFI_IP; - safi = strmatch (argv[idx]->text, "encap") ? SAFI_ENCAP : SAFI_MPLS_VPN; - // advance idx if necessary - argv_find (argv, argc, "unicast", &idx); - } + idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); + if (!idx) + { + vty_out (vty, "View/Vrf Specified: %s is unknown", argv[5]->arg); + return CMD_WARNING; + } + + if (vrf != VRF_ALL) + { + bgp = bgp_lookup_by_vrf_id (vrf); + if (bgp == NULL) + { + vty_out (vty, "Can't find BGP instance %s%s", argv[5]->arg, VTY_NEWLINE); + return CMD_WARNING; + } + } + else + bgp = NULL; /* */ if (argv_find (argv, argc, "A.B.C.D", &idx) || argv_find (argv, argc, "X:X::X:X", &idx)) @@ -8048,7 +8024,7 @@ DEFUN (show_ip_bgp_route, else path_type = BGP_PATH_ALL; - return bgp_show_route (vty, vrf, prefix, afi, safi, NULL, prefix_check, path_type, uj); + return bgp_show_route (vty, bgp, prefix, afi, safi, NULL, prefix_check, path_type, uj); } DEFUN (show_ip_bgp_regexp, From b00b230aa1bf6775b3207c8d0a6b61c36b892449 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 23 Jan 2017 20:29:54 -0500 Subject: [PATCH 424/444] bgp: Fix 'show .... regexp REGEX...' Fix this command to use the correct format for a show command. Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 25fd988009..8adc6bd971 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8029,46 +8029,31 @@ DEFUN (show_ip_bgp_route, DEFUN (show_ip_bgp_regexp, show_ip_bgp_regexp_cmd, - "show [ip] bgp []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] regexp REGEX...", + "show [ip] bgp [ WORD] [ []] regexp REGEX...", SHOW_STR IP_STR BGP_STR + BGP_INSTANCE_HELP_STR + "Address Family\n" "Address Family\n" "Address Family modifier\n" "Address Family modifier\n" "Address Family modifier\n" "Address Family modifier\n" - "Address Family\n" - "Address Family modifier\n" - "Address Family modifier\n" - "Address Family modifier\n" - "Address Family modifier\n" - "Address Family\n" - "Address Family modifier\n" - "Address Family\n" - "Address Family modifier\n" "Display routes matching the AS path regular expression\n" "A regular-expression to match the BGP AS paths\n") { + vrf_id_t vrf = VRF_DEFAULT; afi_t afi = AFI_IP6; safi_t safi = SAFI_UNICAST; int idx = 0; - - /* []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] */ - if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx)) - { - afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; - if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx)) - safi = strmatch (argv[idx]->text, "unicast") ? SAFI_UNICAST : SAFI_MULTICAST; - } - else if (argv_find (argv, argc, "encap", &idx) || argv_find (argv, argc, "vpnv4", &idx)) - { - afi = AFI_IP; - safi = strmatch (argv[idx]->text, "encap") ? SAFI_ENCAP : SAFI_MPLS_VPN; - // advance idx if necessary - argv_find (argv, argc, "unicast", &idx); - } + idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); + if (!idx) + { + vty_out (vty, "View/Vrf Specified: %s is unknown", argv[5]->arg); + return CMD_WARNING; + } // get index of regex argv_find (argv, argc, "regexp", &idx); From f2a8972b0b746522ab4442a30f4b27da6f3620a2 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 23 Jan 2017 20:50:50 -0500 Subject: [PATCH 425/444] bgpd: Cleanup 'view all' command 1) Make [ WORD] consistent 2) Fix inconsistent help string 3) Fix the show .. vrf all command Signed-off-by: Donald Sharp --- bgpd/bgp_nexthop.c | 4 ++-- bgpd/bgp_route.c | 36 ++++++++++-------------------------- bgpd/bgp_vty.c | 6 +++--- 3 files changed, 15 insertions(+), 31 deletions(-) diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 0a9747b526..0cf96101c2 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -492,7 +492,7 @@ bgp_show_all_instances_nexthops_vty (struct vty *vty) DEFUN (show_ip_bgp_nexthop, show_ip_bgp_nexthop_cmd, - "show [ip] bgp [ VRFNAME] nexthop [detail]", + "show [ip] bgp [ WORD] nexthop [detail]", SHOW_STR IP_STR BGP_STR @@ -501,7 +501,7 @@ DEFUN (show_ip_bgp_nexthop, "Show detailed information\n") { int idx = 0; - char *vrf = argv_find (argv, argc, "VRFNAME", &idx) ? argv[idx]->arg : NULL; + char *vrf = argv_find (argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; int detail = argv_find (argv, argc, "detail", &idx) ? 1 : 0; return show_ip_bgp_nexthop_table (vty, vrf, detail); } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 8adc6bd971..c9fcbf9fb4 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8067,53 +8067,37 @@ DEFUN (show_ip_bgp_regexp, DEFUN (show_ip_bgp_instance_all, show_ip_bgp_instance_all_cmd, - "show [ip] bgp all []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] [json]", + "show [ip] bgp all [ []] [json]", SHOW_STR IP_STR BGP_STR BGP_INSTANCE_ALL_HELP_STR "Address Family\n" - "Address Family modifier\n" - "Address Family modifier\n" "Address Family\n" "Address Family modifier\n" "Address Family modifier\n" - "Address Family\n" "Address Family modifier\n" - "Address Family\n" "Address Family modifier\n" JSON_STR) { + vrf_id_t vrf = VRF_DEFAULT; afi_t afi = AFI_IP; safi_t safi = SAFI_UNICAST; int idx = 0; - - /* show [ip] bgp */ - if (argv_find (argv, argc, "ip", &idx)) - afi = AFI_IP; - /* []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] */ - if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx)) - { - afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; - if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx)) - safi = strmatch (argv[idx]->text, "unicast") ? SAFI_UNICAST : SAFI_MULTICAST; - } - else if (argv_find (argv, argc, "encap", &idx) || argv_find (argv, argc, "vpnv4", &idx)) - { - afi = AFI_IP; - safi = strmatch (argv[idx]->text, "encap") ? SAFI_ENCAP : SAFI_MPLS_VPN; - // advance idx if necessary - argv_find (argv, argc, "unicast", &idx); - } - - u_char uj = use_json(argc, argv); + idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); + if (!idx) + { + vty_out (vty, "View/Vrf Specified: %s is unknown", argv[5]->arg); + return CMD_WARNING; + } + int uj = use_json (argc, argv); + if (uj) argc--; bgp_show_all_instances_routes_vty (vty, afi, safi, uj); return CMD_SUCCESS; } - static int bgp_show_regexp (struct vty *vty, const char *regstr, afi_t afi, safi_t safi, enum bgp_show_type type) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 7f4bd49d29..fa19308cb1 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -8605,7 +8605,7 @@ DEFUN (show_ip_bgp_neighbors, SHOW_STR IP_STR BGP_STR - BGP_INSTANCE_ALL_HELP_STR + BGP_INSTANCE_HELP_STR "Address Family\n" "Address Family\n" "Address Family\n" @@ -9241,7 +9241,7 @@ bgp_show_peer_group_vty (struct vty *vty, const char *name, DEFUN (show_ip_bgp_peer_groups, show_ip_bgp_peer_groups_cmd, - "show [ip] bgp [ VRFNAME] peer-group [PGNAME]", + "show [ip] bgp [ WORD] peer-group [PGNAME]", SHOW_STR IP_STR BGP_STR @@ -9253,7 +9253,7 @@ DEFUN (show_ip_bgp_peer_groups, vrf = pg = NULL; int idx = 0; - vrf = argv_find (argv, argc, "VRFNAME", &idx) ? argv[idx]->arg : NULL; + vrf = argv_find (argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; pg = argv_find (argv, argc, "PGNAME", &idx) ? argv[idx]->arg : NULL; return bgp_show_peer_group_vty (vty, vrf, show_all_groups, pg); From e01ca200c6db1b7d5ae17c8d90b9ea39ca7382cb Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 23 Jan 2017 21:34:36 -0500 Subject: [PATCH 426/444] bgpd: Cleanup 'show .... statistics' command Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 86 ++++-------------------------------------------- 1 file changed, 7 insertions(+), 79 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index c9fcbf9fb4..48636ef34a 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -7811,6 +7811,8 @@ bgp_show_route (struct vty *vty, struct bgp *bgp, const char *ip_str, use_json); } +static int bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi); + /* BGP route print out function. */ DEFUN (show_ip_bgp, show_ip_bgp_cmd, @@ -7821,6 +7823,7 @@ DEFUN (show_ip_bgp, |route-map WORD\ |prefix-list WORD\ |filter-list WORD\ + |statistics\ |community [ [exact-match]]\ |community-list <(1-500)|WORD> [exact-match]\ |A.B.C.D/M longer-prefixes\ @@ -7847,6 +7850,7 @@ DEFUN (show_ip_bgp, "Prefix-list name\n" "Display routes conforming to the filter-list\n" "Regular expression access list name\n" + "BGP RIB advertisement statistics\n" "Display routes matching the communities\n" COMMUNITY_AANN_STR "Do not send outside local AS (well-known community)\n" @@ -7911,6 +7915,9 @@ DEFUN (show_ip_bgp, if (argv_find(argv, argc, "filter-list", &idx)) return bgp_show_filter_list (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_filter_list); + if (argv_find(argv, argc, "statistics", &idx)) + return bgp_table_stats (vty, bgp, afi, safi); + if (argv_find(argv, argc, "route-map", &idx)) return bgp_show_route_map (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_route_map); @@ -8598,81 +8605,6 @@ bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi) return CMD_SUCCESS; } -static int -bgp_table_stats_vty (struct vty *vty, const char *name, - const char *afi_str, const char *safi_str) -{ - struct bgp *bgp; - afi_t afi; - safi_t safi; - - if (name) - bgp = bgp_lookup_by_name (name); - else - bgp = bgp_get_default (); - - if (!bgp) - { - vty_out (vty, "%% No such BGP instance exist%s", VTY_NEWLINE); - return CMD_WARNING; - } - afi = bgp_vty_afi_from_arg(afi_str); - if (afi == AFI_MAX) - { - vty_out (vty, "%% Invalid address family \"%s\"%s", - afi_str, VTY_NEWLINE); - return CMD_WARNING; - } - safi = bgp_vty_safi_from_arg(safi_str); - if (safi == SAFI_MAX) - { - vty_out (vty, "%% Invalid subsequent address family %s%s", - safi_str, VTY_NEWLINE); - return CMD_WARNING; - } - - return bgp_table_stats (vty, bgp, afi, safi); -} - -DEFUN (show_bgp_statistics, - show_bgp_statistics_cmd, - "show [ip] bgp statistics", - SHOW_STR - IP_STR - BGP_STR - "Address Family\n" - "Address Family\n" - "Address Family modifier\n" - "Address Family modifier\n" - "Address Family modifier\n" - "Address Family modifier\n" - "BGP RIB advertisement statistics\n") -{ - int idx_afi = 2; - int idx_safi = 3; - return bgp_table_stats_vty (vty, NULL, argv[idx_afi]->arg, argv[idx_safi]->arg); -} - -DEFUN (show_bgp_statistics_view, - show_bgp_statistics_view_cmd, - "show [ip] bgp WORD statistics", - SHOW_STR - IP_STR - BGP_STR - BGP_INSTANCE_HELP_STR - "Address Family\n" - "Address Family\n" - "Address Family modifier\n" - "Address Family modifier\n" - "Address Family modifier\n" - "Address Family modifier\n" - "BGP RIB advertisement statistics\n") -{ - int idx_word = 3; - int idx_afi = 4; - return bgp_table_stats_vty (vty, NULL, argv[idx_word]->arg, argv[idx_afi]->arg); -} - enum bgp_pcounts { PCOUNT_ADJ_IN = 0, @@ -10411,10 +10343,6 @@ bgp_route_init (void) install_element (BGP_IPV6M_NODE, &ipv6_bgp_network_cmd); install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_network_cmd); - /* Statistics */ - install_element (ENABLE_NODE, &show_bgp_statistics_cmd); - install_element (ENABLE_NODE, &show_bgp_statistics_view_cmd); - install_element (BGP_NODE, &bgp_distance_cmd); install_element (BGP_NODE, &no_bgp_distance_cmd); install_element (BGP_NODE, &bgp_distance_source_cmd); From 30a6a167a191f6898e1dda754daf6cd054196eae Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 23 Jan 2017 22:30:37 -0500 Subject: [PATCH 427/444] bgpd: Clean up 'show bgp neighbor ...' commands Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 329 ++++++++++++++++------------------------------- 1 file changed, 112 insertions(+), 217 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 48636ef34a..c5b7c4e776 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8264,52 +8264,13 @@ bgp_show_prefix_longer (struct vty *vty, struct bgp *bgp, } static struct peer * -peer_lookup_in_view (struct vty *vty, const char *view_name, +peer_lookup_in_view (struct vty *vty, struct bgp *bgp, const char *ip_str, u_char use_json) { int ret; - struct bgp *bgp; struct peer *peer; union sockunion su; - /* BGP structure lookup. */ - if (view_name) - { - bgp = bgp_lookup_by_name (view_name); - if (! bgp) - { - if (use_json) - { - json_object *json_no = NULL; - json_no = json_object_new_object(); - json_object_string_add(json_no, "warning", "Can't find BGP view"); - vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE); - json_object_free(json_no); - } - else - vty_out (vty, "Can't find BGP instance %s%s", view_name, VTY_NEWLINE); - return NULL; - } - } - else - { - bgp = bgp_get_default (); - if (! bgp) - { - if (use_json) - { - json_object *json_no = NULL; - json_no = json_object_new_object(); - json_object_string_add(json_no, "warning", "No BGP process configured"); - vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE); - json_object_free(json_no); - } - else - vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); - return NULL; - } - } - /* Get peer sockunion. */ ret = str2sockunion (ip_str, &su); if (ret < 0) @@ -8796,117 +8757,20 @@ bgp_peer_counts (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, u_c return CMD_SUCCESS; } -DEFUN (show_ip_bgp_neighbor_prefix_counts, - show_ip_bgp_neighbor_prefix_counts_cmd, - "show [ip] bgp neighbors prefix-counts [json]", - SHOW_STR - IP_STR - BGP_STR - "Detailed information on TCP and BGP neighbor connections\n" - "Neighbor to display information about\n" - "Neighbor to display information about\n" - "Neighbor on BGP configured interface\n" - "Display detailed prefix count information\n" - JSON_STR) -{ - int idx_peer = 4; - struct peer *peer; - u_char uj = use_json(argc, argv); - - peer = peer_lookup_in_view (vty, NULL, argv[idx_peer]->arg, uj); - if (! peer) - return CMD_WARNING; - - return bgp_peer_counts (vty, peer, AFI_IP, SAFI_UNICAST, uj); -} - DEFUN (show_ip_bgp_instance_neighbor_prefix_counts, show_ip_bgp_instance_neighbor_prefix_counts_cmd, - "show [ip] bgp WORD neighbors prefix-counts [json]", - SHOW_STR - IP_STR - BGP_STR - BGP_INSTANCE_HELP_STR - "Detailed information on TCP and BGP neighbor connections\n" - "Neighbor to display information about\n" - "Neighbor to display information about\n" - "Neighbor on BGP configured interface\n" - "Display detailed prefix count information\n" - JSON_STR) -{ - int idx_word = 4; - int idx_peer = 6; - struct peer *peer; - u_char uj = use_json(argc, argv); - - peer = peer_lookup_in_view (vty, argv[idx_word]->arg, argv[idx_peer]->arg, uj); - if (! peer) - return CMD_WARNING; - - return bgp_peer_counts (vty, peer, AFI_IP, SAFI_UNICAST, uj); -} - -DEFUN (show_bgp_ipv6_neighbor_prefix_counts, - show_bgp_ipv6_neighbor_prefix_counts_cmd, - "show [ip] bgp ipv6 neighbors prefix-counts [json]", - SHOW_STR - IP_STR - BGP_STR - "Address Family\n" - "Detailed information on TCP and BGP neighbor connections\n" - "Neighbor to display information about\n" - "Neighbor to display information about\n" - "Neighbor on BGP configured interface\n" - "Display detailed prefix count information\n" - JSON_STR) -{ - int idx_peer = 4; - struct peer *peer; - u_char uj = use_json(argc, argv); - - peer = peer_lookup_in_view (vty, NULL, argv[idx_peer]->arg, uj); - if (! peer) - return CMD_WARNING; - - return bgp_peer_counts (vty, peer, AFI_IP6, SAFI_UNICAST, uj); -} - -DEFUN (show_bgp_instance_ipv6_neighbor_prefix_counts, - show_bgp_instance_ipv6_neighbor_prefix_counts_cmd, - "show [ip] bgp WORD ipv6 neighbors prefix-counts [json]", + "show [ip] bgp [ WORD] [ []] " + "neighbors prefix-counts [json]", SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR "Address Family\n" - "Detailed information on TCP and BGP neighbor connections\n" - "Neighbor to display information about\n" - "Neighbor to display information about\n" - "Neighbor on BGP configured interface\n" - "Display detailed prefix count information\n" - JSON_STR) -{ - int idx_word = 3; - int idx_peer = 6; - struct peer *peer; - u_char uj = use_json(argc, argv); - - peer = peer_lookup_in_view (vty, argv[idx_word]->arg, argv[idx_peer]->arg, uj); - if (! peer) - return CMD_WARNING; - - return bgp_peer_counts (vty, peer, AFI_IP6, SAFI_UNICAST, uj); -} - -DEFUN (show_ip_bgp_ipv4_neighbor_prefix_counts, - show_ip_bgp_ipv4_neighbor_prefix_counts_cmd, - "show [ip] bgp ipv4 neighbors prefix-counts [json]", - SHOW_STR - IP_STR - BGP_STR "Address Family\n" "Address Family modifier\n" "Address Family modifier\n" + "Address Family modifier\n" + "Address Family modifier\n" "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" @@ -8914,18 +8778,48 @@ DEFUN (show_ip_bgp_ipv4_neighbor_prefix_counts, "Display detailed prefix count information\n" JSON_STR) { - int idx_safi = 4; - int idx_peer = 6; + vrf_id_t vrf = VRF_DEFAULT; + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; struct peer *peer; - u_char uj = use_json(argc, argv); + int idx = 0; + struct bgp *bgp = NULL; - peer = peer_lookup_in_view (vty, NULL, argv[idx_peer]->arg, uj); + idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); + if (!idx) + { + vty_out (vty, "View/Vrf Specified: %s is unknown", argv[5]->arg); + return CMD_WARNING; + } + int uj = use_json (argc, argv); + if (uj) argc--; + + if (vrf != VRF_ALL) + { + bgp = bgp_lookup_by_vrf_id (vrf); + if (bgp == NULL) + { + if (uj) + { + json_object *json_no = NULL; + json_no = json_object_new_object(); + json_object_string_add(json_no, "warning", "Can't find BGP view"); + vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE); + json_object_free(json_no); + } + else + vty_out (vty, "Can't find BGP instance %s%s", argv[5]->arg, VTY_NEWLINE); + return CMD_WARNING; + } + } + else + bgp = NULL; + + argv_find (argv, argc, "neighbors", &idx); + peer = peer_lookup_in_view (vty, bgp, argv[idx+1]->arg, uj); if (! peer) return CMD_WARNING; - if (strncmp (argv[idx_safi]->arg, "m", 1) == 0) - return bgp_peer_counts (vty, peer, AFI_IP, SAFI_MULTICAST, uj); - return bgp_peer_counts (vty, peer, AFI_IP, SAFI_UNICAST, uj); } @@ -9218,20 +9112,17 @@ peer_adj_routes (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, DEFUN (show_ip_bgp_instance_neighbor_advertised_route, show_ip_bgp_instance_neighbor_advertised_route_cmd, - "show [ip] bgp [ WORD] []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] neighbors [ [route-map WORD]] [json]", + "show [ip] bgp [ WORD] [ []] " + "neighbors [ [route-map WORD]] [json]", SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR "Address Family\n" - "Address Family modifier\n" - "Address Family modifier\n" "Address Family\n" "Address Family modifier\n" "Address Family modifier\n" - "Address Family\n" "Address Family modifier\n" - "Address Family\n" "Address Family modifier\n" "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" @@ -9243,51 +9134,54 @@ DEFUN (show_ip_bgp_instance_neighbor_advertised_route, "Name of the route map\n" JSON_STR) { + vrf_id_t vrf = VRF_DEFAULT; afi_t afi = AFI_IP6; safi_t safi = SAFI_UNICAST; - char *vrf = NULL; char *rmap_name = NULL; char *peerstr = NULL; int rcvd = 0; - + struct bgp *bgp = NULL; struct peer *peer; int idx = 0; - /* show [ip] bgp */ - if (argv_find (argv, argc, "ip", &idx)) - afi = AFI_IP; - /* [ WORD] */ - if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) - vrf = argv[++idx]->arg; - /* []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] */ - if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx)) - { - afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; - if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx)) - safi = strmatch (argv[idx]->text, "unicast") ? SAFI_UNICAST : SAFI_MULTICAST; - } - else if (argv_find (argv, argc, "encap", &idx) || argv_find (argv, argc, "vpnv4", &idx)) - { - afi = AFI_IP; - safi = strmatch (argv[idx]->text, "encap") ? SAFI_ENCAP : SAFI_MPLS_VPN; - // advance idx if necessary - argv_find (argv, argc, "unicast", &idx); - } + idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); + if (!idx) + { + vty_out (vty, "View/Vrf Specified: %s is unknown", argv[5]->arg); + return CMD_WARNING; + } + int uj = use_json (argc, argv); + if (uj) argc--; + + if (vrf != VRF_ALL) + { + bgp = bgp_lookup_by_vrf_id (vrf); + if (bgp == NULL) + { + if (uj) + { + json_object *json_no = NULL; + json_no = json_object_new_object(); + json_object_string_add(json_no, "warning", "Can't find BGP view"); + vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE); + json_object_free(json_no); + } + else + vty_out (vty, "Can't find BGP instance %s%s", argv[5]->arg, VTY_NEWLINE); + return CMD_WARNING; + } + } + else + bgp = NULL; /* neighbors */ argv_find (argv, argc, "neighbors", &idx); peerstr = argv[++idx]->arg; - u_char uj = use_json(argc, argv); - - peer = peer_lookup_in_view (vty, vrf, peerstr, uj); - + peer = peer_lookup_in_view (vty, bgp, peerstr, uj); if (! peer) - { - vty_out (vty, "No such neighbor%s", VTY_NEWLINE); - return CMD_WARNING; - } + return CMD_WARNING; if (argv_find (argv, argc, "received-routes", &idx)) rcvd = 1; @@ -9410,20 +9304,17 @@ bgp_show_neighbor_route (struct vty *vty, struct peer *peer, afi_t afi, DEFUN (show_ip_bgp_neighbor_routes, show_ip_bgp_neighbor_routes_cmd, - "show [ip] bgp [ WORD] []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] neighbors [json]", + "show [ip] bgp [ WORD] [ []] " + "neighbors [json]", SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR "Address Family\n" - "Address Family modifier\n" - "Address Family modifier\n" "Address Family\n" "Address Family modifier\n" "Address Family modifier\n" - "Address Family\n" "Address Family modifier\n" - "Address Family\n" "Address Family modifier\n" "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" @@ -9434,9 +9325,9 @@ DEFUN (show_ip_bgp_neighbor_routes, "Display routes learned from neighbor\n" JSON_STR) { - char *vrf = NULL; + vrf_id_t vrf = VRF_DEFAULT; char *peerstr = NULL; - + struct bgp *bgp = NULL; afi_t afi = AFI_IP6; safi_t safi = SAFI_UNICAST; struct peer *peer; @@ -9444,33 +9335,41 @@ DEFUN (show_ip_bgp_neighbor_routes, int idx = 0; - /* show [ip] bgp */ - if (argv_find (argv, argc, "ip", &idx)) - afi = AFI_IP; - /* [ WORD] */ - if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) - vrf = argv[++idx]->arg; - /* []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] */ - if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx)) - { - afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; - if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx)) - safi = strmatch (argv[idx]->text, "unicast") ? SAFI_UNICAST : SAFI_MULTICAST; - } - else if (argv_find (argv, argc, "encap", &idx) || argv_find (argv, argc, "vpnv4", &idx)) - { - afi = AFI_IP; - safi = strmatch (argv[idx]->text, "encap") ? SAFI_ENCAP : SAFI_MPLS_VPN; - // advance idx if necessary - argv_find (argv, argc, "unicast", &idx); - } + idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); + if (!idx) + { + vty_out (vty, "View/Vrf Specified: %s is unknown", argv[5]->arg); + return CMD_WARNING; + } + int uj = use_json (argc, argv); + if (uj) argc--; + + if (vrf != VRF_ALL) + { + bgp = bgp_lookup_by_vrf_id (vrf); + if (bgp == NULL) + { + if (uj) + { + json_object *json_no = NULL; + json_no = json_object_new_object(); + json_object_string_add(json_no, "warning", "Can't find BGP view"); + vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE); + json_object_free(json_no); + } + else + vty_out (vty, "Can't find BGP instance %s%s", argv[5]->arg, VTY_NEWLINE); + return CMD_WARNING; + } + } + else + bgp = NULL; + /* neighbors */ argv_find (argv, argc, "neighbors", &idx); peerstr = argv[++idx]->arg; - u_char uj = use_json(argc, argv); - - peer = peer_lookup_in_view (vty, vrf, peerstr, uj); + peer = peer_lookup_in_view (vty, bgp, peerstr, uj); if (! peer) { vty_out (vty, "No such neighbor%s", VTY_NEWLINE); @@ -10321,14 +10220,10 @@ bgp_route_init (void) install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd); /* prefix count */ - install_element (ENABLE_NODE, &show_ip_bgp_neighbor_prefix_counts_cmd); install_element (ENABLE_NODE, &show_ip_bgp_instance_neighbor_prefix_counts_cmd); - install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_prefix_counts_cmd); #ifdef KEEP_OLD_VPN_COMMANDS install_element (ENABLE_NODE, &show_ip_bgp_vpn_neighbor_prefix_counts_cmd); #endif /* KEEP_OLD_VPN_COMMANDS */ - install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_prefix_counts_cmd); - install_element (ENABLE_NODE, &show_bgp_instance_ipv6_neighbor_prefix_counts_cmd); /* New config IPv6 BGP commands. */ install_element (BGP_IPV6_NODE, &bgp_table_map_cmd); From 08435c2b24298d1c716f58fd4fc4d1bb3ea6f03b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 24 Jan 2017 09:47:59 -0500 Subject: [PATCH 428/444] bgpd: Fix crash with parsing the community Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index c5b7c4e776..92a2843ba9 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -7924,12 +7924,11 @@ DEFUN (show_ip_bgp, if (argv_find(argv, argc, "community", &idx)) { /* show a specific community */ - if (argv[idx + 1]->type == VARIABLE_TKN || - strmatch(argv[idx + 1]->text, "local-AS") || - strmatch(argv[idx + 1]->text, "no-advertise") || - strmatch(argv[idx + 1]->text, "no-export")) + if (argv_find (argv, argc, "local-AS", &idx) || + argv_find (argv, argc, "no-advertise", &idx) || + argv_find (argv, argc, "no-export", &idx)) { - if (strmatch(argv[idx + 2]->text, "exact_match")) + if (argv_find (argv, argc, "exact_match", &idx)) exact_match = 1; return bgp_show_community (vty, bgp, argc, argv, exact_match, afi, safi); } From 83364d20d5667c3b43e1e672d2166c22b6fd8cf5 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 25 Jan 2017 02:27:29 +0100 Subject: [PATCH 429/444] lib: parser: fix memory management command.c had: DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command desc") while command_match.c had: DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command Tokens") ... which means that there are 2 distinct MTYPE_CMD_TOKENS. (The description text being different does not matter, even with the same text it'd be 2 distinct types.) command_match.c allocates token->arg in command_match_r() while command.c frees it in del_cmd_token(). Therefore with each command being executed, the allocation count goes up on one, down on the other. => clean up parser allocation counting. Also, use separate MTYPEs for the different fields in struct cmd_token. Fixes: #108 / ee9216cf ("lib, ripngd: clean up merge leftovers") Signed-off-by: David Lamparter Cc: Quentin Young --- lib/command.c | 24 ++++++++++++++---------- lib/command.h | 11 +++++------ lib/command_match.c | 3 +-- lib/command_parse.y | 31 ++++++++++++++----------------- 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/lib/command.c b/lib/command.c index b5dae5f28e..781f627bb5 100644 --- a/lib/command.c +++ b/lib/command.c @@ -43,7 +43,10 @@ DEFINE_MTYPE( LIB, HOST, "Host config") DEFINE_MTYPE( LIB, STRVEC, "String vector") -DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command desc") +DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command Tokens") +DEFINE_MTYPE_STATIC(LIB, CMD_DESC, "Command Token Text") +DEFINE_MTYPE_STATIC(LIB, CMD_TEXT, "Command Token Help") +DEFINE_MTYPE( LIB, CMD_ARG, "Command Argument") /* Command vector which includes some level of command lists. Normally each daemon maintains each own cmdvec. */ @@ -2405,13 +2408,14 @@ cmd_init (int terminal) } struct cmd_token * -new_cmd_token (enum cmd_token_type type, u_char attr, char *text, char *desc) +new_cmd_token (enum cmd_token_type type, u_char attr, + const char *text, const char *desc) { struct cmd_token *token = XCALLOC (MTYPE_CMD_TOKENS, sizeof (struct cmd_token)); token->type = type; token->attr = attr; - token->text = text; - token->desc = desc; + token->text = text ? XSTRDUP (MTYPE_CMD_TEXT, text) : NULL; + token->desc = desc ? XSTRDUP (MTYPE_CMD_DESC, desc) : NULL; token->arg = NULL; token->allowrepeat = false; @@ -2424,11 +2428,11 @@ del_cmd_token (struct cmd_token *token) if (!token) return; if (token->text) - XFREE (MTYPE_CMD_TOKENS, token->text); + XFREE (MTYPE_CMD_TEXT, token->text); if (token->desc) - XFREE (MTYPE_CMD_TOKENS, token->desc); + XFREE (MTYPE_CMD_DESC, token->desc); if (token->arg) - XFREE (MTYPE_CMD_TOKENS, token->arg); + XFREE (MTYPE_CMD_ARG, token->arg); XFREE (MTYPE_CMD_TOKENS, token); } @@ -2439,9 +2443,9 @@ copy_cmd_token (struct cmd_token *token) struct cmd_token *copy = new_cmd_token (token->type, token->attr, NULL, NULL); copy->max = token->max; copy->min = token->min; - copy->text = token->text ? XSTRDUP (MTYPE_CMD_TOKENS, token->text) : NULL; - copy->desc = token->desc ? XSTRDUP (MTYPE_CMD_TOKENS, token->desc) : NULL; - copy->arg = token->arg ? XSTRDUP (MTYPE_CMD_TOKENS, token->arg) : NULL; + copy->text = token->text ? XSTRDUP (MTYPE_CMD_TEXT, token->text) : NULL; + copy->desc = token->desc ? XSTRDUP (MTYPE_CMD_DESC, token->desc) : NULL; + copy->arg = token->arg ? XSTRDUP (MTYPE_CMD_ARG, token->arg) : NULL; return copy; } diff --git a/lib/command.h b/lib/command.h index 1e1698fc7d..1e490cc4cd 100644 --- a/lib/command.h +++ b/lib/command.h @@ -31,6 +31,7 @@ #include "hash.h" DECLARE_MTYPE(HOST) +DECLARE_MTYPE(CMD_ARG) /* for test-commands.c */ DECLARE_MTYPE(STRVEC) @@ -420,12 +421,10 @@ extern void cmd_exit (struct vty *vty); extern int cmd_list_cmds (struct vty *vty, int do_permute); /* memory management for cmd_token */ -struct cmd_token * -new_cmd_token (enum cmd_token_type, u_char attr, char *, char *); -void -del_cmd_token (struct cmd_token *); -struct cmd_token * -copy_cmd_token (struct cmd_token *); +extern struct cmd_token *new_cmd_token (enum cmd_token_type, u_char attr, + const char *text, const char *desc); +extern void del_cmd_token (struct cmd_token *); +extern struct cmd_token *copy_cmd_token (struct cmd_token *); extern void command_parse_format (struct graph *graph, struct cmd_element *cmd); diff --git a/lib/command_match.c b/lib/command_match.c index d228563240..aa58313134 100644 --- a/lib/command_match.c +++ b/lib/command_match.c @@ -27,7 +27,6 @@ #include "command_match.h" #include "memory.h" -DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command Tokens") DEFINE_MTYPE_STATIC(LIB, CMD_MATCHSTACK, "Command Match Stack") #define MAXDEPTH 64 @@ -322,7 +321,7 @@ command_match_r (struct graph_node *start, vector vline, unsigned int n, // copy token, set arg and prepend to currbest struct cmd_token *token = start->data; struct cmd_token *copy = copy_cmd_token (token); - copy->arg = XSTRDUP (MTYPE_CMD_TOKENS, input_token); + copy->arg = XSTRDUP (MTYPE_CMD_ARG, input_token); listnode_add_before (currbest, currbest->head, copy); matcher_rv = MATCHER_OK; } diff --git a/lib/command_parse.y b/lib/command_parse.y index c920e11380..7f98704f90 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -115,7 +115,7 @@ }; /* helper functions for parser */ - static char * + static const char * doc_next (struct parser_ctx *ctx); static struct graph_node * @@ -130,8 +130,8 @@ static struct graph_node * new_token_node (struct parser_ctx *, enum cmd_token_type type, - char *text, - char *doc); + const char *text, + const char *doc); static void terminate_graph (struct parser_ctx *ctx, @@ -222,7 +222,7 @@ compound_token: literal_token: WORD { - $$ = new_token_node (ctx, WORD_TKN, strdup($1), doc_next(ctx)); + $$ = new_token_node (ctx, WORD_TKN, $1, doc_next(ctx)); free ($1); } ; @@ -230,32 +230,32 @@ literal_token: WORD placeholder_token: IPV4 { - $$ = new_token_node (ctx, IPV4_TKN, strdup($1), doc_next(ctx)); + $$ = new_token_node (ctx, IPV4_TKN, $1, doc_next(ctx)); free ($1); } | IPV4_PREFIX { - $$ = new_token_node (ctx, IPV4_PREFIX_TKN, strdup($1), doc_next(ctx)); + $$ = new_token_node (ctx, IPV4_PREFIX_TKN, $1, doc_next(ctx)); free ($1); } | IPV6 { - $$ = new_token_node (ctx, IPV6_TKN, strdup($1), doc_next(ctx)); + $$ = new_token_node (ctx, IPV6_TKN, $1, doc_next(ctx)); free ($1); } | IPV6_PREFIX { - $$ = new_token_node (ctx, IPV6_PREFIX_TKN, strdup($1), doc_next(ctx)); + $$ = new_token_node (ctx, IPV6_PREFIX_TKN, $1, doc_next(ctx)); free ($1); } | VARIABLE { - $$ = new_token_node (ctx, VARIABLE_TKN, strdup($1), doc_next(ctx)); + $$ = new_token_node (ctx, VARIABLE_TKN, $1, doc_next(ctx)); free ($1); } | RANGE { - $$ = new_token_node (ctx, RANGE_TKN, strdup($1), doc_next(ctx)); + $$ = new_token_node (ctx, RANGE_TKN, $1, doc_next(ctx)); struct cmd_token *token = $$->data; // get the numbers out @@ -462,10 +462,7 @@ terminate_graph (struct parser_ctx *ctx, struct graph_node *finalnode) // * -> finalnode -> END_TKN -> cmd_element struct cmd_element *element = ctx->el; struct graph_node *end_token_node = - new_token_node (ctx, - END_TKN, - strdup (CMD_CR_TEXT), - strdup ("")); + new_token_node (ctx, END_TKN, CMD_CR_TEXT, ""); struct graph_node *end_element_node = graph_new_node (ctx->graph, element, NULL); @@ -476,7 +473,7 @@ terminate_graph (struct parser_ctx *ctx, struct graph_node *finalnode) graph_add_edge (end_token_node, end_element_node); } -static char * +static const char * doc_next (struct parser_ctx *ctx) { const char *piece = ctx->docstr ? strsep (&ctx->docstr, "\n") : ""; @@ -486,12 +483,12 @@ doc_next (struct parser_ctx *ctx) piece = ""; } - return strdup (piece); + return piece; } static struct graph_node * new_token_node (struct parser_ctx *ctx, enum cmd_token_type type, - char *text, char *doc) + const char *text, const char *doc) { struct cmd_token *token = new_cmd_token (type, ctx->el->attr, text, doc); return graph_new_node (ctx->graph, token, (void (*)(void *)) &del_cmd_token); From c74e21947484b45ef5a484b6570ac90b4ffcd02c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 25 Jan 2017 08:20:06 -0500 Subject: [PATCH 430/444] pimd: Fix double add of command We were adding the 'ip msdp ...' command to the parser 2x. Some new code added to the parser apparently catches this for us now. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 85baa4eafe..cfccdeba98 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -6134,8 +6134,6 @@ 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); From 47350fd9f4b56b3e8200ea6c8c9c8b07d0fbb9c6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 25 Jan 2017 08:26:21 -0500 Subject: [PATCH 431/444] bgpd: Add ability to clean lcommunity hash Ensure that we don't leak any memory on shutdown. Since the bgp_lcommunity.c file mirrors bgp_ecommunity.c Add the same code for shutdown that ecommunity has. Signed-off-by: Donald Sharp --- bgpd/bgp_lcommunity.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c index a4b6d96ed3..dc98809f60 100644 --- a/bgpd/bgp_lcommunity.c +++ b/bgpd/bgp_lcommunity.c @@ -54,6 +54,12 @@ lcommunity_free (struct lcommunity **lcom) lcom = NULL; } +static void +lcommunity_hash_free (struct lcommunity *lcom) +{ + lcommunity_free (&lcom); +} + /* Add a new Large Communities value to Large Communities Attribute structure. When the value is already exists in the structure, we don't add the value. Newly added value is sorted by @@ -287,6 +293,7 @@ lcommunity_init (void) void lcommunity_finish (void) { + hash_clean (lcomhash, (void (*)(void *))lcommunity_hash_free); hash_free (lcomhash); lcomhash = NULL; } From 5cd459e86e9df4e7716ace5f997520183f34f3b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Fingen?= Date: Wed, 25 Jan 2017 14:33:01 +0100 Subject: [PATCH 432/444] lib: Fix missing break in zlcient switch --- lib/zclient.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/zclient.c b/lib/zclient.c index a4c5fa4afb..42fa41c9c8 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1626,6 +1626,7 @@ zclient_read (struct thread *thread) case ZEBRA_REDISTRIBUTE_IPV6_DEL: if (zclient->redistribute_route_ipv6_del) (*zclient->redistribute_route_ipv6_del) (command, zclient, length, vrf_id); + break; case ZEBRA_INTERFACE_LINK_PARAMS: if (zclient->interface_link_params) (*zclient->interface_link_params) (command, zclient, length); From a957a05bb47a8bf444ce0aee1b81d786cac9e3a9 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 25 Jan 2017 09:13:46 -0500 Subject: [PATCH 433/444] pimd: Cleanup some missing help strings. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 89 +++++++++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 51 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index cfccdeba98..b8bb694b78 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2578,7 +2578,8 @@ DEFUN (show_ip_pim_join, SHOW_STR IP_STR PIM_STR - "PIM interface join information\n") + "PIM interface join information\n" + JSON_STR) { u_char uj = use_json(argc, argv); pim_show_join(vty, uj); @@ -2592,7 +2593,8 @@ DEFUN (show_ip_pim_local_membership, SHOW_STR IP_STR PIM_STR - "PIM interface local-membership\n") + "PIM interface local-membership\n" + JSON_STR) { u_char uj = use_json(argc, argv); pim_show_membership(vty, uj); @@ -3134,7 +3136,8 @@ DEFUN (show_ip_mroute, "show ip mroute [json]", SHOW_STR IP_STR - MROUTE_STR) + MROUTE_STR + JSON_STR) { u_char uj = use_json(argc, argv); show_mroute(vty, uj); @@ -3443,7 +3446,8 @@ DEFUN (ip_pim_packets, "ip pim packets <1-100>", IP_STR "pim multicast routing\n" - "Number of packets to process at one time per fd\n") + "packets to process at one time per fd\n" + "Number of packets\n") { qpim_packet_process = atoi (argv[3]->arg); return CMD_SUCCESS; @@ -3455,7 +3459,8 @@ DEFUN (no_ip_pim_packets, NO_STR IP_STR "pim multicast routing\n" - "Number of packets to process at one time per fd\n") + "packets to process at one time per fd\n" + "Number of packets\n") { qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS; return CMD_SUCCESS; @@ -3467,7 +3472,8 @@ DEFUN (ip_pim_rp, IP_STR "pim multicast routing\n" "Rendevous Point\n" - "ip address of RP\n") + "ip address of RP\n" + "Group Address range to cover\n") { int idx_ipv4 = 3; return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL); @@ -3520,7 +3526,8 @@ DEFUN (no_ip_pim_rp, IP_STR "pim multicast routing\n" "Rendevous Point\n" - "ip address of RP\n") + "ip address of RP\n" + "Group Address range to cover\n") { int idx_ipv4 = 4; return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL); @@ -4093,7 +4100,8 @@ DEFUN (interface_no_ip_igmp_query_max_response_time, NO_STR IP_STR IFACE_IGMP_STR - IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR) + IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR + "Time for response in deci-seconds\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct pim_interface *pim_ifp; @@ -4823,22 +4831,9 @@ DEFUN (no_debug_pim_events, return CMD_SUCCESS; } - DEFUN (debug_pim_packets, debug_pim_packets_cmd, - "debug pim packets", - DEBUG_STR - DEBUG_PIM_STR - DEBUG_PIM_PACKETS_STR) -{ - PIM_DO_DEBUG_PIM_PACKETS; - vty_out (vty, "PIM Packet debugging is on %s", VTY_NEWLINE); - return CMD_SUCCESS; -} - -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 @@ -4846,66 +4841,60 @@ DEFUN (debug_pim_packets_filter, 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) + int idx; + if (argv_find (argv, argc, "hello", &idx)) { PIM_DO_DEBUG_PIM_HELLO; vty_out (vty, "PIM Hello debugging is on%s", VTY_NEWLINE); } - else if (strncmp(argv[idx_hello_join]->arg,"j",1) == 0) + else if (argv_find (argv, argc ,"joins", &idx)) { PIM_DO_DEBUG_PIM_J_P; vty_out (vty, "PIM Join/Prune debugging is on%s", VTY_NEWLINE); } - else if (strncmp(argv[idx_hello_join]->arg,"r",1) == 0) + else if (argv_find (argv, argc, "register", &idx)) { PIM_DO_DEBUG_PIM_REG; vty_out (vty, "PIM Register debugging is on%s", VTY_NEWLINE); } + else + { + PIM_DO_DEBUG_PIM_PACKETS; + vty_out (vty, "PIM Packet debugging is on %s", VTY_NEWLINE); + } return CMD_SUCCESS; } DEFUN (no_debug_pim_packets, no_debug_pim_packets_cmd, - "no debug pim packets", + "no debug pim packets []", NO_STR 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) { - PIM_DONT_DEBUG_PIM_PACKETS; - vty_out (vty, "PIM Packet debugging is off %s", VTY_NEWLINE); - return CMD_SUCCESS; -} - -DEFUN (no_debug_pim_packets_filter, - no_debug_pim_packets_filter_cmd, - "no debug pim packets ", - NO_STR - DEBUG_STR - DEBUG_PIM_STR - DEBUG_PIM_PACKETS_STR - DEBUG_PIM_HELLO_PACKETS_STR - DEBUG_PIM_J_P_PACKETS_STR) -{ - int idx_hello_join = 4; - if (strncmp(argv[idx_hello_join]->arg,"h",1) == 0) + int idx = 0; + if (argv_find (argv, argc,"hello",&idx)) { 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 (argv_find (argv, argc, "joins", &idx)) { PIM_DONT_DEBUG_PIM_J_P; vty_out (vty, "PIM Join/Prune debugging is off %s", VTY_NEWLINE); } - else if (strncmp (argv[idx_hello_join]->arg, "r", 1) == 0) + else if (argv_find (argv, argc, "register", &idx)) { PIM_DONT_DEBUG_PIM_REG; vty_out (vty, "PIM Register debugging is off%s", VTY_NEWLINE); } + else + PIM_DONT_DEBUG_PIM_PACKETS; + return CMD_SUCCESS; } @@ -5459,6 +5448,7 @@ DEFUN (no_ip_msdp_mesh_group_source, CFG_MSDP_STR "Delete MSDP mesh-group source\n" "mesh group name\n" + "mesh group source\n" "mesh group local address\n") { if (argv[6]->arg) @@ -5954,6 +5944,7 @@ 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); @@ -6074,9 +6065,7 @@ void pim_cmd_init() install_element (ENABLE_NODE, &debug_pim_events_cmd); install_element (ENABLE_NODE, &no_debug_pim_events_cmd); install_element (ENABLE_NODE, &debug_pim_packets_cmd); - install_element (ENABLE_NODE, &debug_pim_packets_filter_cmd); install_element (ENABLE_NODE, &no_debug_pim_packets_cmd); - install_element (ENABLE_NODE, &no_debug_pim_packets_filter_cmd); install_element (ENABLE_NODE, &debug_pim_packetdump_send_cmd); install_element (ENABLE_NODE, &no_debug_pim_packetdump_send_cmd); install_element (ENABLE_NODE, &debug_pim_packetdump_recv_cmd); @@ -6116,9 +6105,7 @@ void pim_cmd_init() install_element (CONFIG_NODE, &debug_pim_events_cmd); install_element (CONFIG_NODE, &no_debug_pim_events_cmd); install_element (CONFIG_NODE, &debug_pim_packets_cmd); - install_element (CONFIG_NODE, &debug_pim_packets_filter_cmd); install_element (CONFIG_NODE, &no_debug_pim_packets_cmd); - install_element (CONFIG_NODE, &no_debug_pim_packets_filter_cmd); install_element (CONFIG_NODE, &debug_pim_trace_cmd); install_element (CONFIG_NODE, &no_debug_pim_trace_cmd); install_element (CONFIG_NODE, &debug_ssmpingd_cmd); From 7eeee51e02e815ae79d6ed78f490fb45ea2ebae7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 25 Jan 2017 09:37:13 -0500 Subject: [PATCH 434/444] bgpd: Add some documentation for bgp_vty_find_and_parse_afi_safi_vrf The use of this function was causing some confusion. As such let's add some documentation. Signed-off-by: Donald Sharp --- bgpd/bgp_vty.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index fa19308cb1..e98c231064 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -197,6 +197,36 @@ argv_find_and_parse_safi (struct cmd_token **argv, int argc, int *index, safi_t return ret; } +/* + * bgp_vty_find_and_parse_afi_safi_vrf + * + * For a given 'show ...' command, correctly parse the afi/safi/vrf out from it + * This function *assumes* that the calling function pre-sets the afi/safi/vrf + * to appropriate values for the calling function. This is to allow the + * calling function to make decisions appropriate for the show command + * that is being parsed. + * + * The show commands are generally of the form: + * "show [ip] bgp [ WORD] [ []] ..." + * + * Since we use argv_find if the show command in particular doesn't have: + * [ip] + * [ WORD] + * [ []] + * The command parsing should still be ok. + * + * vty -> The vty for the command so we can output some useful data in + * the event of a parse error in the vrf. + * argv -> The command tokens + * argc -> How many command tokens we have + * idx -> The current place in the command, generally should be 0 for this function + * afi -> The parsed afi if it was included in the show command, returned here + * safi -> The parsed safi if it was included in the show command, returned here + * vrf -> The parsed vrf id if it was included in the show command, returned here + * + * The function returns the correct location in the parse tree for the + * last token found. + */ int bgp_vty_find_and_parse_afi_safi_vrf (struct vty *vty, struct cmd_token **argv, int argc, int idx, afi_t *afi, safi_t *safi, vrf_id_t *vrf) From c493f2d83a990b5fec0ea927915c46c47d7ed636 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 25 Jan 2017 09:43:11 -0500 Subject: [PATCH 435/444] bgpd: Remove redundant warning message When bgp_vty_find_and_parse_afi_safi_vrf detects a invalidly named vrf, it warns the user. There is no need for the calling function to warn again. Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 42 +++++++++++++----------------------------- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 92a2843ba9..02ba731f04 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -7877,10 +7877,8 @@ DEFUN (show_ip_bgp, idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); if (!idx) - { - vty_out (vty, "View/Vrf Specified: %s is unknown", argv[5]->arg); - return CMD_WARNING; - } + return CMD_WARNING; + int uj = use_json (argc, argv); if (uj) argc--; @@ -7986,10 +7984,7 @@ DEFUN (show_ip_bgp_route, idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); if (!idx) - { - vty_out (vty, "View/Vrf Specified: %s is unknown", argv[5]->arg); - return CMD_WARNING; - } + return CMD_WARNING; if (vrf != VRF_ALL) { @@ -8056,10 +8051,7 @@ DEFUN (show_ip_bgp_regexp, int idx = 0; idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); if (!idx) - { - vty_out (vty, "View/Vrf Specified: %s is unknown", argv[5]->arg); - return CMD_WARNING; - } + return CMD_WARNING; // get index of regex argv_find (argv, argc, "regexp", &idx); @@ -8093,10 +8085,8 @@ DEFUN (show_ip_bgp_instance_all, int idx = 0; idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); if (!idx) - { - vty_out (vty, "View/Vrf Specified: %s is unknown", argv[5]->arg); - return CMD_WARNING; - } + return CMD_WARNING; + int uj = use_json (argc, argv); if (uj) argc--; @@ -8786,10 +8776,8 @@ DEFUN (show_ip_bgp_instance_neighbor_prefix_counts, idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); if (!idx) - { - vty_out (vty, "View/Vrf Specified: %s is unknown", argv[5]->arg); - return CMD_WARNING; - } + return CMD_WARNING; + int uj = use_json (argc, argv); if (uj) argc--; @@ -9146,10 +9134,8 @@ DEFUN (show_ip_bgp_instance_neighbor_advertised_route, idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); if (!idx) - { - vty_out (vty, "View/Vrf Specified: %s is unknown", argv[5]->arg); - return CMD_WARNING; - } + return CMD_WARNING; + int uj = use_json (argc, argv); if (uj) argc--; @@ -9334,12 +9320,10 @@ DEFUN (show_ip_bgp_neighbor_routes, int idx = 0; - idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); + idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); if (!idx) - { - vty_out (vty, "View/Vrf Specified: %s is unknown", argv[5]->arg); - return CMD_WARNING; - } + return CMD_WARNING; + int uj = use_json (argc, argv); if (uj) argc--; From 2acb4ac250c9c7363a8ee4455677c69764f9f97c Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 25 Jan 2017 22:29:31 +0100 Subject: [PATCH 436/444] bgpd: lcommunity: fix whitespace & copyright (to match surrounding code) "git diff -w" should be almost empty. Copyright edited to say FRR, this is not GNU Zebra :) Signed-off-by: David Lamparter --- bgpd/bgp_attr.c | 48 +++++++-------- bgpd/bgp_attr.h | 2 +- bgpd/bgp_clist.c | 42 ++++++------- bgpd/bgp_lcommunity.c | 37 ++++++----- bgpd/bgp_lcommunity.h | 37 ++++++----- bgpd/bgp_route.c | 72 +++++++++++----------- bgpd/bgp_routemap.c | 140 +++++++++++++++++++++--------------------- bgpd/bgp_vty.c | 76 +++++++++++------------ 8 files changed, 225 insertions(+), 229 deletions(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index fc9440dddc..3a58546676 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -673,7 +673,7 @@ attrhash_key_make (void *p) if (extra) { if (extra->lcommunity) - MIX(lcommunity_hash_make (extra->lcommunity)); + MIX(lcommunity_hash_make (extra->lcommunity)); if (extra->ecommunity) MIX(ecommunity_hash_make (extra->ecommunity)); if (extra->cluster) @@ -1042,7 +1042,7 @@ bgp_attr_unintern_sub (struct attr *attr) if (attr->extra->lcommunity) lcommunity_unintern (&attr->extra->lcommunity); UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES)); - + if (attr->extra->cluster) cluster_unintern (attr->extra->cluster); UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST)); @@ -1113,7 +1113,7 @@ bgp_attr_flush (struct attr *attr) if (attre->ecommunity && ! attre->ecommunity->refcnt) ecommunity_free (&attre->ecommunity); if (attre->lcommunity && ! attre->lcommunity->refcnt) - lcommunity_free (&attre->lcommunity); + lcommunity_free (&attre->lcommunity); if (attre->cluster && ! attre->cluster->refcnt) { cluster_free (attre->cluster); @@ -1272,7 +1272,7 @@ const u_int8_t attr_flags_values [] = { [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, - [BGP_ATTR_LARGE_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL + [BGP_ATTR_LARGE_COMMUNITIES]= BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, }; static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1; @@ -3165,17 +3165,17 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES))) { if (attr->extra->lcommunity->size * 12 > 255) - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); - stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES); - stream_putw (s, attr->extra->lcommunity->size * 12); - } + { + stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); + stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES); + stream_putw (s, attr->extra->lcommunity->size * 12); + } else - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES); - stream_putc (s, attr->extra->lcommunity->size * 12); - } + { + stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); + stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES); + stream_putc (s, attr->extra->lcommunity->size * 12); + } stream_put (s, attr->extra->lcommunity->val, attr->extra->lcommunity->size * 12); } @@ -3532,17 +3532,17 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr, if (attr->extra && attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES)) { if (attr->extra->lcommunity->size * 12 > 255) - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); - stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES); - stream_putw (s, attr->extra->lcommunity->size * 12); - } + { + stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); + stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES); + stream_putw (s, attr->extra->lcommunity->size * 12); + } else - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES); - stream_putc (s, attr->extra->lcommunity->size * 12); - } + { + stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); + stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES); + stream_putc (s, attr->extra->lcommunity->size * 12); + } stream_put (s, attr->extra->lcommunity->val, attr->extra->lcommunity->size * 12); } diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 9c931051d8..c5799ccd0d 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -95,7 +95,7 @@ struct attr_extra /* Large Communities attribute. */ struct lcommunity *lcommunity; - + /* Route-Reflector Cluster attribute */ struct cluster_list *cluster; diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c index 47192f0f03..b37034bf29 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -43,11 +43,11 @@ community_list_master_lookup (struct community_list_handler *ch, int master) switch (master) { case COMMUNITY_LIST_MASTER: - return &ch->community_list; + return &ch->community_list; case EXTCOMMUNITY_LIST_MASTER: - return &ch->extcommunity_list; + return &ch->extcommunity_list; case LARGE_COMMUNITY_LIST_MASTER: - return &ch->lcommunity_list; + return &ch->lcommunity_list; } return NULL; } @@ -412,15 +412,14 @@ community_str_get (struct community *com, int i) } /* Internal function to perform regular expression match for - * * a single community. */ + * a single community. */ static int community_regexp_include (regex_t * reg, struct community *com, int i) { char *str; int rv; - /* When there is no communities attribute it is treated as empty - * string. */ + /* When there is no communities attribute it is treated as empty string. */ if (com == NULL || com->size == 0) str = XSTRDUP(MTYPE_COMMUNITY_STR, ""); else @@ -503,14 +502,13 @@ lcommunity_str_get (struct lcommunity *lcom, int i) } /* Internal function to perform regular expression match for - * * a single community. */ + * a single community. */ static int lcommunity_regexp_include (regex_t * reg, struct lcommunity *lcom, int i) { const char *str; - /* When there is no communities attribute it is treated as empty - * string. */ + /* When there is no communities attribute it is treated as empty string. */ if (lcom == NULL || lcom->size == 0) str = ""; else @@ -826,7 +824,7 @@ community_list_dup_check (struct community_list *list, break; case COMMUNITY_LIST_EXPANDED: case EXTCOMMUNITY_LIST_EXPANDED: - case LARGE_COMMUNITY_LIST_EXPANDED: + case LARGE_COMMUNITY_LIST_EXPANDED: if (strcmp (entry->config, new->config) == 0) return 1; break; @@ -947,7 +945,7 @@ community_list_unset (struct community_list_handler *ch, /* Delete all permitted large communities in the list from com. */ struct lcommunity * lcommunity_list_match_delete (struct lcommunity *lcom, - struct community_list *list) + struct community_list *list) { struct community_entry *entry; u_int32_t com_index_to_delete[lcom->size]; @@ -1013,7 +1011,7 @@ lcommunity_list_match_delete (struct lcommunity *lcom, /* Set lcommunity-list. */ int lcommunity_list_set (struct community_list_handler *ch, - const char *name, const char *str, int direct, int style) + const char *name, const char *str, int direct, int style) { struct community_entry *entry = NULL; struct community_list *list; @@ -1033,22 +1031,22 @@ lcommunity_list_set (struct community_list_handler *ch, first = list->head; if (style != first->style) - { - return (first->style == COMMUNITY_LIST_STANDARD - ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT - : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT); - } + { + return (first->style == COMMUNITY_LIST_STANDARD + ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT + : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT); + } } if (str) { if (style == LARGE_COMMUNITY_LIST_STANDARD) - lcom = lcommunity_str2com (str); + lcom = lcommunity_str2com (str); else - regex = bgp_regcomp (str); + regex = bgp_regcomp (str); if (! lcom && ! regex) - return COMMUNITY_LIST_ERR_MALFORMED_VAL; + return COMMUNITY_LIST_ERR_MALFORMED_VAL; } entry = community_entry_new (); @@ -1077,8 +1075,8 @@ lcommunity_list_set (struct community_list_handler *ch, community-list entry belongs to the specified name. */ int lcommunity_list_unset (struct community_list_handler *ch, - const char *name, const char *str, - int direct, int style) + const char *name, const char *str, + int direct, int style) { struct community_entry *entry = NULL; struct community_list *list; diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c index dc98809f60..549a2ebad8 100644 --- a/bgpd/bgp_lcommunity.c +++ b/bgpd/bgp_lcommunity.c @@ -1,23 +1,22 @@ /* BGP Large Communities Attribute - -Copyright (C) 2016 Keyur Patel - -This file is part of GNU Zebra. - -GNU Zebra 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. - -GNU Zebra 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. */ + * + * Copyright (C) 2016 Keyur Patel + * + * This file is part of FreeRangeRouting (FRR). + * + * FRR 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. + * + * FRR 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 FRR; see the file COPYING. If not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ #include diff --git a/bgpd/bgp_lcommunity.h b/bgpd/bgp_lcommunity.h index 7841b4b9a6..de3697f477 100644 --- a/bgpd/bgp_lcommunity.h +++ b/bgpd/bgp_lcommunity.h @@ -1,23 +1,22 @@ /* BGP Large Communities Attribute. - -Copyright (C) 2016 Keyur Patel - -This file is part of GNU Zebra. - -GNU Zebra 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. - -GNU Zebra 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. */ + * + * Copyright (C) 2016 Keyur Patel + * + * This file is part of FreeRangeRouting (FRR). + * + * FRR 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. + * + * FRR 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 FRR; see the file COPYING. If not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ #ifndef _QUAGGA_BGP_LCOMMUNITY_H #define _QUAGGA_BGP_LCOMMUNITY_H diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 330e7ed52e..afcf05d2b3 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -7063,8 +7063,8 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, /* Line 6 display Large community */ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) - vty_out (vty, " Large Community: %s%s", - attr->extra->lcommunity->str, VTY_NEWLINE); + vty_out (vty, " Large Community: %s%s", + attr->extra->lcommunity->str, VTY_NEWLINE); /* Line 7 display Originator, Cluster-id */ if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) || @@ -7426,32 +7426,32 @@ bgp_show_table (struct vty *vty, struct bgp *bgp, struct bgp_table *table, if (! community_list_exact_match (ri->attr->community, list)) continue; } - if (type == bgp_show_type_community_all) - { - if (! ri->attr->community) - continue; - } - if (type == bgp_show_type_lcommunity) - { - struct lcommunity *lcom = output_arg; + if (type == bgp_show_type_community_all) + { + if (! ri->attr->community) + continue; + } + if (type == bgp_show_type_lcommunity) + { + struct lcommunity *lcom = output_arg; - if (! ri->attr->extra || ! ri->attr->extra->lcommunity || - ! lcommunity_match (ri->attr->extra->lcommunity, lcom)) - continue; - } - if (type == bgp_show_type_lcommunity_list) - { - struct community_list *list = output_arg; + if (! ri->attr->extra || ! ri->attr->extra->lcommunity || + ! lcommunity_match (ri->attr->extra->lcommunity, lcom)) + continue; + } + if (type == bgp_show_type_lcommunity_list) + { + struct community_list *list = output_arg; - if (! ri->attr->extra || - ! lcommunity_list_match (ri->attr->extra->lcommunity, list)) - continue; - } - if (type == bgp_show_type_lcommunity_all) - { - if (! ri->attr->extra || ! ri->attr->extra->lcommunity) - continue; - } + if (! ri->attr->extra || + ! lcommunity_list_match (ri->attr->extra->lcommunity, list)) + continue; + } + if (type == bgp_show_type_lcommunity_all) + { + if (! ri->attr->extra || ! ri->attr->extra->lcommunity) + continue; + } if (type == bgp_show_type_dampend_paths || type == bgp_show_type_damp_neighbor) { @@ -7870,7 +7870,7 @@ bgp_show_route (struct vty *vty, const char *view_name, const char *ip_str, static int bgp_show_lcommunity (struct vty *vty, struct bgp *bgp, int argc, - struct cmd_token **argv, afi_t afi, safi_t safi, u_char uj) + struct cmd_token **argv, afi_t afi, safi_t safi, u_char uj) { struct lcommunity *lcom; struct buffer *b; @@ -7884,13 +7884,13 @@ bgp_show_lcommunity (struct vty *vty, struct bgp *bgp, int argc, if (first) buffer_putc (b, ' '); else - { - if (strmatch (argv[i]->text, "")) - { - first = 1; - buffer_putstr (b, argv[i]->arg); - } - } + { + if (strmatch (argv[i]->text, "")) + { + first = 1; + buffer_putstr (b, argv[i]->arg); + } + } } buffer_putc (b, '\0'); @@ -7910,7 +7910,7 @@ bgp_show_lcommunity (struct vty *vty, struct bgp *bgp, int argc, static int bgp_show_lcommunity_list (struct vty *vty, struct bgp *bgp, const char *lcom, - afi_t afi, safi_t safi, u_char uj) + afi_t afi, safi_t safi, u_char uj) { struct community_list *list; @@ -7918,7 +7918,7 @@ bgp_show_lcommunity_list (struct vty *vty, struct bgp *bgp, const char *lcom, if (list == NULL) { vty_out (vty, "%% %s is not a valid large-community-list name%s", lcom, - VTY_NEWLINE); + VTY_NEWLINE); return CMD_WARNING; } diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 693a807c89..58d9b20f90 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -853,7 +853,7 @@ struct route_map_rule_cmd route_match_community_cmd = /* Match function for lcommunity match. */ static route_map_result_t route_match_lcommunity (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) + route_map_object_t type, void *object) { struct community_list *list; struct bgp_info *bgp_info; @@ -865,13 +865,13 @@ route_match_lcommunity (void *rule, struct prefix *prefix, rcom = rule; list = community_list_lookup (bgp_clist, rcom->name, - LARGE_COMMUNITY_LIST_MASTER); + LARGE_COMMUNITY_LIST_MASTER); if (! list) - return RMAP_NOMATCH; + return RMAP_NOMATCH; if (bgp_info->attr->extra && - lcommunity_list_match (bgp_info->attr->extra->lcommunity, list)) - return RMAP_MATCH; + lcommunity_list_match (bgp_info->attr->extra->lcommunity, list)) + return RMAP_MATCH; } return RMAP_NOMATCH; @@ -1631,7 +1631,7 @@ struct rmap_lcom_set /* For lcommunity set mechanism. */ static route_map_result_t route_set_lcommunity (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) + route_map_object_t type, void *object) { struct rmap_lcom_set *rcs; struct bgp_info *binfo; @@ -1649,37 +1649,37 @@ route_set_lcommunity (void *rule, struct prefix *prefix, /* "none" case. */ if (rcs->none) - { - attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES)); - if (attr->extra) { - attr->extra->lcommunity = NULL; - } - /* See the longer comment down below. */ - if (old && old->refcnt == 0) - lcommunity_free(&old); - return RMAP_OKAY; - } + { + attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES)); + if (attr->extra) + attr->extra->lcommunity = NULL; + + /* See the longer comment down below. */ + if (old && old->refcnt == 0) + lcommunity_free(&old); + return RMAP_OKAY; + } if (rcs->additive && old) - { - merge = lcommunity_merge (lcommunity_dup (old), rcs->lcom); + { + merge = lcommunity_merge (lcommunity_dup (old), rcs->lcom); - /* HACK: if the old large-community is not intern'd, + /* HACK: if the old large-community is not intern'd, * we should free it here, or all reference to it may be lost. * Really need to cleanup attribute caching sometime. */ - if (old->refcnt == 0) - lcommunity_free (&old); - new = lcommunity_uniq_sort (merge); - lcommunity_free (&merge); - } + if (old->refcnt == 0) + lcommunity_free (&old); + new = lcommunity_uniq_sort (merge); + lcommunity_free (&merge); + } else - new = lcommunity_dup (rcs->lcom); + new = lcommunity_dup (rcs->lcom); + + /* will be interned by caller if required */ + if (attr->extra) + attr->extra->lcommunity = new; - /* will be interned by caller if required */ - if (attr->extra) { - attr->extra->lcommunity = new; - } attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES); } @@ -1703,19 +1703,19 @@ route_set_lcommunity_compile (const char *arg) sp = strstr (arg, "additive"); if (sp && sp > arg) - { - /* "additive" keyworkd is included. */ - additive = 1; - *(sp - 1) = '\0'; - } + { + /* "additive" keyworkd is included. */ + additive = 1; + *(sp - 1) = '\0'; + } lcom = lcommunity_str2com (arg); - if (additive) - *(sp - 1) = ' '; + if (additive) + *(sp - 1) = ' '; - if (! lcom) - return NULL; + if (! lcom) + return NULL; } rcs = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_com_set)); @@ -1752,7 +1752,7 @@ struct route_map_rule_cmd route_set_lcommunity_cmd = /* For large community set mechanism. */ static route_map_result_t route_set_lcommunity_delete (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) + route_map_object_t type, void *object) { struct community_list *list; struct lcommunity *merge; @@ -1763,38 +1763,38 @@ route_set_lcommunity_delete (void *rule, struct prefix *prefix, if (type == RMAP_BGP) { if (! rule) - return RMAP_OKAY; + return RMAP_OKAY; binfo = object; list = community_list_lookup (bgp_clist, rule, - LARGE_COMMUNITY_LIST_MASTER); + LARGE_COMMUNITY_LIST_MASTER); old = ((binfo->attr->extra) ? binfo->attr->extra->lcommunity : NULL); if (list && old) - { - merge = lcommunity_list_match_delete (lcommunity_dup (old), list); - new = lcommunity_uniq_sort (merge); - lcommunity_free (&merge); + { + merge = lcommunity_list_match_delete (lcommunity_dup (old), list); + new = lcommunity_uniq_sort (merge); + lcommunity_free (&merge); - /* HACK: if the old community is not intern'd, - * we should free it here, or all reference to it may be lost. - * Really need to cleanup attribute caching sometime. - */ - if (old->refcnt == 0) - lcommunity_free (&old); + /* HACK: if the old community is not intern'd, + * we should free it here, or all reference to it may be lost. + * Really need to cleanup attribute caching sometime. + */ + if (old->refcnt == 0) + lcommunity_free (&old); - if (new->size == 0) - { - binfo->attr->extra->lcommunity = NULL; - binfo->attr->flag &= ~ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES); - lcommunity_free (&new); - } - else - { - binfo->attr->extra->lcommunity = new; - binfo->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES); - } - } + if (new->size == 0) + { + binfo->attr->extra->lcommunity = NULL; + binfo->attr->flag &= ~ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES); + lcommunity_free (&new); + } + else + { + binfo->attr->extra->lcommunity = new; + binfo->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES); + } + } } return RMAP_OKAY; @@ -3418,7 +3418,7 @@ DEFUN (match_lcommunity, "Large Community-list name\n") { return bgp_route_match_add (vty, "large-community", argv[2]->arg, - RMAP_EVENT_LLIST_ADDED); + RMAP_EVENT_LLIST_ADDED); } DEFUN (no_match_lcommunity, @@ -3432,7 +3432,7 @@ DEFUN (no_match_lcommunity, "Large Community-list name\n") { return bgp_route_match_delete (vty, "large-community", NULL, - RMAP_EVENT_LLIST_DELETED); + RMAP_EVENT_LLIST_DELETED); } DEFUN (match_ecommunity, @@ -3891,7 +3891,7 @@ DEFUN (set_lcommunity_none, "No large community attribute\n") { return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "large-community", "none"); + "large-community", "none"); } DEFUN (no_set_lcommunity, @@ -3903,7 +3903,7 @@ DEFUN (no_set_lcommunity, "No community attribute\n") { return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "large-community", NULL); + "large-community", NULL); } DEFUN (no_set_lcommunity1, @@ -3915,7 +3915,7 @@ DEFUN (no_set_lcommunity1, "Large community in AA:BB:CC... format or additive\n") { return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "large-community", NULL); + "large-community", NULL); } DEFUN (set_lcommunity_delete, @@ -3935,7 +3935,7 @@ DEFUN (set_lcommunity_delete, strcpy (str + strlen (argv[2]->arg), " delete"); generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "large-comm-list", str); + "large-comm-list", str); XFREE (MTYPE_TMP, str); return CMD_SUCCESS; @@ -3953,7 +3953,7 @@ DEFUN (no_set_lcommunity_delete, "Delete matching large communities\n") { return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "large-comm-list", NULL); + "large-comm-list", NULL); } DEFUN (set_ecommunity_rt, diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index b3eaaaf111..aa97586639 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -6157,7 +6157,7 @@ DEFUN (show_bgp_memory, VTY_NEWLINE); if ((count = mtype_stats_alloc (MTYPE_LCOMMUNITY))) vty_out (vty, "%ld BGP large-community entries, using %s of memory%s", - count, + count, mtype_memstr (memstrbuf, sizeof (memstrbuf), count * sizeof (struct lcommunity)), VTY_NEWLINE); @@ -8677,7 +8677,7 @@ lcommunity_show_all_iterator (struct hash_backet *backet, struct vty *vty) lcom = (struct lcommunity *) backet->data; vty_out (vty, "[%p] (%ld) %s%s", (void *)backet, lcom->refcnt, - lcommunity_str (lcom), VTY_NEWLINE); + lcommunity_str (lcom), VTY_NEWLINE); } /* Show BGP's community internal data. */ @@ -8692,9 +8692,9 @@ DEFUN (show_ip_bgp_lcommunity_info, vty_out (vty, "Address Refcnt Large-community%s", VTY_NEWLINE); hash_iterate (lcommunity_hash (), - (void (*) (struct hash_backet *, void *)) - lcommunity_show_all_iterator, - vty); + (void (*) (struct hash_backet *, void *)) + lcommunity_show_all_iterator, + vty); return CMD_SUCCESS; } @@ -11140,7 +11140,7 @@ DEFUN (show_ip_community_list_arg, */ static int lcommunity_list_set_vty (struct vty *vty, int argc, struct cmd_token **argv, - int style, int reject_all_digit_name) + int style, int reject_all_digit_name) { int ret; int direct; @@ -11187,7 +11187,7 @@ lcommunity_list_set_vty (struct vty *vty, int argc, struct cmd_token **argv, static int lcommunity_list_unset_vty (struct vty *vty, int argc, struct cmd_token **argv, - int style) + int style) { int ret; int direct = 0; @@ -11201,9 +11201,9 @@ lcommunity_list_unset_vty (struct vty *vty, int argc, struct cmd_token **argv, { /* Check the list direct. */ if (strncmp (argv[idx]->arg, "p", 1) == 0) - direct = COMMUNITY_PERMIT; + direct = COMMUNITY_PERMIT; else - direct = COMMUNITY_DENY; + direct = COMMUNITY_DENY; idx = 0; argv_find (argv, argc, "LINE", &idx); @@ -11409,27 +11409,27 @@ lcommunity_list_show (struct vty *vty, struct community_list *list) for (entry = list->head; entry; entry = entry->next) { if (entry == list->head) - { - if (all_digit (list->name)) - vty_out (vty, "Large community %s list %s%s", - entry->style == EXTCOMMUNITY_LIST_STANDARD ? - "standard" : "(expanded) access", - list->name, VTY_NEWLINE); - else - vty_out (vty, "Named large community %s list %s%s", - entry->style == EXTCOMMUNITY_LIST_STANDARD ? - "standard" : "expanded", - list->name, VTY_NEWLINE); - } + { + if (all_digit (list->name)) + vty_out (vty, "Large community %s list %s%s", + entry->style == EXTCOMMUNITY_LIST_STANDARD ? + "standard" : "(expanded) access", + list->name, VTY_NEWLINE); + else + vty_out (vty, "Named large community %s list %s%s", + entry->style == EXTCOMMUNITY_LIST_STANDARD ? + "standard" : "expanded", + list->name, VTY_NEWLINE); + } if (entry->any) - vty_out (vty, " %s%s", - community_direct_str (entry->direct), VTY_NEWLINE); + vty_out (vty, " %s%s", + community_direct_str (entry->direct), VTY_NEWLINE); else - vty_out (vty, " %s %s%s", - community_direct_str (entry->direct), - entry->style == EXTCOMMUNITY_LIST_STANDARD ? - entry->u.ecom->str : entry->config, - VTY_NEWLINE); + vty_out (vty, " %s %s%s", + community_direct_str (entry->direct), + entry->style == EXTCOMMUNITY_LIST_STANDARD ? + entry->u.ecom->str : entry->config, + VTY_NEWLINE); } } @@ -11796,20 +11796,20 @@ community_list_config_write (struct vty *vty) for (list = cm->num.head; list; list = list->next) for (entry = list->head; entry; entry = entry->next) { - vty_out (vty, "ip large-community-list %s %s %s%s", - list->name, community_direct_str (entry->direct), - community_list_config_str (entry), VTY_NEWLINE); - write++; + vty_out (vty, "ip large-community-list %s %s %s%s", + list->name, community_direct_str (entry->direct), + community_list_config_str (entry), VTY_NEWLINE); + write++; } for (list = cm->str.head; list; list = list->next) for (entry = list->head; entry; entry = entry->next) { - vty_out (vty, "ip large-community-list %s %s %s %s%s", - entry->style == LARGE_COMMUNITY_LIST_STANDARD - ? "standard" : "expanded", - list->name, community_direct_str (entry->direct), - community_list_config_str (entry), VTY_NEWLINE); - write++; + vty_out (vty, "ip large-community-list %s %s %s %s%s", + entry->style == LARGE_COMMUNITY_LIST_STANDARD + ? "standard" : "expanded", + list->name, community_direct_str (entry->direct), + community_list_config_str (entry), VTY_NEWLINE); + write++; } return write; From ed165abf905e10b7d8b9b9989c52d9a405c513f1 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 25 Jan 2017 22:33:29 +0100 Subject: [PATCH 437/444] bgpd: lcommunity: fix minor issues - route_set_lcommunity would do nothing (and leak memory) if attr->extra wasn't up yet - an if() arch in bgp_show_table() was duplicated (with no effect) Signed-off-by: David Lamparter --- bgpd/bgp_route.c | 5 ----- bgpd/bgp_routemap.c | 5 ++--- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index afcf05d2b3..06584cf681 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -7426,11 +7426,6 @@ bgp_show_table (struct vty *vty, struct bgp *bgp, struct bgp_table *table, if (! community_list_exact_match (ri->attr->community, list)) continue; } - if (type == bgp_show_type_community_all) - { - if (! ri->attr->community) - continue; - } if (type == bgp_show_type_lcommunity) { struct lcommunity *lcom = output_arg; diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 58d9b20f90..a3c61e2155 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -1676,9 +1676,8 @@ route_set_lcommunity (void *rule, struct prefix *prefix, else new = lcommunity_dup (rcs->lcom); - /* will be interned by caller if required */ - if (attr->extra) - attr->extra->lcommunity = new; + /* will be intern()'d or attr_flush()'d by bgp_update_main() */ + (bgp_attr_extra_get (attr))->lcommunity = new; attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES); } From 72d98ee94360a5da0af76d8e800a72c8d51c48b5 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 25 Jan 2017 04:13:14 +0100 Subject: [PATCH 438/444] lib: graph: fix deletions Iterating over an array while deleting items needs to consider interactions between the iteration position and deletion. The previous code completely ignored that problem, leading to memleaks (graph_delete skipping half of the nodes) and dangling pointers (if parallel edges exist in graph_remove_edge). Iterating backwards is safe and reduces "move to fill hole" overhead in deletion. Signed-off-by: David Lamparter Cc: Quentin Young --- lib/graph.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/graph.c b/lib/graph.c index 891ecc33c0..035e552d08 100644 --- a/lib/graph.c +++ b/lib/graph.c @@ -117,11 +117,11 @@ void graph_remove_edge (struct graph_node *from, struct graph_node *to) { // remove from from to->from - for (unsigned int i = 0; i < vector_active (to->from); i++) + for (unsigned int i = vector_active (to->from); i--; /**/) if (vector_slot (to->from, i) == from) vector_remove (to->from, i); // remove to from from->to - for (unsigned int i = 0; i < vector_active (from->to); i++) + for (unsigned int i = vector_active (from->to); i--; /**/) if (vector_slot (from->to, i) == to) vector_remove (from->to, i); } @@ -130,7 +130,7 @@ void graph_delete_graph (struct graph *graph) { // delete each node in the graph - for (unsigned int i = 0; i < vector_active (graph->nodes); i++) + for (unsigned int i = vector_active (graph->nodes); i--; /**/) graph_delete_node (graph, vector_slot (graph->nodes, i)); vector_free (graph->nodes); From 5bf313994d01bc05f0fe90fdb69322812c399440 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 26 Jan 2017 06:56:48 +0100 Subject: [PATCH 439/444] lib: graph: speed up node deletion We don't need to copy the from/to arrays, we can just iterate backwards. NB: this makes graph_remove_edge delete only one edge (which is more consistent with graph_add_edge allowing parallel edges). Iterating graph->nodes backwards also makes graph_delete_graph faster since that also iterates backwards. Signed-off-by: David Lamparter --- lib/graph.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/lib/graph.c b/lib/graph.c index 035e552d08..9ca0a3152c 100644 --- a/lib/graph.c +++ b/lib/graph.c @@ -71,22 +71,18 @@ graph_delete_node (struct graph *graph, struct graph_node *node) struct graph_node *adj; // remove all edges from other nodes to us - vector edges = vector_copy (node->from); - for (unsigned int i = 0; i < vector_active (edges); i++) + for (unsigned int i = vector_active (node->from); i--; /**/) { - adj = vector_slot (edges, i); + adj = vector_slot (node->from, i); graph_remove_edge (adj, node); } - vector_free (edges); // remove all edges from us to other nodes - edges = vector_copy (node->to); - for (unsigned int i = 0; i < vector_active (edges); i++) + for (unsigned int i = vector_active (node->to); i--; /**/) { - adj = vector_slot (edges, i); + adj = vector_slot (node->to, i); graph_remove_edge (node, adj); } - vector_free (edges); // if there is a deletion callback, call it if (node->del && node->data) @@ -97,9 +93,12 @@ graph_delete_node (struct graph *graph, struct graph_node *node) vector_free (node->from); // remove node from graph->nodes - for (unsigned int i = 0; i < vector_active (graph->nodes); i++) + for (unsigned int i = vector_active (graph->nodes); i--; /**/) if (vector_slot (graph->nodes, i) == node) - vector_remove (graph->nodes, i); + { + vector_remove (graph->nodes, i); + break; + } // free the node itself XFREE (MTYPE_GRAPH_NODE, node); @@ -119,11 +118,17 @@ graph_remove_edge (struct graph_node *from, struct graph_node *to) // remove from from to->from for (unsigned int i = vector_active (to->from); i--; /**/) if (vector_slot (to->from, i) == from) - vector_remove (to->from, i); + { + vector_remove (to->from, i); + break; + } // remove to from from->to for (unsigned int i = vector_active (from->to); i--; /**/) if (vector_slot (from->to, i) == to) - vector_remove (from->to, i); + { + vector_remove (from->to, i); + break; + } } void From c30420200bf9e0a8c076da5348a0c538de87640c Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 26 Jan 2017 05:59:50 +0100 Subject: [PATCH 440/444] lib: graph: fix vector_remove() vector_remove would corrupt the data in the following sequence: 1. assume vector v = [a, b], active = 2 2. vector_unset(v, 0) => v = [NULL, b], active = 2 3. vector_remove(v, 1) vector_remove calls vector_unset(v, 1), vector_unset notices index #0 is also NULL and thus sets active to 0. The equality test in vector_remove() now fails, leading it to decrement v->active *again*, leading to an underflow that will likely crash the daemon (and might even be exploitable). This call sequence does not happen in existing code since vector_unset() is not used on graph from/to lists. Nonetheless this is a buried land mine in the code at best. Rewrite the function - while we're at it, there's no reason to move the entire array around, just fill the hole with the last element. Signed-off-by: David Lamparter Cc: Quentin Young --- lib/graph.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/graph.c b/lib/graph.c index 9ca0a3152c..0992059ef1 100644 --- a/lib/graph.c +++ b/lib/graph.c @@ -55,11 +55,16 @@ graph_new_node (struct graph *graph, void *data, void (*del) (void*)) static void vector_remove (vector v, unsigned int ix) { - vector_unset (v, ix); - if (ix == vector_active (v)) return; - for (; ix < vector_active (v) - 1; ix++) - v->index[ix] = v->index[ix+1]; + if (ix >= v->active) + return; + + /* v->active is guaranteed >= 1 because ix can't be lower than 0 + * and v->active is > ix. */ v->active--; + /* if ix == v->active--, we set the item to itself, then to NULL... + * still correct, no check neccessary. */ + v->index[ix] = v->index[v->active]; + v->index[v->active] = NULL; } void From 0e37c258a3f238ae532ee4e0b4cd308556da8bae Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 27 Jan 2017 04:57:44 -0500 Subject: [PATCH 441/444] bgpd: Fix possible crash and some minor CR issues This fix addresses these things: 1) Clean up documentation as requested 2) Fix a wrong search for "exact-match" 3) Fix possible crash. Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 15 ++++++++++++--- bgpd/bgp_vty.c | 3 +++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 657cd076e7..573fc76655 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8120,7 +8120,7 @@ DEFUN (show_ip_bgp, if (argv_find(argv, argc, "community-list", &idx)) { const char *clist_number_or_name = argv[++idx]->arg; - if (++idx < argc && strmatch (argv[idx]->arg, "exact-match")) + if (++idx < argc && strmatch (argv[idx]->text, "exact-match")) exact_match = 1; return bgp_show_community_list (vty, bgp, clist_number_or_name, exact_match, afi, safi); } @@ -8179,7 +8179,10 @@ DEFUN (show_ip_bgp_route, } } else - bgp = NULL; + { + vty_out (vty, "Specified 'all' vrf's but this command currently only works per view/vrf%s", VTY_NEWLINE); + return CMD_WARNING; + } /* */ if (argv_find (argv, argc, "A.B.C.D", &idx) || argv_find (argv, argc, "X:X::X:X", &idx)) @@ -9034,9 +9037,15 @@ DEFUN (show_ip_bgp_vpn_all_route_prefix, { int idx = 0; char *network = NULL; + struct bgp *bgp = bgp_get_default(); + if (!bgp) + { + vty_out (vty, "Can't find default instance%s", VTY_NEWLINE); + return CMD_WARNING; + } network = argv_find (argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL; network = argv_find (argv, argc, "A.B.C.D/M", &idx) ? argv[idx]->arg : NULL; - return bgp_show_route (vty, NULL, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0, BGP_PATH_ALL, use_json(argc, argv)); + return bgp_show_route (vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0, BGP_PATH_ALL, use_json(argc, argv)); } #endif /* KEEP_OLD_VPN_COMMANDS */ diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 59af567800..208dd54460 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -227,6 +227,9 @@ argv_find_and_parse_safi (struct cmd_token **argv, int argc, int *index, safi_t * * The function returns the correct location in the parse tree for the * last token found. + * + * Returns 0 for failure to parse correctly, else the idx position of where + * it found the last token. */ int bgp_vty_find_and_parse_afi_safi_vrf (struct vty *vty, struct cmd_token **argv, int argc, int idx, From 9317e17dc86bdaaa345bfedc14d453a2af3ab60f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 27 Jan 2017 08:12:53 -0500 Subject: [PATCH 442/444] bgpd: Make usage of idx consistent Convert the idx to &idx to make our api more consistent Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 15 ++++++++------- bgpd/bgp_vty.c | 19 +++++++++++-------- bgpd/bgp_vty.h | 2 +- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 573fc76655..0225a0bbef 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8058,7 +8058,7 @@ DEFUN (show_ip_bgp, struct bgp *bgp = NULL; int idx = 0; - idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); + bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, &idx, &afi, &safi, &vrf); if (!idx) return CMD_WARNING; @@ -8067,6 +8067,7 @@ DEFUN (show_ip_bgp, if (vrf != VRF_ALL) { + vty_out(vty, "VRF-id: %d", vrf); bgp = bgp_lookup_by_vrf_id (vrf); if (bgp == NULL) { @@ -8165,7 +8166,7 @@ DEFUN (show_ip_bgp_route, int idx = 0; - idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); + bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, &idx, &afi, &safi, &vrf); if (!idx) return CMD_WARNING; @@ -8235,7 +8236,7 @@ DEFUN (show_ip_bgp_regexp, safi_t safi = SAFI_UNICAST; int idx = 0; - idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); + bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, &idx, &afi, &safi, &vrf); if (!idx) return CMD_WARNING; @@ -8269,7 +8270,7 @@ DEFUN (show_ip_bgp_instance_all, safi_t safi = SAFI_UNICAST; int idx = 0; - idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); + bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, &idx, &afi, &safi, &vrf); if (!idx) return CMD_WARNING; @@ -8960,7 +8961,7 @@ DEFUN (show_ip_bgp_instance_neighbor_prefix_counts, int idx = 0; struct bgp *bgp = NULL; - idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); + bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, &idx, &afi, &safi, &vrf); if (!idx) return CMD_WARNING; @@ -9324,7 +9325,7 @@ DEFUN (show_ip_bgp_instance_neighbor_advertised_route, int idx = 0; - idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); + bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, &idx, &afi, &safi, &vrf); if (!idx) return CMD_WARNING; @@ -9512,7 +9513,7 @@ DEFUN (show_ip_bgp_neighbor_routes, int idx = 0; - idx = bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, idx, &afi, &safi, &vrf); + bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, &idx, &afi, &safi, &vrf); if (!idx) return CMD_WARNING; diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 208dd54460..7462f29e31 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -232,22 +232,22 @@ argv_find_and_parse_safi (struct cmd_token **argv, int argc, int *index, safi_t * it found the last token. */ int -bgp_vty_find_and_parse_afi_safi_vrf (struct vty *vty, struct cmd_token **argv, int argc, int idx, +bgp_vty_find_and_parse_afi_safi_vrf (struct vty *vty, struct cmd_token **argv, int argc, int *idx, afi_t *afi, safi_t *safi, vrf_id_t *vrf) { char *vrf_name = NULL; - if (argv_find (argv, argc, "ip", &idx)) + if (argv_find (argv, argc, "ip", idx)) *afi = AFI_IP; - if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) + if (argv_find (argv, argc, "view", idx) || argv_find (argv, argc, "vrf", idx)) { - vrf_name = argv[idx + 1]->arg; - idx += 2; + vrf_name = argv[*idx + 1]->arg; + *idx += 2; } - if (argv_find_and_parse_afi (argv, argc, &idx, afi)) - argv_find_and_parse_safi (argv, argc, &idx, safi); + if (argv_find_and_parse_afi (argv, argc, idx, afi)) + argv_find_and_parse_safi (argv, argc, idx, safi); if (vrf_name) { @@ -260,9 +260,12 @@ bgp_vty_find_and_parse_afi_safi_vrf (struct vty *vty, struct cmd_token **argv, i if (*vrf == VRF_UNKNOWN) { vty_out (vty, "View/Vrf specified is unknown: %s", vrf_name); + *idx = 0; return 0; } - return idx + 1; + + *idx += 1; + return *idx; } static int diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h index cfc4f6cdfb..13e67d112e 100644 --- a/bgpd/bgp_vty.h +++ b/bgpd/bgp_vty.h @@ -64,6 +64,6 @@ extern int argv_find_and_parse_safi(struct cmd_token **argv, int argc, int *index, safi_t *safi); extern int -bgp_vty_find_and_parse_afi_safi_vrf (struct vty *vty, struct cmd_token **argv, int argc, int idx, +bgp_vty_find_and_parse_afi_safi_vrf (struct vty *vty, struct cmd_token **argv, int argc, int *idx, afi_t *afi, safi_t *safi, vrf_id_t *vrf); #endif /* _QUAGGA_BGP_VTY_H */ From b4898a387bc919e80de1a98aba2215a46c7cc070 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 27 Jan 2017 09:07:44 -0500 Subject: [PATCH 443/444] bgp: Add Asserts and remove dead code Add asserts to how I expect bgp_vty_find_and_parse_afi_safi to be used. Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 43 ++++++++++++++++--------------------------- bgpd/bgp_vty.c | 4 ++++ 2 files changed, 20 insertions(+), 27 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 0225a0bbef..ca96bae020 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8065,18 +8065,12 @@ DEFUN (show_ip_bgp, int uj = use_json (argc, argv); if (uj) argc--; - if (vrf != VRF_ALL) + bgp = bgp_lookup_by_vrf_id (vrf); + if (bgp == NULL) { - vty_out(vty, "VRF-id: %d", vrf); - bgp = bgp_lookup_by_vrf_id (vrf); - if (bgp == NULL) - { - vty_out (vty, "Can't find BGP instance %s%s", argv[5]->arg, VTY_NEWLINE); - return CMD_WARNING; - } + vty_out (vty, "Can't find BGP instance %s%s", argv[5]->arg, VTY_NEWLINE); + return CMD_WARNING; } - else - bgp = NULL; if (argv_find(argv, argc, "cidr-only", &idx)) return bgp_show (vty, bgp, afi, safi, bgp_show_type_cidr_only, NULL, uj); @@ -9332,26 +9326,21 @@ DEFUN (show_ip_bgp_instance_neighbor_advertised_route, int uj = use_json (argc, argv); if (uj) argc--; - if (vrf != VRF_ALL) + bgp = bgp_lookup_by_vrf_id (vrf); + if (bgp == NULL) { - bgp = bgp_lookup_by_vrf_id (vrf); - if (bgp == NULL) - { - if (uj) - { - json_object *json_no = NULL; - json_no = json_object_new_object(); - json_object_string_add(json_no, "warning", "Can't find BGP view"); - vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE); - json_object_free(json_no); + if (uj) + { + json_object *json_no = NULL; + json_no = json_object_new_object(); + json_object_string_add(json_no, "warning", "Can't find BGP view"); + vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE); + json_object_free(json_no); } - else - vty_out (vty, "Can't find BGP instance %s%s", argv[5]->arg, VTY_NEWLINE); - return CMD_WARNING; - } + else + vty_out (vty, "Can't find BGP instance %s%s", argv[5]->arg, VTY_NEWLINE); + return CMD_WARNING; } - else - bgp = NULL; /* neighbors */ argv_find (argv, argc, "neighbors", &idx); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 7462f29e31..52ba24d36b 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -237,6 +237,10 @@ bgp_vty_find_and_parse_afi_safi_vrf (struct vty *vty, struct cmd_token **argv, i { char *vrf_name = NULL; + assert (afi); + assert (safi); + assert (*vrf == VRF_UNKNOWN); + if (argv_find (argv, argc, "ip", idx)) *afi = AFI_IP; From 69d143a005c19770f727cc247739ded471e8a32a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 27 Jan 2017 09:49:30 -0500 Subject: [PATCH 444/444] bgpd: Fix assert condition error. Signed-off-by: Donald Sharp --- bgpd/bgp_vty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 52ba24d36b..d9043e520d 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -239,7 +239,7 @@ bgp_vty_find_and_parse_afi_safi_vrf (struct vty *vty, struct cmd_token **argv, i assert (afi); assert (safi); - assert (*vrf == VRF_UNKNOWN); + assert (vrf && *vrf != VRF_UNKNOWN); if (argv_find (argv, argc, "ip", idx)) *afi = AFI_IP;