From 34687162ce39d4c34bf60bc55ea13b597b04c2ac Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 29 Mar 2017 23:02:41 -0400 Subject: [PATCH 01/53] pimd: Convert pim address family from #define -> enum Convert the pim address family from a #define into an enum. Signed-off-by: Donald Sharp --- pimd/pim_msg.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pimd/pim_msg.h b/pimd/pim_msg.h index de663aa3b5..e5676289b7 100644 --- a/pimd/pim_msg.h +++ b/pimd/pim_msg.h @@ -34,7 +34,11 @@ From: http://www.iana.org/assignments/address-family-numbers */ -#define PIM_MSG_ADDRESS_FAMILY_IPV4 (1) +enum pim_msg_address_family { + PIM_MSG_ADDRESS_FAMILY_RESERVED, + PIM_MSG_ADDRESS_FAMILY_IPV4, + PIM_MSG_ADDRESS_FAMILY_IPV6, +}; /* * Network Order pim_msg_hdr From 71bbe73dc4fb308b1abca5a326c6c59e1193d794 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 29 Mar 2017 23:23:25 -0400 Subject: [PATCH 02/53] pimd: Add code to allow backwards compatibility This code change adds the ability to specify that we should be able to work with older versions of PIM. In future commits we will actually use this data. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 27 +++++++++++++++++++++++++++ pimd/pim_vty.c | 6 ++++++ pimd/pimd.c | 2 ++ pimd/pimd.h | 2 ++ 4 files changed, 37 insertions(+) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index cf101b3e24..66fc8185d0 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3509,6 +3509,31 @@ DEFUN (no_ip_pim_packets, return CMD_SUCCESS; } +DEFUN (ip_pim_v6_secondary, + ip_pim_v6_secondary_cmd, + "ip pim send-v6-secondary", + IP_STR + "pim multicast routing\n" + "Send v6 secondary addresses\n") +{ + pimg->send_v6_secondary = 1; + + return CMD_SUCCESS; +} + +DEFUN (no_ip_pim_v6_secondary, + no_ip_pim_v6_secondary_cmd, + "no ip pim send-v6-secondary", + NO_STR + IP_STR + "pim multicast routing\n" + "Send v6 secondary addresses\n") +{ + pimg->send_v6_secondary = 0; + + return CMD_SUCCESS; +} + DEFUN (ip_pim_rp, ip_pim_rp_cmd, "ip pim rp A.B.C.D [A.B.C.D/M]", @@ -6037,6 +6062,8 @@ void pim_cmd_init() 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_pim_v6_secondary_cmd); + install_element (CONFIG_NODE, &no_ip_pim_v6_secondary_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 5b6a79b95a..9788c58cd9 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -148,6 +148,12 @@ int pim_global_config_write(struct vty *vty) writes += pim_msdp_config_write (vty); + if (!pimg->send_v6_secondary) + { + vty_out (vty, "no ip pim send-v6-secondary%s", VTY_NEWLINE); + ++writes; + } + writes += pim_rp_config_write (vty); if (qpim_register_suppress_time != PIM_REGISTER_SUPPRESSION_TIME_DEFAULT) diff --git a/pimd/pimd.c b/pimd/pimd.c index b67544b28e..9058e14b0a 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -109,6 +109,8 @@ pim_vrf_enable (struct vrf *vrf) if (pimg == NULL) zlog_err ("%s %s: pim class init failure ", __FILE__, __PRETTY_FUNCTION__); + + pimg->send_v6_secondary = 1; } return 0; } diff --git a/pimd/pimd.h b/pimd/pimd.h index b3bdd9e243..8dc5899022 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -240,6 +240,8 @@ struct pim_instance afi_t afi; vrf_id_t vrf_id; struct hash *rpf_hash; + + int send_v6_secondary; }; extern struct pim_instance *pimg; //Pim Global Instance From 7399328a6fbd9e41e03cc8d0c9bfbf16a5738c9a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 29 Mar 2017 23:27:25 -0400 Subject: [PATCH 03/53] pimd: Fix RP determination to handle secondary addresses better When we are checking RP addresses and looking at the secondary address. With the addition of the ability to handle v6 addresses in the secondary list. Assuming that the secondary address is a v4 address is a no go. Convert to prefix_same. 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 6c83811d9a..8afc87956d 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -261,7 +261,7 @@ pim_rp_check_interface_addrs(struct rp_info *rp_info, } 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) { + if (prefix_same(&sec_addr->addr, &rp_info->rp.rpf_addr)) { return 1; } } From 07b17d5927499beaf42665bb7bd2bcaea0b1e9d6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 29 Mar 2017 23:44:12 -0400 Subject: [PATCH 04/53] pimd: Add code to find neighbor by secondary With RFC 5549 we need a methodology to find a neighbor based upon a nexthop that is v6 based. This commit sets us up for that by allowing you to find the neigbor by the secondary list. In a future commit we will add code to pass the v6 secondary addresses. Signed-off-by: Donald Sharp --- pimd/pim_iface.c | 7 ++++++- pimd/pim_neighbor.c | 38 ++++++++++++++++++++++++++++++-------- pimd/pim_neighbor.h | 5 +++-- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 0864796431..a753cc4aff 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -1105,6 +1105,7 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp, struct listnode *neighnode; struct pim_neighbor *neigh; struct pim_interface *pim_ifp; + struct prefix p; zassert(ifp); @@ -1116,6 +1117,10 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp, return 0; } + p.family = AF_INET; + p.u.prefix4 = addr; + p.prefixlen = IPV4_MAX_PREFIXLEN; + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { /* primary address ? */ @@ -1123,7 +1128,7 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp, return neigh; /* secondary address ? */ - if (pim_neighbor_find_secondary(neigh, addr)) + if (pim_neighbor_find_secondary(neigh, &p)) return neigh; } diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index c1325df260..133d4edb21 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -423,6 +423,31 @@ void pim_neighbor_free(struct pim_neighbor *neigh) XFREE(MTYPE_PIM_NEIGHBOR, neigh); } +struct pim_neighbor * +pim_neighbor_find_by_secondary (struct interface *ifp, + struct prefix *src) +{ + struct pim_interface *pim_ifp; + struct listnode *node, *pnode; + struct pim_neighbor *neigh; + struct prefix *p; + + pim_ifp = ifp->info; + if (!pim_ifp) + return NULL; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) + { + for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, pnode, p)) + { + if (prefix_same (p, src)) + return neigh; + } + } + + return NULL; +} + struct pim_neighbor *pim_neighbor_find(struct interface *ifp, struct in_addr source_addr) { @@ -669,7 +694,7 @@ void pim_neighbor_delete_all(struct interface *ifp, } struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh, - struct in_addr addr) + struct prefix *addr) { struct listnode *node; struct prefix *p; @@ -678,14 +703,11 @@ struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh, return 0; for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, node, p)) { - if (p->family == AF_INET) { - if (addr.s_addr == p->u.prefix4.s_addr) { - return p; - } - } + if (prefix_same (p, addr)) + return p; } - return 0; + return NULL; } /* @@ -729,7 +751,7 @@ static void delete_from_neigh_addr(struct interface *ifp, for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, neigh)) { { - struct prefix *p = pim_neighbor_find_secondary(neigh, addr->u.prefix4); + struct prefix *p = pim_neighbor_find_secondary(neigh, addr); if (p) { char addr_str[INET_ADDRSTRLEN]; char this_neigh_str[INET_ADDRSTRLEN]; diff --git a/pimd/pim_neighbor.h b/pimd/pim_neighbor.h index 986721666e..e27920fdd8 100644 --- a/pimd/pim_neighbor.h +++ b/pimd/pim_neighbor.h @@ -50,7 +50,8 @@ 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); - +struct pim_neighbor *pim_neighbor_find_by_secondary (struct interface *ifp, + struct prefix *src); struct pim_neighbor *pim_neighbor_find_if (struct interface *ifp); @@ -77,7 +78,7 @@ void pim_neighbor_update(struct pim_neighbor *neigh, uint32_t dr_priority, struct list *addr_list); struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh, - struct in_addr addr); + struct prefix *addr); int pim_if_dr_election(struct interface *ifp); #endif /* PIM_NEIGHBOR_H */ From 0f4b1d2d95e4f9bdb1412b5792941289332a7cc6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 30 Mar 2017 00:07:18 -0400 Subject: [PATCH 05/53] pimd: Add ability to encode/decode v6 secondary addresses Add ability to encode/decode the v6 secondary addresses if they are passed to us. This also fixes the issue where if we are passed a v6 secondary address list we will not refuse to form neighbors. Signed-off-by: Donald Sharp --- pimd/pim_hello.c | 3 ++- pimd/pim_tlv.c | 53 +++++++++++++++++++++++++++++++++++++++--------- pimd/pim_tlv.h | 3 ++- 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/pimd/pim_hello.c b/pimd/pim_hello.c index 3d7ae4ad22..d9b04ea952 100644 --- a/pimd/pim_hello.c +++ b/pimd/pim_hello.c @@ -507,7 +507,8 @@ int pim_hello_build_tlv(const char *ifname, if (ifconnected) { curr = pim_tlv_append_addrlist_ucast(curr, pastend, - ifconnected); + ifconnected, + AF_INET); if (!curr) { if (PIM_DEBUG_PIM_HELLO) { zlog_debug("%s: could not set PIM hello Secondary Address List option for interface %s", diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index 5223f60e1b..1d58ce3ac6 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -94,6 +94,7 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf, } #define ucast_ipv4_encoding_len (2 + sizeof(struct in_addr)) +#define ucast_ipv6_encoding_len (2 + sizeof(struct in6_addr)) /* * An Encoded-Unicast address takes the following format: @@ -135,6 +136,14 @@ pim_encode_addr_ucast (uint8_t *buf, struct prefix *p) memcpy (buf, &p->u.prefix4, sizeof (struct in_addr)); return ucast_ipv4_encoding_len; break; + case AF_INET6: + *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV6; + ++buf; + *(uint8_t *)buf = 0; + ++buf; + memcpy (buf, &p->u.prefix6, sizeof (struct in6_addr)); + return ucast_ipv6_encoding_len; + break; default: return 0; break; @@ -216,12 +225,13 @@ pim_encode_addr_group (uint8_t *buf, afi_t afi, int bidir, int scope, struct in_ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend, - struct list *ifconnected) + struct list *ifconnected, + int family) { struct listnode *node; uint16_t option_len = 0; - uint8_t *curr; + size_t uel; node = listhead(ifconnected); @@ -230,8 +240,10 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, return buf; } - /* Skip first address (primary) */ - node = listnextnode(node); + if (family == AF_INET) + uel = ucast_ipv4_encoding_len; + else + uel = ucast_ipv6_encoding_len; /* Scan secondary address list */ curr = buf + 4; /* skip T and L */ @@ -240,8 +252,14 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, struct prefix *p = ifc->address; int l_encode; - if ((curr + ucast_ipv4_encoding_len) > buf_pastend) - return 0; + if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) + continue; + + if ((curr + uel) > buf_pastend) + return 0; + + if (p->family != family) + continue; l_encode = pim_encode_addr_ucast (curr, p); curr += l_encode; @@ -251,7 +269,7 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, if (PIM_DEBUG_PIM_TRACE_DETAIL) { zlog_debug("%s: number of encoded secondary unicast IPv4 addresses: %zu", __PRETTY_FUNCTION__, - option_len / ucast_ipv4_encoding_len); + option_len / uel); } if (option_len < 1) { @@ -491,9 +509,23 @@ pim_parse_addr_ucast (struct prefix *p, p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */ memcpy(&p->u.prefix4, addr, sizeof(struct in_addr)); - + p->prefixlen = IPV4_MAX_PREFIXLEN; addr += sizeof(struct in_addr); + break; + case PIM_MSG_ADDRESS_FAMILY_IPV6: + if ((addr + sizeof(struct in6_addr)) > pastend) { + zlog_warn ("%s: IPv6 unicast address overflow: left=%zd needed %zu", + __PRETTY_FUNCTION__, + pastend - addr, sizeof(struct in6_addr)); + return -3; + } + + p->family = AF_INET6; + p->prefixlen = IPV6_MAX_PREFIXLEN; + memcpy(&p->u.prefix6, addr, 16); + addr += sizeof(struct in6_addr); + break; default: { @@ -706,6 +738,8 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, addr_str, src_str, ifname); } break; + case AF_INET6: + break; default: { char src_str[INET_ADDRSTRLEN]; @@ -759,8 +793,7 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, FREE_ADDR_LIST(*hello_option_addr_list); return -3; } - p->family = tmp.family; - p->u.prefix4 = tmp.u.prefix4; + prefix_copy(p, &tmp); listnode_add(*hello_option_addr_list, p); } diff --git a/pimd/pim_tlv.h b/pimd/pim_tlv.h index 9c4ebc9f0f..7e0a8a147f 100644 --- a/pimd/pim_tlv.h +++ b/pimd/pim_tlv.h @@ -80,7 +80,8 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf, uint32_t option_value); uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend, - struct list *ifconnected); + struct list *ifconnected, + int family); int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, From dba7860904ec03bf3c856efee1fae9fc06821121 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 30 Mar 2017 09:01:09 -0400 Subject: [PATCH 06/53] pimd: Send v6 secondary addresses to neighbors in hello Send v6 secondary addresses to our neighbor in hello's. Additionally allow the disabling it via the cli introduced earlier. Signed-off-by: Donald Sharp --- pimd/pim_hello.c | 35 ++++++++++++++++++++++++----------- pimd/pim_hello.h | 5 ++--- pimd/pim_pim.c | 5 ++--- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/pimd/pim_hello.c b/pimd/pim_hello.c index d9b04ea952..ee9433d797 100644 --- a/pimd/pim_hello.c +++ b/pimd/pim_hello.c @@ -428,15 +428,14 @@ int pim_hello_recv(struct interface *ifp, return 0; } -int pim_hello_build_tlv(const char *ifname, +int pim_hello_build_tlv(struct interface *ifp, uint8_t *tlv_buf, int tlv_buf_size, uint16_t holdtime, uint32_t dr_priority, uint32_t generation_id, uint16_t propagation_delay, uint16_t override_interval, - int can_disable_join_suppression, - struct list *ifconnected) + int can_disable_join_suppression) { uint8_t *curr = tlv_buf; uint8_t *pastend = tlv_buf + tlv_buf_size; @@ -454,7 +453,7 @@ int pim_hello_build_tlv(const char *ifname, if (!curr) { if (PIM_DEBUG_PIM_HELLO) { zlog_debug("%s: could not set PIM hello Holdtime option for interface %s", - __PRETTY_FUNCTION__, ifname); + __PRETTY_FUNCTION__, ifp->name); } return -1; } @@ -468,7 +467,7 @@ int pim_hello_build_tlv(const char *ifname, if (!tmp) { if (PIM_DEBUG_PIM_HELLO) { zlog_debug("%s: could not set PIM LAN Prune Delay option for interface %s", - __PRETTY_FUNCTION__, ifname); + __PRETTY_FUNCTION__, ifp->name); } return -1; } @@ -485,7 +484,7 @@ int pim_hello_build_tlv(const char *ifname, if (!curr) { if (PIM_DEBUG_PIM_HELLO) { zlog_debug("%s: could not set PIM hello DR Priority option for interface %s", - __PRETTY_FUNCTION__, ifname); + __PRETTY_FUNCTION__, ifp->name); } return -2; } @@ -498,24 +497,38 @@ int pim_hello_build_tlv(const char *ifname, if (!curr) { if (PIM_DEBUG_PIM_HELLO) { zlog_debug("%s: could not set PIM hello Generation ID option for interface %s", - __PRETTY_FUNCTION__, ifname); + __PRETTY_FUNCTION__, ifp->name); } return -3; } /* Secondary Address List */ - if (ifconnected) { + if (ifp->connected->count) { curr = pim_tlv_append_addrlist_ucast(curr, pastend, - ifconnected, + ifp->connected, AF_INET); if (!curr) { if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("%s: could not set PIM hello Secondary Address List option for interface %s", - __PRETTY_FUNCTION__, ifname); + zlog_debug("%s: could not set PIM hello v4 Secondary Address List option for interface %s", + __PRETTY_FUNCTION__, ifp->name); } return -4; } + if (pimg->send_v6_secondary) + { + curr = pim_tlv_append_addrlist_ucast(curr, + pastend, + ifp->connected, + AF_INET6); + if (!curr) { + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug("%s: could not sent PIM hello v6 secondary Address List option for interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + return -4; + } + } } return curr - tlv_buf; diff --git a/pimd/pim_hello.h b/pimd/pim_hello.h index 3a6d3361ba..de5359e2c0 100644 --- a/pimd/pim_hello.h +++ b/pimd/pim_hello.h @@ -29,15 +29,14 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr, uint8_t *tlv_buf, int tlv_buf_size); -int pim_hello_build_tlv(const char *ifname, +int pim_hello_build_tlv(struct interface *ifname, uint8_t *tlv_buf, int tlv_buf_size, uint16_t holdtime, uint32_t dr_priority, uint32_t generation_id, uint16_t propagation_delay, uint16_t override_interval, - int can_disable_join_suppression, - struct list *ifconnected); + int can_disable_join_suppression); void pim_hello_require(struct interface *ifp); diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index f82687245d..bc13e10a61 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -629,7 +629,7 @@ static int hello_send(struct interface *ifp, listcount(ifp->connected)); } - pim_tlv_size = pim_hello_build_tlv(ifp->name, + pim_tlv_size = pim_hello_build_tlv(ifp, pim_msg + PIM_PIM_MIN_LEN, sizeof(pim_msg) - PIM_PIM_MIN_LEN, holdtime, @@ -637,8 +637,7 @@ static int hello_send(struct interface *ifp, pim_ifp->pim_generation_id, pim_ifp->pim_propagation_delay_msec, pim_ifp->pim_override_interval_msec, - PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options), - ifp->connected); + PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)); if (pim_tlv_size < 0) { return -1; } From eeff6d3f99c8965bbb4870d9ca0f8da5f6a53e57 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 30 Mar 2017 09:07:06 -0400 Subject: [PATCH 07/53] pimd: Use better 5549 resolution When we receive a v6 nexthop in v4, lookup the nbr by it's secondary address. Signed-off-by: Donald Sharp --- pimd/pim_zlookup.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index f77990ab5a..620137b33b 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -222,6 +222,7 @@ static int zclient_read_nexthop(struct zclient *zlookup, for (i = 0; i < nexthop_num; ++i) { enum nexthop_types_t nexthop_type; struct pim_neighbor *nbr; + struct prefix p; nexthop_type = stream_getc(s); if (num_ifindex >= tab_size) { @@ -253,7 +254,18 @@ static int zclient_read_nexthop(struct zclient *zlookup, 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 (nexthop_tab[num_ifindex].ifindex, VRF_DEFAULT)); + + p.family = AF_INET6; + p.prefixlen = IPV6_MAX_PREFIXLEN; + memcpy (&p.u.prefix6, &nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, 16); + + /* + * If we are sending v6 secondary assume we receive v6 secondary + */ + if (pimg->send_v6_secondary) + nbr = pim_neighbor_find_by_secondary(if_lookup_by_index (nexthop_tab[num_ifindex].ifindex, VRF_DEFAULT), &p); + else + nbr = pim_neighbor_find_if (if_lookup_by_index (nexthop_tab[num_ifindex].ifindex, VRF_DEFAULT)); if (nbr) { nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; From 294b6d7243983270d69c85aaa8528c78a2521da5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 30 Mar 2017 09:10:05 -0400 Subject: [PATCH 08/53] pimd: Receive incoming v6 addresses and place in pim_ifp list Add code to properly receive v6 addresses up from zebra and to properly place them into our interface secondary address list. Additionally cleanup some code in pim_cmd.c that was broken by these changes. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 17 +++++++------- pimd/pim_iface.c | 60 ++++++++++++++++++++++++++++++------------------ pimd/pim_iface.h | 2 +- pimd/pim_zebra.c | 22 +----------------- 4 files changed, 48 insertions(+), 53 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 66fc8185d0..91d870fb1e 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -816,6 +816,7 @@ 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) { + char pbuf[PREFIX2STR_BUFFER]; json_row = json_object_new_object(); json_object_pim_ifp_add(json_row, ifp); @@ -827,7 +828,8 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch 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_array_add(sec_list, + json_object_new_string(prefix2str(&sec_addr->addr, pbuf, PREFIX2STR_BUFFER))); } json_object_object_add(json_row, "secondaryAddressList", sec_list); } @@ -918,11 +920,12 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch vty_out(vty, "Use Source : %s%s", inet_ntoa(pim_ifp->update_source), VTY_NEWLINE); } if (pim_ifp->sec_addr_list) { + char pbuf[PREFIX2STR_BUFFER]; vty_out(vty, "Address : %s (primary)%s", - inet_ntoa(ifaddr), VTY_NEWLINE); + 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); + prefix2str(&sec_addr->addr, pbuf, PREFIX2STR_BUFFER), VTY_NEWLINE); } } else { vty_out(vty, "Address : %s%s", inet_ntoa(ifaddr), VTY_NEWLINE); @@ -1607,13 +1610,9 @@ 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[INET_ADDRSTRLEN]; + char neigh_sec_str[100]; - if (p->family != AF_INET) - continue; - - pim_inet4_dump("", p->u.prefix4, - neigh_sec_str, sizeof(neigh_sec_str)); + prefix2str(p, neigh_sec_str, 100); vty_out(vty, "%-9s %-15s %-15s %-15s%s", ifp->name, diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index a753cc4aff..f038acab8f 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -324,12 +324,29 @@ 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)) + if (sec1->addr.family == AF_INET && + sec2->addr.family == AF_INET6) return -1; - if (ntohl(sec1->addr.s_addr) > ntohl(sec2->addr.s_addr)) + if (sec1->addr.family == AF_INET6 && + sec2->addr.family == AF_INET) return 1; + if (sec1->addr.family == AF_INET) + { + if (ntohl(sec1->addr.u.prefix4.s_addr) < ntohl(sec2->addr.u.prefix4.s_addr)) + return -1; + + if (ntohl(sec1->addr.u.prefix4.s_addr) > ntohl(sec2->addr.u.prefix4.s_addr)) + return 1; + } + else + { + return memcmp (&sec1->addr.u.prefix6, + &sec2->addr.u.prefix6, + sizeof (struct in6_addr)); + } + return 0; } @@ -339,7 +356,7 @@ static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr) } static struct pim_secondary_addr * -pim_sec_addr_find(struct pim_interface *pim_ifp, struct in_addr addr) +pim_sec_addr_find(struct pim_interface *pim_ifp, struct prefix *addr) { struct pim_secondary_addr *sec_addr; struct listnode *node; @@ -349,7 +366,7 @@ pim_sec_addr_find(struct pim_interface *pim_ifp, struct in_addr addr) } for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { - if (sec_addr->addr.s_addr == addr.s_addr) { + if (prefix_cmp(&sec_addr->addr, addr)) { return sec_addr; } } @@ -364,7 +381,7 @@ static void pim_sec_addr_del(struct pim_interface *pim_ifp, pim_sec_addr_free(sec_addr); } -static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct in_addr addr) +static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct prefix *addr) { int changed = 0; struct pim_secondary_addr *sec_addr; @@ -391,7 +408,7 @@ static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct in_addr addr) } changed = 1; - sec_addr->addr = addr; + sec_addr->addr = *addr; listnode_add_sort(pim_ifp->sec_addr_list, sec_addr); return changed; @@ -433,10 +450,6 @@ static int pim_sec_addr_update(struct interface *ifp) 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; } @@ -446,7 +459,7 @@ static int pim_sec_addr_update(struct interface *ifp) continue; } - if (pim_sec_addr_add(pim_ifp, p->u.prefix4)) { + if (pim_sec_addr_add(pim_ifp, p)) { changed = 1; } } @@ -571,12 +584,15 @@ void pim_if_addr_add(struct connected *ifc) detect_address_change(ifp, 0, __PRETTY_FUNCTION__); + if (ifc->address->family != AF_INET) + return; + if (PIM_IF_TEST_IGMP(pim_ifp->options)) { struct igmp_sock *igmp; /* lookup IGMP socket */ igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, - ifaddr); + ifaddr); if (!igmp) { /* if addr new, add IGMP socket */ pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr, ifp); @@ -675,14 +691,17 @@ void pim_if_addr_del(struct connected *ifc, int force_prim_as_any) ifp = ifc->ifp; zassert(ifp); + if (ifc->address->family != AF_INET) + return; + if (PIM_DEBUG_ZEBRA) { char buf[BUFSIZ]; prefix2str(ifc->address, buf, BUFSIZ); zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s", - __PRETTY_FUNCTION__, - ifp->name, ifp->ifindex, buf, - CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ? - "secondary" : "primary"); + __PRETTY_FUNCTION__, + ifp->name, ifp->ifindex, buf, + CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ? + "secondary" : "primary"); } detect_address_change(ifp, force_prim_as_any, __PRETTY_FUNCTION__); @@ -709,12 +728,9 @@ void pim_if_addr_add_all(struct interface *ifp) struct prefix *p = ifc->address; if (p->family != AF_INET) - { - v6_addrs++; - continue; - } - - v4_addrs++; + v6_addrs++; + else + v4_addrs++; pim_if_addr_add(ifc); } diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index 8d332c70b0..f4d7518d7a 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -69,7 +69,7 @@ enum pim_secondary_addr_flags { }; struct pim_secondary_addr { - struct in_addr addr; + struct prefix addr; enum pim_secondary_addr_flags flags; }; diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index d02560bfc2..bbee95bddd 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -257,31 +257,11 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient, #endif } - if (p->family != AF_INET) - { - 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); - pim_if_add_vif (c->ifp); - } - return 0; - } - if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) { /* trying to add primary address */ struct in_addr primary_addr = pim_find_primary_addr(c->ifp); - if (primary_addr.s_addr != p->u.prefix4.s_addr) { + if (p->family != AF_INET || primary_addr.s_addr != p->u.prefix4.s_addr) { if (PIM_DEBUG_ZEBRA) { /* but we had a primary address already */ From 2e725ad140e14ed03195028881be65c2cefc079a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 30 Mar 2017 10:22:00 -0400 Subject: [PATCH 09/53] pimd: Fix header to be more descriptive of what it is doing Signed-off-by: Donald Sharp --- pimd/pim_hello.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_hello.h b/pimd/pim_hello.h index de5359e2c0..1f8b348bd7 100644 --- a/pimd/pim_hello.h +++ b/pimd/pim_hello.h @@ -29,7 +29,7 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr, uint8_t *tlv_buf, int tlv_buf_size); -int pim_hello_build_tlv(struct interface *ifname, +int pim_hello_build_tlv(struct interface *ifp, uint8_t *tlv_buf, int tlv_buf_size, uint16_t holdtime, uint32_t dr_priority, From 508f9997f271c066b0ffc4fe0d5861ef20430317 Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Sun, 2 Apr 2017 13:55:58 -0400 Subject: [PATCH 10/53] bgp: fix a couple of instances of bm being used before init'ed Signed-off-by: Lou Berger --- bgpd/bgp_main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 423c9453eb..55bf410628 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -363,6 +363,7 @@ main (int argc, char **argv) int bgp_port = BGP_PORT_DEFAULT; char *bgp_address = NULL; + int no_fib_flag = 0; frr_preinit(&bgpd_di, argc, argv); frr_opt_add("p:l:rne:", longopts, @@ -389,7 +390,7 @@ main (int argc, char **argv) if (tmp_port <= 0 || tmp_port > 0xffff) bgp_port = BGP_PORT_DEFAULT; else - bm->port = tmp_port; + bgp_port = tmp_port; break; case 'e': multipath_num = atoi (optarg); @@ -406,7 +407,7 @@ main (int argc, char **argv) bgp_address = optarg; /* listenon implies -n */ case 'n': - bgp_option_set (BGP_OPT_NO_FIB); + no_fib_flag = 1; break; default: frr_help_exit (1); @@ -418,6 +419,8 @@ main (int argc, char **argv) bgp_master_init (frr_init ()); bm->port = bgp_port; bm->address = bgp_address; + if (no_fib_flag) + bgp_option_set (BGP_OPT_NO_FIB); /* Initializations. */ bgp_vrf_init (); From c888ea16473ea3b0c69f59d62030d7c678b64b63 Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Sun, 2 Apr 2017 13:57:10 -0400 Subject: [PATCH 11/53] lib/frr: fix reference to zsuid before it is set Signed-off-by: Lou Berger --- lib/privs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/privs.c b/lib/privs.c index 376d6f3365..87ad074f1b 100644 --- a/lib/privs.c +++ b/lib/privs.c @@ -769,6 +769,7 @@ zprivs_init(struct zebra_privs_t *zprivs) } } + zprivs_state.zsuid = geteuid(); /* initial uid */ /* add groups only if we changed uid - otherwise skip */ if ((ngroups) && (zprivs_state.zsuid != zprivs_state.zuid)) { From 3135834e1f8c4b3a13d2cd43f30e30313980112e Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Sun, 2 Apr 2017 15:34:55 -0400 Subject: [PATCH 12/53] bgpd: restore -S, --skip_runas options Signed-off-by: Lou Berger --- bgpd/bgp_main.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 55bf410628..1773070fe3 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -66,6 +66,7 @@ static const struct option longopts[] = { "listenon", required_argument, NULL, 'l'}, { "retain", no_argument, NULL, 'r'}, { "no_kernel", no_argument, NULL, 'n'}, + { "skip_runas", no_argument, NULL, 'S'}, { "ecmp", required_argument, NULL, 'e'}, { 0 } }; @@ -151,7 +152,8 @@ sigint (void) if (! retain_mode) { bgp_terminate (); - zprivs_terminate (&bgpd_privs); + if (bgpd_privs.user) /* NULL if skip_runas flag set */ + zprivs_terminate (&bgpd_privs); } bgp_exit (0); @@ -364,6 +366,7 @@ main (int argc, char **argv) int bgp_port = BGP_PORT_DEFAULT; char *bgp_address = NULL; int no_fib_flag = 0; + int skip_runas = 0; frr_preinit(&bgpd_di, argc, argv); frr_opt_add("p:l:rne:", longopts, @@ -371,6 +374,7 @@ main (int argc, char **argv) " -l, --listenon Listen on specified address (implies -n)\n" " -r, --retain When program terminates, retain added route by bgpd.\n" " -n, --no_kernel Do not install route to kernel.\n" + " -S, --skip_runas Skip capabilities checks, and changing user and group IDs.\n" " -e, --ecmp Specify ECMP to use.\n"); /* Command line argument treatment. */ @@ -409,11 +413,16 @@ main (int argc, char **argv) case 'n': no_fib_flag = 1; break; + case 'S': + skip_runas = 1; + break; default: frr_help_exit (1); break; } } + if (skip_runas) + memset (&bgpd_privs, 0, sizeof (bgpd_privs)); /* BGP master init. */ bgp_master_init (frr_init ()); From 52884837196a26d75150b55a88d768b3a27eab8b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 4 Apr 2017 20:18:24 -0400 Subject: [PATCH 13/53] *: Clean up some wrong references Signed-off-by: Donald Sharp --- README | 10 +++++----- bgpd/bgp_attr_evpn.c | 8 ++++---- bgpd/bgp_attr_evpn.h | 8 ++++---- bgpd/bgp_evpn.c | 8 ++++---- bgpd/bgp_evpn.h | 8 ++++---- bgpd/bgp_evpn_vty.c | 8 ++++---- bgpd/bgp_evpn_vty.h | 8 ++++---- bgpd/bgp_vpn.c | 8 ++++---- bgpd/bgp_vpn.h | 8 ++++---- 9 files changed, 37 insertions(+), 37 deletions(-) diff --git a/README b/README index a0aa895367..7c6ef7034e 100644 --- a/README +++ b/README @@ -1,13 +1,13 @@ -Free Range Routing is free software that manages various IPv4 and IPv6 routing +FRRouting is free software that manages various IPv4 and IPv6 routing protocols. -Currently Free Range Routing supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1, +Currently FRRouting supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1, RIPv2, RIPng, PIM-SM/MSDP and LDP as well as very early support for IS-IS. See the file REPORTING-BUGS to report bugs. -Free Range Routing is free software. See the file COPYING for copying conditions. +Free RRRouting is free software. See the file COPYING for copying conditions. -Public email discussion can be found at https://lists.nox.tf/listinfo/frr +Public email discussion can be found at https://lists.frrouting.org/listinfo -Our public slack channel is at https://freerangerouting.slack.com +Our public slack channel is at https://frrouting.slack.com diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c index be97ffda69..5b24d4ec61 100644 --- a/bgpd/bgp_attr_evpn.c +++ b/bgpd/bgp_attr_evpn.c @@ -1,20 +1,20 @@ /* Ethernet-VPN Attribute handling file Copyright (C) 2016 6WIND -This file is part of Free Range Routing. +This file is part of FRRouting. -Free Range Routing is free software; you can redistribute it and/or modify it +FRRouting 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. -Free Range Routing is distributed in the hope that it will be useful, but +FRRouting 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 Free Range Routing; see the file COPYING. If not, write to the Free +along with FRRouting; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h index e6da7e7080..4b7d24de18 100644 --- a/bgpd/bgp_attr_evpn.h +++ b/bgpd/bgp_attr_evpn.h @@ -1,20 +1,20 @@ /* E-VPN attribute handling structure file Copyright (C) 2016 6WIND -This file is part of Free Range Routing. +This file is part of FRRouting. -Free Range Routing is free software; you can redistribute it and/or modify it +FRRouting 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. -Free Range Routing is distributed in the hope that it will be useful, but +FRRouting 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 Free Range Routing; see the file COPYING. If not, write to the Free +along with FRRouting; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 1ab8e23236..612f49f1cb 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -1,20 +1,20 @@ /* Ethernet-VPN Packet and vty Processing File Copyright (C) 2016 6WIND -This file is part of Free Range Routing. +This file is part of FRRouting. -Free Range Routing is free software; you can redistribute it and/or modify it +FRRouting 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. -Free Range Routing is distributed in the hope that it will be useful, but +FRRouting 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 Free Range Routing; see the file COPYING. If not, write to the Free +along with FRRouting; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index 63c1a766ea..9b24bb066a 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -1,20 +1,20 @@ /* E-VPN header for packet handling Copyright (C) 2016 6WIND -This file is part of Free Range Routing. +This file is part of FRRouting. -Free Range Routing is free software; you can redistribute it and/or modify it +FRRouting 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. -Free Range Routing is distributed in the hope that it will be useful, but +FRRouting 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 Free Range Routing; see the file COPYING. If not, write to the Free +along with FRRouting; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 1654265a72..97ce7ee969 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -1,20 +1,20 @@ /* Ethernet-VPN Packet and vty Processing File Copyright (C) 2017 6WIND -This file is part of Free Range Routing +This file is part of FRRouting -Free Range Routing is free software; you can redistribute it and/or modify it +FRRouting 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. -Free Range Routing is distributed in the hope that it will be useful, but +FRRouting 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 Free Range Routing; see the file COPYING. If not, write to the Free +along with FRRouting; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ diff --git a/bgpd/bgp_evpn_vty.h b/bgpd/bgp_evpn_vty.h index 11e93a5281..68b5f5cfbf 100644 --- a/bgpd/bgp_evpn_vty.h +++ b/bgpd/bgp_evpn_vty.h @@ -1,20 +1,20 @@ /* EVPN VTY functions to EVPN Copyright (C) 2017 6WIND -This file is part of Free Range Routing. +This file is part of FRRouting. -Free Range Routing is free software; you can redistribute it and/or modify it +FRRouting 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. -Free Range Routing is distributed in the hope that it will be useful, but +FRRouting 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 Free Range Routing; see the file COPYING. If not, write to the Free +along with FRRouting; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ diff --git a/bgpd/bgp_vpn.c b/bgpd/bgp_vpn.c index edc5891d22..5b1b1b85b2 100644 --- a/bgpd/bgp_vpn.c +++ b/bgpd/bgp_vpn.c @@ -1,20 +1,20 @@ /* VPN Related functions Copyright (C) 2017 6WIND -This file is part of Free Range Routing +This file is part of FRRouting -Free Range Routing is free software; you can redistribute it and/or modify it +FRRouting 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. -Free Range Routing is distributed in the hope that it will be useful, but +FRRouting 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 Free Range Routing; see the file COPYING. If not, write to the Free +along with FRRouting; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ diff --git a/bgpd/bgp_vpn.h b/bgpd/bgp_vpn.h index a16914b65e..dd53503bf3 100644 --- a/bgpd/bgp_vpn.h +++ b/bgpd/bgp_vpn.h @@ -1,20 +1,20 @@ /* VPN common functions to MP-BGP Copyright (C) 2017 6WIND -This file is part of Free Range Routing. +This file is part of FRRouting. -Free Range Routing is free software; you can redistribute it and/or modify it +FRRouting 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. -Free Range Routing is distributed in the hope that it will be useful, but +FRRouting 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 Free Range Routing; see the file COPYING. If not, write to the Free +along with FRRouting; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ From fab7c7260158439d57209479a0d3244bfe0e076d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 4 Apr 2017 20:36:16 -0400 Subject: [PATCH 14/53] doc: Cleanup 'Build the Software' The frrouting.org web page: https://frrouting.org/manual/Build-the-Software.html#Build-the-Software is built from doc/install.texi. The output on this page is a bit missleading, let's clean it up some. Signed-off-by: Donald Sharp --- doc/install.texi | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/doc/install.texi b/doc/install.texi index b34f316844..d989928b8f 100644 --- a/doc/install.texi +++ b/doc/install.texi @@ -218,18 +218,14 @@ routing utility. It contains @command{ifconfig}, @command{route}, After configuring the software, you will need to compile it for your system. Simply issue the command @command{make} in the root of the source -directory and the software will be compiled. If you have *any* problems -at this stage, be certain to send a bug report @xref{Bug Reports}. +directory and the software will be compiled. Cliff Note versions of +different compilation examples can be found in the doc/Building_FRR_on_XXX.md +files. If you have *any* problems at this stage, be certain to send a +bug report @xref{Bug Reports}. @example -% ./configure -. -. -. -./configure output -. -. -. +% ./bootstrap.sh +% ./configure % make @end example @c A - End of node, Building the Software From 0e374d906d8934e6054a54906449f83a3deefd71 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 24 Mar 2017 15:10:11 -0400 Subject: [PATCH 15/53] pimd: Add # of ifchannels to 'show ip pim int' Add the ability to see the number of ifchannels associated with a particular interface. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 3c5a16ec68..4b12f48314 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1040,6 +1040,7 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) struct pim_upstream *up; int fhr = 0; int pim_nbrs = 0; + int pim_ifchannels = 0; json_object *json = NULL; json_object *json_row = NULL; json_object *json_tmp; @@ -1056,6 +1057,7 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) continue; pim_nbrs = pim_ifp->pim_neighbor_list->count; + pim_ifchannels = pim_ifp->pim_ifchannel_list->count; fhr = 0; for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) @@ -1066,6 +1068,7 @@ static void pim_show_interfaces(struct vty *vty, u_char 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, "pimIfChannels", pim_ifchannels); json_object_int_add(json_row, "firstHopRouter", fhr); json_object_string_add(json_row, "pimDesignatedRouter", inet_ntoa(pim_ifp->pim_dr_addr)); @@ -1078,7 +1081,7 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) if (uj) { vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); } else { - vty_out(vty, "Interface State Address PIM Nbrs PIM DR FHR%s", VTY_NEWLINE); + vty_out(vty, "Interface State Address PIM Nbrs PIM DR FHR IfChannels%s", VTY_NEWLINE); json_object_object_foreach(json, key, val) { vty_out(vty, "%-9s ", key); @@ -1100,7 +1103,10 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) } json_object_object_get_ex(val, "firstHopRouter", &json_tmp); - vty_out(vty, "%3d%s", json_object_get_int(json_tmp), VTY_NEWLINE); + vty_out(vty, "%3d ", json_object_get_int(json_tmp)); + + json_object_object_get_ex(val, "pimIfChannels", &json_tmp); + vty_out(vty, "%9d%s", json_object_get_int(json_tmp), VTY_NEWLINE); } } From 850a9f99b8e4ba6e043a75c28d25c9cb092770c5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 22 Mar 2017 21:07:57 -0400 Subject: [PATCH 16/53] pimd: Allow SPT switchover This allows SPT switchover for S,G upon receipt of packets on the LHR. 1) When we create a *,G from a IGMP Group Report, install the *,G route with the pimreg device on the OIL. 2) When a packet hits the LHR that matches the *,G, we will get a WHOLEPKT callback from the kernel and if we cannot find the S,G, that means we have matched it on the LHR via the *,G mroute. Create the S,G start the KAT and run inherited_olist. 3) When the S,G times out, safely remove the S,G via the KAT expiry 4) When the *,G is removed, remove any S,G associated with it via the LHR flag. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 1 + pimd/pim_mroute.c | 17 ++++++++++ pimd/pim_upstream.c | 77 ++++++++++++++++++++++++++++---------------- pimd/pim_upstream.h | 5 +++ 4 files changed, 72 insertions(+), 28 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index e6b4ba92a9..e1697960e4 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -1006,6 +1006,7 @@ pim_ifchannel_local_membership_add(struct interface *ifp, pim_upstream_switch (child, PIM_UPSTREAM_JOINED); } } + pim_channel_add_oif(up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); } return 1; diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 2fb243b9bd..cfbd07ede0 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -200,6 +200,23 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf) up = pim_upstream_find(&sg); if (!up) { + struct prefix_sg star = sg; + star.src.s_addr = INADDR_ANY; + + up = pim_upstream_find(&star); + + if (up && PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) + { + up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_LHR, __PRETTY_FUNCTION__); + pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); + pim_upstream_inherited_olist (up); + pim_upstream_switch(up, PIM_UPSTREAM_JOINED); + + if (PIM_DEBUG_MROUTE) + zlog_debug ("%s: Creating %s upstream on LHR", + __PRETTY_FUNCTION__, up->sg_str); + return 0; + } if (PIM_DEBUG_MROUTE_DETAIL) { zlog_debug("%s: Unable to find upstream channel WHOLEPKT%s", __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 172d0d21c9..3e81aaf496 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -198,7 +198,20 @@ pim_upstream_del(struct pim_upstream *up, const char *name) upstream_channel_oil_detach(up); if (up->sources) - list_delete (up->sources); + { + struct listnode *node, *nnode; + struct pim_upstream *child; + for (ALL_LIST_ELEMENTS (up->sources, node, nnode, child)) + { + if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(child->flags)) + { + PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(child->flags); + pim_upstream_del(child, __PRETTY_FUNCTION__); + } + } + + list_delete (up->sources); + } up->sources = NULL; /* @@ -1083,26 +1096,31 @@ pim_upstream_keep_alive_timer (struct thread *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. + */ + } /* source is no longer active - pull the SA from MSDP's cache */ pim_msdp_sa_local_del(&up->sg); /* 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", up->sg_str); - PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags); - pim_upstream_del(up, __PRETTY_FUNCTION__); - } + { + pim_upstream_fhr_kat_expiry(up); + if (PIM_DEBUG_TRACE) + 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__); + } + else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) + { + PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(up->flags); + pim_upstream_del(up, __PRETTY_FUNCTION__); + } return 0; } @@ -1633,25 +1651,28 @@ pim_upstream_sg_running (void *arg) return; } - 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_upstream_kat_start_ok(up)) { - if (PIM_DEBUG_TRACE) - zlog_debug ("source reference created on kat restart %s", up->sg_str); + /* 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", 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); + 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); } + else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) 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); - } + { + pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface); + } return; } diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 6f7556f323..94bc5a55b9 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -34,6 +34,8 @@ #define PIM_UPSTREAM_FLAG_MASK_SRC_STREAM (1 << 5) #define PIM_UPSTREAM_FLAG_MASK_SRC_MSDP (1 << 6) #define PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE (1 << 7) +#define PIM_UPSTREAM_FLAG_MASK_SRC_LHR (1 << 8) +#define PIM_UPSTREAM_FLAG_ALL 0xFFFFFFFF #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) @@ -43,6 +45,7 @@ #define PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) #define PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) #define PIM_UPSTREAM_FLAG_TEST_SEND_SG_RPT_PRUNE(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE) +#define PIM_UPSTREAM_FLAG_TEST_SRC_LHR(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_LHR) #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) @@ -52,6 +55,7 @@ #define PIM_UPSTREAM_FLAG_SET_SRC_STREAM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) #define PIM_UPSTREAM_FLAG_SET_SRC_MSDP(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) #define PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE) +#define PIM_UPSTREAM_FLAG_SET_SRC_LHR(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_LHR) #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) @@ -61,6 +65,7 @@ #define PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) #define PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) #define PIM_UPSTREAM_FLAG_UNSET_SEND_SG_RPT_PRUNE(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE) +#define PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_LHR) enum pim_upstream_state { PIM_UPSTREAM_NOTJOINED, From 2830b0186384ff53ed33186276936739f2e079cb Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 30 Mar 2017 10:50:04 -0400 Subject: [PATCH 17/53] pimd: Fix crash when failure to create upstream When we have a *,G mroute that starts receiving any particular S,G, we will get wholepkt callbacks due to the pimreg in the OIL for the *,G. So we need to do SPT switchover, but this can fail if we do not have a path to the S( but we do to the RP!). In this case fail gracefully. Ticket: CM-15621 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 cfbd07ede0..1df4c033bc 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -208,6 +208,13 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf) if (up && PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) { up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_LHR, __PRETTY_FUNCTION__); + if (!up) + { + if (PIM_DEBUG_MROUTE) + zlog_debug ("%s: Unable to create upstream information for %s", + __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); + return 0; + } pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); pim_upstream_inherited_olist (up); pim_upstream_switch(up, PIM_UPSTREAM_JOINED); From a7b2b1e29862f82d8a68bda2c72a460cd26aa5a8 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 5 Apr 2017 12:08:53 -0400 Subject: [PATCH 18/53] pimd: Add the ability to never SPT switchover Add the ability to allow pim to determine if we should allow spt-switchover or not on the LHR. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 31 +++++++++++++++++++++++++++++++ pimd/pim_ifchannel.c | 3 ++- pimd/pim_upstream.c | 36 ++++++++++++++++++++++++++++++++++++ pimd/pim_upstream.h | 3 +++ pimd/pim_vty.c | 6 ++++++ pimd/pimd.c | 1 + pimd/pimd.h | 8 ++++++++ 7 files changed, 87 insertions(+), 1 deletion(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 4b12f48314..de2b7cbba6 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3416,6 +3416,35 @@ pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, const cha return CMD_SUCCESS; } +DEFUN (ip_pim_spt_switchover_infinity, + ip_pim_spt_switchover_infinity_cmd, + "ip pim spt-switchover infinity-and-beyond", + IP_STR + PIM_STR + "SPT-Switchover\n" + "Never switch to SPT Tree\n") +{ + pimg->spt_switchover = PIM_SPT_INFINITY; + + pim_upstream_remove_lhr_star_pimreg(); + return CMD_SUCCESS; +} + +DEFUN (no_ip_pim_spt_switchover_infinity, + no_ip_pim_spt_switchover_infinity_cmd, + "no ip pim spt-switchover infinity-and-beyond", + NO_STR + IP_STR + PIM_STR + "SPT_Switchover\n" + "Never switch to SPT Tree\n") +{ + pimg->spt_switchover = PIM_SPT_IMMEDIATE; + + pim_upstream_add_lhr_star_pimreg(); + return CMD_SUCCESS; +} + DEFUN (ip_pim_joinprune_time, ip_pim_joinprune_time_cmd, "ip pim join-prune-interval <60-600>", @@ -6187,6 +6216,8 @@ void pim_cmd_init() install_element (CONFIG_NODE, &ip_pim_ssm_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_spt_switchover_infinity_cmd); + install_element (CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_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); diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index e1697960e4..ebd36f8782 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -1006,7 +1006,8 @@ pim_ifchannel_local_membership_add(struct interface *ifp, pim_upstream_switch (child, PIM_UPSTREAM_JOINED); } } - pim_channel_add_oif(up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); + if (pimg->spt_switchover != PIM_SPT_INFINITY) + pim_channel_add_oif(up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); } return 1; diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 3e81aaf496..5743dac654 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1676,6 +1676,42 @@ pim_upstream_sg_running (void *arg) return; } +void +pim_upstream_add_lhr_star_pimreg (void) +{ + struct pim_upstream *up; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, node, up)) + { + if (up->sg.src.s_addr != INADDR_ANY) + continue; + + if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags)) + continue; + + pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); + } +} + +void +pim_upstream_remove_lhr_star_pimreg (void) +{ + struct pim_upstream *up; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, node, up)) + { + if (up->sg.src.s_addr != INADDR_ANY) + continue; + + if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags)) + continue; + + pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); + } +} + void pim_upstream_init (void) { diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 94bc5a55b9..a1af4483ac 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -198,4 +198,7 @@ void pim_upstream_terminate (void); void join_timer_start (struct pim_upstream *up); int pim_upstream_compare (void *arg1, void *arg2); void pim_upstream_register_reevaluate (void); + +void pim_upstream_add_lhr_star_pimreg (void); +void pim_upstream_remove_lhr_star_pimreg (void); #endif /* PIM_UPSTREAM_H */ diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index f4bfcc5ce0..3d52dc9c41 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -182,6 +182,12 @@ int pim_global_config_write(struct vty *vty) ssm->plist_name, VTY_NEWLINE); ++writes; } + if (pimg->spt_switchover == PIM_SPT_INFINITY) + { + vty_out (vty, "ip pim spt-switchover infinity-and-beyond%s", + VTY_NEWLINE); + ++writes; + } if (qpim_ssmpingd_list) { struct listnode *node; diff --git a/pimd/pimd.c b/pimd/pimd.c index bdbd251e20..eaef4ff5c0 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -249,6 +249,7 @@ pim_instance_init (vrf_id_t vrf_id, afi_t afi) pim->vrf_id = vrf_id; pim->afi = afi; + pim->spt_switchover = PIM_SPT_IMMEDIATE; pim->rpf_hash = hash_create_size (256, pim_rpf_hash_key, pim_rpf_equal); if (PIM_DEBUG_ZEBRA) diff --git a/pimd/pimd.h b/pimd/pimd.h index 69aee28f8f..6c3dcfafca 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -237,11 +237,19 @@ extern int32_t qpim_register_probe_time; #define PIM_DONT_DEBUG_MSDP_PACKETS (qpim_debugs &= ~PIM_MASK_MSDP_PACKETS) #define PIM_DONT_DEBUG_MSDP_INTERNAL (qpim_debugs &= ~PIM_MASK_MSDP_INTERNAL) +enum pim_spt_switchover { + PIM_SPT_IMMEDIATE, + PIM_SPT_INFINITY, +}; + /* Per VRF PIM DB */ struct pim_instance { afi_t afi; vrf_id_t vrf_id; + + enum pim_spt_switchover spt_switchover; + struct hash *rpf_hash; void *ssm_info; /* per-vrf SSM configuration */ }; From 856377cc390301751fa2d4111f6f66cd75b59ec2 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 5 Apr 2017 23:08:19 -0400 Subject: [PATCH 19/53] lib: Fix missing help strings Signed-off-by: Donald Sharp --- lib/distribute.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/distribute.c b/lib/distribute.c index 01c338f177..f85994c9a8 100644 --- a/lib/distribute.c +++ b/lib/distribute.c @@ -254,6 +254,7 @@ DEFUN (distribute_list, distribute_list_cmd, "distribute-list [prefix] WORD [WORD]", "Filter networks in routing updates\n" + "Specify a prefix\n" "Access-list name\n" "Filter incoming routing updates\n" "Filter outgoing routing updates\n" @@ -316,7 +317,9 @@ DEFUN (no_distribute_list, no_distribute_list_cmd, "no [ipv6] distribute-list [prefix] WORD [WORD]", NO_STR + "IPv6\n" "Filter networks in routing updates\n" + "Specify a prefix\n" "Access-list name\n" "Filter incoming routing updates\n" "Filter outgoing routing updates\n" From fa35a883c1d627cac5516d7b751341d5934688b6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 5 Apr 2017 23:18:12 -0400 Subject: [PATCH 20/53] *: Switchover to 3.0 Signed-off-by: Donald Sharp --- configure.ac | 2 +- debian/changelog | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 6eac0e3c86..6661f45d7c 100755 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ ## AC_PREREQ(2.60) -AC_INIT(frr, 2.1-dev, [https://github.com/frrouting/frr/issues]) +AC_INIT(frr, 3.0, [https://github.com/frrouting/frr/issues]) PACKAGE_URL="https://frrouting.org/" PACKAGE_FULLNAME="FRRouting" AC_SUBST(PACKAGE_FULLNAME) diff --git a/debian/changelog b/debian/changelog index 8302af4b4c..fe4ee6b334 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,24 @@ +frr (3.0) Released; urgency=medium + + * New Enabled: BGP Shutdown Message + * New Enabled: BGP Large Community + * New Enabled: BGP RFC 7432 Partial Support w/ Ethernet VPN + * New Enabled: BGP EVPN RT-5 + * New Enabled: LDP RFC 5561 + * New Enabled: LDP RFC 5918 + * New Enabled: LDP RFC 5919 + * New Enabled: LDP RFC 6667 + * New Enabled: LDP RFC 7473 + * New Enabled: OSPF RFC 4552 + * New Enabled: ISIS SPF Backoff draft + * New Enabled: PIM Unnumbered Interfaces + * New Enabled: PIM RFC 4611 + * New Enabled: PIM Sparse Mode + * New Enabled: NHRP RFC 2332 + * New Enabled: Label Manager + + -- frr Wed, 5 Apr 2017 22:23:42 -0500 + frr (2.1) Released; urgency=medium * Switchover to FRR From 4952d0f0b0c30021242fe9d33e8e09015fd26161 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 5 Apr 2017 23:18:12 -0400 Subject: [PATCH 21/53] *: Switchover to 3.1-dev Signed-off-by: Donald Sharp --- configure.ac | 2 +- debian/changelog | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index b4a3e37fd2..822c032fe6 100755 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ ## AC_PREREQ(2.60) -AC_INIT(frr, 2.1-dev, [https://github.com/frrouting/frr/issues]) +AC_INIT(frr, 3.1-dev, [https://github.com/frrouting/frr/issues]) PACKAGE_URL="https://frrouting.org/" PACKAGE_FULLNAME="FRRouting" AC_SUBST(PACKAGE_FULLNAME) diff --git a/debian/changelog b/debian/changelog index 8302af4b4c..4ea86929fc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,30 @@ +frr (3.1-dev) Released; urgency=medium + + * New Enabled: PIM draft Unnumbered + + -- frr Wed, 5 Apr 2017 22:29:42 -0500 + +frr (3.0) Released; urgency=medium + + * New Enabled: BGP Shutdown Message + * New Enabled: BGP Large Community + * New Enabled: BGP RFC 7432 Partial Support w/ Ethernet VPN + * New Enabled: BGP EVPN RT-5 + * New Enabled: LDP RFC 5561 + * New Enabled: LDP RFC 5918 + * New Enabled: LDP RFC 5919 + * New Enabled: LDP RFC 6667 + * New Enabled: LDP RFC 7473 + * New Enabled: OSPF RFC 4552 + * New Enabled: ISIS SPF Backoff draft + * New Enabled: PIM Unnumbered Interfaces + * New Enabled: PIM RFC 4611 + * New Enabled: PIM Sparse Mode + * New Enabled: NHRP RFC 2332 + * New Enabled: Label Manager + + -- frr Wed, 5 Apr 2017 22:23:42 -0500 + frr (2.1) Released; urgency=medium * Switchover to FRR From cba444817883b8b3b22a7ed9958dc9ed77f76230 Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Wed, 5 Apr 2017 13:14:12 -0700 Subject: [PATCH 22/53] pimd: Pim Nexthop Tracking support with ECMP In this patch, PIM nexthop tracking uses locally populated nexthop cached list to determine ECMP based nexthop (w/ ECMP knob enabled), otherwise picks the first nexthop as RPF. Introduced '[no] ip pim ecmp' command to enable/disable PIM ECMP knob. By default, PIM ECMP is disabled. Intorudced '[no] ip pim ecmp rebalance' command to provide existing mcache entry to switch new path based on hash chosen path. Introduced, show command to display pim registered addresses and respective nexthops. Introuduce, show command to find nexthop and out interface for (S,G) or (RP,G). Re-Register an address with nexthop when Interface UP event received, to ensure the PIM nexthop cache is updated (being PIM enabled). During PIM neighbor UP, traverse all RPs and Upstreams nexthop and determine, if any of nexthop's IPv4 address changes/resolves due to neigbor UP event. Testing Done: Run various LHR, RP and FHR related cases to resolve RPF using nexthop cache with ECMP knob disabled, performed interface/PIM neighbor flap events. Executed pim-smoke with knob disabled. Signed-off-by: Chirag Shah --- pimd/pim_cmd.c | 216 ++++++++++++++++- pimd/pim_iface.c | 45 +++- pimd/pim_mroute.c | 12 +- pimd/pim_neighbor.c | 14 ++ pimd/pim_nht.c | 561 ++++++++++++++++++++++++++++++++++++++------ pimd/pim_nht.h | 13 +- pimd/pim_oil.c | 4 +- pimd/pim_register.c | 9 + pimd/pim_rp.c | 174 ++++++++++++-- pimd/pim_rp.h | 2 +- pimd/pim_rpf.c | 69 ++++-- pimd/pim_upstream.c | 22 +- pimd/pim_zebra.c | 168 ++++++++++--- pimd/pimd.c | 4 +- pimd/pimd.h | 3 + 15 files changed, 1143 insertions(+), 173 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 3c5a16ec68..6af072f32f 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -26,6 +26,8 @@ #include "prefix.h" #include "zclient.h" #include "plist.h" +#include "hash.h" +#include "nexthop.h" #include "pimd.h" #include "pim_mroute.h" @@ -55,6 +57,7 @@ #include "pim_zlookup.h" #include "pim_msdp.h" #include "pim_ssm.h" +#include "pim_nht.h" static struct cmd_node pim_global_node = { PIM_NODE, @@ -2059,6 +2062,50 @@ static void pim_show_rpf(struct vty *vty, u_char uj) } } +static int +pim_print_pnc_cache_walkcb (struct hash_backet *backet, void *arg) +{ + struct pim_nexthop_cache *pnc = backet->data; + struct vty *vty = arg; + struct nexthop *nh_node = NULL; + ifindex_t first_ifindex; + struct interface *ifp = NULL; + + if (!pnc) + return CMD_SUCCESS; + + for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) + { + first_ifindex = nh_node->ifindex; + ifp = if_lookup_by_index (first_ifindex, VRF_DEFAULT); + + vty_out (vty, "%-15s ", inet_ntoa (pnc->rpf.rpf_addr.u.prefix4)); + vty_out (vty, "%-14s ", ifp ? ifp->name : "NULL"); + vty_out (vty, "%s ", inet_ntoa (nh_node->gate.ipv4)); + vty_out (vty, "%s", VTY_NEWLINE); + } + return CMD_SUCCESS; +} + +static void +pim_show_nexthop (struct vty *vty) +{ + + if (pimg && !pimg->rpf_hash) + { + vty_out (vty, "no nexthop cache %s", VTY_NEWLINE); + return; + } + + vty_out (vty, "Number of registered addresses: %lu %s", + pimg->rpf_hash->count, VTY_NEWLINE); + vty_out (vty, "Address Interface Nexthop%s", VTY_NEWLINE); + vty_out (vty, "-------------------------------------------%s", VTY_NEWLINE); + + hash_walk (pimg->rpf_hash, pim_print_pnc_cache_walkcb, vty); + +} + static void igmp_show_groups(struct vty *vty, u_char uj) { struct listnode *ifnode; @@ -2793,6 +2840,99 @@ DEFUN (show_ip_pim_rpf, return CMD_SUCCESS; } +DEFUN (show_ip_pim_nexthop, + show_ip_pim_nexthop_cmd, + "show ip pim nexthop", + SHOW_STR + IP_STR + PIM_STR + "PIM cached nexthop rpf information\n") +{ + pim_show_nexthop (vty); + + return CMD_SUCCESS; +} + +DEFUN (show_ip_pim_nexthop_lookup, + show_ip_pim_nexthop_lookup_cmd, + "show ip pim nexthop-lookup A.B.C.D A.B.C.D", + SHOW_STR + IP_STR + PIM_STR + "PIM cached nexthop rpf lookup\n" + "Source/RP address\n" + "Multicast Group address\n") +{ + struct pim_nexthop_cache pnc; + struct prefix nht_p; + int result = 0; + struct in_addr src_addr, grp_addr; + struct in_addr vif_source; + const char *addr_str, *addr_str1; + struct prefix grp; + struct pim_nexthop nexthop; + char nexthop_addr_str[PREFIX_STRLEN]; + char grp_str[PREFIX_STRLEN]; + + addr_str = (const char *)argv[0]; + result = inet_pton (AF_INET, addr_str, &src_addr); + if (result <= 0) + { + vty_out (vty, "Bad unicast address %s: errno=%d: %s%s", + addr_str, errno, safe_strerror (errno), VTY_NEWLINE); + return CMD_WARNING; + } + + if (pim_is_group_224_4 (src_addr)) + { + vty_out (vty, "Invalid argument. Expected Valid Source Address.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + addr_str1 = (const char *)argv[1]; + result = inet_pton (AF_INET, addr_str1, &grp_addr); + if (result <= 0) + { + vty_out (vty, "Bad unicast address %s: errno=%d: %s%s", + addr_str, errno, safe_strerror (errno), VTY_NEWLINE); + return CMD_WARNING; + } + + if (!pim_is_group_224_4 (grp_addr)) + { + vty_out (vty, "Invalid argument. Expected Valid Multicast Group Address.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (!pim_rp_set_upstream_addr (&vif_source, src_addr, grp_addr)) + return CMD_SUCCESS; + + memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = vif_source; + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = grp_addr; + memset (&nexthop, 0, sizeof (nexthop)); + + if ((pim_find_or_track_nexthop (&nht_p, NULL, NULL, &pnc)) == 1) + { + //Compute PIM RPF using Cached nexthop + pim_ecmp_nexthop_search (&pnc, &nexthop, &nht_p, &grp, 0); + } + else + pim_ecmp_nexthop_lookup (&nexthop, vif_source, &nht_p, &grp, 0); + + pim_addr_dump ("", &grp, grp_str, sizeof (grp_str)); + pim_addr_dump ("", &nexthop.mrib_nexthop_addr, + nexthop_addr_str, sizeof (nexthop_addr_str)); + vty_out (vty, "Group %s --- Nexthop %s Interface %s %s", grp_str, + nexthop_addr_str, nexthop.interface->name, VTY_NEWLINE); + + return CMD_SUCCESS; +} + static void show_multicast_interfaces(struct vty *vty) { struct listnode *node; @@ -2871,15 +3011,17 @@ DEFUN (show_ip_multicast, PIM_MAX_USABLE_VIFS, VTY_NEWLINE); - vty_out(vty, "%s", VTY_NEWLINE); - vty_out(vty, "Upstream Join Timer: %d secs%s", - qpim_t_periodic, - VTY_NEWLINE); - vty_out(vty, "Join/Prune Holdtime: %d secs%s", - PIM_JP_HOLDTIME, - VTY_NEWLINE); + vty_out (vty, "%s", VTY_NEWLINE); + vty_out (vty, "Upstream Join Timer: %d secs%s", + qpim_t_periodic, VTY_NEWLINE); + vty_out (vty, "Join/Prune Holdtime: %d secs%s", + PIM_JP_HOLDTIME, VTY_NEWLINE); + vty_out (vty, "PIM ECMP: %s%s", + qpim_ecmp_enable ? "Enable" : "Disable", VTY_NEWLINE); + vty_out (vty, "PIM ECMP Rebalance: %s%s", + qpim_ecmp_rebalance_enable ? "Enable" : "Disable", VTY_NEWLINE); - vty_out(vty, "%s", VTY_NEWLINE); + vty_out (vty, "%s", VTY_NEWLINE); show_rpf_refresh_stats(vty, now, NULL); @@ -3826,6 +3968,58 @@ DEFUN (no_ip_ssmpingd, return CMD_SUCCESS; } +DEFUN (ip_pim_ecmp, + ip_pim_ecmp_cmd, + "ip pim ecmp", + IP_STR + "pim multicast routing\n" + "Enable PIM ECMP \n") +{ + qpim_ecmp_enable = 1; + + return CMD_SUCCESS; +} + +DEFUN (no_ip_pim_ecmp, + no_ip_pim_ecmp_cmd, + "no ip pim ecmp", + NO_STR + IP_STR + "pim multicast routing\n" + "Disable PIM ECMP \n") +{ + qpim_ecmp_enable = 0; + + return CMD_SUCCESS; +} + +DEFUN (ip_pim_ecmp_rebalance, + ip_pim_ecmp_rebalance_cmd, + "ip pim ecmp rebalance", + IP_STR + "pim multicast routing\n" + "Enable PIM ECMP \n" + "Enable PIM ECMP Rebalance\n") +{ + qpim_ecmp_rebalance_enable = 1; + + return CMD_SUCCESS; +} + +DEFUN (no_ip_pim_ecmp_rebalance, + no_ip_pim_ecmp_rebalance_cmd, + "no ip pim ecmp rebalance", + NO_STR + IP_STR + "pim multicast routing\n" + "Disable PIM ECMP \n" + "Disable PIM ECMP Rebalance\n") +{ + qpim_ecmp_rebalance_enable = 0; + + return CMD_SUCCESS; +} + static int pim_cmd_igmp_start (struct vty *vty, struct interface *ifp) { @@ -6191,6 +6385,10 @@ void pim_cmd_init() 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 (CONFIG_NODE, &ip_pim_ecmp_cmd); + install_element (CONFIG_NODE, &no_ip_pim_ecmp_cmd); + install_element (CONFIG_NODE, &ip_pim_ecmp_rebalance_cmd); + install_element (CONFIG_NODE, &no_ip_pim_ecmp_rebalance_cmd); install_element (INTERFACE_NODE, &interface_ip_igmp_cmd); install_element (INTERFACE_NODE, &interface_no_ip_igmp_cmd); @@ -6246,6 +6444,8 @@ 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_debugging_pim_cmd); + install_element (VIEW_NODE, &show_ip_pim_nexthop_cmd); + install_element (VIEW_NODE, &show_ip_pim_nexthop_lookup_cmd); install_element (ENABLE_NODE, &clear_ip_interfaces_cmd); install_element (ENABLE_NODE, &clear_ip_igmp_interfaces_cmd); diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 0864796431..bdad1c531c 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -30,6 +30,7 @@ #include "hash.h" #include "pimd.h" +#include "pim_zebra.h" #include "pim_iface.h" #include "pim_igmp.h" #include "pim_mroute.h" @@ -42,6 +43,7 @@ #include "pim_time.h" #include "pim_ssmpingd.h" #include "pim_rp.h" +#include "pim_nht.h" struct interface *pim_regiface = NULL; struct list *pim_ifchannel_list = NULL; @@ -583,21 +585,40 @@ void pim_if_addr_add(struct connected *ifc) } } /* igmp */ - if (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)) { + 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); - } - } + /* 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); + } + } + struct pim_nexthop_cache *pnc = NULL; + struct pim_rpf rpf; + struct zclient *zclient = NULL; - } - } /* pim */ + zclient = pim_zebra_zclient_get (); + /* RP config might come prior to (local RP's interface) IF UP event. + In this case, pnc would not have pim enabled nexthops. + Once Interface is UP and pim info is available, reregister + with RNH address to receive update and add the interface as nexthop. */ + memset (&rpf, 0, sizeof (struct pim_rpf)); + rpf.rpf_addr.family = AF_INET; + rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN; + rpf.rpf_addr.u.prefix4 = ifc->address->u.prefix4; + pnc = pim_nexthop_cache_find (&rpf); + if (pnc) + pim_sendmsg_zebra_rnh (zclient, pnc, + ZEBRA_NEXTHOP_REGISTER); + } + } /* pim */ /* PIM or IGMP is enabled on interface, and there is at least one diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 2fb243b9bd..23f08efc04 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -178,6 +178,15 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg up->channel_oil->cc.pktcnt++; PIM_UPSTREAM_FLAG_SET_FHR(up->flags); + // resolve mfcc_parent prior to mroute_add in channel_add_oif + if (up->channel_oil->oil.mfcc_parent >= MAXVIFS) + { + int vif_index = 0; + vif_index = + pim_if_find_vifindex_by_ifindex (up->rpf.source_nexthop. + interface->ifindex); + up->channel_oil->oil.mfcc_parent = vif_index; + } pim_register_join (up); return 0; @@ -858,9 +867,8 @@ int pim_mroute_del (struct channel_oil *c_oil, const char *name) pim_channel_oil_dump (c_oil, buf, sizeof(buf))); } - /*reset incoming vifi and kernel installed flags*/ + //Reset kernel installed flag c_oil->installed = 0; - c_oil->oil.mfcc_parent = MAXVIFS; return 0; } diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index c1325df260..71d7ac4148 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -502,6 +502,12 @@ struct pim_neighbor *pim_neighbor_add(struct interface *ifp, listnode_add(pim_ifp->pim_neighbor_list, neigh); + if (PIM_DEBUG_PIM_TRACE_DETAIL) + { + char str[INET_ADDRSTRLEN]; + pim_inet4_dump("", source_addr, str, sizeof (str)); + zlog_debug ("%s: neighbor %s added ", __PRETTY_FUNCTION__, str); + } /* RFC 4601: 4.3.2. DR Election @@ -532,6 +538,14 @@ struct pim_neighbor *pim_neighbor_add(struct interface *ifp, pim_upstream_find_new_rpf(); + /* RNH can send nexthop update prior to PIM neibhor UP + in that case nexthop cache would not consider this neighbor + as RPF. + Upon PIM neighbor UP, iterate all RPs and update + nexthop cache with this neighbor. + */ + pim_resolve_rp_nh (); + pim_rp_setup (); pim_neighbor_rpf_update(); diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index fe96d01a06..23efd554ea 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -39,12 +39,13 @@ #include "pim_join.h" #include "pim_jp_agg.h" #include "pim_zebra.h" +#include "pim_zlookup.h" /** * pim_sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister * command to Zebra. */ -static void +void pim_sendmsg_zebra_rnh (struct zclient *zclient, struct pim_nexthop_cache *pnc, int command) { @@ -87,9 +88,9 @@ pim_sendmsg_zebra_rnh (struct zclient *zclient, struct pim_nexthop_cache *pnc, { char buf[PREFIX2STR_BUFFER]; prefix2str (p, buf, sizeof (buf)); - zlog_debug ("%s: NHT Addr %s %sregistered with Zebra ret:%d ", - __PRETTY_FUNCTION__, buf, - (command == ZEBRA_NEXTHOP_REGISTER) ? " " : "de", ret); + zlog_debug ("%s: NHT %sregistered addr %s with Zebra ret:%d ", + __PRETTY_FUNCTION__, + (command == ZEBRA_NEXTHOP_REGISTER) ? " " : "de", buf, ret); } return; @@ -149,7 +150,8 @@ pim_nexthop_cache_add (struct pim_rpf *rpf_addr) /* This API is used to Register an address with Zebra */ int pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up, - struct rp_info *rp) + struct rp_info *rp, + struct pim_nexthop_cache *out_pnc) { struct pim_nexthop_cache *pnc = NULL; struct pim_rpf rpf; @@ -174,11 +176,14 @@ pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up, } pnc = pim_nexthop_cache_add (&rpf); if (pnc) - pim_sendmsg_zebra_rnh (zclient, pnc, - ZEBRA_NEXTHOP_REGISTER); + pim_sendmsg_zebra_rnh (zclient, pnc, ZEBRA_NEXTHOP_REGISTER); else { - zlog_warn ("%s: pnc node allocation failed. ", __PRETTY_FUNCTION__); + char rpf_str[PREFIX_STRLEN]; + pim_addr_dump ("", addr, rpf_str, sizeof (rpf_str)); + zlog_warn ("%s: pnc node allocation failed. addr %s ", + __PRETTY_FUNCTION__, rpf_str); + return -1; } } @@ -192,7 +197,7 @@ pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up, char rp_str[PREFIX_STRLEN]; pim_addr_dump ("", &rp->rp.rpf_addr, rp_str, sizeof (rp_str)); - zlog_debug ("%s: NHT add RP %s node to cached list", + zlog_debug ("%s: Add RP %s node to pnc cached list", __PRETTY_FUNCTION__, rp_str); } listnode_add_sort (pnc->rp_list, rp); @@ -209,15 +214,18 @@ pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up, char buf[PREFIX2STR_BUFFER]; prefix2str (addr, buf, sizeof (buf)); zlog_debug - ("%s: NHT add upstream %s node to cached list, rpf %s", + ("%s: Add upstream %s node to pnc cached list, rpf %s", __PRETTY_FUNCTION__, up->sg_str, buf); } listnode_add_sort (pnc->upstream_list, up); } } - if (CHECK_FLAG (pnc->flags, PIM_NEXTHOP_VALID)) - return 1; + if (pnc && CHECK_FLAG (pnc->flags, PIM_NEXTHOP_VALID)) + { + memcpy (out_pnc, pnc, sizeof (struct pim_nexthop_cache)); + return 1; + } return 0; } @@ -249,8 +257,7 @@ pim_delete_tracked_nexthop (struct prefix *addr, struct pim_upstream *up, if (pnc->rp_list->count == 0 && pnc->upstream_list->count == 0) { - pim_sendmsg_zebra_rnh (zclient, pnc, - ZEBRA_NEXTHOP_UNREGISTER); + pim_sendmsg_zebra_rnh (zclient, pnc, ZEBRA_NEXTHOP_UNREGISTER); list_delete (pnc->rp_list); list_delete (pnc->upstream_list); @@ -277,21 +284,16 @@ pim_update_rp_nh (struct pim_nexthop_cache *pnc) 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) - zlog_debug ("Unable to lookup nexthop for rp specified"); - ret++; - continue; - } + //Compute PIM RPF using cached nexthop + pim_ecmp_nexthop_search (pnc, &rp_info->rp.source_nexthop, + &rp_info->rp.rpf_addr, &rp_info->group, 1); if (PIM_DEBUG_TRACE) { char rp_str[PREFIX_STRLEN]; pim_addr_dump ("", &rp_info->rp.rpf_addr, rp_str, sizeof (rp_str)); - zlog_debug ("%s: NHT update nexthop for RP %s to interface %s ", + zlog_debug ("%s: NHT update, nexthop for RP %s is interface %s ", __PRETTY_FUNCTION__, rp_str, rp_info->rp.source_nexthop.interface->name); } @@ -304,6 +306,48 @@ pim_update_rp_nh (struct pim_nexthop_cache *pnc) } +/* This API is used to traverse nexthop cache of RPF addr + of upstream entry whose IPv4 nexthop address is in + unresolved state and due to event like pim neighbor + UP event if it can be resolved. +*/ +void +pim_resolve_upstream_nh (struct prefix *nht_p) +{ + struct nexthop *nh_node = NULL; + struct pim_nexthop_cache pnc; + struct pim_neighbor *nbr = NULL; + + memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); + if ((pim_find_or_track_nexthop (nht_p, NULL, NULL, &pnc)) == 1) + { + for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) + { + if (nh_node->gate.ipv4.s_addr == 0) + { + nbr = + pim_neighbor_find_if (if_lookup_by_index + (nh_node->ifindex, VRF_DEFAULT)); + if (nbr) + { + nh_node->gate.ipv4 = nbr->source_addr; + if (PIM_DEBUG_TRACE) + { + char str[PREFIX_STRLEN]; + char str1[INET_ADDRSTRLEN]; + pim_inet4_dump ("", nbr->source_addr, str1, + sizeof (str1)); + pim_addr_dump ("", nht_p, str, sizeof (str)); + zlog_debug + ("%s: addr %s new nexthop addr %s ifindex %d ", + __PRETTY_FUNCTION__, str, str1, nh_node->ifindex); + } + } + } + } + } +} + /* Update Upstream nexthop info based on Nexthop update received from Zebra.*/ static int pim_update_upstream_nh (struct pim_nexthop_cache *pnc) @@ -312,8 +356,8 @@ pim_update_upstream_nh (struct pim_nexthop_cache *pnc) struct listnode *ifnode; struct listnode *up_nextnode; struct listnode *node; - struct pim_upstream *up; - struct interface *ifp; + struct pim_upstream *up = NULL; + struct interface *ifp = NULL; int vif_index = 0; for (ALL_LIST_ELEMENTS (pnc->upstream_list, up_node, up_nextnode, up)) @@ -326,6 +370,26 @@ pim_update_upstream_nh (struct pim_nexthop_cache *pnc) if (rpf_result == PIM_RPF_FAILURE) continue; + /* update kernel multicast forwarding cache (MFC) */ + if (up->channel_oil) + { + vif_index = + pim_if_find_vifindex_by_ifindex (up->rpf. + source_nexthop.interface-> + ifindex); + /* Pass Current selected NH vif index to mroute download */ + if (vif_index) + pim_scan_individual_oil (up->channel_oil, vif_index); + else + { + if (PIM_DEBUG_ZEBRA) + zlog_debug + ("%s: NHT upstream %s channel_oil IIF %s vif_index is not valid", + __PRETTY_FUNCTION__, up->sg_str, + up->rpf.source_nexthop.interface->name); + } + } + if (rpf_result == PIM_RPF_CHANGED) { struct pim_neighbor *nbr; @@ -377,7 +441,7 @@ pim_update_upstream_nh (struct pim_nexthop_cache *pnc) returning PIM_RPF_CHANGED ? */ pim_upstream_update_join_desired (up); - } /* PIM_RPF_CHANGED */ + } /* PIM_RPF_CHANGED */ if (PIM_DEBUG_TRACE) { @@ -386,26 +450,7 @@ pim_update_upstream_nh (struct pim_nexthop_cache *pnc) old.source_nexthop.interface->name, up->rpf.source_nexthop.interface->name); } - /* update kernel multicast forwarding cache (MFC) */ - if (up->channel_oil) - { - vif_index = - pim_if_find_vifindex_by_ifindex (up->rpf. - source_nexthop.interface-> - ifindex); - /* Pass Current selected NH vif index to mroute download */ - if (vif_index) - pim_scan_individual_oil (up->channel_oil, vif_index); - else - { - if (PIM_DEBUG_ZEBRA) - zlog_debug ("%s: NHT upstream %s channel_oil IIF %s vif_index is not valid", - __PRETTY_FUNCTION__, up->sg_str, - up->rpf.source_nexthop.interface->name); - } - } - - } /* for (pnc->upstream_list) */ + } /* for (pnc->upstream_list) */ for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) if (ifp->info) @@ -426,10 +471,209 @@ pim_update_upstream_nh (struct pim_nexthop_cache *pnc) return 0; } -/* - * This API is used to parse Registered address nexthop update - * coming from Zebra - */ +uint32_t +pim_compute_ecmp_hash (struct prefix * src, struct prefix * grp) +{ + uint32_t hash_val; + uint32_t s = 0, g = 0; + + if ((!src)) + return 0; + + switch (src->family) + { + case AF_INET: + { + s = src->u.prefix4.s_addr; + s = s == 0 ? 1 : s; + if (grp) + g = grp->u.prefix4.s_addr; + } + break; + default: + break; + } + + hash_val = jhash_2words (g, s, 101); + if (PIM_DEBUG_TRACE) + { + char buf[PREFIX2STR_BUFFER]; + char bufg[PREFIX2STR_BUFFER]; + prefix2str (src, buf, sizeof (buf)); + if (grp) + prefix2str (grp, bufg, sizeof (bufg)); + zlog_debug ("%s: addr %s %s hash_val %u", __PRETTY_FUNCTION__, buf, + grp ? bufg : "", hash_val); + + } + return hash_val; +} + +int +pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc, + struct pim_nexthop *nexthop, struct prefix *src, + struct prefix *grp, int neighbor_needed) +{ + struct pim_neighbor *nbr = NULL; + struct nexthop *nh_node = NULL; + ifindex_t first_ifindex; + struct interface *ifp = NULL; + uint32_t hash_val = 0, mod_val = 0; + uint8_t nh_iter = 0, found = 0; + + if (!pnc || !pnc->nexthop_num || !nexthop) + return -1; + + if (qpim_ecmp_enable) + { + //User configured knob to explicitly switch to new path. + if (qpim_ecmp_rebalance_enable == 0) + { + //Current Nexthop is VALID then stay on the current path. + if (nexthop->interface && nexthop->interface->info && + nexthop->mrib_nexthop_addr.u.prefix4.s_addr != + PIM_NET_INADDR_ANY) + { + if (neighbor_needed + && !pim_if_connected_to_source (nexthop->interface, + src->u.prefix4)) + { + nbr = pim_neighbor_find (nexthop->interface, + nexthop->mrib_nexthop_addr. + u.prefix4); + if (!nbr && !if_is_loopback (nexthop->interface)) + { + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: current nexthop does not have nbr ", + __PRETTY_FUNCTION__); + } + else + { + if (PIM_DEBUG_TRACE) + { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump ("", src->u.prefix4, src_str, + sizeof (src_str)); + char grp_str[INET_ADDRSTRLEN]; + pim_inet4_dump ("", grp->u.prefix4, grp_str, + sizeof (grp_str)); + zlog_debug + ("%s: %s %s current nexthop %d is valid, not choosing new path", + __PRETTY_FUNCTION__, src_str, grp_str, + nexthop->interface->ifindex); + } + return 0; + } + } + } + } + //PIM ECMP flag is enable then choose ECMP path. + hash_val = pim_compute_ecmp_hash (src, grp); + mod_val = hash_val % pnc->nexthop_num; + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: hash_val %u mod_val %u ", + __PRETTY_FUNCTION__, hash_val, mod_val); + } + + for (nh_node = pnc->nexthop; nh_node && (found == 0); + nh_node = nh_node->next) + { + first_ifindex = nh_node->ifindex; + ifp = if_lookup_by_index (first_ifindex, VRF_DEFAULT); + if (!ifp) + { + if (PIM_DEBUG_ZEBRA) + { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump ("", src->u.prefix4, 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); + } + if (nh_iter == mod_val) + mod_val++; //Select nexthpath + nh_iter++; + continue; + } + if (!ifp->info) + { + if (PIM_DEBUG_ZEBRA) + { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump ("", src->u.prefix4, 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 (nh_iter == mod_val) + mod_val++; //Select nexthpath + nh_iter++; + continue; + } + + if (neighbor_needed + && !pim_if_connected_to_source (ifp, src->u.prefix4)) + { + nbr = pim_neighbor_find (ifp, nh_node->gate.ipv4); + if (PIM_DEBUG_PIM_TRACE_DETAIL) + zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr); + if (!nbr && !if_is_loopback (ifp)) + { + if (PIM_DEBUG_ZEBRA) + zlog_debug + ("%s: pim nbr not found on input interface %s", + __PRETTY_FUNCTION__, ifp->name); + if (nh_iter == mod_val) + mod_val++; //Select nexthpath + nh_iter++; + continue; + } + } + + if (nh_iter == mod_val) + { + nexthop->interface = ifp; + nexthop->mrib_nexthop_addr.family = AF_INET; + nexthop->mrib_nexthop_addr.prefixlen = IPV4_MAX_BITLEN; + nexthop->mrib_nexthop_addr.u.prefix4 = nh_node->gate.ipv4; + nexthop->mrib_metric_preference = pnc->distance; + nexthop->mrib_route_metric = pnc->metric; + nexthop->last_lookup = src->u.prefix4; + nexthop->last_lookup_time = pim_time_monotonic_usec (); + nexthop->nbr = nbr; + found = 1; + + if (PIM_DEBUG_ZEBRA) + { + char buf[NEXTHOP_STRLEN]; + char buf2[PREFIX2STR_BUFFER]; + char buf3[PREFIX2STR_BUFFER]; + char buf4[PREFIX2STR_BUFFER]; + pim_inet4_dump ("", src->u.prefix4, buf2, sizeof (buf2)); + if (grp) + pim_inet4_dump ("", grp->u.prefix4, buf3, + sizeof (buf3)); + pim_inet4_dump ("", + nexthop->mrib_nexthop_addr.u.prefix4, buf4, + sizeof (buf4)); + snprintf (buf, sizeof (buf), "%s if %u", + inet_ntoa (nh_node->gate.ipv4), nh_node->ifindex); + zlog_debug + ("%s: NHT %s %s selected nhop interface %s nhop %s (%s) mod_val:%u iter:%d ecmp_enable:%d", + __PRETTY_FUNCTION__, buf2, grp ? buf3 : " ", ifp->name, + buf, buf4, mod_val, nh_iter, qpim_ecmp_enable); + } + } + nh_iter++; + + } + + return 0; +} + +/* This API is used to parse Registered address nexthop update coming from Zebra */ int pim_parse_nexthop_update (int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) @@ -437,7 +681,6 @@ pim_parse_nexthop_update (int command, struct zclient *zclient, struct stream *s; struct prefix p; struct nexthop *nexthop; - struct nexthop *oldnh; struct nexthop *nhlist_head = NULL; struct nexthop *nhlist_tail = NULL; uint32_t metric, distance; @@ -476,8 +719,9 @@ pim_parse_nexthop_update (int command, struct zclient *zclient, { char buf[PREFIX2STR_BUFFER]; prefix2str (&rpf.rpf_addr, buf, sizeof (buf)); - zlog_debug ("%s: NHT addr %s is not in local cached DB.", - __PRETTY_FUNCTION__, buf); + zlog_debug + ("%s: Skipping NHT update, addr %s is not in local cached DB.", + __PRETTY_FUNCTION__, buf); } return 0; } @@ -490,7 +734,7 @@ pim_parse_nexthop_update (int command, struct zclient *zclient, return 0; } - pnc->last_update = pim_time_monotonic_sec (); + pnc->last_update = pim_time_monotonic_usec (); distance = stream_getc (s); metric = stream_getl (s); nexthop_num = stream_getc (s); @@ -499,17 +743,15 @@ pim_parse_nexthop_update (int command, struct zclient *zclient, { char buf[PREFIX2STR_BUFFER]; prefix2str (&p, buf, sizeof (buf)); - zlog_debug ("%s: NHT Update for %s nexthop_num %d vrf:%d upcount %d rpcount %d", - __PRETTY_FUNCTION__, buf, nexthop_num, vrf_id, - listcount (pnc->upstream_list), listcount (pnc->rp_list)); + zlog_debug + ("%s: NHT Update for %s nexthop_num %d vrf:%d upcount %d rpcount %d", + __PRETTY_FUNCTION__, buf, nexthop_num, vrf_id, + listcount (pnc->upstream_list), listcount (pnc->rp_list)); } if (nexthop_num) { - pnc->flags |= PIM_NEXTHOP_VALID; - pnc->distance = distance; - pnc->metric = metric; - pnc->nexthop_num = nexthop_num; + pnc->nexthop_num = 0; //Only increment for pim enabled rpf. for (i = 0; i < nexthop_num; i++) { @@ -539,7 +781,34 @@ pim_parse_nexthop_update (int command, struct zclient *zclient, (nexthop->ifindex, VRF_DEFAULT)); /* Overwrite with Nbr address as NH addr */ if (nbr) - nexthop->gate.ipv4 = nbr->source_addr; + { + nexthop->gate.ipv4 = nbr->source_addr; + if (PIM_DEBUG_TRACE) + { + char str[INET_ADDRSTRLEN]; + pim_inet4_dump ("", nbr->source_addr, str, + sizeof (str)); + zlog_debug + ("%s: NHT using pim nbr addr %s ifindex %d as rpf", + __PRETTY_FUNCTION__, str, nexthop->ifindex); + } + } + else + { + if (PIM_DEBUG_TRACE) + { + struct interface *ifp1 = + if_lookup_by_index (nexthop->ifindex, + VRF_DEFAULT); + struct pim_interface *pim_ifp = ifp1->info; + zlog_debug + ("%s: NHT pim nbr not found on interface %s nbr count:%d ", + __PRETTY_FUNCTION__, ifp1->name, + pim_ifp->pim_neighbor_list->count); + } + //Mark nexthop address to 0 until PIM Nbr is resolved. + nexthop->gate.ipv4.s_addr = PIM_NET_INADDR_ANY; + } break; default: @@ -562,9 +831,10 @@ pim_parse_nexthop_update (int command, struct zclient *zclient, if (PIM_DEBUG_ZEBRA) { char buf[NEXTHOP_STRLEN]; - zlog_debug("%s: could not find interface for ifindex %d (addr %s)", - __PRETTY_FUNCTION__, - nexthop->ifindex, nexthop2str (nexthop, buf, sizeof (buf))); + zlog_debug + ("%s: could not find interface for ifindex %d (addr %s)", + __PRETTY_FUNCTION__, nexthop->ifindex, + nexthop2str (nexthop, buf, sizeof (buf))); } nexthop_free (nexthop); continue; @@ -594,14 +864,18 @@ pim_parse_nexthop_update (int command, struct zclient *zclient, nhlist_tail = nexthop; nhlist_head = nexthop; } - - for (oldnh = pnc->nexthop; oldnh; oldnh = oldnh->next) - if (nexthop_same_no_recurse (oldnh, nexthop)) - break; + //Only keep track of nexthops which are PIM enabled. + pnc->nexthop_num++; } /* Reset existing pnc->nexthop before assigning new list */ nexthops_free (pnc->nexthop); pnc->nexthop = nhlist_head; + if (pnc->nexthop_num) + { + pnc->flags |= PIM_NEXTHOP_VALID; + pnc->distance = distance; + pnc->metric = metric; + } } else { @@ -611,6 +885,16 @@ pim_parse_nexthop_update (int command, struct zclient *zclient, pnc->nexthop = NULL; } + if (PIM_DEBUG_TRACE) + { + char buf[PREFIX2STR_BUFFER]; + prefix2str (&p, buf, sizeof (buf)); + zlog_debug + ("%s: NHT Update for %s nexthop_num:%d pim nexthop_num %d vrf:%d up %d rp %d", + __PRETTY_FUNCTION__, buf, nexthop_num, pnc->nexthop_num, vrf_id, + listcount (pnc->upstream_list), listcount (pnc->rp_list)); + } + pim_rpf_set_refresh_time (); if (listcount (pnc->rp_list)) @@ -620,3 +904,142 @@ pim_parse_nexthop_update (int command, struct zclient *zclient, return 0; } + +int +pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr, + struct prefix *src, struct prefix *grp, + int neighbor_needed) +{ + struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; + struct pim_neighbor *nbr = NULL; + int num_ifindex; + struct interface *ifp; + int first_ifindex; + int found = 0; + uint8_t i = 0; + uint32_t hash_val = 0, mod_val = 0; + + 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", + __PRETTY_FUNCTION__, addr_str, nexthop->last_lookup_time); + } + + 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); + 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); + return -1; + } + + //If PIM ECMP enable then choose ECMP path + if (qpim_ecmp_enable) + { + hash_val = pim_compute_ecmp_hash (src, grp); + mod_val = hash_val % num_ifindex; + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: hash_val %u mod_val %u ", + __PRETTY_FUNCTION__, hash_val, mod_val); + } + + while (!found && (i < num_ifindex)) + { + first_ifindex = nexthop_tab[i].ifindex; + + ifp = if_lookup_by_index (first_ifindex, VRF_DEFAULT); + if (!ifp) + { + 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 interface for ifindex %d (address %s)", + __FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str); + } + if (i == mod_val) + mod_val++; + i++; + continue; + } + + if (!ifp->info) + { + 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); + } + if (i == mod_val) + mod_val++; + i++; + continue; + } + if (neighbor_needed && !pim_if_connected_to_source (ifp, addr)) + { + nbr = + pim_neighbor_find (ifp, nexthop_tab[i].nexthop_addr.u.prefix4); + if (PIM_DEBUG_PIM_TRACE_DETAIL) + zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr); + if (!nbr && !if_is_loopback (ifp)) + { + if (i == mod_val) + mod_val++; + i++; + if (PIM_DEBUG_ZEBRA) + { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump ("", addr, addr_str, + sizeof (addr_str)); + zlog_debug + ("%s: NBR not found on input interface %s (RPF for source %s)", + __PRETTY_FUNCTION__, ifp->name, addr_str); + } + continue; + } + } + + if (i == mod_val) + { + if (PIM_DEBUG_ZEBRA) + { + char nexthop_str[PREFIX_STRLEN]; + char addr_str[INET_ADDRSTRLEN]; + 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 addr %s interface %s metric=%d pref=%d", + __FILE__, __PRETTY_FUNCTION__, nexthop_str, addr_str, + ifp->name, nexthop_tab[i].route_metric, + nexthop_tab[i].protocol_distance); + } + /* update nextop data */ + nexthop->interface = ifp; + 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(); + nexthop->nbr = nbr; + found = 1; + } + i++; + } + if (found) + return 0; + else + return -1; +} diff --git a/pimd/pim_nht.h b/pimd/pim_nht.h index 5348ec3704..b4b2d91e47 100644 --- a/pimd/pim_nht.h +++ b/pimd/pim_nht.h @@ -51,10 +51,19 @@ struct pim_nexthop_cache int pim_parse_nexthop_update (int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id); int pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up, - struct rp_info *rp); + struct rp_info *rp, struct pim_nexthop_cache *out_pnc); void pim_delete_tracked_nexthop (struct prefix *addr, struct pim_upstream *up, struct rp_info *rp); struct pim_nexthop_cache *pim_nexthop_cache_add (struct pim_rpf *rpf_addr); struct pim_nexthop_cache *pim_nexthop_cache_find (struct pim_rpf *rpf); - +uint32_t pim_compute_ecmp_hash (struct prefix *src, struct prefix *grp); +int pim_ecmp_nexthop_search (struct pim_nexthop_cache * pnc, + struct pim_nexthop *nexthop, struct prefix *src, + struct prefix *grp, int neighbor_needed); +int pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr, + struct prefix *src, struct prefix *grp, + int neighbor_needed); +void pim_sendmsg_zebra_rnh (struct zclient *zclient, struct pim_nexthop_cache *pnc, + int command); +void pim_resolve_upstream_nh (struct prefix *nht_p); #endif diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 2701079053..2d4aa3febc 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -289,10 +289,10 @@ pim_channel_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_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d", + zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u IIF:%d OIF=%s vif_index=%d", __FILE__, __PRETTY_FUNCTION__, source_str, group_str, - proto_mask, oif->name, pim_ifp->mroute_vif_index); + proto_mask, channel_oil->oil.mfcc_parent ,oif->name, pim_ifp->mroute_vif_index); } return 0; diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 65a3e8714f..12f8dd53f2 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -187,6 +187,15 @@ pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct return; } + if (PIM_DEBUG_PIM_REG) + { + char rp_str[INET_ADDRSTRLEN]; + strcpy (rp_str, inet_ntoa (rpg->rpf_addr.u.prefix4)); + zlog_debug ("%s: Sending %s %sRegister Packet to %s on %s", + __PRETTY_FUNCTION__, up->sg_str, + null_register ? "NULL " : "", rp_str, ifp->name); + } + memset(buffer, 0, 10000); b1 = buffer + PIM_MSG_HEADER_LEN; *b1 |= null_register << 6; diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 78bbd14405..ec31069eb5 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -30,6 +30,7 @@ #include "vty.h" #include "vrf.h" #include "plist.h" +#include "nexthop.h" #include "pimd.h" #include "pim_vty.h" @@ -280,7 +281,7 @@ pim_rp_check_interfaces (struct rp_info *rp_info) int pim_rp_new (const char *rp, const char *group_range, const char *plist) { - int result; + int result, ret = 0; struct rp_info *rp_info; struct rp_info *rp_all; struct prefix group_all; @@ -288,6 +289,7 @@ pim_rp_new (const char *rp, const char *group_range, const char *plist) struct rp_info *tmp_rp_info; char buffer[BUFSIZ]; struct prefix nht_p; + struct pim_nexthop_cache pnc; rp_info = XCALLOC (MTYPE_PIM_RP, sizeof (*rp_info)); if (!rp_info) @@ -387,21 +389,31 @@ pim_rp_new (const char *rp, const char *group_range, const char *plist) /* Register addr with Zebra NHT */ nht_p.family = AF_INET; nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = rp_all->rp.rpf_addr.u.prefix4; + nht_p.u.prefix4 = rp_all->rp.rpf_addr.u.prefix4; //RP address if (PIM_DEBUG_PIM_TRACE) { char buf[PREFIX2STR_BUFFER]; + char buf1[PREFIX2STR_BUFFER]; prefix2str (&nht_p, buf, sizeof (buf)); - zlog_debug ("%s: NHT Register rp_all addr %s with NHT ", - __PRETTY_FUNCTION__, buf); + prefix2str (&rp_all->group, buf1, sizeof (buf1)); + zlog_debug ("%s: NHT Register rp_all addr %s grp %s ", + __PRETTY_FUNCTION__, buf, buf1); + } + memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); + if ((ret = + pim_find_or_track_nexthop (&nht_p, NULL, rp_all, &pnc)) == 1) + { + //Compute PIM RPF using Cached nexthop + pim_ecmp_nexthop_search (&pnc, &rp_all->rp.source_nexthop, + &nht_p, &rp_all->group, 1); + } + else + { + if (pim_nexthop_lookup (&rp_all->rp.source_nexthop, rp_all->rp.rpf_addr.u.prefix4, 1) != 0) + return PIM_RP_NO_PATH; } - pim_find_or_track_nexthop (&nht_p, NULL, rp_all); - - 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); - pim_rp_refresh_group_to_rp_mapping(); + pim_rp_refresh_group_to_rp_mapping (); return PIM_SUCCESS; } @@ -451,13 +463,25 @@ pim_rp_new (const char *rp, const char *group_range, const char *plist) if (PIM_DEBUG_PIM_TRACE) { char buf[PREFIX2STR_BUFFER]; + char buf1[PREFIX2STR_BUFFER]; prefix2str (&nht_p, buf, sizeof (buf)); - zlog_debug ("%s: NHT Register RP addr %s with Zebra ", __PRETTY_FUNCTION__, buf); + prefix2str (&rp_info->group, buf1, sizeof (buf1)); + zlog_debug ("%s: NHT Register RP addr %s grp %s with Zebra ", + __PRETTY_FUNCTION__, buf, buf1); } - pim_find_or_track_nexthop (&nht_p, NULL, rp_info); - if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1) != 0) - return PIM_RP_NO_PATH; + memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); + if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1) + { + //Compute PIM RPF using Cached nexthop + pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop, + &nht_p, &rp_info->group, 1); + } + else + { + 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); pim_rp_refresh_group_to_rp_mapping (); @@ -509,7 +533,8 @@ pim_rp_del (const char *rp, const char *group_range, const char *plist) { char buf[PREFIX2STR_BUFFER]; prefix2str (&nht_p, buf, sizeof (buf)); - zlog_debug ("%s: Deregister RP addr %s with NHT ", __PRETTY_FUNCTION__, buf); + zlog_debug ("%s: Deregister RP addr %s with Zebra ", __PRETTY_FUNCTION__, + buf); } pim_delete_tracked_nexthop (&nht_p, NULL, rp_info); @@ -535,17 +560,39 @@ pim_rp_setup (void) struct listnode *node; struct rp_info *rp_info; int ret = 0; + struct prefix nht_p; + struct pim_nexthop_cache pnc; 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) + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; + memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); + if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1) { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("Unable to lookup nexthop for rp specified"); - ret++; + //Compute PIM RPF using Cached nexthop + pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop, + &nht_p, &rp_info->group, 1); + } + else + { + if (PIM_DEBUG_ZEBRA) + { + char buf[PREFIX2STR_BUFFER]; + prefix2str (&nht_p, buf, sizeof (buf)); + zlog_debug ("%s: NHT Local Nexthop not found for RP %s ", + __PRETTY_FUNCTION__, buf); + } + if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1) != 0) + { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug ("Unable to lookup nexthop for rp specified"); + ret++; + } } } @@ -680,7 +727,43 @@ 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, 1); + int ret = 0; + struct prefix nht_p; + struct pim_nexthop_cache pnc; + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; + if (PIM_DEBUG_PIM_TRACE) + { + char buf[PREFIX2STR_BUFFER]; + char buf1[PREFIX2STR_BUFFER]; + prefix2str (&nht_p, buf, sizeof (buf)); + prefix2str (&rp_info->group, buf1, sizeof (buf1)); + zlog_debug ("%s: NHT Register RP addr %s grp %s with Zebra ", + __PRETTY_FUNCTION__, buf, buf1); + } + memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); + if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1) + { + //Compute PIM RPF using Cached nexthop + pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop, + &nht_p, &rp_info->group, 1); + } + else + { + if (PIM_DEBUG_ZEBRA) + { + char buf[PREFIX2STR_BUFFER]; + char buf1[PREFIX2STR_BUFFER]; + prefix2str (&nht_p, buf, sizeof (buf)); + prefix2str (&g, buf1, sizeof (buf1)); + zlog_debug ("%s: NHT nexthop cache not found for RP %s grp %s", + __PRETTY_FUNCTION__, buf, buf1); + } + pim_rpf_set_refresh_time (); + pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1); + } return (&rp_info->rp); } @@ -862,3 +945,54 @@ pim_rp_show_information (struct vty *vty, u_char uj) json_object_free(json); } } + +void +pim_resolve_rp_nh (void) +{ + struct listnode *node = NULL; + struct rp_info *rp_info = NULL; + struct nexthop *nh_node = NULL; + struct prefix nht_p; + struct pim_nexthop_cache pnc; + struct pim_neighbor *nbr = NULL; + + for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) + { + if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) + continue; + + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; + memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); + if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1) + { + for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) + { + if (nh_node->gate.ipv4.s_addr == 0) + { + nbr = + pim_neighbor_find_if (if_lookup_by_index + (nh_node->ifindex, VRF_DEFAULT)); + if (nbr) + { + nh_node->gate.ipv4 = nbr->source_addr; + if (PIM_DEBUG_TRACE) + { + char str[PREFIX_STRLEN]; + char str1[INET_ADDRSTRLEN]; + pim_inet4_dump ("", nbr->source_addr, + str1, sizeof (str1)); + pim_addr_dump ("", &nht_p, str, + sizeof (str)); + zlog_debug + ("%s: addr %s new nexthop addr %s ifindex %d ", + __PRETTY_FUNCTION__, str, str1, + nh_node->ifindex); + } + } + } + } + } + } +} diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index 84ab9be482..df18c998d6 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -61,6 +61,6 @@ struct pim_rpf *pim_rp_g (struct in_addr group); #define RP(G) pim_rp_g ((G)) void pim_rp_show_information (struct vty *vty, u_char uj); - +void pim_resolve_rp_nh (void); int pim_rp_list_cmp (void *v1, void *v2); #endif diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 400048738a..0f5fab0d93 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -67,11 +67,14 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei { 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", + char nexthop_str[PREFIX_STRLEN]; + pim_addr_dump("", &nexthop->mrib_nexthop_addr, + nexthop_str, sizeof(nexthop_str)); + zlog_debug ("%s: Using last lookup for %s at %lld, %lld addr%s", __PRETTY_FUNCTION__, addr_str, nexthop->last_lookup_time, - last_route_change_time); + last_route_change_time, nexthop_str); } nexthop_lookups_avoided++; return 0; @@ -190,32 +193,56 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, struct pim_rpf *rpf = &up->rpf; struct pim_rpf saved; struct prefix nht_p; + struct pim_nexthop_cache pnc; + int ret = 0; + struct prefix src, grp; saved.source_nexthop = rpf->source_nexthop; saved.rpf_addr = rpf->rpf_addr; - if (is_new) + if (is_new && PIM_DEBUG_ZEBRA) { - if (PIM_DEBUG_ZEBRA) - { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", up->upstream_addr, source_str, sizeof(source_str)); - zlog_debug ("%s: NHT Register upstream %s addr %s with Zebra.", - __PRETTY_FUNCTION__, up->sg_str, source_str); - } - /* Register addr with Zebra NHT */ - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; - pim_find_or_track_nexthop (&nht_p, up, NULL); + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump ("", up->upstream_addr, source_str, + sizeof (source_str)); + zlog_debug ("%s: NHT Register upstream %s addr %s with Zebra.", + __PRETTY_FUNCTION__, up->sg_str, source_str); } + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; - if (pim_nexthop_lookup(&rpf->source_nexthop, - up->upstream_addr, - !PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) && - !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags))) { - return PIM_RPF_FAILURE; - } + src.family = AF_INET; + src.prefixlen = IPV4_MAX_BITLEN; + src.u.prefix4 = up->upstream_addr; //RP or Src address + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = up->sg.grp; + memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); + if ((ret = pim_find_or_track_nexthop (&nht_p, up, NULL, &pnc)) == 1) + { + if (pnc.nexthop_num) + { + //Compute PIM RPF using Cached nexthop + pim_ecmp_nexthop_search (&pnc, &up->rpf.source_nexthop, + &src, &grp, + !PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) && + !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up-> + flags)); + } + } + else + { + if (pim_ecmp_nexthop_lookup (&rpf->source_nexthop, + up->upstream_addr, &src, &grp, + !PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) && + !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up-> + flags))) + { + return PIM_RPF_FAILURE; + } + } rpf->rpf_addr.family = AF_INET; rpf->rpf_addr.u.prefix4 = pim_rpf_find_rpf_addr(up); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 172d0d21c9..c9c2795762 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -227,8 +227,8 @@ pim_upstream_del(struct pim_upstream *up, const char *name) { char buf[PREFIX2STR_BUFFER]; prefix2str (&nht_p, buf, sizeof (buf)); - zlog_debug ("%s: Deregister upstream %s upstream addr %s with NHT ", - __PRETTY_FUNCTION__, up->sg_str, buf); + zlog_debug ("%s: Deregister upstream %s addr %s with Zebra", + __PRETTY_FUNCTION__, up->sg_str, buf); } pim_delete_tracked_nexthop (&nht_p, up, NULL); @@ -694,10 +694,12 @@ 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); - + if (up->rpf.source_nexthop.interface) + { + 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) @@ -768,10 +770,14 @@ 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", + { + char buf[PREFIX2STR_BUFFER]; + prefix2str (&up->rpf.rpf_addr, buf, sizeof (buf)); + zlog_debug("%s(%s): %s, iif %s found: %d: ref_count: %d", __PRETTY_FUNCTION__, name, - up->sg_str, found, + up->sg_str, buf, found, up->ref_count); + } else zlog_debug("%s(%s): (%s) failure to create", __PRETTY_FUNCTION__, name, diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 4e18c478d6..80e7d77642 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -372,6 +372,12 @@ static void scan_upstream_rpf_cache() for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { enum pim_rpf_result rpf_result; struct pim_rpf old; + struct prefix nht_p; + + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; + pim_resolve_upstream_nh (&nht_p); old.source_nexthop.interface = up->rpf.source_nexthop.interface; old.source_nexthop.nbr = up->rpf.source_nexthop.nbr; @@ -574,7 +580,8 @@ 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 (); + //It is called as part of pim_neighbor_add + //pim_rp_setup (); return 0; } @@ -836,6 +843,7 @@ void igmp_source_forward_start(struct igmp_source *source) struct igmp_group *group; struct prefix_sg sg; int result; + int input_iface_vif_index = 0; memset (&sg, 0, sizeof (struct prefix_sg)); sg.src = source->source_addr; @@ -861,11 +869,61 @@ void igmp_source_forward_start(struct igmp_source *source) if (!source->source_channel_oil) { struct in_addr vif_source; struct pim_interface *pim_oif; + struct prefix nht_p, src, grp; + int ret = 0; + struct pim_nexthop_cache out_pnc; + struct pim_nexthop nexthop; 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); + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = vif_source; + memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache)); + + if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1) + { + if (out_pnc.nexthop_num) + { + src.family = AF_INET; + src.prefixlen = IPV4_MAX_BITLEN; + src.u.prefix4 = vif_source; //RP or Src address + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = sg.grp; + memset (&nexthop, 0, sizeof (nexthop)); + //Compute PIM RPF using Cached nexthop + pim_ecmp_nexthop_search (&out_pnc, &nexthop, + &src, &grp, 0); + if (nexthop.interface) + input_iface_vif_index = pim_if_find_vifindex_by_ifindex (nexthop.interface->ifindex); + } + else + { + if (PIM_DEBUG_ZEBRA) + { + char buf1[INET_ADDRSTRLEN]; + char buf2[INET_ADDRSTRLEN]; + pim_inet4_dump("", nht_p.u.prefix4, buf1, sizeof(buf1)); + pim_inet4_dump("", grp.u.prefix4, buf2, sizeof(buf2)); + zlog_debug ("%s: NHT Nexthop not found for addr %s grp %s" , + __PRETTY_FUNCTION__, buf1, buf2); + } + } + } + else + input_iface_vif_index = fib_lookup_if_vif_index(vif_source); + + if (PIM_DEBUG_ZEBRA) + { + char buf2[INET_ADDRSTRLEN]; + pim_inet4_dump("", vif_source, buf2, sizeof(buf2)); + zlog_debug ("%s: NHT %s vif_source %s vif_index:%d ", __PRETTY_FUNCTION__, + pim_str_sg_dump (&sg), buf2, input_iface_vif_index); + } + if (input_iface_vif_index < 1) { if (PIM_DEBUG_IGMP_TRACE) { @@ -1013,49 +1071,105 @@ void pim_forward_start(struct pim_ifchannel *ch) { struct pim_upstream *up = ch->upstream; uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; + int input_iface_vif_index = 0; if (PIM_DEBUG_PIM_TRACE) { char source_str[INET_ADDRSTRLEN]; - char group_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)); pim_inet4_dump("", up->upstream_addr, upstream_str, sizeof(upstream_str)); - zlog_debug("%s: (S,G)=(%s,%s) oif=%s(%s)", + zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__, source_str, group_str, ch->interface->name, upstream_str); } - if (!up->channel_oil) { - int input_iface_vif_index = fib_lookup_if_vif_index(up->upstream_addr); - if (input_iface_vif_index < 1) { - 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; - } + /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS, + as part of mroute_del called by pim_forward_stop. + */ + if (!up->channel_oil || + (up->channel_oil && up->channel_oil->oil.mfcc_parent >= MAXVIFS)) + { + struct prefix nht_p, src, grp; + int ret = 0; + struct pim_nexthop_cache out_pnc; + struct pim_nexthop nexthop; - up->channel_oil = pim_channel_oil_add(&up->sg, - input_iface_vif_index); - if (!up->channel_oil) { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug("%s %s: could not create OIL for channel (S,G)=%s", - __FILE__, __PRETTY_FUNCTION__, - up->sg_str); - return; + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = up->sg.grp; + memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache)); + + if ((ret = + pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1) + { + if (out_pnc.nexthop_num) + { + src.family = AF_INET; + src.prefixlen = IPV4_MAX_BITLEN; + src.u.prefix4 = up->upstream_addr; //RP or Src address + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = up->sg.grp; + memset (&nexthop, 0, sizeof (nexthop)); + //Compute PIM RPF using Cached nexthop + pim_ecmp_nexthop_search (&out_pnc, &nexthop, &src, &grp, 0); + input_iface_vif_index = + pim_if_find_vifindex_by_ifindex (nexthop.interface->ifindex); + } + else + { + if (PIM_DEBUG_ZEBRA) + { + char buf1[INET_ADDRSTRLEN]; + char buf2[INET_ADDRSTRLEN]; + pim_inet4_dump("", nht_p.u.prefix4, buf1, sizeof(buf1)); + pim_inet4_dump("", grp.u.prefix4, buf2, sizeof(buf2)); + zlog_debug ("%s: NHT pnc is NULL for addr %s grp %s" , + __PRETTY_FUNCTION__, buf1, buf2); + } + } + } + else + input_iface_vif_index = fib_lookup_if_vif_index (up->upstream_addr); + + if (input_iface_vif_index < 1) + { + 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; + } + if (PIM_DEBUG_TRACE) + { + zlog_debug ("%s: NHT entry %s update channel_oil vif_index %d ", + __PRETTY_FUNCTION__, up->sg_str, input_iface_vif_index); + } + up->channel_oil = pim_channel_oil_add (&up->sg, input_iface_vif_index); + if (!up->channel_oil) + { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug ("%s %s: could not create OIL for channel (S,G)=%s", + __FILE__, __PRETTY_FUNCTION__, up->sg_str); + return; + } } - } if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) mask = PIM_OIF_FLAG_PROTO_IGMP; - pim_channel_add_oif(up->channel_oil, ch->interface, mask); + pim_channel_add_oif (up->channel_oil, ch->interface, mask); } void pim_forward_stop(struct pim_ifchannel *ch) diff --git a/pimd/pimd.c b/pimd/pimd.c index bdbd251e20..653856665c 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -75,7 +75,9 @@ 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; -struct pim_instance *pimg = NULL; +uint8_t qpim_ecmp_enable = 0; +uint8_t qpim_ecmp_rebalance_enable = 0; +struct pim_instance *pimg = NULL; 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 69aee28f8f..d1ada02203 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -155,6 +155,9 @@ struct list *qpim_static_route_list; /* list of routes added static extern unsigned int qpim_keep_alive_time; extern signed int qpim_rp_keep_alive_time; extern int qpim_packet_process; +extern uint8_t qpim_ecmp_enable; +extern uint8_t qpim_ecmp_rebalance_enable; + #define PIM_DEFAULT_PACKET_PROCESS 3 #define PIM_JP_HOLDTIME (qpim_t_periodic * 7 / 2) From 4390fb9991e78d759c25ffc23be378c8b9242614 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 6 Apr 2017 17:57:24 -0400 Subject: [PATCH 23/53] pimd: Fix various sizeof and buffer length issues Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 12 ++++++++---- pimd/pim_tlv.c | 2 +- pimd/pim_zlookup.c | 8 ++++++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 627971d3f9..0478dc1b48 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -830,7 +830,9 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch 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(prefix2str(&sec_addr->addr, pbuf, PREFIX2STR_BUFFER))); + json_object_new_string(prefix2str(&sec_addr->addr, + pbuf, + sizeof(pbuf)))); } json_object_object_add(json_row, "secondaryAddressList", sec_list); } @@ -926,7 +928,9 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch inet_ntoa(ifaddr), VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) { vty_out(vty, " %s%s", - prefix2str(&sec_addr->addr, pbuf, PREFIX2STR_BUFFER), VTY_NEWLINE); + prefix2str(&sec_addr->addr, + pbuf, + sizeof(pbuf)), VTY_NEWLINE); } } else { vty_out(vty, "Address : %s%s", inet_ntoa(ifaddr), VTY_NEWLINE); @@ -1611,9 +1615,9 @@ 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[PREFIX2STR_BUFFER]; - prefix2str(p, neigh_sec_str, 100); + prefix2str(p, neigh_sec_str, sizeof(neigh_sec_str)); vty_out(vty, "%-9s %-15s %-15s %-15s%s", ifp->name, diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index 1d58ce3ac6..259ed44c71 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -523,7 +523,7 @@ pim_parse_addr_ucast (struct prefix *p, p->family = AF_INET6; p->prefixlen = IPV6_MAX_PREFIXLEN; - memcpy(&p->u.prefix6, addr, 16); + memcpy(&p->u.prefix6, addr, sizeof(struct in6_addr)); addr += sizeof(struct in6_addr); break; diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 620137b33b..27bd137043 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -252,12 +252,16 @@ static int zclient_read_nexthop(struct zclient *zlookup, 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); + stream_get (&nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, + s, + sizeof(struct in6_addr)); nexthop_tab[num_ifindex].ifindex = stream_getl (s); p.family = AF_INET6; p.prefixlen = IPV6_MAX_PREFIXLEN; - memcpy (&p.u.prefix6, &nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, 16); + memcpy (&p.u.prefix6, + &nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, + sizeof(struct in6_addr)); /* * If we are sending v6 secondary assume we receive v6 secondary From 073845da5e32aa15b9636bcbe7be994e2bd7f8b4 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Fri, 7 Apr 2017 17:40:11 +0000 Subject: [PATCH 24/53] lib: add #pragma's to ignore flex sign cmp error Signed-off-by: Quentin Young --- lib/command_lex.l | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/command_lex.l b/lib/command_lex.l index deec1757c2..c020d193a1 100644 --- a/lib/command_lex.l +++ b/lib/command_lex.l @@ -23,6 +23,9 @@ */ %{ +/* ignore harmless bug in old versions of flex */ +#pragma GCC diagnostic ignored "-Wsign-compare" + #include "command_parse.h" #define YY_USER_ACTION yylloc->last_column += yyleng; From 6be4da3dfac66de52b48d8fb56e24fa35b9a24ea Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 8 Apr 2017 08:47:59 -0400 Subject: [PATCH 25/53] ospfd: Fix the 'show ip ospf int ...' command Fixed output: robot.cumulusnetworks.com# show ip ospf int enp0s3 is up ifindex 2, MTU 1500 bytes, BW 0 Mbit Internet Address 10.0.2.15/24, Broadcast 10.0.2.255, Area 0.0.0.0 MTU mismatch detection:enabled Router ID 192.168.0.1, Network Type BROADCAST, Cost: 10 Transmit Delay is 1 sec, State Waiting, Priority 1 No backup designated router on this network Multicast group memberships: OSPFAllRouters Timer intervals configured, Hello 10s, Dead 40s, Wait 40s, Retransmit 5 Hello due in 9.611s Neighbor Count is 0, Adjacent neighbor count is 0 enp0s10 is up ifindex 7, MTU 1500 bytes, BW 0 Mbit Internet Address 192.168.201.146/24, Broadcast 192.168.201.255, Area 0.0.0.0 MTU mismatch detection:enabled Router ID 192.168.0.1, Network Type BROADCAST, Cost: 10 Transmit Delay is 1 sec, State Waiting, Priority 1 No backup designated router on this network Multicast group memberships: OSPFAllRouters Timer intervals configured, Hello 10s, Dead 40s, Wait 40s, Retransmit 5 Hello due in 7.241s Neighbor Count is 0, Adjacent neighbor count is 0 robot.cumulusnetworks.com# show ip ospf int enp0s3 enp0s3 is up ifindex 2, MTU 1500 bytes, BW 0 Mbit Internet Address 10.0.2.15/24, Broadcast 10.0.2.255, Area 0.0.0.0 MTU mismatch detection:enabled Router ID 192.168.0.1, Network Type BROADCAST, Cost: 10 Transmit Delay is 1 sec, State Waiting, Priority 1 No backup designated router on this network Multicast group memberships: OSPFAllRouters Timer intervals configured, Hello 10s, Dead 40s, Wait 40s, Retransmit 5 Hello due in 2.915s Neighbor Count is 0, Adjacent neighbor count is 0 robot.cumulusnetworks.com# show ip ospf int enp0s10 json { "enp0s10":{ "ifUp":true, "ifIndex":7, "mtuBytes":1500, "bandwidthMbit":0, "ifFlags":"", "ospfEnabled":true, "ipAddress":"192.168.201.146", "ipAddressPrefixlen":24, "ospfIfType":"Broadcast", "localIfUsed":"192.168.201.255", "area":"0.0.0.0", "routerId":"192.168.0.1", "networkType":"BROADCAST", "cost":10, "transmitDelayMsecs":1000, "state":"Waiting", "priority":1, "mcastMemberOspfAllRouters":true, "timerMsecs":100, "timerDeadMsecs":25, "timerWaitMsecs":25, "timerRetransmit":200, "timerHelloInMsecs":2106, "nbrCount":0, "nbrAdjacentCount":0 } } robot.cumulusnetworks.com# Signed-off-by: Donald Sharp --- ospfd/ospf_vty.c | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 49474df826..b4c456e0aa 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -3557,7 +3557,7 @@ show_ip_ospf_interface_common (struct vty *vty, struct ospf *ospf, int argc, VTY_NEWLINE, VTY_NEWLINE); } - if (argc == (iface_argv + 1)) + if (argc == iface_argv) { /* Show All Interfaces.*/ for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) @@ -3570,25 +3570,6 @@ show_ip_ospf_interface_common (struct vty *vty, struct ospf *ospf, int argc, } } } - else if (argv[iface_argv] && strcmp(argv[iface_argv]->arg, "json") == 0) - { - if (!use_json) - { - json = json_object_new_object(); - json_interface_sub = json_object_new_object (); - use_json = 1; - } - /* Show All Interfaces. */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - if (ospf_oi_count(ifp)) - { - show_ip_ospf_interface_sub (vty, ospf, ifp, json_interface_sub, use_json); - if (use_json) - json_object_object_add(json, ifp->name, json_interface_sub); - } - } - } else { /* Interface name is specified. */ @@ -3634,7 +3615,10 @@ DEFUN (show_ip_ospf_interface, if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) return CMD_SUCCESS; - return show_ip_ospf_interface_common(vty, ospf, argc, argv, 0, uj); + if (uj) + argc--; + + return show_ip_ospf_interface_common(vty, ospf, argc, argv, 4, uj); } DEFUN (show_ip_ospf_instance_interface, @@ -3657,7 +3641,10 @@ DEFUN (show_ip_ospf_instance_interface, if ((ospf = ospf_lookup_instance (instance)) == NULL || !ospf->oi_running) return CMD_SUCCESS; - return show_ip_ospf_interface_common(vty, ospf, argc, argv, 1, uj); + if (uj) + argc--; + + return show_ip_ospf_interface_common(vty, ospf, argc, argv, 5, uj); } static void From 08c08a35c6552e90aafcdd857ad17e9beecac61f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 8 Apr 2017 08:55:40 -0400 Subject: [PATCH 26/53] lib: Fix debugs to be guarded. Signed-off-by: Donald Sharp --- lib/zclient.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/lib/zclient.c b/lib/zclient.c index 71b95ae7db..d2a5186315 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1486,7 +1486,9 @@ lm_label_manager_connect (struct zclient *zclient) vrf_id_t vrf_id; u_int16_t cmd; - zlog_debug ("Connecting to Label Manager"); + if (zclient_debug) + zlog_debug ("Connecting to Label Manager"); + if (zclient->sock < 0) return -1; @@ -1518,7 +1520,8 @@ lm_label_manager_connect (struct zclient *zclient) zclient->sock = -1; return -1; } - zlog_debug ("%s: Label manager connect request (%d bytes) sent", __func__, ret); + if (zclient_debug) + zlog_debug ("%s: Label manager connect request (%d bytes) sent", __func__, ret); /* read response */ s = zclient->ibuf; @@ -1532,8 +1535,9 @@ lm_label_manager_connect (struct zclient *zclient) } /* result */ result = stream_getc(s); - zlog_debug ("%s: Label Manager connect response (%d bytes) received, result %u", - __func__, size, result); + if (zclient_debug) + zlog_debug ("%s: Label Manager connect response (%d bytes) received, result %u", + __func__, size, result); return (int)result; } @@ -1564,7 +1568,9 @@ lm_get_label_chunk (struct zclient *zclient, u_char keep, uint32_t chunk_size, u_int16_t cmd; u_char response_keep; - zlog_debug ("Getting Label Chunk"); + if (zclient_debug) + zlog_debug ("Getting Label Chunk"); + if (zclient->sock < 0) return -1; @@ -1594,7 +1600,8 @@ lm_get_label_chunk (struct zclient *zclient, u_char keep, uint32_t chunk_size, zclient->sock = -1; return -1; } - zlog_debug ("%s: Label chunk request (%d bytes) sent", __func__, ret); + if (zclient_debug) + zlog_debug ("%s: Label chunk request (%d bytes) sent", __func__, ret); /* read response */ s = zclient->ibuf; @@ -1606,7 +1613,9 @@ lm_get_label_chunk (struct zclient *zclient, u_char keep, uint32_t chunk_size, zlog_err ("%s: Invalid Get Label Chunk Message Reply Header", __func__); return -1; } - zlog_debug ("%s: Label chunk response (%d bytes) received", __func__, size); + if (zclient_debug) + zlog_debug ("%s: Label chunk response (%d bytes) received", __func__, size); + /* keep */ response_keep = stream_getc(s); /* start and end labels */ @@ -1627,8 +1636,9 @@ lm_get_label_chunk (struct zclient *zclient, u_char keep, uint32_t chunk_size, return -1; } - zlog_debug ("Label Chunk assign: %u - %u (%u) ", - *start, *end, response_keep); + if (zclient_debug) + zlog_debug ("Label Chunk assign: %u - %u (%u) ", + *start, *end, response_keep); return 0; } @@ -1647,7 +1657,9 @@ lm_release_label_chunk (struct zclient *zclient, uint32_t start, uint32_t end) int ret; struct stream *s; - zlog_debug ("Releasing Label Chunk"); + if (zclient_debug) + zlog_debug ("Releasing Label Chunk"); + if (zclient->sock < 0) return -1; From 2caafa8c6f815ae3018ce338c083fd75ff2a9102 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 8 Apr 2017 17:52:57 -0300 Subject: [PATCH 27/53] ripd: fix argv index numbers in the redistribute command Fixes Issue#350 Signed-off-by: Renato Westphal --- ripd/rip_zebra.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index 7fa3baea7e..578c513c78 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -339,7 +339,7 @@ DEFUN (rip_redistribute_type, for(i = 0; redist_type[i].str; i++) { - if (strncmp (redist_type[i].str, argv[2]->arg, + if (strncmp (redist_type[i].str, argv[1]->arg, redist_type[i].str_min_len) == 0) { zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, @@ -348,7 +348,7 @@ DEFUN (rip_redistribute_type, } } - vty_out(vty, "Invalid type %s%s", argv[2]->arg, + vty_out(vty, "Invalid type %s%s", argv[1]->arg, VTY_NEWLINE); return CMD_WARNING; @@ -365,7 +365,7 @@ DEFUN (no_rip_redistribute_type, for (i = 0; redist_type[i].str; i++) { - if (strncmp(redist_type[i].str, argv[3]->arg, + if (strncmp(redist_type[i].str, argv[2]->arg, redist_type[i].str_min_len) == 0) { rip_metric_unset (redist_type[i].type, DONT_CARE_METRIC_RIP); @@ -375,7 +375,7 @@ DEFUN (no_rip_redistribute_type, } } - vty_out(vty, "Invalid type %s%s", argv[3]->arg, + vty_out(vty, "Invalid type %s%s", argv[2]->arg, VTY_NEWLINE); return CMD_WARNING; From d536095fd34c8c14c7bd064dfb8f407256aad373 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Mon, 10 Apr 2017 12:28:45 -0300 Subject: [PATCH 28/53] bgpd: fixes for the "show bgp large-community" command * Fix a segfault when the "show bgp large-community" command is given without any optional large communities; * Fix parsing of optional large communities. Without this fix a "Large-community malformed" error is shown even for valid large communities. Signed-off-by: Renato Westphal --- bgpd/bgp_route.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 1fa3e8bc44..4e87ea1ece 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8171,7 +8171,7 @@ bgp_show_lcommunity (struct vty *vty, struct bgp *bgp, int argc, buffer_putc (b, ' '); else { - if (strmatch (argv[i]->text, "")) + if (strmatch (argv[i]->text, "AA:BB:CC")) { first = 1; buffer_putstr (b, argv[i]->arg); @@ -8187,7 +8187,7 @@ bgp_show_lcommunity (struct vty *vty, struct bgp *bgp, int argc, XFREE (MTYPE_TMP, str); if (! lcom) { - vty_out (vty, "%% Large-community malformed: %s", VTY_NEWLINE); + vty_out (vty, "%% Large-community malformed%s", VTY_NEWLINE); return CMD_WARNING; } @@ -8299,8 +8299,7 @@ DEFUN (show_ip_bgp_large_community, return CMD_WARNING; } - argv_find (argv, argc, "large-community", &idx); - if (strmatch(argv[idx+1]->text, "AA:BB:CC")) + if (argv_find (argv, argc, "AA:BB:CC", &idx)) 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); From b6ab29296fc7dc5b0a6ad0e5345aca3c2c701cba Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 14 Apr 2017 20:13:26 -0400 Subject: [PATCH 29/53] bgpd: Fix 'set as-path prepend last-as 10' 1) Fix missing newline in help string 2) Make the ability to have 10 be consistent with the stable/2.0 branch. Signed-off-by: Donald Sharp --- bgpd/bgp_routemap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index bafc81eaf8..9b5a7a5ebb 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -1437,7 +1437,7 @@ route_set_aspath_prepend_compile (const char *arg) { unsigned int num; - if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num < 10) + if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num <= 10) return (void*)(uintptr_t)num; return route_aspath_compile(arg); @@ -3677,12 +3677,12 @@ DEFUN (set_aspath_prepend_asn, DEFUN (set_aspath_prepend_lastas, set_aspath_prepend_lastas_cmd, - "set as-path prepend last-as (1-9)", + "set as-path prepend last-as (1-10)", SET_STR "Transform BGP AS_PATH attribute\n" "Prepend to the as-path\n" "Use the peer's AS-number\n" - "Number of times to insert") + "Number of times to insert\n") { return set_aspath_prepend_asn (self, vty, argc, argv); } From 5260e25d2000dcd65b9e7f710f20482e1bb9f2df Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 14 Apr 2017 20:39:56 -0400 Subject: [PATCH 30/53] bgpd: 'show .... bgp regexp WORD' fixed The command was always just returning as part of the bgp_regexp_show function. Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 4e87ea1ece..32cf0bcb89 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8562,8 +8562,6 @@ static int bgp_show_regexp (struct vty *vty, const char *regstr, afi_t afi, safi_t safi, enum bgp_show_type type) { - return CMD_SUCCESS; - regex_t *regex; int rc; From 529aa94e24a39e8203efebbaf2fbc9f6de69fa52 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Sat, 15 Apr 2017 06:23:22 +0000 Subject: [PATCH 31/53] pimd: fix off-by-one in `no ip pim rp ...` Signed-off-by: Quentin Young --- pimd/pim_cmd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 0ce2525847..313414159c 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3640,10 +3640,10 @@ DEFUN (no_ip_pim_rp, "ip address of RP\n" "Group Address range to cover\n") { - int idx_ipv4 = 4; + int idx_ipv4 = 4, idx_group = 0; - if (argc == (idx_ipv4 + 1)) - return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL); + if (argv_find (argv, argc, "A.B.C.D/M", &idx_group)) + return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_group]->arg, NULL); else return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, NULL, NULL); } From 6cbc63316b75e72a04e57ffca146e81ee89d645c Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Mon, 17 Apr 2017 00:06:02 +0000 Subject: [PATCH 32/53] lib: add removal by item to pqueue Signed-off-by: Quentin Young --- lib/pqueue.c | 8 ++++++++ lib/pqueue.h | 1 + 2 files changed, 9 insertions(+) diff --git a/lib/pqueue.c b/lib/pqueue.c index 0f870564da..fa502b462a 100644 --- a/lib/pqueue.c +++ b/lib/pqueue.c @@ -188,3 +188,11 @@ pqueue_remove_at (int index, struct pqueue *queue) trickle_down (index, queue); } } + +void +pqueue_remove (void *data, struct pqueue *queue) +{ + for (int i = 0; i < queue->size; i++) + if (queue->array[i] == data) + pqueue_remove_at (i, queue); +} diff --git a/lib/pqueue.h b/lib/pqueue.h index 8bb6961d86..b39fb92ee9 100644 --- a/lib/pqueue.h +++ b/lib/pqueue.h @@ -39,6 +39,7 @@ extern void pqueue_delete (struct pqueue *queue); extern void pqueue_enqueue (void *data, struct pqueue *queue); extern void *pqueue_dequeue (struct pqueue *queue); extern void pqueue_remove_at (int index, struct pqueue *queue); +extern void pqueue_remove (void *data, struct pqueue *queue); extern void trickle_down (int index, struct pqueue *queue); extern void trickle_up (int index, struct pqueue *queue); From 9ea49d61d2ea060c97066f445da65537f034772b Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Mon, 17 Apr 2017 19:21:06 +0000 Subject: [PATCH 33/53] pimd: fix 'show ip msdp sa ...' Signed-off-by: Quentin Young --- pimd/pim_cmd.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 313414159c..2401991b8c 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -6212,13 +6212,16 @@ DEFUN (show_ip_msdp_sa_sg, "JavaScript Object Notation\n") { u_char uj = use_json(argc, argv); - if (uj) - argc--; - if (argc == 5) - ip_msdp_show_sa_sg(vty, argv[4]->arg, argv[5]->arg, uj); - else if (argc == 4) - ip_msdp_show_sa_addr(vty, argv[4]->arg, uj); + int idx = 0; + char *src_ip = argv_find (argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg : NULL; + char *grp_ip = idx < argc && argv_find (argv, argc, "A.B.C.D", &idx) ? + argv[idx]->arg : NULL; + + if (src_ip && grp_ip) + ip_msdp_show_sa_sg(vty, src_ip, grp_ip, uj); + else if (src_ip) + ip_msdp_show_sa_addr(vty, src_ip, uj); else ip_msdp_show_sa(vty, uj); From d2c1e06d83d6793c1de311c099d31cc053a2826e Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Wed, 12 Apr 2017 15:22:41 +0200 Subject: [PATCH 34/53] vtysh: remove deprecated HAVE_EVPN flag This flag prevents from entering into evpn address-family node, when calling command from vtysh. Signed-off-by: Philippe Guibert --- vtysh/vtysh.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index d0038ea3cf..424597c0d0 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -1221,9 +1221,7 @@ DEFUNSH (VTYSH_BGPD, "Layer2 VPN Address family\n" "Ethernet Virtual Private Network Subsequent Address Family\n") { -#if defined(HAVE_EVPN) vty->node = BGP_EVPN_NODE; -#endif /* HAVE_EVPN */ return CMD_SUCCESS; } From f4c14c3a80d690f3fd589a04844c8355a207629e Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Wed, 12 Apr 2017 16:00:43 -0700 Subject: [PATCH 35/53] snapcraft: Improve README.usage.md based on feedback received - Fix snap connect (it's now called core, not ubuntu-core) - Add section on MPLS configuration - Add FAQ topic on ospfd/ospf6d crashing before privs are assigned to snap - Add pointer to official webpage Signed-off-by: Martin Winter --- snapcraft/README.usage.md | 59 +++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/snapcraft/README.usage.md b/snapcraft/README.usage.md index aaff59438a..c678c8805c 100644 --- a/snapcraft/README.usage.md +++ b/snapcraft/README.usage.md @@ -3,7 +3,7 @@ Using the FRRouting Snap After installing the Snap, the priviledged plug need to be connected: - snap connect frr:network-control ubuntu-core:network-control + snap connect frr:network-control core:network-control Enabling/Disabling FRRouting Daemons ------------------------------------------- @@ -53,25 +53,74 @@ depend on them). These are mainly intended to debug the Snap - `frr.ldpd-debug`: Starts ldpd daemon in foreground +MPLS (LDP) +---------- +The MPLS forwarding requires a Linux Kernel version 4.5 or newer and +specific MPLS kernel modules loaded. It will be auto-detected by +FRR. You can check the detected setup with the `show mpls status` +command from within `frr.vtysh` + +The following kernel modules `mpls-router` and `mpls-iptunnel` +need to be loaded. On Ubuntu 16.04, this can be done by editing +'/etc/modules-load.d/modules.conf' and add the following lines: + + # Load MPLS Kernel Modules + mpls-router + mpls-iptunnel + +For other distributions, please check the documentation on loading +modules. You need to either reboot or use `modprobe` to manually load +the modules as well before MPLS will be available. + +In addition to this, the MPLS Label-Processing needs to be enabled +with `sysctl` on the required interfaces. Assuming the interfaces +are named `eth0`, `eth1` and `eth2`, then the additional lines in +`/etc/sysctl.conf` will enable it on a Ubuntu 16.04 system: + + # Enable MPLS Label processing on all interfaces + net.mpls.conf.eth0.input=1 + net.mpls.conf.eth1.input=1 + net.mpls.conf.eth2.input=1 + net.mpls.platform_labels=100000 + +These settings require either a reboot or a manual configuration with +`sysctl` as well. + FAQ --- - frr.vtysh displays `--MORE--` on long output. How to suppress this? - Define `VTYSH_PAGER` to `cat` (default is `more`). (Ie add `export VTYSH_PAGER=cat` to the end of your `.profile`) +- ospfd / ospf6d are not running after installation + - Installing a new snap starts the daemons, but at this time they + may not have the required priviledged access. Make sure you + issue the `snap connect` command as given above (can be verified + with `snap interfaces`) and **THEN** restart the daemons (or + reboot the system). + This is a limitation of any snap package at this time which + requires priviledged interfaces (ie to manipulate routing tables) + Sourcecode available ==================== The source for this SNAP is available as part of the FRRouting -Source Code Distribution. +Source Code Distribution under `GPLv2 or later` - https://github.com/frrouting/frr.git + -Instructions for rebuilding the snap are in `README.snap_build.md` +Instructions for rebuilding the snap are in `snapcraft/README.snap_build.md` + +*Please checkout the desired branch before following the instructions +as they may have changed between versions of FRR* + +Official Webpage for FRR +======================== + +Official webpage for FRR is at Feedback welcome ================ Please send Feedback about this snap to Martin Winter at `mwinter@opensourcerouting.org` - From 6f2a494a8304a8480896de0cfba5b07c15316330 Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Thu, 20 Apr 2017 16:58:24 -0700 Subject: [PATCH 36/53] snapcraft: Update snapcraft requirements for FRR 3.0 (from 2.0) Signed-off-by: Martin Winter --- snapcraft/snapcraft.yaml.in | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/snapcraft/snapcraft.yaml.in b/snapcraft/snapcraft.yaml.in index a20a1d0392..d0a421c62b 100644 --- a/snapcraft/snapcraft.yaml.in +++ b/snapcraft/snapcraft.yaml.in @@ -148,7 +148,6 @@ parts: - gawk - libreadline-dev - texinfo - - dejagnu - libncurses5-dev - texlive-latex-base - texlive-generic-recommended @@ -161,6 +160,10 @@ parts: - chrpath - pkg-config - libjson-c-dev + - libc-ares-dev + - bison + - flex + - python3-dev stage-packages: - coreutils - iproute2 From 5ae4018e5d536c4ca7a34358897e2b7feef64954 Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Thu, 20 Apr 2017 17:24:12 -0700 Subject: [PATCH 37/53] snapcraft: Fix another old leftover of ubuntu-core in build doc Signed-off-by: Martin Winter --- snapcraft/README.snap_build.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/snapcraft/README.snap_build.md b/snapcraft/README.snap_build.md index c4db51bd6a..e1f2ce82da 100644 --- a/snapcraft/README.snap_build.md +++ b/snapcraft/README.snap_build.md @@ -47,8 +47,10 @@ Installing the snap Connect the priviledged `network-control` plug to the snap: - snap connect frr:network-control ubuntu-core:network-control + snap connect frr:network-control core:network-control +See README.usage.md for more details on setting up and using the snap + DONE. The Snap will be auto-started and running. From ae4989487412cc455bfed48a6ceab63423ba5f08 Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Thu, 20 Apr 2017 18:18:40 -0700 Subject: [PATCH 38/53] snapcraft: Add nhrpd to snap Signed-off-by: Martin Winter --- snapcraft/defaults/nhrpd.conf.default | 0 snapcraft/scripts/Makefile | 2 +- snapcraft/scripts/nhrpd-service | 12 ++++++++++++ snapcraft/snapcraft.yaml.in | 18 ++++++++++++++++-- 4 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 snapcraft/defaults/nhrpd.conf.default create mode 100644 snapcraft/scripts/nhrpd-service diff --git a/snapcraft/defaults/nhrpd.conf.default b/snapcraft/defaults/nhrpd.conf.default new file mode 100644 index 0000000000..e69de29bb2 diff --git a/snapcraft/scripts/Makefile b/snapcraft/scripts/Makefile index 00984c2afa..0f9a24b649 100644 --- a/snapcraft/scripts/Makefile +++ b/snapcraft/scripts/Makefile @@ -11,4 +11,4 @@ install: install -D -m 0755 isisd-service $(DESTDIR)/bin/ install -D -m 0755 pimd-service $(DESTDIR)/bin/ install -D -m 0755 ldpd-service $(DESTDIR)/bin/ - + install -D -m 0755 nhrpd-service $(DESTDIR)/bin/ diff --git a/snapcraft/scripts/nhrpd-service b/snapcraft/scripts/nhrpd-service new file mode 100644 index 0000000000..a3ba5e3fe9 --- /dev/null +++ b/snapcraft/scripts/nhrpd-service @@ -0,0 +1,12 @@ +#!/bin/sh + +set -e -x + +if ! [ -e $SNAP_DATA/nhrpd.conf ]; then + cp $SNAP/etc/frr/nhrpd.conf.default $SNAP_DATA/nhrpd.conf +fi +exec $SNAP/sbin/nhrpd \ + -f $SNAP_DATA/nhrpd.conf \ + --pid_file $SNAP_DATA/nhrpd.pid \ + --socket $SNAP_DATA/zsock \ + --vty_socket $SNAP_DATA diff --git a/snapcraft/snapcraft.yaml.in b/snapcraft/snapcraft.yaml.in index d0a421c62b..54a1cfd4f0 100644 --- a/snapcraft/snapcraft.yaml.in +++ b/snapcraft/snapcraft.yaml.in @@ -83,6 +83,13 @@ apps: - network - network-bind - network-control + nhrpd: + command: bin/nhrpd-service + daemon: simple + plugs: + - network + - network-bind + - network-control zebra-debug: command: sbin/zebra -f $SNAP_DATA/zebra.conf --pid_file $SNAP_DATA/zebra.pid --socket $SNAP_DATA/zsock --vty_socket $SNAP_DATA plugs: @@ -132,12 +139,18 @@ apps: - network-bind - network-control ldpd-debug: - command: sbin/ldpd -f $SNAP_DATA/pimd.conf --pid_file $SNAP_DATA/pimd.pid --socket $SNAP_DATA/zsock --ctl_socket $SNAP_DATA --vty_socket $SNAP_DATA + command: sbin/ldpd -f $SNAP_DATA/ldpd.conf --pid_file $SNAP_DATA/ldpd.pid --socket $SNAP_DATA/zsock --ctl_socket $SNAP_DATA --vty_socket $SNAP_DATA plugs: - network - network-bind - network-control - + nhrpd-debug: + command: sbin/nhrpd -f $SNAP_DATA/nhrpd.conf --pid_file $SNAP_DATA/nhrpd.pid --socket $SNAP_DATA/zsock --vty_socket $SNAP_DATA + plugs: + - network + - network-bind + - network-control + parts: frr: build-packages: @@ -215,6 +228,7 @@ parts: ripd.conf.default: etc/frr/ripd.conf.default ripngd.conf.default: etc/frr/ripngd.conf.default ldpd.conf.default: etc/frr/ldpd.conf.default + nhrpd.conf.default: etc/frr/nhrpd.conf.default vtysh.conf.default: etc/frr/vtysh.conf.default frr-scripts: plugin: make From 80b4df3b082f5f51afc0add1f2e59dc5822deef1 Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Thu, 20 Apr 2017 23:03:03 -0700 Subject: [PATCH 39/53] lib: Add CLI option --moduledir to override default module location (needed for snap support) Signed-off-by: Martin Winter --- lib/libfrr.c | 21 ++++++++++++++++++--- lib/libfrr.h | 2 ++ lib/module.c | 6 +++--- lib/module.h | 2 +- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/lib/libfrr.c b/lib/libfrr.c index 64f8be2ca6..de83e14f0e 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -34,6 +34,7 @@ DEFINE_HOOK(frr_late_init, (struct thread_master *tm), (tm)) const char frr_sysconfdir[] = SYSCONFDIR; const char frr_vtydir[] = DAEMON_VTY_DIR; +const char frr_moduledir[] = MODULE_PATH; char config_default[256]; static char pidfile_default[256]; @@ -61,7 +62,8 @@ static void opt_extend(const struct optspec *os) } -#define OPTION_VTYSOCK 1000 +#define OPTION_VTYSOCK 1000 +#define OPTION_MODULEDIR 1002 static const struct option lo_always[] = { { "help", no_argument, NULL, 'h' }, @@ -69,6 +71,7 @@ static const struct option lo_always[] = { { "daemon", no_argument, NULL, 'd' }, { "module", no_argument, NULL, 'M' }, { "vty_socket", required_argument, NULL, OPTION_VTYSOCK }, + { "moduledir", required_argument, NULL, OPTION_MODULEDIR }, { NULL } }; static const struct optspec os_always = { @@ -77,7 +80,8 @@ static const struct optspec os_always = { " -v, --version Print program version\n" " -d, --daemon Runs in daemon mode\n" " -M, --module Load specified module\n" - " --vty_socket Override vty socket path\n", + " --vty_socket Override vty socket path\n" + " --moduledir Override modules directory\n", lo_always }; @@ -193,6 +197,7 @@ struct option_chain { struct option_chain *next; const char *arg; }; + static struct option_chain *modules = NULL, **modnext = &modules; static int errors = 0; @@ -277,6 +282,14 @@ static int frr_opt(int opt) } di->vty_sock_path = optarg; break; + case OPTION_MODULEDIR: + if (di->module_path) { + fprintf(stderr, "----moduledir option specified more than once!\n"); + errors++; + break; + } + di->module_path = optarg; + break; case 'u': if (di->flags & FRR_NO_PRIVSEP) return 1; @@ -319,6 +332,8 @@ struct thread_master *frr_init(void) struct option_chain *oc; struct frrmod_runtime *module; char moderr[256]; + const char *dir; + dir = di->module_path ? di->module_path : frr_moduledir; srandom(time(NULL)); @@ -331,7 +346,7 @@ struct thread_master *frr_init(void) frrmod_init(di->module); while (modules) { modules = (oc = modules)->next; - module = frrmod_load(oc->arg, moderr, sizeof(moderr)); + module = frrmod_load(oc->arg, dir, moderr, sizeof(moderr)); if (!module) { fprintf(stderr, "%s\n", moderr); exit(1); diff --git a/lib/libfrr.h b/lib/libfrr.h index a40fc34892..0cc7ad564b 100644 --- a/lib/libfrr.h +++ b/lib/libfrr.h @@ -52,6 +52,7 @@ struct frr_daemon_info { const char *config_file; const char *pid_file; const char *vty_path; + const char *module_path; const char *proghelp; void (*printhelp)(FILE *target); @@ -107,5 +108,6 @@ extern void frr_run(struct thread_master *master); extern char config_default[256]; extern const char frr_sysconfdir[]; extern const char frr_vtydir[]; +extern const char frr_moduledir[]; #endif /* _ZEBRA_FRR_H */ diff --git a/lib/module.c b/lib/module.c index 4ebe3c0da2..c7dd5538cd 100644 --- a/lib/module.c +++ b/lib/module.c @@ -69,7 +69,7 @@ void frrmod_init(struct frrmod_runtime *modinfo) } struct frrmod_runtime *frrmod_load(const char *spec, - char *err, size_t err_len) + const char *dir, char *err, size_t err_len) { void *handle = NULL; char name[PATH_MAX], fullpath[PATH_MAX], *args; @@ -84,12 +84,12 @@ struct frrmod_runtime *frrmod_load(const char *spec, if (!strchr(name, '/')) { if (!handle && execname) { snprintf(fullpath, sizeof(fullpath), "%s/%s_%s.so", - MODULE_PATH, execname, name); + dir, execname, name); handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL); } if (!handle) { snprintf(fullpath, sizeof(fullpath), "%s/%s.so", - MODULE_PATH, name); + dir, name); handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL); } } diff --git a/lib/module.h b/lib/module.h index cb66e60976..01819f91e1 100644 --- a/lib/module.h +++ b/lib/module.h @@ -95,7 +95,7 @@ extern struct frrmod_runtime *frrmod_list; extern void frrmod_init(struct frrmod_runtime *modinfo); extern struct frrmod_runtime *frrmod_load(const char *spec, - char *err, size_t err_len); + const char *dir, char *err, size_t err_len); #if 0 /* not implemented yet */ extern void frrmod_unload(struct frrmod_runtime *module); From d851b2fc0d872e461b3c90056f0a1b551c0e4cf6 Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Fri, 21 Apr 2017 02:49:39 -0700 Subject: [PATCH 40/53] snapcraft: Add FPM module with command to set mode or disable it - New snap command: frr.set fpm {disable | protobuf | netlink} Signed-off-by: Martin Winter --- snapcraft/README.usage.md | 16 +++++++++++++ snapcraft/scripts/Makefile | 1 + snapcraft/scripts/set-options | 40 +++++++++++++++++++++++++++++++++ snapcraft/scripts/zebra-service | 8 +++++-- snapcraft/snapcraft.yaml.in | 5 +++++ 5 files changed, 68 insertions(+), 2 deletions(-) create mode 100755 snapcraft/scripts/set-options diff --git a/snapcraft/README.usage.md b/snapcraft/README.usage.md index c678c8805c..537147303a 100644 --- a/snapcraft/README.usage.md +++ b/snapcraft/README.usage.md @@ -30,6 +30,8 @@ Commands defined by this snap options - `frr.readme`: Returns this document `cat README_usage.md` +- `frr.set`: + Allows to enable `FPM` module. See FPM section below and for debugging defined at this time (May get removed later - do not depend on them). These are mainly intended to debug the Snap @@ -86,6 +88,20 @@ are named `eth0`, `eth1` and `eth2`, then the additional lines in These settings require either a reboot or a manual configuration with `sysctl` as well. +FPM Module +---------- +The `frr.set` allows to turn FPM module on or off. + + frr.set fpm {disable|protobuf|netlink} + + Disables FPM or enables FPM with selected mode + +By default, the FPM module is disabled, but installed with netlink and +protobuf support. To enable the FPM module, use the `frr.set fpm protobuf` +or `frr.set fpm netlink` command. The command will only enable the mode +for the next restart of zebra. Please reboot or restart zebra after +changing the mode to become effective. + FAQ --- - frr.vtysh displays `--MORE--` on long output. How to suppress this? diff --git a/snapcraft/scripts/Makefile b/snapcraft/scripts/Makefile index 0f9a24b649..2a60d4d652 100644 --- a/snapcraft/scripts/Makefile +++ b/snapcraft/scripts/Makefile @@ -12,3 +12,4 @@ install: install -D -m 0755 pimd-service $(DESTDIR)/bin/ install -D -m 0755 ldpd-service $(DESTDIR)/bin/ install -D -m 0755 nhrpd-service $(DESTDIR)/bin/ + install -D -m 0755 set-options $(DESTDIR)/bin/ diff --git a/snapcraft/scripts/set-options b/snapcraft/scripts/set-options new file mode 100755 index 0000000000..e76e321ef8 --- /dev/null +++ b/snapcraft/scripts/set-options @@ -0,0 +1,40 @@ +#!/bin/sh + +set -e + +case $1 in + fpm) + case $2 in + disable) + rm -f $SNAP_DATA/fpm.conf + echo "FPM module disabled. Please restart FRR" + ;; + protobuf) + echo "-M fpm:protobuf" > $SNAP_DATA/fpm.conf + echo "FPM enabled and set to protobuf mode. Please restart FRR" + ;; + netlink) + echo "-M fpm:netlink" > $SNAP_DATA/fpm.conf + echo "FPM enabled and set to netlink mode. Please restart FRR" + ;; + *) + echo "Usage:" + echo " ${SNAP_NAME}.set fpm {disable|protobuf|netlink}" + echo "" + echo " Disables FPM module or enables it with specified mode" + echo " Mode will be saved for next restart of zebra, but zebra" + echo " is not automatically restarted" + exit 1 + ;; + esac + ;; + *) + echo "Usage:" + echo " ${SNAP_NAME}.set fpm {disable|protobuf|netlink}" + echo "" + echo " Disables FPM or enables FPM with selected mode" + exit 1 + ;; +esac + +exit 0 diff --git a/snapcraft/scripts/zebra-service b/snapcraft/scripts/zebra-service index 9119a4055d..2ee131f9e5 100644 --- a/snapcraft/scripts/zebra-service +++ b/snapcraft/scripts/zebra-service @@ -8,9 +8,13 @@ fi if ! [ -e $SNAP_DATA/vtysh.conf ]; then cp $SNAP/etc/frr/vtysh.conf.default $SNAP_DATA/vtysh.conf fi +EXTRA_OPTIONS="" +if [ -e $SNAP_DATA/fpm.conf ]; then + EXTRA_OPTIONS="`cat $SNAP_DATA/fpm.conf`" +fi exec $SNAP/sbin/zebra \ -f $SNAP_DATA/zebra.conf \ --pid_file $SNAP_DATA/zebra.pid \ --socket $SNAP_DATA/zsock \ - --vty_socket $SNAP_DATA - + --vty_socket $SNAP_DATA \ + --moduledir $SNAP/lib/frr/modules $EXTRA_OPTIONS diff --git a/snapcraft/snapcraft.yaml.in b/snapcraft/snapcraft.yaml.in index 54a1cfd4f0..b5fb24a361 100644 --- a/snapcraft/snapcraft.yaml.in +++ b/snapcraft/snapcraft.yaml.in @@ -90,6 +90,8 @@ apps: - network - network-bind - network-control + set: + command: bin/set-options zebra-debug: command: sbin/zebra -f $SNAP_DATA/zebra.conf --pid_file $SNAP_DATA/zebra.pid --socket $SNAP_DATA/zsock --vty_socket $SNAP_DATA plugs: @@ -177,6 +179,7 @@ parts: - bison - flex - python3-dev + - protobuf-c-compiler stage-packages: - coreutils - iproute2 @@ -208,6 +211,8 @@ parts: - --enable-group=root - --enable-pimd - --enable-ldpd + - --enable-fpm + - --enable-protobuf - --enable-configfile-mask=0640 - --enable-logfile-mask=0640 - --localstatedir=/var/run From 02f3b0512ad45f7519480fb0a32e9aded1f722ea Mon Sep 17 00:00:00 2001 From: Phil Huang Date: Thu, 13 Apr 2017 18:11:28 +0800 Subject: [PATCH 41/53] Add user `frr` into group `frrvty` Signed-off-by: Phil Huang --- doc/Building_FRR_on_Debian8.md | 8 ++++---- doc/Building_FRR_on_Ubuntu1204.md | 5 +++-- doc/Building_FRR_on_Ubuntu1404.md | 5 +++-- doc/Building_FRR_on_Ubuntu1604.md | 5 +++-- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/doc/Building_FRR_on_Debian8.md b/doc/Building_FRR_on_Debian8.md index b902033d5e..1e57c1bea1 100644 --- a/doc/Building_FRR_on_Debian8.md +++ b/doc/Building_FRR_on_Debian8.md @@ -31,9 +31,9 @@ any packages** sudo addgroup --system --gid 92 frr sudo addgroup --system --gid 85 frrvty - sudo adduser --system --ingroup frr --groups frrvty --home /var/run/frr/ \ - --gecos "FRR FRRouting suite" --shell /bin/false frr - sudo usermode + sudo adduser --system --ingroup frr --home /var/run/frr/ \ + --gecos "FRR suite" --shell /bin/false frr + sudo usermod -a -G frrvty frr ### Download Source, configure and compile it (You may prefer different options on configure statement. These are just @@ -94,4 +94,4 @@ other settings) # based on Router Advertisements for this host net.ipv6.conf.all.forwarding=1 -**Reboot** or use `sysctl` to apply the same config to the running system +**Reboot** or use `sysctl -p` to apply the same config to the running system diff --git a/doc/Building_FRR_on_Ubuntu1204.md b/doc/Building_FRR_on_Ubuntu1204.md index 82404097c5..aa6cdcea7b 100644 --- a/doc/Building_FRR_on_Ubuntu1204.md +++ b/doc/Building_FRR_on_Ubuntu1204.md @@ -65,8 +65,9 @@ any packages** sudo groupadd -g 92 frr sudo groupadd -r -g 85 frrvty - sudo adduser --system --ingroup frr --groups frrvty --home /var/run/frr/ \ + sudo adduser --system --ingroup frr --home /var/run/frr/ \ --gecos "FRR suite" --shell /sbin/nologin frr + sudo usermod -a -G frrvty frr ### Download Source, configure and compile it (You may prefer different options on configure statement. These are just @@ -131,4 +132,4 @@ other settings) # based on Router Advertisements for this host net.ipv6.conf.all.forwarding=1 -**Reboot** or use `sysctl` to apply the same config to the running system +**Reboot** or use `sysctl -p` to apply the same config to the running system diff --git a/doc/Building_FRR_on_Ubuntu1404.md b/doc/Building_FRR_on_Ubuntu1404.md index 0d7c6f76fe..1f1caf4a58 100644 --- a/doc/Building_FRR_on_Ubuntu1404.md +++ b/doc/Building_FRR_on_Ubuntu1404.md @@ -25,8 +25,9 @@ any packages** sudo groupadd -g 92 frr sudo groupadd -r -g 85 frrvty - sudo adduser --system --ingroup frr --groups frrvty --home /var/run/frr/ \ + sudo adduser --system --ingroup frr --home /var/run/frr/ \ --gecos "FRR suite" --shell /sbin/nologin frr + sudo usermod -a -G frrvty frr ### Download Source, configure and compile it (You may prefer different options on configure statement. These are just @@ -90,4 +91,4 @@ other settings) # based on Router Advertisements for this host net.ipv6.conf.all.forwarding=1 -**Reboot** or use `sysctl` to apply the same config to the running system +**Reboot** or use `sysctl -p` to apply the same config to the running system diff --git a/doc/Building_FRR_on_Ubuntu1604.md b/doc/Building_FRR_on_Ubuntu1604.md index b6e18088f0..ace5f2b7f7 100644 --- a/doc/Building_FRR_on_Ubuntu1604.md +++ b/doc/Building_FRR_on_Ubuntu1604.md @@ -26,8 +26,9 @@ any packages** sudo groupadd -g 92 frr sudo groupadd -r -g 85 frrvty - sudo adduser --system --ingroup frr --groups frrvty --home /var/run/frr/ \ + sudo adduser --system --ingroup frr --home /var/run/frr/ \ --gecos "FRR suite" --shell /sbin/nologin frr + sudo usermod -a -G frrvty frr ### Download Source, configure and compile it (You may prefer different options on configure statement. These are just @@ -111,4 +112,4 @@ Add the following lines to `/etc/modules-load.d/modules.conf`: mpls-router mpls-iptunnel -**Reboot** or use `sysctl` to apply the same config to the running system +**Reboot** or use `sysctl -p` to apply the same config to the running system From aa1322f9f66c7e461267ec433823c602afb52d53 Mon Sep 17 00:00:00 2001 From: Phil Huang Date: Thu, 13 Apr 2017 21:20:53 +0800 Subject: [PATCH 42/53] Clean installation guide with Debian/Ubuntu Signed-off-by: Phil Huang --- doc/Building_FRR_on_Debian8.md | 3 +++ doc/Building_FRR_on_Ubuntu1204.md | 28 ++++++++++++---------------- doc/Building_FRR_on_Ubuntu1404.md | 28 +++++++++++++--------------- doc/Building_FRR_on_Ubuntu1604.md | 28 ++++++++++++---------------- 4 files changed, 40 insertions(+), 47 deletions(-) diff --git a/doc/Building_FRR_on_Debian8.md b/doc/Building_FRR_on_Debian8.md index 1e57c1bea1..635f9680b6 100644 --- a/doc/Building_FRR_on_Debian8.md +++ b/doc/Building_FRR_on_Debian8.md @@ -62,6 +62,7 @@ an example.) --enable-rtadv \ --enable-tcp-zebra \ --enable-fpm \ + --enable-ldpd \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion make @@ -69,6 +70,7 @@ an example.) sudo make install ### Create empty FRR configuration files + sudo install -m 755 -o frr -g frr -d /var/log/frr sudo install -m 775 -o frr -g frrvty -d /etc/frr sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf @@ -79,6 +81,7 @@ an example.) sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf ### Enable IP & IPv6 forwarding diff --git a/doc/Building_FRR_on_Ubuntu1204.md b/doc/Building_FRR_on_Ubuntu1204.md index aa6cdcea7b..cafed0fb31 100644 --- a/doc/Building_FRR_on_Ubuntu1204.md +++ b/doc/Building_FRR_on_Ubuntu1204.md @@ -102,22 +102,18 @@ an example.) ### Create empty FRR configuration files - sudo mkdir /var/log/frr - sudo chown frr:fee /var/log/frr - sudo mkdir /etc/frr - sudo touch /etc/frr/etc/zebra.conf - sudo touch /etc/frr/etc/bgpd.conf - sudo touch /etc/frr/etc/ospfd.conf - sudo touch /etc/frr/etc/ospf6d.conf - sudo touch /etc/frr/etc/isisd.conf - sudo touch /etc/frr/etc/ripd.conf - sudo touch /etc/frr/etc/ripngd.conf - sudo touch /etc/frr/etc/pimd.conf - sudo touch /etc/frr/etc/ldpd.conf - sudo chown frr:frr /etc/frr/ - sudo touch /etc/frr/etc/vtysh.conf - sudo chown frr:frrvty /etc/frr/etc/vtysh.conf - sudo chmod 640 /etc/frr/*.conf + sudo install -m 755 -o frr -g frr -d /var/log/frr + sudo install -m 775 -o frr -g frrvty -d /etc/frr + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf + sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf ### Enable IP & IPv6 forwarding diff --git a/doc/Building_FRR_on_Ubuntu1404.md b/doc/Building_FRR_on_Ubuntu1404.md index 1f1caf4a58..1524dd7778 100644 --- a/doc/Building_FRR_on_Ubuntu1404.md +++ b/doc/Building_FRR_on_Ubuntu1404.md @@ -54,6 +54,7 @@ an example.) --enable-rtadv \ --enable-tcp-zebra \ --enable-fpm \ + --enable-ldpd \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion make @@ -62,21 +63,18 @@ an example.) ### Create empty FRR configuration files - sudo mkdir /var/log/frr - sudo chown frr:fee /var/log/frr - sudo mkdir /etc/frr - sudo touch /etc/frr/etc/zebra.conf - sudo touch /etc/frr/etc/bgpd.conf - sudo touch /etc/frr/etc/ospfd.conf - sudo touch /etc/frr/etc/ospf6d.conf - sudo touch /etc/frr/etc/isisd.conf - sudo touch /etc/frr/etc/ripd.conf - sudo touch /etc/frr/etc/ripngd.conf - sudo touch /etc/frr/etc/pimd.conf - sudo chown frr:frr /etc/frr/ - sudo touch /etc/frr/etc/vtysh.conf - sudo chown frr:frrvty /etc/frr/etc/vtysh.conf - sudo chmod 640 /etc/frr/*.conf + sudo install -m 755 -o frr -g frr -d /var/log/frr + sudo install -m 775 -o frr -g frrvty -d /etc/frr + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf + sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf ### Enable IP & IPv6 forwarding diff --git a/doc/Building_FRR_on_Ubuntu1604.md b/doc/Building_FRR_on_Ubuntu1604.md index ace5f2b7f7..ed599a2551 100644 --- a/doc/Building_FRR_on_Ubuntu1604.md +++ b/doc/Building_FRR_on_Ubuntu1604.md @@ -63,22 +63,18 @@ an example.) ### Create empty FRR configuration files - sudo mkdir /var/log/frr - sudo chown frr:fee /var/log/frr - sudo mkdir /etc/frr - sudo touch /etc/frr/etc/zebra.conf - sudo touch /etc/frr/etc/bgpd.conf - sudo touch /etc/frr/etc/ospfd.conf - sudo touch /etc/frr/etc/ospf6d.conf - sudo touch /etc/frr/etc/isisd.conf - sudo touch /etc/frr/etc/ripd.conf - sudo touch /etc/frr/etc/ripngd.conf - sudo touch /etc/frr/etc/pimd.conf - sudo touch /etc/frr/etc/ldpd.conf - sudo chown frr:frr /etc/frr/ - sudo touch /etc/frr/etc/vtysh.conf - sudo chown frr:frrvty /etc/frr/etc/vtysh.conf - sudo chmod 640 /etc/frr/*.conf + sudo install -m 755 -o frr -g frr -d /var/log/frr + sudo install -m 775 -o frr -g frrvty -d /etc/frr + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf + sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf ### Enable IP & IPv6 forwarding From 97b02007935d00ad8f9126045922ccc8173296ee Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Fri, 21 Apr 2017 03:55:14 -0700 Subject: [PATCH 43/53] doc: Add nhrpd to relevant section in Building_FRR_on_xxxx doc Signed-off-by: Martin Winter --- doc/Building_FRR_on_Debian8.md | 1 + doc/Building_FRR_on_Fedora24.md | 3 ++- doc/Building_FRR_on_OpenBSD6.md | 1 + doc/Building_FRR_on_Ubuntu1204.md | 1 + doc/Building_FRR_on_Ubuntu1404.md | 1 + doc/Building_FRR_on_Ubuntu1604.md | 1 + 6 files changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/Building_FRR_on_Debian8.md b/doc/Building_FRR_on_Debian8.md index 635f9680b6..a42ca6d781 100644 --- a/doc/Building_FRR_on_Debian8.md +++ b/doc/Building_FRR_on_Debian8.md @@ -82,6 +82,7 @@ an example.) sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf ### Enable IP & IPv6 forwarding diff --git a/doc/Building_FRR_on_Fedora24.md b/doc/Building_FRR_on_Fedora24.md index 941126da42..1f5f12b9cc 100644 --- a/doc/Building_FRR_on_Fedora24.md +++ b/doc/Building_FRR_on_Fedora24.md @@ -70,6 +70,7 @@ them if you are not building on a x86_64 architecture sudo touch /etc/frr/ripngd.conf sudo touch /etc/frr/pimd.conf sudo touch /etc/frr/ldpd.conf + sudo touch /etc/frr/nhrpd.conf sudo chown -R frr:frr /etc/frr/ sudo touch /etc/frr/vtysh.conf sudo chown frr:frrvt /etc/frr/vtysh.conf @@ -111,7 +112,7 @@ Create a new file `/etc/modules-load.d/mpls.conf` with the following content: install -p -m 644 redhat/ospf6d.service /usr/lib/systemd/system/ospf6d.service install -p -m 644 redhat/ripngd.service /usr/lib/systemd/system/ripngd.service install -p -m 644 redhat/pimd.service /usr/lib/systemd/system/pimd.service - install -p -m 644 redhat/pimd.service /usr/lib/systemd/system/ldpd.service + install -p -m 644 redhat/ldpd.service /usr/lib/systemd/system/ldpd.service install -p -m 644 redhat/frr.sysconfig /etc/sysconfig/frr install -p -m 644 redhat/frr.logrotate /etc/logrotate.d/frr diff --git a/doc/Building_FRR_on_OpenBSD6.md b/doc/Building_FRR_on_OpenBSD6.md index a59452a72b..c1b583664d 100644 --- a/doc/Building_FRR_on_OpenBSD6.md +++ b/doc/Building_FRR_on_OpenBSD6.md @@ -75,6 +75,7 @@ an example) sudo touch /etc/frr/ripngd.conf sudo touch /etc/frr/pimd.conf sudo touch /etc/frr/ldpd.conf + sudo touch /etc/frr/nhrpd.conf sudo chown -R _frr:_frr /etc/frr sudo touch /etc/frr/vtysh.conf sudo chown -R _frr:_frrvty /etc/frr/vtysh.conf diff --git a/doc/Building_FRR_on_Ubuntu1204.md b/doc/Building_FRR_on_Ubuntu1204.md index cafed0fb31..2d6ccffd9f 100644 --- a/doc/Building_FRR_on_Ubuntu1204.md +++ b/doc/Building_FRR_on_Ubuntu1204.md @@ -113,6 +113,7 @@ an example.) sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf ### Enable IP & IPv6 forwarding diff --git a/doc/Building_FRR_on_Ubuntu1404.md b/doc/Building_FRR_on_Ubuntu1404.md index 1524dd7778..5da423affc 100644 --- a/doc/Building_FRR_on_Ubuntu1404.md +++ b/doc/Building_FRR_on_Ubuntu1404.md @@ -74,6 +74,7 @@ an example.) sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf ### Enable IP & IPv6 forwarding diff --git a/doc/Building_FRR_on_Ubuntu1604.md b/doc/Building_FRR_on_Ubuntu1604.md index ed599a2551..70a8159cc1 100644 --- a/doc/Building_FRR_on_Ubuntu1604.md +++ b/doc/Building_FRR_on_Ubuntu1604.md @@ -74,6 +74,7 @@ an example.) sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf + sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf ### Enable IP & IPv6 forwarding From 34288970c42bcfaebc6d101e500c0fdad6420ff5 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 22 Apr 2017 17:41:54 -0300 Subject: [PATCH 44/53] ospf6d: fix "no router ospf6" The "no router ospf6" command wasn't working. Regression introduced by commit 16cedbb. Signed-off-by: Renato Westphal --- ospf6d/ospf6_top.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index f2a1c8c2ec..e592d3c4f9 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -315,6 +315,14 @@ DEFUN (no_router_ospf6, ROUTER_STR OSPF6_STR) { + if (ospf6 == NULL) + vty_out (vty, "OSPFv3 is not configured%s", VNL); + else + { + ospf6_delete (ospf6); + ospf6 = NULL; + } + /* return to config node . */ VTY_PUSH_CONTEXT_NULL(CONFIG_NODE); From 27821f6a5a1d469e878dc4d35a87475c6643141f Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Mon, 24 Apr 2017 18:22:29 +0000 Subject: [PATCH 45/53] vtysh: "Command incomplete: log syslog" Signed-off-by: Daniel Walton Before ====== root@spine-1[~]# cat /etc/frr/frr.conf no log monitor ! service integrated-vtysh-config ! log syslog ! log syslog informational ! line vty ! root@spine-1[~]# root@spine-1[~]# vtysh -m -f /etc/frr/frr.conf no log monitor ! service integrated-vtysh-config ! line 5: % Command incomplete: log syslog root@spine-1[~]# After ===== root@spine-1[~]# vtysh -m -f /etc/frr/frr.conf no log monitor ! service integrated-vtysh-config ! log syslog ! log syslog informational ! line vty ! end root@spine-1[~]# --- vtysh/vtysh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index d0038ea3cf..74f865b613 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -2165,7 +2165,7 @@ DEFUNSH (VTYSH_ALL, DEFUNSH (VTYSH_ALL, vtysh_log_syslog, vtysh_log_syslog_cmd, - "log syslog ", + "log syslog []", "Logging control\n" "Set syslog logging level\n" LOG_LEVEL_DESC) From 0ca036b4569d695cfe668a0d9efbe7da94016673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Sat, 25 Mar 2017 17:27:24 +0200 Subject: [PATCH 46/53] nhrpd: implement 'show ip nhrp nhs' --- nhrpd/nhrp_nhs.c | 28 ++++++++------- nhrpd/nhrp_vty.c | 88 +++++++++++++++++++++++++++++++----------------- nhrpd/nhrpd.h | 13 +++++++ 3 files changed, 86 insertions(+), 43 deletions(-) diff --git a/nhrpd/nhrp_nhs.c b/nhrpd/nhrp_nhs.c index 10245d308a..555c0d1de1 100644 --- a/nhrpd/nhrp_nhs.c +++ b/nhrpd/nhrp_nhs.c @@ -18,19 +18,6 @@ DEFINE_MTYPE_STATIC(NHRPD, NHRP_NHS, "NHRP next hop server") DEFINE_MTYPE_STATIC(NHRPD, NHRP_REGISTRATION, "NHRP registration entries") static int nhrp_nhs_resolve(struct thread *t); - -struct nhrp_registration { - struct list_head reglist_entry; - struct thread *t_register; - struct nhrp_nhs *nhs; - struct nhrp_reqid reqid; - unsigned int timeout; - unsigned mark : 1; - union sockunion proto_addr; - struct nhrp_peer *peer; - struct notifier_block peer_notifier; -}; - static int nhrp_reg_send_req(struct thread *t); static void nhrp_reg_reply(struct nhrp_reqid *reqid, void *arg) @@ -370,3 +357,18 @@ void nhrp_nhs_terminate(void) } } } + +void nhrp_nhs_foreach(struct interface *ifp, afi_t afi, void (*cb)(struct nhrp_nhs *, struct nhrp_registration *, void *), void *ctx) +{ + struct nhrp_interface *nifp = ifp->info; + struct nhrp_nhs *nhs; + struct nhrp_registration *reg; + + list_for_each_entry(nhs, &nifp->afi[afi].nhslist_head, nhslist_entry) { + if (!list_empty(&nhs->reglist_head)) { + list_for_each_entry(reg, &nhs->reglist_head, reglist_entry) + cb(nhs, reg, ctx); + } else + cb(nhs, 0, ctx); + } +} diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c index 2e3164410c..f127d24dc8 100644 --- a/nhrpd/nhrp_vty.c +++ b/nhrpd/nhrp_vty.c @@ -592,6 +592,56 @@ static void show_ip_nhrp_cache(struct nhrp_cache *c, void *pctx) VTY_NEWLINE); } +static void show_ip_nhrp_nhs(struct nhrp_nhs *n, struct nhrp_registration *reg, void *pctx) +{ + struct info_ctx *ctx = pctx; + struct vty *vty = ctx->vty; + char buf[2][SU_ADDRSTRLEN]; + + if (!ctx->count) { + vty_out(vty, "%-8s %-24s %-16s %-16s%s", + "Iface", + "FQDN", + "NBMA", + "Protocol", + VTY_NEWLINE); + } + ctx->count++; + + vty_out(vty, "%-8s %-24s %-16s %-16s%s", + n->ifp->name, + n->nbma_fqdn, + (reg && reg->peer) ? sockunion2str(®->peer->vc->remote.nbma, buf[0], sizeof buf[0]) : "-", + sockunion2str(reg ? ®->proto_addr : &n->proto_addr, buf[1], sizeof buf[1]), + VTY_NEWLINE); +} + +static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx) +{ + struct info_ctx *ctx = pctx; + struct nhrp_cache *c; + struct vty *vty = ctx->vty; + char buf1[PREFIX_STRLEN], buf2[SU_ADDRSTRLEN]; + + if (!ctx->count) { + vty_out(vty, "%-8s %-24s %-24s %s%s", + "Type", + "Prefix", + "Via", + "Identity", + VTY_NEWLINE); + } + ctx->count++; + + c = s->cache; + vty_out(ctx->vty, "%-8s %-24s %-24s %s%s", + nhrp_cache_type_str[s->type], + prefix2str(s->p, buf1, sizeof buf1), + c ? sockunion2str(&c->remote_addr, buf2, sizeof buf2) : "", + (c && c->cur.peer) ? c->cur.peer->vc->remote.id : "", + VTY_NEWLINE); +} + static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx) { struct info_ctx *ctx = pctx; @@ -631,38 +681,13 @@ static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx) vty_out(ctx->vty, "%s", VTY_NEWLINE); } -static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx) -{ - struct info_ctx *ctx = pctx; - struct nhrp_cache *c; - struct vty *vty = ctx->vty; - char buf1[PREFIX_STRLEN], buf2[SU_ADDRSTRLEN]; - - if (!ctx->count) { - vty_out(vty, "%-8s %-24s %-24s %s%s", - "Type", - "Prefix", - "Via", - "Identity", - VTY_NEWLINE); - } - ctx->count++; - - c = s->cache; - vty_out(ctx->vty, "%-8s %-24s %-24s %s%s", - nhrp_cache_type_str[s->type], - prefix2str(s->p, buf1, sizeof buf1), - c ? sockunion2str(&c->remote_addr, buf2, sizeof buf2) : "", - (c && c->cur.peer) ? c->cur.peer->vc->remote.id : "", - VTY_NEWLINE); -} - DEFUN(show_ip_nhrp, show_ip_nhrp_cmd, - "show " AFI_CMD " nhrp [cache|shortcut|opennhrp]", + "show " AFI_CMD " nhrp [cache|nhs|shortcut|opennhrp]", SHOW_STR AFI_STR "NHRP information\n" "Forwarding cache information\n" + "Next hop server information\n" "Shortcut information\n" "opennhrpctl style cache dump\n") { @@ -676,13 +701,16 @@ DEFUN(show_ip_nhrp, show_ip_nhrp_cmd, if (argc <= 3 || argv[3]->text[0] == 'c') { for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) nhrp_cache_foreach(ifp, show_ip_nhrp_cache, &ctx); - } else if (argv[3]->text[0] == 'o') { + } else if (argv[3]->text[0] == 'n') { + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) + nhrp_nhs_foreach(ifp, ctx.afi, show_ip_nhrp_nhs, &ctx); + } else if (argv[3]->text[0] == 's') { + nhrp_shortcut_foreach(ctx.afi, show_ip_nhrp_shortcut, &ctx); + } else { vty_out(vty, "Status: ok%s%s", VTY_NEWLINE, VTY_NEWLINE); ctx.count++; for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) nhrp_cache_foreach(ifp, show_ip_opennhrp_cache, &ctx); - } else { - nhrp_shortcut_foreach(ctx.afi, show_ip_nhrp_shortcut, &ctx); } if (!ctx.count) { diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h index cd2b0d5580..9a4f26d577 100644 --- a/nhrpd/nhrpd.h +++ b/nhrpd/nhrpd.h @@ -254,6 +254,18 @@ struct nhrp_nhs { struct list_head reglist_head; }; +struct nhrp_registration { + struct list_head reglist_entry; + struct thread *t_register; + struct nhrp_nhs *nhs; + struct nhrp_reqid reqid; + unsigned int timeout; + unsigned mark : 1; + union sockunion proto_addr; + struct nhrp_peer *peer; + struct notifier_block peer_notifier; +}; + #define NHRP_IFF_SHORTCUT 0x0001 #define NHRP_IFF_REDIRECT 0x0002 #define NHRP_IFF_REG_NO_UNIQUE 0x0100 @@ -311,6 +323,7 @@ int nhrp_nhs_add(struct interface *ifp, afi_t afi, union sockunion *proto_addr, int nhrp_nhs_del(struct interface *ifp, afi_t afi, union sockunion *proto_addr, const char *nbma_fqdn); int nhrp_nhs_free(struct nhrp_nhs *nhs); void nhrp_nhs_terminate(void); +void nhrp_nhs_foreach(struct interface *ifp, afi_t afi, void (*cb)(struct nhrp_nhs *, struct nhrp_registration *, void *), void *ctx); void nhrp_route_update_nhrp(const struct prefix *p, struct interface *ifp); void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix *p, struct interface *ifp, const union sockunion *nexthop, uint32_t mtu); From 2d4eab226953e4754a38f179a2733a165e176c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Fri, 21 Apr 2017 13:37:07 +0300 Subject: [PATCH 47/53] nhrp: implement 'no ip nhrp map' command was accidentally not implemented earlier --- nhrpd/nhrp_vty.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c index f127d24dc8..3d1d29ecb9 100644 --- a/nhrpd/nhrp_vty.c +++ b/nhrpd/nhrp_vty.c @@ -504,6 +504,32 @@ DEFUN(if_nhrp_map, if_nhrp_map_cmd, return CMD_SUCCESS; } +DEFUN(if_no_nhrp_map, if_no_nhrp_map_cmd, + "no " AFI_CMD " nhrp map (A.B.C.D|X:X::X:X)", + NO_STR + AFI_STR + NHRP_STR + "Nexthop Server configuration\n" + "IPv4 protocol address\n" + "IPv6 protocol address\n") +{ + VTY_DECLVAR_CONTEXT(interface,ifp); + afi_t afi = cmd_to_afi(argv[1]); + union sockunion proto_addr; + struct nhrp_cache *c; + + if (str2sockunion(argv[4]->arg, &proto_addr) < 0 || + afi2family(afi) != sockunion_family(&proto_addr)) + return nhrp_vty_return(vty, NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH); + + c = nhrp_cache_get(ifp, &proto_addr, 0); + if (!c || !c->map) + return nhrp_vty_return(vty, NHRP_ERR_ENTRY_NOT_FOUND); + + nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL); + return CMD_SUCCESS; +} + DEFUN(if_nhrp_nhs, if_nhrp_nhs_cmd, AFI_CMD " nhrp nhs nbma ", AFI_STR @@ -947,6 +973,7 @@ void nhrp_config_init(void) install_element(INTERFACE_NODE, &if_nhrp_reg_flags_cmd); install_element(INTERFACE_NODE, &if_no_nhrp_reg_flags_cmd); install_element(INTERFACE_NODE, &if_nhrp_map_cmd); + install_element(INTERFACE_NODE, &if_no_nhrp_map_cmd); install_element(INTERFACE_NODE, &if_nhrp_nhs_cmd); install_element(INTERFACE_NODE, &if_no_nhrp_nhs_cmd); } From 8c01a3bd14f1ed70963159e5e0866dad412020c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Thu, 20 Apr 2017 16:24:14 +0300 Subject: [PATCH 48/53] nhrp: fix protocol address family parsing on receive See bugzilla #948 --- nhrpd/nhrp_peer.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c index 4c1d97a489..1f624eba0b 100644 --- a/nhrpd/nhrp_peer.c +++ b/nhrpd/nhrp_peer.c @@ -730,6 +730,15 @@ static void nhrp_packet_debug(struct zbuf *zb, const char *dir) reply ? buf[0] : buf[1]); } +static int proto2afi(uint16_t proto) +{ + switch (proto) { + case ETH_P_IP: return AFI_IP; + case ETH_P_IPV6: return AFI_IP6; + } + return AF_UNSPEC; +} + struct nhrp_route_info { int local; struct interface *ifp; @@ -749,7 +758,7 @@ void nhrp_peer_recv(struct nhrp_peer *p, struct zbuf *zb) const char *info = NULL; union sockunion *target_addr; unsigned paylen, extoff, extlen, realsize; - afi_t afi; + afi_t nbma_afi, proto_afi; debugf(NHRP_DEBUG_KERNEL, "PACKET: Recv %s -> %s", sockunion2str(&vc->remote.nbma, buf[0], sizeof buf[0]), @@ -777,20 +786,21 @@ void nhrp_peer_recv(struct nhrp_peer *p, struct zbuf *zb) pp.hdr = hdr; pp.peer = p; - afi = htons(hdr->afnum); + nbma_afi = htons(hdr->afnum); + proto_afi = proto2afi(htons(hdr->protocol_type)); if (hdr->type > ZEBRA_NUM_OF(packet_types) || hdr->version != NHRP_VERSION_RFC2332 || - afi >= AFI_MAX || + nbma_afi >= AFI_MAX || proto_afi == AF_UNSPEC || packet_types[hdr->type].type == PACKET_UNKNOWN || htons(hdr->packet_size) > realsize) { - zlog_info("From %s: error: packet type %d, version %d, AFI %d, size %d (real size %d)", + zlog_info("From %s: error: packet type %d, version %d, AFI %d, proto %x, size %d (real size %d)", sockunion2str(&vc->remote.nbma, buf[0], sizeof buf[0]), - (int) hdr->type, (int) hdr->version, (int) afi, - (int) htons(hdr->packet_size), - (int) realsize); + (int) hdr->type, (int) hdr->version, + (int) nbma_afi, (int) htons(hdr->protocol_type), + (int) htons(hdr->packet_size), (int) realsize); goto drop; } - pp.if_ad = &((struct nhrp_interface *)ifp->info)->afi[afi]; + pp.if_ad = &((struct nhrp_interface *)ifp->info)->afi[proto_afi]; extoff = htons(hdr->extension_offset); if (extoff) { @@ -806,7 +816,7 @@ void nhrp_peer_recv(struct nhrp_peer *p, struct zbuf *zb) extlen = zbuf_used(zb); zbuf_init(&pp.extensions, zbuf_pulln(zb, extlen), extlen, extlen); - if (!nifp->afi[afi].network_id) { + if (!nifp->afi[proto_afi].network_id) { info = "nhrp not enabled"; goto drop; } From 3d3813b22976a1092a03ac7d94885f9d2ed5e56d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Fri, 21 Apr 2017 13:57:28 +0300 Subject: [PATCH 49/53] nhrp: explicitly cast ints to size_t for vici_request_vc va_list handling --- nhrpd/vici.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nhrpd/vici.c b/nhrpd/vici.c index 507dd14a9c..12409f90b9 100644 --- a/nhrpd/vici.c +++ b/nhrpd/vici.c @@ -449,9 +449,9 @@ void vici_request_vc(const char *profile, union sockunion *src, union sockunion vici_submit_request( vici, "initiate", VICI_KEY_VALUE, "child", strlen(profile), profile, - VICI_KEY_VALUE, "timeout", 2, "-1", - VICI_KEY_VALUE, "async", 1, "1", - VICI_KEY_VALUE, "init-limits", 1, prio ? "0" : "1", + VICI_KEY_VALUE, "timeout", (size_t) 2, "-1", + VICI_KEY_VALUE, "async", (size_t) 1, "1", + VICI_KEY_VALUE, "init-limits", (size_t) 1, prio ? "0" : "1", VICI_KEY_VALUE, "my-host", strlen(buf[0]), buf[0], VICI_KEY_VALUE, "other-host", strlen(buf[1]), buf[1], VICI_END); From 111aec1e42fd5f3130518a90e56a0dd3d4e48375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Fri, 21 Apr 2017 14:56:45 +0300 Subject: [PATCH 50/53] nhrp: notify 'tunnel protection' changes to triggers refresh of IKE SAs immediately on this command --- nhrpd/nhrp_interface.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c index bbaa630cd5..58ad167549 100644 --- a/nhrpd/nhrp_interface.c +++ b/nhrpd/nhrp_interface.c @@ -393,6 +393,8 @@ void nhrp_interface_set_protection(struct interface *ifp, const char *profile, c if (nifp->ipsec_fallback_profile) free(nifp->ipsec_fallback_profile); nifp->ipsec_fallback_profile = fallback_profile ? strdup(fallback_profile) : NULL; + + notifier_call(&nifp->notifier_list, NOTIFY_INTERFACE_ADDRESS_CHANGED); } void nhrp_interface_set_source(struct interface *ifp, const char *ifname) From 8ec0c3c125d2a6abda67eef2d990fa3ea15b94ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Fri, 21 Apr 2017 14:57:57 +0300 Subject: [PATCH 51/53] nhrp: fix potential crash when vici profile name is not configured --- nhrpd/nhrp_peer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c index 1f624eba0b..3cc91a9083 100644 --- a/nhrpd/nhrp_peer.c +++ b/nhrpd/nhrp_peer.c @@ -250,6 +250,8 @@ int nhrp_peer_check(struct nhrp_peer *p, int establish) return 0; if (p->requested) return 0; + if (!nifp->ipsec_profile) + return 0; if (sockunion_family(&vc->local.nbma) == AF_UNSPEC) return 0; From d139786ae8be106a0ec7d9f16dd5480fc6cb1193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Fri, 21 Apr 2017 14:58:17 +0300 Subject: [PATCH 52/53] nhrp: parse and log command response errors from strongSwan helps to debug configuration problems --- nhrpd/vici.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/nhrpd/vici.c b/nhrpd/vici.c index 12409f90b9..5491bacf7c 100644 --- a/nhrpd/vici.c +++ b/nhrpd/vici.c @@ -220,6 +220,23 @@ static void parse_sa_message( } } +static void parse_cmd_response( + struct vici_message_ctx *ctx, + enum vici_type_t msgtype, + const struct blob *key, const struct blob *val) +{ + char buf[512]; + + switch (msgtype) { + case VICI_KEY_VALUE: + if (blob_equal(key, "errmsg") && blob2buf(val, buf, sizeof(buf))) + zlog_err("VICI: strongSwan: %s", buf); + break; + default: + break; + } +} + static void vici_recv_sa(struct vici_conn *vici, struct zbuf *msg, int event) { char buf[32]; @@ -265,11 +282,14 @@ static void vici_recv_message(struct vici_conn *vici, struct zbuf *msg) else if (blob_equal(&name, "child-state-destroying")) vici_recv_sa(vici, msg, 2); break; + case VICI_CMD_RESPONSE: + vici_parse_message(vici, msg, parse_cmd_response, 0); + break; case VICI_EVENT_UNKNOWN: + case VICI_CMD_UNKNOWN: zlog_err("VICI: StrongSwan does not support mandatory events (unpatched?)"); break; case VICI_EVENT_CONFIRM: - case VICI_CMD_RESPONSE: break; default: zlog_notice("VICI: Unrecognized message type %d", msgtype); From c1c17a0ff78fbd37dd587fe2c08435cfe414fca1 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 25 Apr 2017 09:07:05 -0400 Subject: [PATCH 53/53] nhrpd: Fix cli changes missed Signed-off-by: Donald Sharp --- nhrpd/nhrp_vty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c index 3d1d29ecb9..9b8463fb54 100644 --- a/nhrpd/nhrp_vty.c +++ b/nhrpd/nhrp_vty.c @@ -505,7 +505,7 @@ DEFUN(if_nhrp_map, if_nhrp_map_cmd, } DEFUN(if_no_nhrp_map, if_no_nhrp_map_cmd, - "no " AFI_CMD " nhrp map (A.B.C.D|X:X::X:X)", + "no " AFI_CMD " nhrp map ", NO_STR AFI_STR NHRP_STR