diff options
72 files changed, 1362 insertions, 497 deletions
diff --git a/Makefile.am b/Makefile.am index ed22c60e7c..f9fb231962 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,8 +5,7 @@ include common.am AM_CPPFLAGS += -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/lib \ -I$(top_builddir) -I$(top_builddir)/include -I$(top_builddir)/lib -VERSION_TYPE := $(shell if echo $(VERSION) | grep -q '^[0-9\.]*$$'; then echo RELEASE ; else echo DEV ; fi) -DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" -DCONFDATE=$(CONFDATE) -DVERSION_TYPE_$(VERSION_TYPE) +DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" -DCONFDATE=$(CONFDATE) LIBCAP = @LIBCAP@ EXTRA_DIST = diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index 3880d2020d..2f19bbbd73 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -134,6 +134,7 @@ dist_examples_DATA = bgpd.conf.sample bgpd.conf.sample2 \ bgp_vty.o: bgp_vty_clippy.c bgp_route.o: bgp_route_clippy.c +bgp_debug.o: bgp_debug_clippy.c EXTRA_DIST = BGP4-MIB.txt diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 6596e7cfa2..e5ad5e2338 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -1890,6 +1890,16 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args) /* Check if this is a Gateway MAC-IP advertisement */ attr->default_gw = bgp_attr_default_gw(attr); + /* Handle scenario where router flag ecommunity is not + * set but default gw ext community is present. + * Use default gateway, set and propogate R-bit. + */ + if (attr->default_gw) + attr->router_flag = 1; + + /* Check EVPN Neighbor advertisement flags, R-bit */ + bgp_attr_evpn_na_flag(attr, &attr->router_flag); + /* Extract the Rmac, if any */ bgp_attr_rmac(attr, &attr->rmac); diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index f17c2a68e4..883b129136 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -185,6 +185,9 @@ struct attr { /* Flag for default gateway extended community in EVPN */ uint8_t default_gw; + /* NA router flag (R-bit) support in EVPN */ + uint8_t router_flag; + /* route tag */ route_tag_t tag; diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c index 14ff01ada5..88e520fdc5 100644 --- a/bgpd/bgp_attr_evpn.c +++ b/bgpd/bgp_attr_evpn.c @@ -210,6 +210,39 @@ uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky) return 0; } +/* + * return true if attr contains router flag extended community + */ +void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag) +{ + struct ecommunity *ecom; + int i; + uint8_t val; + + ecom = attr->ecommunity; + if (!ecom || !ecom->size) + return; + + /* If there is a evpn na extendd community set router_flag */ + for (i = 0; i < ecom->size; i++) { + uint8_t *pnt; + uint8_t type, sub_type; + + pnt = (ecom->val + (i * ECOMMUNITY_SIZE)); + type = *pnt++; + sub_type = *pnt++; + + if (type == ECOMMUNITY_ENCODE_EVPN && + sub_type == ECOMMUNITY_EVPN_SUBTYPE_ND) { + val = *pnt++; + if (val & ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG) { + *router_flag = 1; + break; + } + } + } +} + /* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */ extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag, struct prefix *dst) diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h index 7454b81b96..b036702151 100644 --- a/bgpd/bgp_attr_evpn.h +++ b/bgpd/bgp_attr_evpn.h @@ -65,4 +65,6 @@ extern uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky); extern uint8_t bgp_attr_default_gw(struct attr *attr); +extern void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag); + #endif /* _QUAGGA_BGP_ATTR_EVPN_H */ diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index a4ded57c25..1e95a887bc 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -42,6 +42,8 @@ #include "bgpd/bgp_ecommunity.h" #include "bgpd/bgp_label.h" #include "bgpd/bgp_evpn.h" +#include "bgpd/bgp_evpn_private.h" +#include "bgpd/bgp_vty.h" #include "bgpd/bgp_flowspec.h" unsigned long conf_bgp_debug_as4; @@ -169,6 +171,8 @@ static const struct message bgp_notify_capability_msg[] = { const char *bgp_origin_str[] = {"i", "e", "?"}; const char *bgp_origin_long_str[] = {"IGP", "EGP", "incomplete"}; +static int bgp_debug_print_evpn_prefix(struct vty *vty, const char *desc, + struct prefix *p); /* Given a string return a pointer the corresponding peer structure */ static struct peer *bgp_find_peer(struct vty *vty, const char *peer_str) { @@ -216,11 +220,11 @@ static void bgp_debug_list_free(struct list *list) /* Print the desc along with a list of peers/prefixes this debug is * enabled for */ static void bgp_debug_list_print(struct vty *vty, const char *desc, - struct list *list) + struct list *list, uint8_t evpn_dbg) { struct bgp_debug_filter *filter; struct listnode *node, *nnode; - char buf[INET6_ADDRSTRLEN]; + char buf[PREFIX2STR_BUFFER]; vty_out(vty, "%s", desc); @@ -230,12 +234,17 @@ static void bgp_debug_list_print(struct vty *vty, const char *desc, if (filter->host) vty_out(vty, " %s", filter->host); - if (filter->p) - vty_out(vty, " %s/%d", - inet_ntop(filter->p->family, - &filter->p->u.prefix, buf, - INET6_ADDRSTRLEN), - filter->p->prefixlen); + if (filter->p) { + if (!evpn_dbg) { + vty_out(vty, " %s", + prefix2str(filter->p, buf, + sizeof(buf))); + } else { + if (filter->p->family == AF_EVPN) + bgp_debug_print_evpn_prefix(vty, + "", filter->p); + } + } } } @@ -246,11 +255,11 @@ static void bgp_debug_list_print(struct vty *vty, const char *desc, * enabled for */ static int bgp_debug_list_conf_print(struct vty *vty, const char *desc, - struct list *list) + struct list *list, uint8_t evpn_dbg) { struct bgp_debug_filter *filter; struct listnode *node, *nnode; - char buf[INET6_ADDRSTRLEN]; + char buf[PREFIX2STR_BUFFER]; int write = 0; if (list && !list_isempty(list)) { @@ -262,12 +271,17 @@ static int bgp_debug_list_conf_print(struct vty *vty, const char *desc, if (filter->p) { - vty_out(vty, "%s %s/%d\n", desc, - inet_ntop(filter->p->family, - &filter->p->u.prefix, buf, - INET6_ADDRSTRLEN), - filter->p->prefixlen); - write++; + if (!evpn_dbg) { + vty_out(vty, "%s %s\n", desc, + prefix2str(filter->p, buf, + sizeof(buf))); + write++; + } else { + if (filter->p->family == AF_EVPN) + bgp_debug_print_evpn_prefix(vty, + desc, filter->p); + write++; + } } } } @@ -543,6 +557,118 @@ static void bgp_debug_clear_updgrp_update_dbg(struct bgp *bgp) update_group_walk(bgp, update_group_clear_update_dbg, NULL); } +static int bgp_debug_print_evpn_prefix(struct vty *vty, const char *desc, + struct prefix *p) +{ + char evpn_desc[PREFIX2STR_BUFFER + INET_ADDRSTRLEN]; + char buf[PREFIX2STR_BUFFER]; + char buf2[ETHER_ADDR_STRLEN]; + + if (p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE) { + if (is_evpn_prefix_ipaddr_none((struct prefix_evpn *)p)) { + sprintf(evpn_desc, "l2vpn evpn type macip mac %s", + prefix_mac2str( + &p->u.prefix_evpn.macip_addr.mac, + buf2, sizeof(buf2))); + } else { + uint8_t family = is_evpn_prefix_ipaddr_v4( + (struct prefix_evpn *)p) ? + AF_INET : AF_INET6; + sprintf(evpn_desc, "l2vpn evpn type macip mac %s ip %s", + prefix_mac2str( + &p->u.prefix_evpn.macip_addr.mac, + buf2, sizeof(buf2)), + inet_ntop(family, + &p->u.prefix_evpn.macip_addr.ip.ip.addr, + buf, PREFIX2STR_BUFFER)); + } + } else if (p->u.prefix_evpn.route_type == BGP_EVPN_IMET_ROUTE) { + sprintf(evpn_desc, "l2vpn evpn type multicast ip %s", + inet_ntoa(p->u.prefix_evpn.imet_addr.ip.ipaddr_v4)); + } else if (p->u.prefix_evpn.route_type == BGP_EVPN_IP_PREFIX_ROUTE) { + uint8_t family = is_evpn_prefix_ipaddr_v4( + (struct prefix_evpn *)p) ? AF_INET + : AF_INET6; + sprintf(evpn_desc, "l2vpn evpn type prefix ip %s/%d", + inet_ntop(family, + &p->u.prefix_evpn.prefix_addr.ip.ip.addr, buf, + PREFIX2STR_BUFFER), + p->u.prefix_evpn.prefix_addr.ip_prefix_length); + } + + vty_out(vty, "%s %s\n", desc, evpn_desc); + + return 0; +} + +static int bgp_debug_parse_evpn_prefix(struct vty *vty, struct cmd_token **argv, + int argc, struct prefix **argv_pp) +{ + struct prefix *argv_p; + struct ethaddr mac; + struct ipaddr ip; + int evpn_type; + int type_idx = 0; + int mac_idx = 0; + int ip_idx = 0; + + argv_p = *argv_pp; + + if (argv_find(argv, argc, "type", &type_idx) == 0) + return CMD_WARNING; + + if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0) + evpn_type = BGP_EVPN_MAC_IP_ROUTE; + else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0) + evpn_type = BGP_EVPN_IMET_ROUTE; + else if (strncmp(argv[type_idx + 1]->arg, "pr", 2) == 0) + evpn_type = BGP_EVPN_IP_PREFIX_ROUTE; + else + evpn_type = 0; + + if (evpn_type == BGP_EVPN_MAC_IP_ROUTE) { + memset(&ip, 0, sizeof(struct ipaddr)); + /* get the ip if specified */ + if (argv_find(argv, argc, "ip", &ip_idx)) { + if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) { + vty_out(vty, "%% Malformed IP address\n"); + return CMD_WARNING; + } + } + argv_find(argv, argc, "mac", &mac_idx); + if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) { + vty_out(vty, "%% Malformed MAC address\n"); + return CMD_WARNING; + } + + build_evpn_type2_prefix((struct prefix_evpn *)argv_p, + &mac, &ip); + } else if (evpn_type == BGP_EVPN_IMET_ROUTE) { + memset(&ip, 0, sizeof(struct ipaddr)); + /* get the ip if specified */ + if (argv_find(argv, argc, "ip", &ip_idx)) { + if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) { + vty_out(vty, "%% Malformed IP address\n"); + return CMD_WARNING; + } + } + build_evpn_type3_prefix((struct prefix_evpn *)argv_p, + ip.ipaddr_v4); + } else if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) { + struct prefix ip_prefix; + + memset(&ip_prefix, 0, sizeof(struct prefix)); + if (argv_find(argv, argc, "ip", &ip_idx)) { + (void)str2prefix(argv[ip_idx + 1]->arg, &ip_prefix); + apply_mask(&ip_prefix); + } + build_type5_prefix_from_ip_prefix( + (struct prefix_evpn *)argv_p, + &ip_prefix); + } + + return CMD_SUCCESS; +} /* Debug option setting interface. */ unsigned long bgp_debug_option = 0; @@ -1266,6 +1392,148 @@ DEFUN (no_debug_bgp_update_direct_peer, return CMD_SUCCESS; } +#ifndef VTYSH_EXTRACT_PL +#include "bgpd/bgp_debug_clippy.c" +#endif + +DEFPY (debug_bgp_update_prefix_afi_safi, + debug_bgp_update_prefix_afi_safi_cmd, + "debug bgp updates prefix <l2vpn>$afi <evpn>$safi type <macip mac WORD [ip WORD]|multicast ip WORD |prefix ip WORD>", + DEBUG_STR + BGP_STR + "BGP updates\n" + "Specify a prefix to debug\n" + "l2vpn\n" + "evpn\n" + "Specify EVPN Route type\n" + "MAC-IP (Type-2) route\n" + "MAC\n" + "MAC address (e.g., 00:e0:ec:20:12:62)\n" + "IP\n" + "IP address (IPv4 or IPv6)\n" + "Multicast (Type-3) route\n" + "IP\n" + "IP address (IPv4 or IPv6)\n" + "Prefix (Type-5) route\n" + "IP\n" + "Prefix route\n") +{ + int idx_ipv4_ipv6_prefixlen = 4; + struct prefix *argv_p; + int ret = CMD_SUCCESS; + afi_t afiz; + safi_t safiz; + + argv_p = prefix_new(); + + afiz = bgp_vty_afi_from_str(afi); + safiz = safi ? bgp_vty_safi_from_str(safi) : SAFI_UNICAST; + + /* check for evpn route type */ + if (afiz == AFI_L2VPN && safiz == SAFI_EVPN) { + ret = bgp_debug_parse_evpn_prefix(vty, argv, argc, &argv_p); + if (ret != CMD_SUCCESS) + return ret; + } else { + (void)str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); + apply_mask(argv_p); + } + + if (!bgp_debug_update_prefixes) + bgp_debug_update_prefixes = list_new(); + + if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL, argv_p)) { + vty_out(vty, + "BGP updates debugging is already enabled for %s\n", + argv[idx_ipv4_ipv6_prefixlen]->arg); + return CMD_SUCCESS; + } + + bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, argv_p); + + if (vty->node == CONFIG_NODE) { + DEBUG_ON(update, UPDATE_PREFIX); + } else { + TERM_DEBUG_ON(update, UPDATE_PREFIX); + vty_out(vty, "BGP updates debugging is on for %s\n", + argv[idx_ipv4_ipv6_prefixlen]->arg); + } + + return CMD_SUCCESS; +} + +DEFPY (no_debug_bgp_update_prefix_afi_safi, + no_debug_bgp_update_prefix_afi_safi_cmd, + "no debug bgp updates prefix <l2vpn>$afi <evpn>$safi type <macip mac WORD [ip WORD]|multicast ip WORD |prefix ip WORD>", + NO_STR + DEBUG_STR + BGP_STR + "BGP updates\n" + "Specify a prefix to debug\n" + "l2vpn\n" + "evpn\n" + "Specify EVPN Route type\n" + "MAC-IP (Type-2) route\n" + "MAC\n" + "MAC address (e.g., 00:e0:ec:20:12:62)\n" + "IP\n" + "IP address (IPv4 or IPv6)\n" + "Multicast (Type-3) route\n" + "IP\n" + "IP address (IPv4 or IPv6)\n" + "Prefix (Type-5) route\n" + "IP\n" + "Prefix route\n") +{ + int idx_ipv4_ipv6_prefixlen = 5; + struct prefix *argv_p; + int found_prefix = 0; + int ret = CMD_SUCCESS; + afi_t afiz; + safi_t safiz; + + argv_p = prefix_new(); + + afiz = bgp_vty_afi_from_str(afi); + safiz = safi ? bgp_vty_safi_from_str(safi) : SAFI_UNICAST; + + /* check for evpn route type */ + if (afiz == AFI_L2VPN && safiz == SAFI_EVPN) { + ret = bgp_debug_parse_evpn_prefix(vty, argv, argc, &argv_p); + if (ret != CMD_SUCCESS) + return ret; + } else { + (void)str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); + apply_mask(argv_p); + } + + if (bgp_debug_update_prefixes + && !list_isempty(bgp_debug_update_prefixes)) { + found_prefix = bgp_debug_list_remove_entry( + bgp_debug_update_prefixes, NULL, argv_p); + + if (list_isempty(bgp_debug_update_prefixes)) { + if (vty->node == CONFIG_NODE) { + DEBUG_OFF(update, UPDATE_PREFIX); + } else { + TERM_DEBUG_OFF(update, UPDATE_PREFIX); + vty_out(vty, + "BGP updates debugging (per prefix) is off\n"); + } + } + } + + if (found_prefix) + vty_out(vty, "BGP updates debugging is off for %s\n", + argv[idx_ipv4_ipv6_prefixlen]->arg); + else + vty_out(vty, "BGP updates debugging was not enabled for %s\n", + argv[idx_ipv4_ipv6_prefixlen]->arg); + + return CMD_SUCCESS; +} + + DEFUN (debug_bgp_update_prefix, debug_bgp_update_prefix_cmd, "debug bgp updates prefix <A.B.C.D/M|X:X::X:X/M>", @@ -1816,16 +2084,16 @@ DEFUN_NOSH (show_debugging_bgp, if (BGP_DEBUG(bestpath, BESTPATH)) bgp_debug_list_print(vty, " BGP bestpath debugging is on", - bgp_debug_bestpath_prefixes); + bgp_debug_bestpath_prefixes, 0); if (BGP_DEBUG(keepalive, KEEPALIVE)) bgp_debug_list_print(vty, " BGP keepalives debugging is on", - bgp_debug_keepalive_peers); + bgp_debug_keepalive_peers, 0); if (BGP_DEBUG(neighbor_events, NEIGHBOR_EVENTS)) bgp_debug_list_print(vty, " BGP neighbor-events debugging is on", - bgp_debug_neighbor_events_peers); + bgp_debug_neighbor_events_peers, 0); if (BGP_DEBUG(nht, NHT)) vty_out(vty, " BGP next-hop tracking debugging is on\n"); @@ -1835,21 +2103,21 @@ DEFUN_NOSH (show_debugging_bgp, if (BGP_DEBUG(update, UPDATE_PREFIX)) bgp_debug_list_print(vty, " BGP updates debugging is on", - bgp_debug_update_prefixes); + bgp_debug_update_prefixes, 1); if (BGP_DEBUG(update, UPDATE_IN)) bgp_debug_list_print(vty, " BGP updates debugging is on (inbound)", - bgp_debug_update_in_peers); + bgp_debug_update_in_peers, 0); if (BGP_DEBUG(update, UPDATE_OUT)) bgp_debug_list_print(vty, " BGP updates debugging is on (outbound)", - bgp_debug_update_out_peers); + bgp_debug_update_out_peers, 0); if (BGP_DEBUG(zebra, ZEBRA)) bgp_debug_list_print(vty, " BGP zebra debugging is on", - bgp_debug_zebra_prefixes); + bgp_debug_zebra_prefixes, 0); if (BGP_DEBUG(allow_martians, ALLOW_MARTIANS)) vty_out(vty, " BGP allow martian next hop debugging is on\n"); @@ -1955,18 +2223,20 @@ static int bgp_config_write_debug(struct vty *vty) if (CONF_BGP_DEBUG(bestpath, BESTPATH)) { write += bgp_debug_list_conf_print(vty, "debug bgp bestpath", - bgp_debug_bestpath_prefixes); + bgp_debug_bestpath_prefixes, + 0); } if (CONF_BGP_DEBUG(keepalive, KEEPALIVE)) { write += bgp_debug_list_conf_print(vty, "debug bgp keepalives", - bgp_debug_keepalive_peers); + bgp_debug_keepalive_peers, + 0); } if (CONF_BGP_DEBUG(neighbor_events, NEIGHBOR_EVENTS)) { write += bgp_debug_list_conf_print( vty, "debug bgp neighbor-events", - bgp_debug_neighbor_events_peers); + bgp_debug_neighbor_events_peers, 0); } if (CONF_BGP_DEBUG(nht, NHT)) { @@ -1982,17 +2252,20 @@ static int bgp_config_write_debug(struct vty *vty) if (CONF_BGP_DEBUG(update, UPDATE_PREFIX)) { write += bgp_debug_list_conf_print(vty, "debug bgp updates prefix", - bgp_debug_update_prefixes); + bgp_debug_update_prefixes, + 1); } if (CONF_BGP_DEBUG(update, UPDATE_IN)) { write += bgp_debug_list_conf_print(vty, "debug bgp updates in", - bgp_debug_update_in_peers); + bgp_debug_update_in_peers, + 0); } if (CONF_BGP_DEBUG(update, UPDATE_OUT)) { write += bgp_debug_list_conf_print(vty, "debug bgp updates out", - bgp_debug_update_out_peers); + bgp_debug_update_out_peers, + 0); } if (CONF_BGP_DEBUG(zebra, ZEBRA)) { @@ -2003,7 +2276,7 @@ static int bgp_config_write_debug(struct vty *vty) } else { write += bgp_debug_list_conf_print( vty, "debug bgp zebra prefix", - bgp_debug_zebra_prefixes); + bgp_debug_zebra_prefixes, 0); } } @@ -2095,6 +2368,10 @@ void bgp_debug_init(void) install_element(CONFIG_NODE, &debug_bgp_update_prefix_cmd); install_element(ENABLE_NODE, &no_debug_bgp_update_prefix_cmd); install_element(CONFIG_NODE, &no_debug_bgp_update_prefix_cmd); + install_element(ENABLE_NODE, &debug_bgp_update_prefix_afi_safi_cmd); + install_element(CONFIG_NODE, &debug_bgp_update_prefix_afi_safi_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_update_prefix_afi_safi_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_update_prefix_afi_safi_cmd); /* debug bgp zebra prefix A.B.C.D/M */ install_element(ENABLE_NODE, &debug_bgp_zebra_prefix_cmd); diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h index 2f59308d65..c71f371a97 100644 --- a/bgpd/bgp_ecommunity.h +++ b/bgpd/bgp_ecommunity.h @@ -48,8 +48,11 @@ #define ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT 0x02 #define ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC 0x03 #define ECOMMUNITY_EVPN_SUBTYPE_DEF_GW 0x0d +#define ECOMMUNITY_EVPN_SUBTYPE_ND 0x08 #define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY 0x01 +#define ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG 0x01 +#define ECOMMUNITY_EVPN_SUBTYPE_ND_OVERRIDE_FLAG 0x02 /* Low-order octet of the Extended Communities type field for OPAQUE types */ #define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP 0x0c diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index a026df59a0..73f225784c 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -730,10 +730,13 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr, struct ecommunity ecom_sticky; struct ecommunity ecom_default_gw; struct ecommunity ecom_rmac; + struct ecommunity ecom_na; struct ecommunity_val eval; struct ecommunity_val eval_sticky; struct ecommunity_val eval_default_gw; struct ecommunity_val eval_rmac; + struct ecommunity_val eval_na; + bgp_encap_types tnl_type; struct listnode *node, *nnode; struct ecommunity *ecom; @@ -798,6 +801,15 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr, ecommunity_merge(attr->ecommunity, &ecom_default_gw); } + if (attr->router_flag) { + memset(&ecom_na, 0, sizeof(ecom_na)); + encode_na_flag_extcomm(&eval_na, attr->router_flag); + ecom_na.size = 1; + ecom_na.val = (uint8_t *)eval_na.val; + attr->ecommunity = ecommunity_merge(attr->ecommunity, + &ecom_na); + } + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES); } @@ -1089,6 +1101,7 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, { struct bgp_info *old_select, *new_select; struct bgp_info_pair old_and_new; + struct prefix_evpn *evp; afi_t afi = AFI_L2VPN; safi_t safi = SAFI_EVPN; int ret = 0; @@ -1100,6 +1113,7 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, old_select = old_and_new.old; new_select = old_and_new.new; + evp = (struct prefix_evpn *)&rn->p; /* If the best path hasn't changed - see if there is still something to * update * to zebra RIB. @@ -1115,6 +1129,10 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); if (old_select->attr->default_gw) SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); + if (is_evpn_prefix_ipaddr_v6(evp) && + old_select->attr->router_flag) + SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); + ret = evpn_zebra_install( bgp, vpn, (struct prefix_evpn *)&rn->p, old_select->attr->nexthop, flags); @@ -1148,6 +1166,10 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); if (new_select->attr->default_gw) SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); + if (is_evpn_prefix_ipaddr_v6(evp) && + new_select->attr->router_flag) + SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); + ret = evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p, new_select->attr->nexthop, flags); /* If an old best existed and it was a "local" route, the only @@ -1695,6 +1717,8 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; attr.sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY) ? 1 : 0; attr.default_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW) ? 1 : 0; + attr.router_flag = CHECK_FLAG(flags, + ZEBRA_MACIP_TYPE_ROUTER_FLAG) ? 1 : 0; /* PMSI is only needed for type-3 routes */ if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) @@ -1993,11 +2017,13 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr_sticky, 0, 1, &ri, 0); - else if (evpn_route_is_def_gw(bgp, rn)) + else if (evpn_route_is_def_gw(bgp, rn)) { + if (is_evpn_prefix_ipaddr_v6(evp)) + attr_def_gw.router_flag = 1; update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr_def_gw, 0, 1, &ri, 0); - else + } else update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr, 0, 1, &ri, 0); } diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h index bf6a24dea6..8d71c3123e 100644 --- a/bgpd/bgp_evpn_private.h +++ b/bgpd/bgp_evpn_private.h @@ -311,6 +311,16 @@ static inline void encode_mac_mobility_extcomm(int static_mac, uint32_t seq, eval->val[7] = seq & 0xff; } +static inline void encode_na_flag_extcomm(struct ecommunity_val *eval, + uint8_t na_flag) +{ + memset(eval, 0, sizeof(*eval)); + eval->val[0] = ECOMMUNITY_ENCODE_EVPN; + eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_ND; + if (na_flag) + eval->val[2] |= ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG; +} + static inline void ip_prefix_from_type5_prefix(struct prefix_evpn *evp, struct prefix *ip) { @@ -328,7 +338,7 @@ static inline void ip_prefix_from_type5_prefix(struct prefix_evpn *evp, } } -static inline int is_evpn_prefix_default(struct prefix *evp) +static inline int is_evpn_prefix_default(const struct prefix *evp) { if (evp->family != AF_EVPN) return 0; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 795bd15613..f10f7425c6 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8163,7 +8163,7 @@ static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr, afi_t afi, safi_t safi, enum bgp_show_type type); static int bgp_show_community(struct vty *vty, struct bgp *bgp, const char *comstr, int exact, afi_t afi, - safi_t safi); + safi_t safi, uint8_t use_json); static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, @@ -9038,7 +9038,6 @@ DEFUN (show_ip_bgp, |prefix-list WORD\ |filter-list WORD\ |statistics\ - |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\ |community-list <(1-500)|WORD> [exact-match]\ |A.B.C.D/M longer-prefixes\ |X:X::X:X/M longer-prefixes\ @@ -9058,13 +9057,6 @@ DEFUN (show_ip_bgp, "Display routes conforming to the filter-list\n" "Regular expression access list name\n" "BGP RIB advertisement statistics\n" - "Display routes matching the communities\n" - COMMUNITY_AANN_STR - "Do not send outside local AS (well-known community)\n" - "Do not advertise to any peer (well-known community)\n" - "Do not export to next AS (well-known community)\n" - "Graceful shutdown (well-known community)\n" - "Exact match of the communities\n" "Display routes matching the community-list\n" "community-list number\n" "community-list name\n" @@ -9079,7 +9071,6 @@ DEFUN (show_ip_bgp, int exact_match = 0; struct bgp *bgp = NULL; int idx = 0; - int idx_community_type = 0; bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, &bgp); @@ -9106,24 +9097,6 @@ DEFUN (show_ip_bgp, return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_route_map); - if (argv_find(argv, argc, "community", &idx)) { - /* show a specific community */ - if (argv_find(argv, argc, "local-AS", &idx_community_type) - || argv_find(argv, argc, "no-advertise", - &idx_community_type) - || argv_find(argv, argc, "no-export", &idx_community_type) - || argv_find(argv, argc, "graceful-shutdown", - &idx_community_type) - || argv_find(argv, argc, "AA:NN", &idx_community_type)) { - - if (argv_find(argv, argc, "exact-match", &idx)) - exact_match = 1; - return bgp_show_community(vty, bgp, - argv[idx_community_type]->arg, - exact_match, afi, safi); - } - } - if (argv_find(argv, argc, "community-list", &idx)) { const char *clist_number_or_name = argv[++idx]->arg; if (++idx < argc && strmatch(argv[idx]->text, "exact-match")) @@ -9148,7 +9121,7 @@ DEFUN (show_ip_bgp_json, [<\ cidr-only\ |dampening <flap-statistics|dampened-paths>\ - |community \ + |community [<AA:NN|local-AS|no-advertise|no-export|graceful-shutdown>] [exact-match]\ >] [json]", SHOW_STR IP_STR @@ -9161,6 +9134,12 @@ DEFUN (show_ip_bgp_json, "Display flap statistics of routes\n" "Display paths suppressed due to dampening\n" "Display routes matching the communities\n" + COMMUNITY_AANN_STR + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Graceful shutdown (well-known community)\n" + "Exact match of the communities\n" JSON_STR) { afi_t afi = AFI_IP6; @@ -9168,6 +9147,8 @@ DEFUN (show_ip_bgp_json, enum bgp_show_type sh_type = bgp_show_type_normal; struct bgp *bgp = NULL; int idx = 0; + int idx_community_type = 0; + int exact_match = 0; bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, &bgp); @@ -9193,10 +9174,31 @@ DEFUN (show_ip_bgp_json, } if (argv_find(argv, argc, "community", &idx)) { - /* show all communities */ - return bgp_show(vty, bgp, afi, safi, - bgp_show_type_community_all, NULL, uj); + + /* show a specific community */ + if (argv_find(argv, argc, "local-AS", &idx_community_type) || + argv_find(argv, argc, "no-advertise", + &idx_community_type) || + argv_find(argv, argc, "no-export", + &idx_community_type) || + argv_find(argv, argc, "graceful-shutdown", + &idx_community_type) || + argv_find(argv, argc, "AA:NN", &idx_community_type)) { + if (argv_find(argv, argc, "exact-match", &idx)) + exact_match = 1; + + return (bgp_show_community(vty, bgp, + argv[idx_community_type]->arg, + exact_match, afi, safi, uj)); + } else { + + /* show all communities */ + return (bgp_show(vty, bgp, afi, safi, + bgp_show_type_community_all, NULL, + uj)); + } } + return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj); } @@ -9403,7 +9405,7 @@ static int bgp_show_route_map(struct vty *vty, struct bgp *bgp, static int bgp_show_community(struct vty *vty, struct bgp *bgp, const char *comstr, int exact, afi_t afi, - safi_t safi) + safi_t safi, uint8_t use_json) { struct community *com; int ret = 0; @@ -9417,7 +9419,7 @@ static int bgp_show_community(struct vty *vty, struct bgp *bgp, ret = bgp_show(vty, bgp, afi, safi, (exact ? bgp_show_type_community_exact : bgp_show_type_community), - com, 0); + com, use_json); community_free(com); return ret; diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index f9f5142cd0..903018b2a2 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -234,7 +234,8 @@ struct bgp_match_peer_compiled { /* Compares the peer specified in the 'match peer' clause with the peer received in bgp_info->peer. If it is the same, or if the peer structure received is a peer_group containing it, returns RMAP_MATCH. */ -static route_map_result_t route_match_peer(void *rule, struct prefix *prefix, +static route_map_result_t route_match_peer(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -334,7 +335,7 @@ struct route_map_rule_cmd route_match_peer_cmd = {"peer", route_match_peer, /* Match function should return 1 if match is success else return zero. */ static route_map_result_t route_match_ip_address(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -374,7 +375,7 @@ struct route_map_rule_cmd route_match_ip_address_cmd = { /* Match function return 1 if match is success else return zero. */ static route_map_result_t route_match_ip_next_hop(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -421,7 +422,7 @@ struct route_map_rule_cmd route_match_ip_next_hop_cmd = { /* Match function return 1 if match is success else return zero. */ static route_map_result_t route_match_ip_route_source(void *rule, - struct prefix *prefix, + const struct prefix *pfx, route_map_object_t type, void *object) { @@ -430,7 +431,7 @@ static route_map_result_t route_match_ip_route_source(void *rule, struct peer *peer; struct prefix_ipv4 p; - if (type == RMAP_BGP && prefix->family == AF_INET) { + if (type == RMAP_BGP && pfx->family == AF_INET) { bgp_info = object; peer = bgp_info->peer; @@ -473,7 +474,7 @@ struct route_map_rule_cmd route_match_ip_route_source_cmd = { /* `match ip address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -508,7 +509,7 @@ struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { /* `match ip next-hop prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -550,7 +551,8 @@ struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { /* `match ip route-source prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_route_source_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_route_source_prefix_list(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -599,7 +601,7 @@ struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd = { /* Match function should return 1 if match is success else 0 */ static route_map_result_t route_match_evpn_default_route(void *rule, - struct prefix *p, + const struct prefix *p, route_map_object_t type, void *object) { @@ -618,7 +620,7 @@ struct route_map_rule_cmd route_match_evpn_default_route_cmd = { /* Match function should return 1 if match is success else return zero. */ static route_map_result_t route_match_mac_address(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -667,7 +669,8 @@ struct route_map_rule_cmd route_match_mac_address_cmd = { /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t route_match_vni(void *rule, struct prefix *prefix, +static route_map_result_t route_match_vni(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { vni_t vni = 0; @@ -722,7 +725,7 @@ struct route_map_rule_cmd route_match_evpn_vni_cmd = { /* Match function should return 1 if match is success else return zero. */ static route_map_result_t route_match_evpn_route_type(void *rule, - struct prefix *prefix, + const struct prefix *pfx, route_map_object_t type, void *object) { @@ -731,7 +734,7 @@ static route_map_result_t route_match_evpn_route_type(void *rule, if (type == RMAP_BGP) { route_type = *((uint8_t *)rule); - if (route_type == prefix->u.prefix_evpn.route_type) + if (route_type == pfx->u.prefix_evpn.route_type) return RMAP_MATCH; } @@ -770,7 +773,7 @@ struct route_map_rule_cmd route_match_evpn_route_type_cmd = { /* Match function return 1 if match is success else return zero. */ static route_map_result_t route_match_local_pref(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -829,7 +832,8 @@ struct route_map_rule_cmd route_match_local_pref_cmd = { /* `match metric METRIC' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_metric(void *rule, struct prefix *prefix, +static route_map_result_t route_match_metric(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -852,7 +856,8 @@ struct route_map_rule_cmd route_match_metric_cmd = { /* `match as-path ASPATH' */ /* Match function for as-path match. I assume given object is */ -static route_map_result_t route_match_aspath(void *rule, struct prefix *prefix, +static route_map_result_t route_match_aspath(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -901,7 +906,7 @@ struct rmap_community { /* Match function for community match. */ static route_map_result_t route_match_community(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -969,7 +974,7 @@ struct route_map_rule_cmd route_match_community_cmd = { /* Match function for lcommunity match. */ static route_map_result_t route_match_lcommunity(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1030,7 +1035,7 @@ struct route_map_rule_cmd route_match_lcommunity_cmd = { /* Match function for extcommunity match. */ static route_map_result_t route_match_ecommunity(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1072,7 +1077,8 @@ struct route_map_rule_cmd route_match_ecommunity_cmd = { and `address-family vpnv4'. */ /* `match origin' */ -static route_map_result_t route_match_origin(void *rule, struct prefix *prefix, +static route_map_result_t route_match_origin(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1120,7 +1126,7 @@ struct route_map_rule_cmd route_match_origin_cmd = { /* match probability { */ static route_map_result_t route_match_probability(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1175,7 +1181,7 @@ struct route_map_rule_cmd route_match_probability_cmd = { /* Match function should return 1 if match is success else return zero. */ static route_map_result_t route_match_interface(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1221,7 +1227,8 @@ struct route_map_rule_cmd route_match_interface_cmd = { /* `set ip next-hop IP_ADDRESS' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_tag(void *rule, struct prefix *prefix, +static route_map_result_t route_match_tag(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { route_tag_t *tag; @@ -1254,7 +1261,7 @@ struct rmap_ip_nexthop_set { }; static route_map_result_t route_set_ip_nexthop(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1362,7 +1369,7 @@ struct route_map_rule_cmd route_set_ip_nexthop_cmd = { /* Set local preference. */ static route_map_result_t route_set_local_pref(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1396,7 +1403,8 @@ struct route_map_rule_cmd route_set_local_pref_cmd = { /* `set weight WEIGHT' */ /* Set weight. */ -static route_map_result_t route_set_weight(void *rule, struct prefix *prefix, +static route_map_result_t route_set_weight(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1424,7 +1432,8 @@ struct route_map_rule_cmd route_set_weight_cmd = { /* `set metric METRIC' */ /* Set metric to attribute. */ -static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, +static route_map_result_t route_set_metric(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1457,7 +1466,7 @@ struct route_map_rule_cmd route_set_metric_cmd = { /* For AS path prepend mechanism. */ static route_map_result_t route_set_aspath_prepend(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1520,7 +1529,7 @@ struct route_map_rule_cmd route_set_aspath_prepend_cmd = { * Make a deep copy of existing AS_PATH, but for the first ASn only. */ static route_map_result_t route_set_aspath_exclude(void *rule, - struct prefix *dummy, + const struct prefix *dummy, route_map_object_t type, void *object) { @@ -1554,7 +1563,8 @@ struct rmap_com_set { }; /* For community set mechanism. */ -static route_map_result_t route_set_community(void *rule, struct prefix *prefix, +static route_map_result_t route_set_community(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1670,7 +1680,7 @@ struct rmap_lcom_set { /* For lcommunity set mechanism. */ static route_map_result_t route_set_lcommunity(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1783,7 +1793,7 @@ struct route_map_rule_cmd route_set_lcommunity_cmd = { /* For large community set mechanism. */ static route_map_result_t route_set_lcommunity_delete(void *rule, - struct prefix *prefix, + const struct prefix *pfx, route_map_object_t type, void *object) { @@ -1866,10 +1876,11 @@ struct route_map_rule_cmd route_set_lcommunity_delete_cmd = { /* `set comm-list (<1-99>|<100-500>|WORD) delete' */ /* For community set mechanism. */ -static route_map_result_t route_set_community_delete(void *rule, - struct prefix *prefix, - route_map_object_t type, - void *object) +static route_map_result_t route_set_community_delete( + void *rule, + const struct prefix *prefix, + route_map_object_t type, + void *object) { struct community_list *list; struct community *merge; @@ -1950,7 +1961,7 @@ struct route_map_rule_cmd route_set_community_delete_cmd = { /* For community set mechanism. Used by _rt and _soo. */ static route_map_result_t route_set_ecommunity(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -2037,7 +2048,8 @@ struct route_map_rule_cmd route_set_ecommunity_soo_cmd = { /* `set origin ORIGIN' */ /* For origin set. */ -static route_map_result_t route_set_origin(void *rule, struct prefix *prefix, +static route_map_result_t route_set_origin(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -2087,7 +2099,7 @@ struct route_map_rule_cmd route_set_origin_cmd = { /* For atomic aggregate set. */ static route_map_result_t route_set_atomic_aggregate(void *rule, - struct prefix *prefix, + const struct prefix *pfx, route_map_object_t type, void *object) { @@ -2127,7 +2139,7 @@ struct aggregator { }; static route_map_result_t route_set_aggregator_as(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -2180,7 +2192,8 @@ struct route_map_rule_cmd route_set_aggregator_as_cmd = { }; /* Set tag to object. object must be pointer to struct bgp_info */ -static route_map_result_t route_set_tag(void *rule, struct prefix *prefix, +static route_map_result_t route_set_tag(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { route_tag_t *tag; @@ -2205,7 +2218,7 @@ static struct route_map_rule_cmd route_set_tag_cmd = { /* Set label-index to object. object must be pointer to struct bgp_info */ static route_map_result_t route_set_label_index(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -2239,7 +2252,7 @@ static struct route_map_rule_cmd route_set_label_index_cmd = { /* `match ipv6 address IP_ACCESS_LIST' */ static route_map_result_t route_match_ipv6_address(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -2275,7 +2288,7 @@ struct route_map_rule_cmd route_match_ipv6_address_cmd = { /* `match ipv6 next-hop IP_ADDRESS' */ static route_map_result_t route_match_ipv6_next_hop(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -2327,7 +2340,7 @@ struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = { /* `match ipv6 address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ipv6_address_prefix_list(void *rule, struct prefix *prefix, +route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -2363,7 +2376,7 @@ struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = { /* Set nexthop to object. ojbect must be pointer to struct attr. */ static route_map_result_t route_set_ipv6_nexthop_global(void *rule, - struct prefix *prefix, + const struct prefix *p, route_map_object_t type, void *object) { @@ -2423,7 +2436,7 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd = { /* Set next-hop preference value. */ static route_map_result_t -route_set_ipv6_nexthop_prefer_global(void *rule, struct prefix *prefix, +route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct bgp_info *bgp_info; @@ -2477,7 +2490,7 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_prefer_global_cmd = { /* Set nexthop to object. ojbect must be pointer to struct attr. */ static route_map_result_t route_set_ipv6_nexthop_local(void *rule, - struct prefix *prefix, + const struct prefix *p, route_map_object_t type, void *object) { @@ -2540,7 +2553,7 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd = { /* Set nexthop to object. ojbect must be pointer to struct attr. */ static route_map_result_t route_set_ipv6_nexthop_peer(void *rule, - struct prefix *prefix, + const struct prefix *pfx, route_map_object_t type, void *object) { @@ -2619,7 +2632,7 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = { /* `set ipv4 vpn next-hop A.B.C.D' */ static route_map_result_t route_set_vpnv4_nexthop(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -2659,7 +2672,7 @@ static void *route_set_vpnv4_nexthop_compile(const char *arg) /* `set ipv6 vpn next-hop A.B.C.D' */ static route_map_result_t route_set_vpnv6_nexthop(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -2715,7 +2728,7 @@ struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = { /* For origin set. */ static route_map_result_t route_set_originator_id(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index e9d9a846af..33f5180bd3 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -184,6 +184,7 @@ safi_t bgp_node_safi(struct vty *vty) * @param afi string, one of * - "ipv4" * - "ipv6" + * - "l2vpn" * @return the corresponding afi_t */ afi_t bgp_vty_afi_from_str(const char *afi_str) @@ -193,6 +194,8 @@ afi_t bgp_vty_afi_from_str(const char *afi_str) afi = AFI_IP; else if (strmatch(afi_str, "ipv6")) afi = AFI_IP6; + else if (strmatch(afi_str, "l2vpn")) + afi = AFI_L2VPN; return afi; } @@ -222,6 +225,8 @@ safi_t bgp_vty_safi_from_str(const char *safi_str) safi = SAFI_UNICAST; else if (strmatch(safi_str, "vpn")) safi = SAFI_MPLS_VPN; + else if (strmatch(safi_str, "evpn")) + safi = SAFI_EVPN; else if (strmatch(safi_str, "labeled-unicast")) safi = SAFI_LABELED_UNICAST; else if (strmatch(safi_str, "flowspec")) @@ -772,7 +777,7 @@ static void bgp_clear_star_soft_out(struct vty *vty, const char *name) #endif /* BGP global configuration. */ -#if defined(VERSION_TYPE_DEV) && (CONFDATE > 20190601) +#if (CONFDATE > 20190601) CPP_NOTICE("bgpd: time to remove deprecated bgp multiple-instance") CPP_NOTICE("This includes BGP_OPT_MULTIPLE_INSTANCE") #endif @@ -806,7 +811,7 @@ DEFUN_HIDDEN (no_bgp_multiple_instance, return CMD_SUCCESS; } -#if defined(VERSION_TYPE_DEV) && (CONFDATE > 20190601) +#if (CONFDATE > 20190601) CPP_NOTICE("bgpd: time to remove deprecated cli bgp config-type cisco") CPP_NOTICE("This includes BGP_OPT_CISCO_CONFIG") #endif @@ -2013,7 +2018,7 @@ DEFUN (no_bgp_fast_external_failover, } /* "bgp enforce-first-as" configuration. */ -#if defined(VERSION_TYPE_DEV) && CONFDATE > 20180517 +#if CONFDATE > 20180517 CPP_NOTICE("bgpd: remove deprecated '[no] bgp enforce-first-as' commands") #endif @@ -9115,6 +9120,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, uint8_t use_json, json_object_string_add( json_neigh, "remoteRouterId", inet_ntop(AF_INET, &p->remote_id, buf1, sizeof(buf1))); + json_object_string_add( + json_neigh, "localRouterId", + inet_ntop(AF_INET, &bgp->router_id, buf1, + sizeof(buf1))); /* Confederation */ if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) @@ -9134,7 +9143,7 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, uint8_t use_json, uptime -= p->uptime; epoch_tbuf = time(NULL) - uptime; -#if defined(VERSION_TYPE_DEV) && CONFDATE > 20200101 +#if CONFDATE > 20200101 CPP_NOTICE( "bgpTimerUp should be deprecated and can be removed now"); #endif diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index e5b269eb70..b5fb653bae 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -7356,7 +7356,7 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi, } /* clang-format off */ -#if defined(VERSION_TYPE_DEV) && CONFDATE > 20180517 +#if CONFDATE > 20180517 CPP_NOTICE("bgpd: remove 'bgp enforce-first-as' config migration from bgp_config_write") #endif /* clang-format on */ diff --git a/configure.ac b/configure.ac index 8846fcdf71..69a55d01ec 100755 --- a/configure.ac +++ b/configure.ac @@ -1832,7 +1832,13 @@ AM_CONDITIONAL([ZEROMQ], test "x$ZEROMQ" = "xtrue") dnl ---------- dnl configure date dnl ---------- -CONFDATE=`date '+%Y%m%d'` +dev_version=`echo $VERSION | grep dev` +#don't expire deprecated code in non 'dev' branch +if test "${dev_version}" = ""; then + CONFDATE=0 +else + CONFDATE=`date '+%Y%m%d'` +fi AC_SUBST(CONFDATE) dnl ------------------------------ diff --git a/doc/Makefile.am b/doc/Makefile.am index 62cb3c2edb..19aab63ea3 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -193,6 +193,7 @@ EXTRA_DIST = frr-sphinx.mk \ developer/workflow.rst \ developer/zebra.rst \ user/babeld.rst \ + user/ldpd.rst \ user/basic.rst \ user/bgp.rst \ user/bugs.rst \ diff --git a/doc/developer/modules.rst b/doc/developer/modules.rst index b832413a6c..bde7682e4e 100644 --- a/doc/developer/modules.rst +++ b/doc/developer/modules.rst @@ -100,6 +100,15 @@ a function that removes all of a module's installed hooks. There's also the ``frr_module`` symbol in modules, pretty much a standard entry point for loadable modules. +Command line parameters +----------------------- + +Command line parameters can be passed directly to a module by appending a +colon to the module name when loading it, e.g. ``-M mymodule:myparameter``. +The text after the colon will be accessible in the module's code through +``THIS_MODULE->load_args``. For example, see how the format parameter is +configured in the ``zfpm_init()`` function inside ``zebra_fpm.c``. + Hooks ----- diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst index cd03d2733d..358cb9ac7b 100644 --- a/doc/developer/workflow.rst +++ b/doc/developer/workflow.rst @@ -776,7 +776,7 @@ annotations must be ignored non-development branches. For example: .. code-block:: c - #if defined(VERSION_TYPE_DEV) && CONFDATE > 20180403 + #if CONFDATE > 20180403 CPP_NOTICE("Use of <XYZ> is deprecated, please use <ABC>") #endif diff --git a/doc/extra/spelling_wordlist.txt b/doc/extra/spelling_wordlist.txt index 4c9455e8e9..2944592962 100644 --- a/doc/extra/spelling_wordlist.txt +++ b/doc/extra/spelling_wordlist.txt @@ -83,6 +83,7 @@ IPv isis isisd lan +ldpd le libc libcap diff --git a/doc/user/index.rst b/doc/user/index.rst index a8109fe479..746cc1c32d 100644 --- a/doc/user/index.rst +++ b/doc/user/index.rst @@ -41,6 +41,7 @@ Protocols zebra bgp babeld + ldpd eigrpd isisd nhrpd diff --git a/doc/user/ldpd.rst b/doc/user/ldpd.rst new file mode 100644 index 0000000000..8d88ef176b --- /dev/null +++ b/doc/user/ldpd.rst @@ -0,0 +1,309 @@ +.. _ldp: + +*** +LDP +*** + +The *ldpd* daemon is a standardised protocol that permits exchanging MPLS label +information between MPLS devices. The LDP protocol creates peering between +devices, so as to exchange that label information. This information is stored in +MPLS table of *zebra*, and it injects that MPLS information in the underlying +system (Linux kernel or OpenBSD system for instance). +*ldpd* provides necessary options to create a Layer 2 VPN across MPLS network. +For instance, it is possible to interconnect several sites that share the same +broadcast domain. + +FRR implements LDP as described in :rfc:`5036`; other LDP standard are the +following ones: :rfc:`6720`, :rfc:`6667`, :rfc:`5919`, :rfc:`5561`, :rfc:`7552`, +:rfc:`4447`. +Because MPLS is already available, FRR also supports :rfc:`3031`. + +Running Ldpd +============ + +The *ldpd* daemon can be invoked with any of the common +options (:ref:`common-invocation-options`). + +The *zebra* daemon must be running before *ldpd* is invoked. + +Configuration of *ldpd* is done in its configuration file +:file:`ldpd.conf`. + + +.. _understanding-ldp: + +Understanding LDP principles +============================ + +Let's first introduce some definitions that permit understand better the LDP +protocol: + +- `LSR` : Labeled Switch Router. Networking devices handling labels used to + forward traffic between and through them. + +- `LER` : Labeled Edge Router. A Labeled edge router is located at the edge of + an MPLS network, generally between an IP network and an MPLS network. + + +``LDP`` aims at sharing label information across devices. It tries to establish +peering with remote LDP capable devices, first by discovering using UDP port 646 +, then by peering using TCP port 646. Once the TCP session is established, the +label information is shared, through label advertisements. + +There are different methods to send label advertisement modes. The +implementation actually supports the following : Liberal Label Retention + +Downstream Unsolicited + Independent Control. +The other advertising modes are depicted below, and compared with the current +implementation. + +- Liberal label retention versus conservative mode + In liberal mode, every label sent by every LSR is stored in the MPLS table. + In conservative mode, only the label that was sent by the best next hop + (determined by the IGP metric) for that particular FEC is stored in the MPLS + table. + +- Independent LSP Control versus ordered LSP Control + MPLS has two ways of binding labels to FEC’s; either through ordered LSP + control, or independent LSP control. + Ordered LSP control only binds a label to a FEC if it is the egress LSR, or + the router received a label binding for a FEC from the next hop router. In + this mode, an MPLS router will create a label binding for each FEC and + distribute it to its neighbors so long as he has a entry in the RIB for the + destination. + In the other mode, label bindings are made without any dependencies on another + router advertising a label for a particular FEC. Each router makes it own + independent decision to create a label for each FEC. + By default IOS uses Independent LSP Control, while Juniper implements the + Ordered Control. Both modes are interoperable, the difference is that Ordered + Control prevent blackholing during the LDP convergence process, at cost of + slowing down the convergence itself + +- unsolicited downstream versus downstream on demand + Downstream on demand label distribution is where an LSR must explicitly + request that a label be sent from its downstream router for a particular FEC. + Unsolicited label distribution is where a label is sent from the downstream + router without the original router requesting it. + +.. _configuring-ldpd: + +.. _ldp-configuration: + +LDP Configuration +=================== + +.. index:: [no] mpls ldp +.. clicmd:: [no] mpls ldp + + Enable or disable LDP daemon + +.. index:: [no] router-id A.B.C.D +.. clicmd:: [no] router-id A.B.C.D + + The following command located under MPLS router node configures the MPLS + router-id of the local device. + +.. index:: [no] address-family [ipv4 | ipv6] +.. clicmd:: [no] address-family [ipv4 | ipv6] + + Configure LDP for IPv4 or IPv6 address-family. Located under MPLS route node, + this subnode permits configuring the LDP neighbors. + +.. index:: [no] interface IFACE +.. clicmd:: [no] interface IFACE + + Located under MPLS address-family node, use this command to enable or disable + LDP discovery per interface. IFACE stands for the interface name where LDP is + enabled. By default it is disabled. Once this command executed, the + address-family interface node is configured. + +.. index:: [no] discovery transport-address A.B.C.D | A:B::C:D +.. clicmd:: [no] discovery transport-address A.B.C.D | A:B::C:D + + Located under mpls address-family interface node, use this command to set + the IPv4 or IPv6 transport-address used by the LDP protocol to talk on this + interface. + +.. index:: [no] neighbor A.B.C.D password PASSWORD +.. clicmd:: [no] neighbor A.B.C.D password PASSWORD + + The following command located under MPLS router node configures the router + of a LDP device. This device, if found, will have to comply with the + configured password. PASSWORD is a clear text password wit its digest sent + through the network. + +.. index:: [no] neighbor A.B.C.D holdtime HOLDTIME +.. clicmd:: [no] neighbor A.B.C.D holdtime HOLDTIME + + The following command located under MPLS router node configures the holdtime + value in seconds of the LDP neighbor ID. Configuring it triggers a keepalive + mechanism. That value can be configured between 15 and 65535 seconds. After + this time of non response, the LDP established session will be considered as + set to down. By default, no holdtime is configured for the LDP devices. + +.. index:: [no] discovery hello holdtime HOLDTIME +.. clicmd:: [no] discovery hello holdtime HOLDTIME + +.. index:: [no] discovery hello interval INTERVAL +.. clicmd:: [no] discovery hello interval INTERVAL + + INTERVAL value ranges from 1 to 65535 seconds. Default value is 5 seconds. + This is the value between each hello timer message sent. + HOLDTIME value ranges from 1 to 65535 seconds. Default value is 15 seconds. + That value is added as a TLV in the LDP messages. + +.. _show-ldp-information: + +Show LDP Information +==================== + +These commands dump various parts of *ldpd*. + +.. index:: show mpls ldp neighbor [A.B.C.D] +.. clicmd:: show mpls ldp neighbor [A.B.C.D] + + This command dumps the various neighbors discovered. Below example shows that + local machine has an operation neighbor with ID set to 1.1.1.1. + + :: + + west-vm# show mpls ldp neighbor + AF ID State Remote Address Uptime + ipv4 1.1.1.1 OPERATIONAL 1.1.1.1 00:01:37 + west-vm# + +.. index:: show mpls ldp neighbor [A.B.C.D] capabilities +.. clicmd:: show mpls ldp neighbor [A.B.C.D] capabilities + +.. index:: show mpls ldp neighbor [A.B.C.D] detail +.. clicmd:: show mpls ldp neighbor [A.B.C.D] detail + + Above commands dump other neighbor information. + +.. index:: show mpls ldp discovery [detail] +.. clicmd:: show mpls ldp discovery [detail] + +.. index:: show mpls ldp ipv4 discovery [detail] +.. clicmd:: show mpls ldp ipv4 discovery [detail] + +.. index:: show mpls ldp ipv6 discovery [detail] +.. clicmd:: show mpls ldp ipv6 discovery [detail] + + Above commands dump discovery information. + +.. index:: show mpls ldp ipv4 interface +.. clicmd:: show mpls ldp ipv4 interface + +.. index:: show mpls ldp ipv6 interface +.. clicmd:: show mpls ldp ipv6 interface + + Above command dumps the IPv4 or IPv6 interface per where LDP is enabled. + Below output illustrates what is dumped for IPv4. + + :: + + west-vm# show mpls ldp ipv4 interface + AF Interface State Uptime Hello Timers ac + ipv4 eth1 ACTIVE 00:08:35 5/15 0 + ipv4 eth3 ACTIVE 00:08:35 5/15 1 + + +.. index:: show mpls ldp ipv4|ipv6 binding +.. clicmd:: show mpls ldp ipv4|ipv6 binding + + Above command dumps the binding obtained through MPLS exchanges with LDP. + + :: + + west-vm# show mpls ldp ipv4 binding + AF Destination Nexthop Local Label Remote Label In Use + ipv4 1.1.1.1/32 1.1.1.1 16 imp-null yes + ipv4 2.2.2.2/32 1.1.1.1 imp-null 16 no + ipv4 10.0.2.0/24 1.1.1.1 imp-null imp-null no + ipv4 10.115.0.0/24 1.1.1.1 imp-null 17 no + ipv4 10.135.0.0/24 1.1.1.1 imp-null imp-null no + ipv4 10.200.0.0/24 1.1.1.1 17 imp-null yes + west-vm# + +LDP debugging commands +======================== + +.. index:: + simple: debug mpls ldp KIND + simple: no debug mpls ldp KIND + +.. clicmd:: [no] debug mpls ldp KIND + + Enable or disable debugging messages of a given kind. ``KIND`` can + be one of: + + - ``discovery`` + - ``errors`` + - ``event`` + - ``labels`` + - ``messages`` + - ``zebra`` + +LDP Example Configuration +========================= + +Below configuration gives a typical MPLS configuration of a device located in a +MPLS backbone. LDP is enabled on two interfaces and will attempt to peer with +two neighbors with router-id set to either 1.1.1.1 or 3.3.3.3. + +.. code-block:: frr + + mpls ldp + router-id 2.2.2.2 + neighbor 1.1.1.1 password test + neighbor 3.3.3.3 password test + ! + address-family ipv4 + discovery transport-address 2.2.2.2 + ! + interface eth1 + ! + interface eth3 + ! + exit-address-family + ! + + +Deploying LDP across a backbone generally is done in a full mesh configuration +topology. LDP is typically deployed with an IGP like OSPF, that helps discover +the remote IPs. Below example is an OSPF configuration extract that goes with +LDP configuration + +.. code-block:: frr + + router ospf + ospf router-id 2.2.2.2 + network 0.0.0.0/0 area 0 + ! + + +Below output shows the routing entry on the LER side. The OSPF routing entry +(10.200.0.0) is associated with Label entry (17), and shows that MPLS push action +that traffic to that destination will be applied. + +:: + + north-vm# show ip route + Codes: K - kernel route, C - connected, S - static, R - RIP, + O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP, + T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP, + F - PBR, + > - selected route, * - FIB route + + O>* 1.1.1.1/32 [110/120] via 10.115.0.1, eth2, label 16, 00:00:15 + O>* 2.2.2.2/32 [110/20] via 10.115.0.1, eth2, label implicit-null, 00:00:15 + O 3.3.3.3/32 [110/10] via 0.0.0.0, loopback1 onlink, 00:01:19 + C>* 3.3.3.3/32 is directly connected, loopback1, 00:01:29 + O>* 10.0.2.0/24 [110/11] via 10.115.0.1, eth2, label implicit-null, 00:00:15 + O 10.100.0.0/24 [110/10] is directly connected, eth1, 00:00:32 + C>* 10.100.0.0/24 is directly connected, eth1, 00:00:32 + O 10.115.0.0/24 [110/10] is directly connected, eth2, 00:00:25 + C>* 10.115.0.0/24 is directly connected, eth2, 00:00:32 + O>* 10.135.0.0/24 [110/110] via 10.115.0.1, eth2, label implicit-null, 00:00:15 + O>* 10.200.0.0/24 [110/210] via 10.115.0.1, eth2, label 17, 00:00:15 + north-vm# + diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index f8df33d3ee..d51f31ff37 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -638,7 +638,7 @@ int isis_circuit_up(struct isis_circuit *circuit) thread_add_timer(master, isis_run_dr_l2, circuit, 2 * circuit->hello_interval[1], &circuit->u.bc.t_run_dr[1]); - } else { + } else if (circuit->circ_type == CIRCUIT_T_P2P) { /* initializing the hello send threads * for a ptp IF */ @@ -682,9 +682,6 @@ int isis_circuit_up(struct isis_circuit *circuit) void isis_circuit_down(struct isis_circuit *circuit) { - if (circuit->state != C_STATE_UP) - return; - /* Clear the flags for all the lsps of the circuit. */ isis_circuit_update_all_srmflags(circuit, 0); @@ -756,10 +753,12 @@ void isis_circuit_down(struct isis_circuit *circuit) } /* send one gratuitous hello to spead up convergence */ - if (circuit->is_type & IS_LEVEL_1) - send_hello(circuit, IS_LEVEL_1); - if (circuit->is_type & IS_LEVEL_2) - send_hello(circuit, IS_LEVEL_2); + if (circuit->state == C_STATE_UP) { + if (circuit->is_type & IS_LEVEL_1) + send_hello(circuit, IS_LEVEL_1); + if (circuit->is_type & IS_LEVEL_2) + send_hello(circuit, IS_LEVEL_2); + } circuit->upadjcount[0] = 0; circuit->upadjcount[1] = 0; diff --git a/isisd/isis_routemap.c b/isisd/isis_routemap.c index d92207d57c..3c2cf7b3fc 100644 --- a/isisd/isis_routemap.c +++ b/isisd/isis_routemap.c @@ -50,7 +50,7 @@ #include "isis_routemap.h" static route_map_result_t route_match_ip_address(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -83,7 +83,7 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = { /* ------------------------------------------------------------*/ static route_map_result_t -route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -116,7 +116,7 @@ struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { /* ------------------------------------------------------------*/ static route_map_result_t route_match_ipv6_address(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -149,7 +149,7 @@ static struct route_map_rule_cmd route_match_ipv6_address_cmd = { /* ------------------------------------------------------------*/ static route_map_result_t -route_match_ipv6_address_prefix_list(void *rule, struct prefix *prefix, +route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -181,7 +181,8 @@ struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = { /* ------------------------------------------------------------*/ -static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, +static route_map_result_t route_set_metric(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { diff --git a/ldpd/ldp_vty_cmds.c b/ldpd/ldp_vty_cmds.c index 6c86582960..d77a3e7e93 100644 --- a/ldpd/ldp_vty_cmds.c +++ b/ldpd/ldp_vty_cmds.c @@ -861,6 +861,7 @@ ldp_vty_init (void) install_element(LDP_IPV6_NODE, &ldp_label_remote_accept_cmd); install_element(LDP_IPV6_NODE, &ldp_ttl_security_disable_cmd); install_element(LDP_IPV6_NODE, &ldp_interface_cmd); + install_element(LDP_IPV6_NODE, &no_ldp_interface_cmd); install_element(LDP_IPV6_NODE, &ldp_session_holdtime_cmd); install_element(LDP_IPV6_NODE, &ldp_neighbor_ipv6_targeted_cmd); install_element(LDP_IPV6_NODE, &ldp_exit_address_family_cmd); diff --git a/lib/compiler.h b/lib/compiler.h index 773a52e742..b19c33f65e 100644 --- a/lib/compiler.h +++ b/lib/compiler.h @@ -76,6 +76,7 @@ #else #define CPP_WARN(text) +#define CPP_NOTICE(text) #endif #endif /* _FRR_COMPILER_H */ diff --git a/lib/filter.c b/lib/filter.c index 5f391aa767..0528b0f2ad 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -157,7 +157,7 @@ static const char *filter_type_str(struct filter *filter) } /* If filter match to the prefix then return 1. */ -static int filter_match_cisco(struct filter *mfilter, struct prefix *p) +static int filter_match_cisco(struct filter *mfilter, const struct prefix *p) { struct filter_cisco *filter; struct in_addr mask; @@ -181,7 +181,7 @@ static int filter_match_cisco(struct filter *mfilter, struct prefix *p) } /* If filter match to the prefix then return 1. */ -static int filter_match_zebra(struct filter *mfilter, struct prefix *p) +static int filter_match_zebra(struct filter *mfilter, const struct prefix *p) { struct filter_zebra *filter = NULL; @@ -372,10 +372,11 @@ static struct access_list *access_list_get(afi_t afi, const char *name) } /* Apply access list to object (which should be struct prefix *). */ -enum filter_type access_list_apply(struct access_list *access, void *object) +enum filter_type access_list_apply(struct access_list *access, + const void *object) { struct filter *filter; - struct prefix *p = (struct prefix *)object; + const struct prefix *p = (const struct prefix *)object; if (access == NULL) return FILTER_DENY; @@ -549,8 +550,7 @@ static int vty_access_list_remark_unset(struct vty *vty, afi_t afi, access->remark = NULL; } - if (access->head == NULL && access->tail == NULL - && access->remark == NULL) + if (access->head == NULL && access->tail == NULL) access_list_delete(access); return CMD_SUCCESS; diff --git a/lib/filter.h b/lib/filter.h index c02516409b..97854b1e97 100644 --- a/lib/filter.h +++ b/lib/filter.h @@ -59,6 +59,7 @@ extern void access_list_reset(void); extern void access_list_add_hook(void (*func)(struct access_list *)); extern void access_list_delete_hook(void (*func)(struct access_list *)); extern struct access_list *access_list_lookup(afi_t, const char *); -extern enum filter_type access_list_apply(struct access_list *, void *); +extern enum filter_type access_list_apply(struct access_list *access, + const void *object); #endif /* _ZEBRA_FILTER_H */ diff --git a/lib/linklist.h b/lib/linklist.h index 1e2631ea46..cee6c1e505 100644 --- a/lib/linklist.h +++ b/lib/linklist.h @@ -232,7 +232,7 @@ extern void list_sort(struct list *list, * and remove list_delete_original and the list_delete #define * Additionally remove list_free entirely */ -#if defined(VERSION_TYPE_DEV) && CONFDATE > 20181001 +#if CONFDATE > 20181001 CPP_NOTICE("list_delete without double pointer is deprecated, please fixup") #endif diff --git a/lib/module.c b/lib/module.c index 0c85364003..7d5671290b 100644 --- a/lib/module.c +++ b/lib/module.c @@ -85,7 +85,7 @@ struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, char *err, *args++ = '\0'; if (!strchr(name, '/')) { - if (!handle && execname) { + if (execname) { snprintf(fullpath, sizeof(fullpath), "%s/%s_%s.so", dir, execname, name); handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL); diff --git a/lib/plist.c b/lib/plist.c index 056b737f54..2b666f256f 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -656,7 +656,7 @@ static const char *prefix_list_type_str(struct prefix_list_entry *pentry) } static int prefix_list_entry_match(struct prefix_list_entry *pentry, - struct prefix *p) + const struct prefix *p) { int ret; @@ -683,14 +683,15 @@ static int prefix_list_entry_match(struct prefix_list_entry *pentry, return 1; } -enum prefix_list_type prefix_list_apply_which_prefix(struct prefix_list *plist, - struct prefix **which, - void *object) +enum prefix_list_type prefix_list_apply_which_prefix( + struct prefix_list *plist, + const struct prefix **which, + const void *object) { struct prefix_list_entry *pentry, *pbest = NULL; - struct prefix *p = (struct prefix *)object; - uint8_t *byte = p->u.val; + const struct prefix *p = (const struct prefix *)object; + const uint8_t *byte = p->u.val; size_t depth; size_t validbits = p->prefixlen; struct pltrie_table *table; diff --git a/lib/plist.h b/lib/plist.h index 67e345a485..fecbe0e2ce 100644 --- a/lib/plist.h +++ b/lib/plist.h @@ -61,8 +61,9 @@ extern struct prefix_list *prefix_list_lookup(afi_t, const char *); * If it is a empty plist return a NULL pointer. */ extern enum prefix_list_type -prefix_list_apply_which_prefix(struct prefix_list *plist, struct prefix **which, - void *object); +prefix_list_apply_which_prefix(struct prefix_list *plist, + const struct prefix **which, + const void *object); #define prefix_list_apply(A, B) prefix_list_apply_which_prefix((A), NULL, (B)) extern struct prefix_list *prefix_bgp_orf_lookup(afi_t, const char *); diff --git a/lib/routemap.c b/lib/routemap.c index 056c793454..6c4585365a 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -1387,7 +1387,7 @@ int route_map_delete_set(struct route_map_index *index, const char *set_name, static route_map_result_t route_map_apply_match(struct route_map_rule_list *match_list, - struct prefix *prefix, route_map_object_t type, + const struct prefix *prefix, route_map_object_t type, void *object) { route_map_result_t ret = RMAP_NOMATCH; @@ -1417,7 +1417,8 @@ route_map_apply_match(struct route_map_rule_list *match_list, } /* Apply route map to the object. */ -route_map_result_t route_map_apply(struct route_map *map, struct prefix *prefix, +route_map_result_t route_map_apply(struct route_map *map, + const struct prefix *prefix, route_map_object_t type, void *object) { static int recursion = 0; diff --git a/lib/routemap.h b/lib/routemap.h index 0aeba7e1f6..0f7c391f84 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -87,8 +87,10 @@ struct route_map_rule_cmd { const char *str; /* Function for value set or match. */ - route_map_result_t (*func_apply)(void *, struct prefix *, - route_map_object_t, void *); + route_map_result_t (*func_apply)(void *rule, + const struct prefix *prefix, + route_map_object_t type, + void *object); /* Compile argument and return result as void *. */ void *(*func_compile)(const char *); @@ -208,7 +210,7 @@ extern struct route_map *route_map_lookup_by_name(const char *name); /* Apply route map to the object. */ extern route_map_result_t route_map_apply(struct route_map *map, - struct prefix *, + const struct prefix *prefix, route_map_object_t object_type, void *object); diff --git a/lib/stream.h b/lib/stream.h index 11af85c663..e808f039c6 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -133,7 +133,7 @@ struct stream_fifo { #define STREAM_CONCAT_REMAIN(S1, S2, size) ((size) - (S1)->endp - (S2)->endp) /* deprecated macros - do not use in new code */ -#if defined(VERSION_TYPE_DEV) && CONFDATE > 20181128 +#if CONFDATE > 20181128 CPP_NOTICE("lib: time to remove deprecated stream.h macros") #endif #define STREAM_PNT(S) stream_pnt((S)) @@ -628,7 +628,7 @@ int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname, } if (vrf->ns_ctxt != NULL) { ns = (struct ns *)vrf->ns_ctxt; - if (ns && 0 != strcmp(ns->name, pathname)) { + if (!strcmp(ns->name, pathname)) { if (vty) vty_out(vty, "VRF %u already configured with NETNS %s\n", @@ -661,8 +661,7 @@ int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname, ns->vrf_ctxt = (void *)vrf; vrf->ns_ctxt = (void *)ns; /* update VRF netns NAME */ - if (vrf) - strlcpy(vrf->data.l.netns_name, basename(pathname), NS_NAMSIZ); + strlcpy(vrf->data.l.netns_name, basename(pathname), NS_NAMSIZ); if (!ns_enable(ns, vrf_update_vrf_id)) { if (vty) diff --git a/lib/workqueue.h b/lib/workqueue.h index 6085820393..fe1700f8de 100644 --- a/lib/workqueue.h +++ b/lib/workqueue.h @@ -154,7 +154,7 @@ extern struct work_queue *work_queue_new(struct thread_master *, const char *); * The usage of work_queue_free is being transitioned to pass * in the double pointer to remove use after free's. */ -#if defined(VERSION_TYPE_DEV) && CONFDATE > 20190205 +#if CONFDATE > 20190205 CPP_NOTICE("work_queue_free without double pointer is deprecated, please fixup") #endif extern void work_queue_free_and_null(struct work_queue **); diff --git a/lib/zclient.h b/lib/zclient.h index ad98b8db87..49419b3df3 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -448,6 +448,8 @@ enum zapi_iptable_notify_owner { /* Zebra MAC types */ #define ZEBRA_MACIP_TYPE_STICKY 0x01 /* Sticky MAC*/ #define ZEBRA_MACIP_TYPE_GW 0x02 /* gateway (SVI) mac*/ +#define ZEBRA_MACIP_TYPE_ROUTER_FLAG 0x04 /* Router Flag - proxy NA */ +#define ZEBRA_MACIP_TYPE_OVERRIDE_FLAG 0x08 /* Override Flag */ struct zclient_options { bool receive_notify; @@ -457,7 +459,7 @@ struct zclient_options { extern struct zclient *zclient_new(struct thread_master *); /* clang-format off */ -#if defined(VERSION_TYPE_DEV) && CONFDATE > 20181101 +#if CONFDATE > 20181101 CPP_NOTICE("zclient_new_notify can take over or zclient_new now"); #endif /* clang-format on */ @@ -598,7 +600,7 @@ extern void zebra_interface_if_set_value(struct stream *, struct interface *); extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid); /* clang-format off */ -#if defined(VERSION_TYPE_DEV) && CONFDATE > 20180823 +#if CONFDATE > 20180823 CPP_NOTICE("zapi_ipv4_route, zapi_ipv6_route, zapi_ipv4_route_ipv6_nexthop as well as the zapi_ipv4 and zapi_ipv6 data structures should be removed now"); #endif /* clang-format on */ diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index a723396507..e6bd3faf40 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -1345,7 +1345,8 @@ static void ospf6_redistribute_show_config(struct vty *vty) /* Routemap Functions */ static route_map_result_t -ospf6_routemap_rule_match_address_prefixlist(void *rule, struct prefix *prefix, +ospf6_routemap_rule_match_address_prefixlist(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1384,7 +1385,7 @@ struct route_map_rule_cmd ospf6_routemap_rule_match_address_prefixlist_cmd = { /* Match function should return 1 if match is success else return zero. */ static route_map_result_t -ospf6_routemap_rule_match_interface(void *rule, struct prefix *prefix, +ospf6_routemap_rule_match_interface(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct interface *ifp; @@ -1422,7 +1423,7 @@ struct route_map_rule_cmd ospf6_routemap_rule_match_interface_cmd = { /* Match function for matching route tags */ static route_map_result_t ospf6_routemap_rule_match_tag(void *rule, - struct prefix *prefix, + const struct prefix *p, route_map_object_t type, void *object) { @@ -1442,7 +1443,7 @@ static struct route_map_rule_cmd ospf6_routemap_rule_match_tag_cmd = { }; static route_map_result_t -ospf6_routemap_rule_set_metric_type(void *rule, struct prefix *prefix, +ospf6_routemap_rule_set_metric_type(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { char *metric_type = rule; @@ -1478,7 +1479,7 @@ struct route_map_rule_cmd ospf6_routemap_rule_set_metric_type_cmd = { }; static route_map_result_t -ospf6_routemap_rule_set_metric(void *rule, struct prefix *prefix, +ospf6_routemap_rule_set_metric(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { char *metric = rule; @@ -1513,7 +1514,7 @@ struct route_map_rule_cmd ospf6_routemap_rule_set_metric_cmd = { }; static route_map_result_t -ospf6_routemap_rule_set_forwarding(void *rule, struct prefix *prefix, +ospf6_routemap_rule_set_forwarding(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { char *forwarding = rule; @@ -1551,7 +1552,7 @@ struct route_map_rule_cmd ospf6_routemap_rule_set_forwarding_cmd = { }; static route_map_result_t ospf6_routemap_rule_set_tag(void *rule, - struct prefix *prefix, + const struct prefix *p, route_map_object_t type, void *object) { diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 7bf099fbbf..fde47c74fe 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -425,13 +425,13 @@ DEFUN(no_ospf6_router_id, return CMD_SUCCESS; } -#if defined(VERSION_TYPE_DEV) && CONFDATE > 20180828 +#if CONFDATE > 20180828 CPP_NOTICE("ospf6: `router-id A.B.C.D` deprecated 2017/08/28") #endif ALIAS_HIDDEN(ospf6_router_id, ospf6_router_id_hdn_cmd, "router-id A.B.C.D", "Configure OSPF6 Router-ID\n" V4NOTATION_STR) -#if defined(VERSION_TYPE_DEV) && CONFDATE > 20180828 +#if CONFDATE > 20180828 CPP_NOTICE("ospf6: `no router-id A.B.C.D` deprecated 2017/08/28") #endif ALIAS_HIDDEN(no_ospf6_router_id, no_ospf6_router_id_hdn_cmd, diff --git a/ospfd/ospf_routemap.c b/ospfd/ospf_routemap.c index f3271acfa2..c5ec1db336 100644 --- a/ospfd/ospf_routemap.c +++ b/ospfd/ospf_routemap.c @@ -118,7 +118,7 @@ static void ospf_route_map_event(route_map_event_t event, const char *name) /* `match ip netxthop ' */ /* Match function return 1 if match is success else return zero. */ static route_map_result_t route_match_ip_nexthop(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -163,7 +163,7 @@ struct route_map_rule_cmd route_match_ip_nexthop_cmd = { /* `match ip next-hop prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -205,7 +205,7 @@ struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { /* Match function should return 1 if match is success else return zero. */ static route_map_result_t route_match_ip_address(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -244,7 +244,7 @@ struct route_map_rule_cmd route_match_ip_address_cmd = { /* `match ip address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -280,7 +280,7 @@ struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { /* Match function should return 1 if match is success else return zero. */ static route_map_result_t route_match_interface(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -318,7 +318,8 @@ struct route_map_rule_cmd route_match_interface_cmd = { route_match_interface_free}; /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_tag(void *rule, struct prefix *prefix, +static route_map_result_t route_match_tag(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { route_tag_t *tag; @@ -348,7 +349,8 @@ struct ospf_metric { /* `set metric METRIC' */ /* Set metric to attribute. */ -static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, +static route_map_result_t route_set_metric(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -427,7 +429,7 @@ struct route_map_rule_cmd route_set_metric_cmd = { /* `set metric-type TYPE' */ /* Set metric-type to attribute. */ static route_map_result_t route_set_metric_type(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -476,7 +478,7 @@ struct route_map_rule_cmd route_set_metric_type_cmd = { route_set_metric_type_free, }; -static route_map_result_t route_set_tag(void *rule, struct prefix *prefix, +static route_map_result_t route_set_tag(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { route_tag_t *tag; diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index ae2daf40aa..460bbfeae7 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4252,7 +4252,7 @@ DEFUN (show_ip_pim_nexthop_lookup, "Source/RP address\n" "Multicast Group address\n") { - struct pim_nexthop_cache pnc; + struct pim_nexthop_cache *pnc = NULL; struct prefix nht_p; int result = 0; struct in_addr src_addr, grp_addr; @@ -4264,6 +4264,7 @@ DEFUN (show_ip_pim_nexthop_lookup, char grp_str[PREFIX_STRLEN]; int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct pim_rpf rpf; if (!vrf) return CMD_WARNING; @@ -4301,7 +4302,6 @@ DEFUN (show_ip_pim_nexthop_lookup, 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; @@ -4310,12 +4310,18 @@ DEFUN (show_ip_pim_nexthop_lookup, grp.u.prefix4 = grp_addr; memset(&nexthop, 0, sizeof(nexthop)); - if (pim_find_or_track_nexthop(vrf->info, &nht_p, NULL, NULL, &pnc)) - result = pim_ecmp_nexthop_search(vrf->info, &pnc, &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 = vif_source; + + pnc = pim_nexthop_cache_find(vrf->info, &rpf); + if (pnc) + result = pim_ecmp_nexthop_search(vrf->info, pnc, &nexthop, &nht_p, &grp, 0); else - result = pim_ecmp_nexthop_lookup(vrf->info, &nexthop, - vif_source, &nht_p, &grp, 0); + result = pim_ecmp_nexthop_lookup(vrf->info, &nexthop, &nht_p, + &grp, 0); if (!result) { vty_out(vty, diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index e82a7589b7..eb3307589e 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -136,9 +136,8 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) mask = PIM_OIF_FLAG_PROTO_IGMP; /* SGRpt entry could have empty oil */ - if (ch->upstream->channel_oil) - pim_channel_del_oif(ch->upstream->channel_oil, - ch->interface, mask); + pim_channel_del_oif(ch->upstream->channel_oil, ch->interface, + mask); /* * Do we have any S,G's that are inheriting? * Nuke from on high too. diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 42bdd80ce2..b46f1b5e9d 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -909,10 +909,9 @@ static int pim_igmp_read(struct thread *t) socklen_t fromlen = sizeof(from); socklen_t tolen = sizeof(to); ifindex_t ifindex = -1; - int cont = 1; int len; - while (cont) { + while (1) { len = pim_socket_recvfromto(igmp->fd, buf, sizeof(buf), &from, &fromlen, &to, &tolen, &ifindex); if (len < 0) { diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index ac49373da0..7d1940bec1 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -418,16 +418,21 @@ int pim_ecmp_nexthop_search(struct pim_instance *pim, struct pim_nexthop *nexthop, struct prefix *src, struct prefix *grp, int neighbor_needed) { - struct pim_neighbor *nbr = NULL; + struct pim_neighbor *nbrs[MULTIPATH_NUM], *nbr; + struct interface *ifps[MULTIPATH_NUM]; 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; + uint32_t i, num_nbrs = 0; if (!pnc || !pnc->nexthop_num || !nexthop) return 0; + memset(&nbrs, 0, sizeof(nbrs)); + memset(&ifps, 0, sizeof(ifps)); + // Current Nexthop is VALID, check to stay on the current path. if (nexthop->interface && nexthop->interface->info && nexthop->mrib_nexthop_addr.u.prefix4.s_addr @@ -487,16 +492,41 @@ int pim_ecmp_nexthop_search(struct pim_instance *pim, } } } + + /* + * Look up all interfaces and neighbors, + * store for later usage + */ + for (nh_node = pnc->nexthop, i = 0; nh_node; + nh_node = nh_node->next, i++) { + ifps[i] = if_lookup_by_index(nh_node->ifindex, pim->vrf_id); + if (ifps[i]) { + nbrs[i] = pim_neighbor_find(ifps[i], + nh_node->gate.ipv4); + if (nbrs[i] || pim_if_connected_to_source(ifps[i], + + src->u.prefix4)) + num_nbrs++; + } + } if (pim->ecmp_enable) { + uint32_t consider = pnc->nexthop_num; + + if (neighbor_needed && num_nbrs < consider) + consider = num_nbrs; + + if (consider == 0) + 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; + mod_val = hash_val % consider; } 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, pim->vrf_id); + ifp = ifps[nh_iter]; if (!ifp) { if (PIM_DEBUG_PIM_NHT) { char addr_str[INET_ADDRSTRLEN]; @@ -532,7 +562,7 @@ int pim_ecmp_nexthop_search(struct pim_instance *pim, if (neighbor_needed && !pim_if_connected_to_source(ifp, src->u.prefix4)) { - nbr = pim_neighbor_find(ifp, nh_node->gate.ipv4); + nbr = nbrs[nh_iter]; if (!nbr && !if_is_loopback(ifp)) { if (PIM_DEBUG_PIM_NHT) zlog_debug( @@ -767,22 +797,23 @@ int pim_parse_nexthop_update(int command, struct zclient *zclient, } int pim_ecmp_nexthop_lookup(struct pim_instance *pim, - struct pim_nexthop *nexthop, struct in_addr addr, - struct prefix *src, struct prefix *grp, - int neighbor_needed) + struct pim_nexthop *nexthop, struct prefix *src, + struct prefix *grp, int neighbor_needed) { struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; - struct pim_neighbor *nbr = NULL; + struct pim_neighbor *nbrs[MULTIPATH_NUM], *nbr = NULL; int num_ifindex; - struct interface *ifp; + struct interface *ifps[MULTIPATH_NUM], *ifp; int first_ifindex; int found = 0; uint8_t i = 0; uint32_t hash_val = 0, mod_val = 0; + uint32_t num_nbrs = 0; + char addr_str[PREFIX_STRLEN]; if (PIM_DEBUG_PIM_NHT) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); + pim_inet4_dump("<addr?>", src->u.prefix4, addr_str, + sizeof(addr_str)); zlog_debug("%s: Looking up: %s(%s), last lookup time: %lld", __PRETTY_FUNCTION__, addr_str, pim->vrf->name, nexthop->last_lookup_time); @@ -790,44 +821,66 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim, memset(nexthop_tab, 0, sizeof(struct pim_zlookup_nexthop) * MULTIPATH_NUM); - num_ifindex = zclient_lookup_nexthop(pim, nexthop_tab, MULTIPATH_NUM, - addr, PIM_NEXTHOP_LOOKUP_MAX); + num_ifindex = + zclient_lookup_nexthop(pim, nexthop_tab, MULTIPATH_NUM, + src->u.prefix4, PIM_NEXTHOP_LOOKUP_MAX); if (num_ifindex < 1) { - if (PIM_DEBUG_PIM_NHT) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, - sizeof(addr_str)); + if (PIM_DEBUG_PIM_NHT) zlog_warn( "%s: could not find nexthop ifindex for address %s(%s)", __PRETTY_FUNCTION__, addr_str, pim->vrf->name); - } return 0; } + memset(&nbrs, 0, sizeof(nbrs)); + memset(&ifps, 0, sizeof(ifps)); + + /* + * Look up all interfaces and neighbors, + * store for later usage + */ + for (i = 0; i < num_ifindex; i++) { + ifps[i] = if_lookup_by_index(nexthop_tab[i].ifindex, + pim->vrf_id); + if (ifps[i]) { + nbrs[i] = pim_neighbor_find( + ifps[i], nexthop_tab[i].nexthop_addr.u.prefix4); + if (nbrs[i] + || pim_if_connected_to_source(ifps[i], + src->u.prefix4)) + num_nbrs++; + } + } + // If PIM ECMP enable then choose ECMP path. if (pim->ecmp_enable) { + uint32_t consider = num_ifindex; + + if (neighbor_needed && num_nbrs < consider) + consider = num_nbrs; + + if (consider == 0) + return 0; + hash_val = pim_compute_ecmp_hash(src, grp); - mod_val = hash_val % num_ifindex; + mod_val = hash_val % consider; if (PIM_DEBUG_PIM_NHT_DETAIL) zlog_debug("%s: hash_val %u mod_val %u", __PRETTY_FUNCTION__, hash_val, mod_val); } + i = 0; while (!found && (i < num_ifindex)) { first_ifindex = nexthop_tab[i].ifindex; - ifp = if_lookup_by_index(first_ifindex, pim->vrf_id); + ifp = ifps[i]; if (!ifp) { - if (PIM_DEBUG_PIM_NHT) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, - sizeof(addr_str)); + if (PIM_DEBUG_PIM_NHT) zlog_debug( "%s %s: could not find interface for ifindex %d (address %s(%s))", __FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str, pim->vrf->name); - } if (i == mod_val) mod_val++; i++; @@ -835,24 +888,20 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim, } if (!ifp->info) { - if (PIM_DEBUG_PIM_NHT) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, - sizeof(addr_str)); + if (PIM_DEBUG_PIM_NHT) zlog_debug( "%s: multicast not enabled on input interface %s(%s) (ifindex=%d, RPF for source %s)", __PRETTY_FUNCTION__, ifp->name, pim->vrf->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 (neighbor_needed + && !pim_if_connected_to_source(ifp, src->u.prefix4)) { + nbr = nbrs[i]; if (PIM_DEBUG_PIM_NHT_DETAIL) zlog_debug("ifp name: %s(%s), pim nbr: %p", ifp->name, pim->vrf->name, nbr); @@ -860,16 +909,11 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim, if (i == mod_val) mod_val++; i++; - if (PIM_DEBUG_PIM_NHT) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, - addr_str, - sizeof(addr_str)); + if (PIM_DEBUG_PIM_NHT) zlog_debug( "%s: NBR not found on input interface %s(%s) (RPF for source %s)", __PRETTY_FUNCTION__, ifp->name, pim->vrf->name, addr_str); - } continue; } } @@ -877,12 +921,10 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim, if (i == mod_val) { if (PIM_DEBUG_PIM_NHT) { char nexthop_str[PREFIX_STRLEN]; - char addr_str[INET_ADDRSTRLEN]; + pim_addr_dump("<nexthop?>", &nexthop_tab[i].nexthop_addr, nexthop_str, sizeof(nexthop_str)); - pim_inet4_dump("<addr?>", addr, addr_str, - sizeof(addr_str)); zlog_debug( "%s: found nhop %s for addr %s interface %s(%s) metric %d dist %d", __PRETTY_FUNCTION__, nexthop_str, @@ -898,7 +940,7 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim, nexthop_tab[i].protocol_distance; nexthop->mrib_route_metric = nexthop_tab[i].route_metric; - nexthop->last_lookup = addr; + nexthop->last_lookup = src->u.prefix4; nexthop->last_lookup_time = pim_time_monotonic_usec(); nexthop->nbr = nbr; found = 1; @@ -913,59 +955,36 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim, } int pim_ecmp_fib_lookup_if_vif_index(struct pim_instance *pim, - struct in_addr addr, struct prefix *src, - struct prefix *grp) + struct prefix *src, struct prefix *grp) { - struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; - int num_ifindex; + struct pim_nexthop nhop; int vif_index; - ifindex_t first_ifindex; - uint32_t hash_val = 0, mod_val = 0; + ifindex_t ifindex; + char addr_str[PREFIX_STRLEN]; - memset(nexthop_tab, 0, - sizeof(struct pim_zlookup_nexthop) * MULTIPATH_NUM); - num_ifindex = zclient_lookup_nexthop(pim, nexthop_tab, MULTIPATH_NUM, - addr, PIM_NEXTHOP_LOOKUP_MAX); - if (num_ifindex < 1) { - if (PIM_DEBUG_PIM_NHT) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, - sizeof(addr_str)); + if (PIM_DEBUG_PIM_NHT) + pim_inet4_dump("<addr?>", src->u.prefix4, addr_str, + sizeof(addr_str)); + if (!pim_ecmp_nexthop_lookup(pim, &nhop, src, grp, 0)) { + if (PIM_DEBUG_PIM_NHT) zlog_debug( "%s: could not find nexthop ifindex for address %s(%s)", __PRETTY_FUNCTION__, addr_str, pim->vrf->name); - } return -1; } - // If PIM ECMP enable then choose ECMP path. - if (pim->ecmp_enable) { - hash_val = pim_compute_ecmp_hash(src, grp); - mod_val = hash_val % num_ifindex; - if (PIM_DEBUG_PIM_NHT_DETAIL) - zlog_debug("%s: hash_val %u mod_val %u", - __PRETTY_FUNCTION__, hash_val, mod_val); - } - - first_ifindex = nexthop_tab[mod_val].ifindex; - - if (PIM_DEBUG_PIM_NHT) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", addr, addr_str, sizeof(addr_str)); + ifindex = nhop.interface->ifindex; + if (PIM_DEBUG_PIM_NHT) zlog_debug( "%s: found nexthop ifindex=%d (interface %s(%s)) for address %s", - __PRETTY_FUNCTION__, first_ifindex, - ifindex2ifname(first_ifindex, pim->vrf_id), + __PRETTY_FUNCTION__, ifindex, + ifindex2ifname(ifindex, pim->vrf_id), pim->vrf->name, addr_str); - } - vif_index = pim_if_find_vifindex_by_ifindex(pim, first_ifindex); + vif_index = pim_if_find_vifindex_by_ifindex(pim, ifindex); if (vif_index < 0) { if (PIM_DEBUG_PIM_NHT) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, - sizeof(addr_str)); zlog_debug( "%s: low vif_index=%d(%s) < 1 nexthop for address %s", __PRETTY_FUNCTION__, vif_index, pim->vrf->name, diff --git a/pimd/pim_nht.h b/pimd/pim_nht.h index 77e25dcd70..796fbf9731 100644 --- a/pimd/pim_nht.h +++ b/pimd/pim_nht.h @@ -61,13 +61,11 @@ int pim_ecmp_nexthop_search(struct pim_instance *pim, struct pim_nexthop *nexthop, struct prefix *src, struct prefix *grp, int neighbor_needed); int pim_ecmp_nexthop_lookup(struct pim_instance *pim, - struct pim_nexthop *nexthop, struct in_addr addr, - struct prefix *src, struct prefix *grp, - int neighbor_needed); + struct pim_nexthop *nexthop, struct prefix *src, + struct prefix *grp, int neighbor_needed); void pim_sendmsg_zebra_rnh(struct pim_instance *pim, struct zclient *zclient, struct pim_nexthop_cache *pnc, int command); void pim_resolve_upstream_nh(struct pim_instance *pim, struct prefix *nht_p); int pim_ecmp_fib_lookup_if_vif_index(struct pim_instance *pim, - struct in_addr addr, struct prefix *src, - struct prefix *grp); + struct prefix *src, struct prefix *grp); #endif diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 7e053d2aa0..c1623ec15e 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -194,7 +194,7 @@ static int pim_rp_prefix_list_used(struct pim_instance *pim, const char *plist) */ static struct rp_info *pim_rp_find_exact(struct pim_instance *pim, struct in_addr rp, - struct prefix *group) + const struct prefix *group) { struct listnode *node; struct rp_info *rp_info; @@ -212,13 +212,13 @@ static struct rp_info *pim_rp_find_exact(struct pim_instance *pim, * Given a group, return the rp_info for that group */ static struct rp_info *pim_rp_find_match_group(struct pim_instance *pim, - struct prefix *group) + const struct prefix *group) { struct listnode *node; struct rp_info *best = NULL; struct rp_info *rp_info; struct prefix_list *plist; - struct prefix *p, *bp; + const struct prefix *p, *bp; struct route_node *rn; bp = NULL; @@ -477,10 +477,9 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, &rp_all->group, 1)) return PIM_RP_NO_PATH; } else { - if (pim_nexthop_lookup( + if (!pim_ecmp_nexthop_lookup( pim, &rp_all->rp.source_nexthop, - rp_all->rp.rpf_addr.u.prefix4, 1) - != 0) + &nht_p, &rp_all->group, 1)) return PIM_RP_NO_PATH; } pim_rp_check_interfaces(pim, rp_all); @@ -556,9 +555,8 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, &nht_p, &rp_info->group, 1)) return PIM_RP_NO_PATH; } else { - if (pim_nexthop_lookup(pim, &rp_info->rp.source_nexthop, - rp_info->rp.rpf_addr.u.prefix4, 1) - != 0) + if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop, + &nht_p, &rp_info->group, 1)) return PIM_RP_NO_PATH; } @@ -687,9 +685,9 @@ void pim_rp_setup(struct pim_instance *pim) "%s: NHT Local Nexthop not found for RP %s ", __PRETTY_FUNCTION__, buf); } - if (pim_nexthop_lookup( - pim, &rp_info->rp.source_nexthop, - rp_info->rp.rpf_addr.u.prefix4, 1) < 0) + if (!pim_ecmp_nexthop_lookup(pim, + &rp_info->rp.source_nexthop, + &nht_p, &rp_info->group, 1)) if (PIM_DEBUG_PIM_NHT_RP) zlog_debug( "Unable to lookup nexthop for rp specified"); @@ -854,8 +852,9 @@ struct pim_rpf *pim_rp_g(struct pim_instance *pim, struct in_addr group) __PRETTY_FUNCTION__, buf, buf1); } pim_rpf_set_refresh_time(pim); - pim_nexthop_lookup(pim, &rp_info->rp.source_nexthop, - rp_info->rp.rpf_addr.u.prefix4, 1); + pim_ecmp_nexthop_lookup(pim, + &rp_info->rp.source_nexthop, + &nht_p, &rp_info->group, 1); } return (&rp_info->rp); } diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index da14e8b3eb..b02102c8fd 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -203,6 +203,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim, struct prefix nht_p; struct pim_nexthop_cache pnc; struct prefix src, grp; + bool neigh_needed = true; saved.source_nexthop = rpf->source_nexthop; saved.rpf_addr = rpf->rpf_addr; @@ -226,23 +227,20 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim, grp.prefixlen = IPV4_MAX_BITLEN; grp.u.prefix4 = up->sg.grp; memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); + + if ((up->sg.src.s_addr == INADDR_ANY && I_am_RP(pim, up->sg.grp)) || + PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) + neigh_needed = FALSE; if (pim_find_or_track_nexthop(pim, &nht_p, up, NULL, &pnc)) { if (pnc.nexthop_num) { - if (!pim_ecmp_nexthop_search( - pim, &pnc, &up->rpf.source_nexthop, &src, - &grp, - !PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) - && !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP( - up->flags))) + if (!pim_ecmp_nexthop_search(pim, &pnc, + &up->rpf.source_nexthop, + &src, &grp, neigh_needed)) return PIM_RPF_FAILURE; } } else { - if (!pim_ecmp_nexthop_lookup( - pim, &rpf->source_nexthop, up->upstream_addr, &src, - &grp, - !PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) - && !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP( - up->flags))) + if (!pim_ecmp_nexthop_lookup(pim, &rpf->source_nexthop, &src, + &grp, neigh_needed)) return PIM_RPF_FAILURE; } diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index a58dfcdd5f..b947ca0625 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -561,7 +561,7 @@ void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index) __PRETTY_FUNCTION__, source_str, group_str); } input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index( - c_oil->pim, vif_source, &src, &grp); + c_oil->pim, &src, &grp); } if (input_iface_vif_index < 1) { @@ -868,6 +868,7 @@ void igmp_source_forward_reevaluate_all(struct pim_instance *pim) void igmp_source_forward_start(struct pim_instance *pim, struct igmp_source *source) { + struct pim_interface *pim_oif; struct igmp_group *group; struct prefix_sg sg; int result; @@ -893,10 +894,20 @@ void igmp_source_forward_start(struct pim_instance *pim, } group = source->source_group; + pim_oif = group->group_igmp_sock->interface->info; + if (!pim_oif) { + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug( + "%s: multicast not enabled on oif=%s ?", + __PRETTY_FUNCTION__, + source->source_group->group_igmp_sock + ->interface->name); + } + return; + } if (!source->source_channel_oil) { struct in_addr vif_source; - struct pim_interface *pim_oif; struct prefix nht_p, src, grp; struct pim_nexthop_cache out_pnc; struct pim_nexthop nexthop; @@ -953,8 +964,8 @@ void igmp_source_forward_start(struct pim_instance *pim, } } else input_iface_vif_index = - pim_ecmp_fib_lookup_if_vif_index( - pim, vif_source, &src, &grp); + pim_ecmp_fib_lookup_if_vif_index(pim, &src, + &grp); if (PIM_DEBUG_ZEBRA) { char buf2[INET_ADDRSTRLEN]; @@ -983,19 +994,6 @@ void igmp_source_forward_start(struct pim_instance *pim, source and receiver attached to the same interface. See TODO T22. */ - pim_oif = - source->source_group->group_igmp_sock->interface->info; - if (!pim_oif) { - if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug( - "%s: multicast not enabled on oif=%s ?", - __PRETTY_FUNCTION__, - source->source_group->group_igmp_sock - ->interface->name); - } - return; - } - if (input_iface_vif_index == pim_oif->mroute_vif_index) { /* ignore request for looped MFC entry */ if (PIM_DEBUG_IGMP_TRACE) { @@ -1036,12 +1034,15 @@ void igmp_source_forward_start(struct pim_instance *pim, return; } + if (!(PIM_I_am_DR(pim_oif))) + return; + /* Feed IGMPv3-gathered local membership information into PIM per-interface (S,G) state. */ if (!pim_ifchannel_local_membership_add( - group->group_igmp_sock->interface, &sg)) { + group->group_igmp_sock->interface, &sg)) { if (PIM_DEBUG_MROUTE) zlog_warn("%s: Failure to add local membership for %s", __PRETTY_FUNCTION__, pim_str_sg_dump(&sg)); @@ -1153,7 +1154,7 @@ void pim_forward_start(struct pim_ifchannel *ch) /* 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; + nht_p.u.prefix4 = up->upstream_addr; grp.family = AF_INET; grp.prefixlen = IPV4_MAX_BITLEN; grp.u.prefix4 = up->sg.grp; @@ -1204,8 +1205,8 @@ void pim_forward_start(struct pim_ifchannel *ch) } } else input_iface_vif_index = - pim_ecmp_fib_lookup_if_vif_index( - pim, up->upstream_addr, &src, &grp); + pim_ecmp_fib_lookup_if_vif_index(pim, &src, + &grp); if (input_iface_vif_index < 1) { if (PIM_DEBUG_PIM_TRACE) { diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index e2be7050d7..85fb309048 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -370,6 +370,10 @@ ln -s %{_sbindir}/frr %{buildroot}%{_initddir}/frr %endif install %{zeb_rh_src}/daemons %{buildroot}%{_sysconfdir}/frr +# add rpki module to daemon +%if %{with_rpki} + sed -i -e 's/^\(bgpd_options=\)\(.*\)\(".*\)/\1\2 -M rpki\3/' %{buildroot}%{_sysconfdir}/frr/daemons +%endif install -m644 %{zeb_rh_src}/frr.pam %{buildroot}%{_sysconfdir}/pam.d/frr install -m644 %{zeb_rh_src}/frr.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/frr install -d -m750 %{buildroot}%{rundir} diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c index 2c02324876..88473c164e 100644 --- a/ripd/rip_routemap.c +++ b/ripd/rip_routemap.c @@ -58,7 +58,8 @@ static void rip_route_map_update(const char *notused) /* `match metric METRIC' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_metric(void *rule, struct prefix *prefix, +static route_map_result_t route_match_metric(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -111,7 +112,7 @@ struct route_map_rule_cmd route_match_metric_cmd = { /* `match interface IFNAME' */ /* Match function return 1 if match is success else return zero. */ static route_map_result_t route_match_interface(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -159,7 +160,7 @@ struct route_map_rule_cmd route_match_interface_cmd = { /* Match function return 1 if match is success else return zero. */ static route_map_result_t route_match_ip_next_hop(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -206,7 +207,7 @@ static struct route_map_rule_cmd route_match_ip_next_hop_cmd = { /* `match ip next-hop prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -251,7 +252,7 @@ static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { /* Match function should return 1 if match is success else return zero. */ static route_map_result_t route_match_ip_address(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -290,7 +291,7 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = { /* `match ip address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -324,7 +325,7 @@ static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { /* `match tag TAG' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_tag(void *rule, struct prefix *prefix, +static route_map_result_t route_match_tag(void *rule, const struct prefix *p, route_map_object_t type, void *object) { route_tag_t *tag; @@ -354,7 +355,8 @@ static struct route_map_rule_cmd route_match_tag_cmd = { /* `set metric METRIC' */ /* Set metric to attribute. */ -static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, +static route_map_result_t route_set_metric(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -453,7 +455,7 @@ static struct route_map_rule_cmd route_set_metric_cmd = { /* Set nexthop to object. ojbect must be pointer to struct attr. */ static route_map_result_t route_set_ip_nexthop(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -505,7 +507,7 @@ static struct route_map_rule_cmd route_set_ip_nexthop_cmd = { /* `set tag TAG' */ /* Set tag to object. ojbect must be pointer to struct attr. */ -static route_map_result_t route_set_tag(void *rule, struct prefix *prefix, +static route_map_result_t route_set_tag(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { route_tag_t *tag; diff --git a/ripngd/ripng_routemap.c b/ripngd/ripng_routemap.c index e9a38d137b..a18332516e 100644 --- a/ripngd/ripng_routemap.c +++ b/ripngd/ripng_routemap.c @@ -38,7 +38,8 @@ struct rip_metric_modifier { /* `match metric METRIC' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_metric(void *rule, struct prefix *prefix, +static route_map_result_t route_match_metric(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -86,7 +87,7 @@ static struct route_map_rule_cmd route_match_metric_cmd = { /* `match interface IFNAME' */ /* Match function return 1 if match is success else return zero. */ static route_map_result_t route_match_interface(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -128,7 +129,8 @@ static struct route_map_rule_cmd route_match_interface_cmd = { /* `match tag TAG' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_tag(void *rule, struct prefix *prefix, +static route_map_result_t route_match_tag(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { route_tag_t *tag; @@ -157,7 +159,8 @@ static struct route_map_rule_cmd route_match_tag_cmd = { /* `set metric METRIC' */ /* Set metric to attribute. */ -static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, +static route_map_result_t route_set_metric(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -254,7 +257,7 @@ static struct route_map_rule_cmd route_set_metric_cmd = { /* Set nexthop to object. ojbect must be pointer to struct attr. */ static route_map_result_t route_set_ipv6_nexthop_local(void *rule, - struct prefix *prefix, + const struct prefix *p, route_map_object_t type, void *object) { @@ -307,7 +310,8 @@ static struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd = { /* `set tag TAG' */ /* Set tag to object. ojbect must be pointer to struct attr. */ -static route_map_result_t route_set_tag(void *rule, struct prefix *prefix, +static route_map_result_t route_set_tag(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { route_tag_t *tag; diff --git a/tests/bgpd/test_bgp_table.c b/tests/bgpd/test_bgp_table.c index 01ce7480d7..a0382827b9 100644 --- a/tests/bgpd/test_bgp_table.c +++ b/tests/bgpd/test_bgp_table.c @@ -116,8 +116,8 @@ static void check_lookup_result(struct list *list, va_list arglist) assert(prefix_count == listcount(list)); } -static void do_test(struct bgp_table *table, const char *prefix, uint8_t maxlen, - ...) +static void do_test(struct bgp_table *table, const char *prefix, + uint32_t maxlen, ...) { va_list arglist; struct list *list = list_new(); diff --git a/tests/bgpd/test_capability.c b/tests/bgpd/test_capability.c index c75a699a16..4612bdc26b 100644 --- a/tests/bgpd/test_capability.c +++ b/tests/bgpd/test_capability.c @@ -821,6 +821,7 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type) switch (type) { case CAPABILITY: len += 2; /* to cover the OPT-Param header */ + __attribute__ ((fallthrough)); case OPT_PARAM: printf("len: %u\n", len); /* peek_for_as4 wants getp at capibility*/ diff --git a/tests/isisd/test_isis_vertex_queue.c b/tests/isisd/test_isis_vertex_queue.c index 0e473d7a6b..fe528203aa 100644 --- a/tests/isisd/test_isis_vertex_queue.c +++ b/tests/isisd/test_isis_vertex_queue.c @@ -16,43 +16,42 @@ static size_t vertex_count; static void setup_test_vertices(void) { - struct prefix p = { - .family = AF_UNSPEC + union isis_N nid, nip = { + .prefix.family = AF_UNSPEC }; - uint8_t node_id[7]; vertices = XMALLOC(MTYPE_TMP, sizeof(*vertices) * 16); - p.family = AF_INET; - p.prefixlen = 24; - inet_pton(AF_INET, "192.168.1.0", &p.u.prefix4); - vertices[vertex_count] = isis_vertex_new(&p, VTYPE_IPREACH_TE); + nip.prefix.family = AF_INET; + nip.prefix.prefixlen = 24; + inet_pton(AF_INET, "192.168.1.0", &nip.prefix.u.prefix4); + vertices[vertex_count] = isis_vertex_new(&nip, VTYPE_IPREACH_TE); vertices[vertex_count]->d_N = 20; vertex_count++; - p.family = AF_INET; - p.prefixlen = 24; - inet_pton(AF_INET, "192.168.2.0", &p.u.prefix4); - vertices[vertex_count] = isis_vertex_new(&p, VTYPE_IPREACH_TE); + nip.prefix.family = AF_INET; + nip.prefix.prefixlen = 24; + inet_pton(AF_INET, "192.168.2.0", &nip.prefix.u.prefix4); + vertices[vertex_count] = isis_vertex_new(&nip, VTYPE_IPREACH_TE); vertices[vertex_count]->d_N = 20; vertex_count++; - memset(node_id, 0, sizeof(node_id)); - node_id[6] = 1; - vertices[vertex_count] = isis_vertex_new(node_id, VTYPE_PSEUDO_TE_IS); + memset(nid.id, 0, sizeof(nid.id)); + nid.id[6] = 1; + vertices[vertex_count] = isis_vertex_new(&nid, VTYPE_PSEUDO_TE_IS); vertices[vertex_count]->d_N = 15; vertex_count++; - memset(node_id, 0, sizeof(node_id)); - node_id[5] = 2; - vertices[vertex_count] = isis_vertex_new(node_id, VTYPE_NONPSEUDO_TE_IS); + memset(nid.id, 0, sizeof(nid.id)); + nid.id[5] = 2; + vertices[vertex_count] = isis_vertex_new(&nid, VTYPE_NONPSEUDO_TE_IS); vertices[vertex_count]->d_N = 15; vertex_count++; - p.family = AF_INET; - p.prefixlen = 24; - inet_pton(AF_INET, "192.168.3.0", &p.u.prefix4); - vertices[vertex_count] = isis_vertex_new(&p, VTYPE_IPREACH_TE); + nip.prefix.family = AF_INET; + nip.prefix.prefixlen = 24; + inet_pton(AF_INET, "192.168.3.0", &nip.prefix.u.prefix4); + vertices[vertex_count] = isis_vertex_new(&nip, VTYPE_IPREACH_TE); vertices[vertex_count]->d_N = 20; vertex_count++; }; @@ -76,23 +75,23 @@ static void test_ordered(void) assert(isis_vertex_queue_count(&q) == vertex_count); for (size_t i = 0; i < vertex_count; i++) { - assert(isis_find_vertex(&q, vertices[i]->N.id, vertices[i]->type) == vertices[i]); + assert(isis_find_vertex(&q, &vertices[i]->N, vertices[i]->type) == vertices[i]); } assert(isis_vertex_queue_pop(&q) == vertices[2]); - assert(isis_find_vertex(&q, vertices[2]->N.id, vertices[2]->type) == NULL); + assert(isis_find_vertex(&q, &vertices[2]->N, vertices[2]->type) == NULL); assert(isis_vertex_queue_pop(&q) == vertices[3]); - assert(isis_find_vertex(&q, vertices[3]->N.id, vertices[3]->type) == NULL); + assert(isis_find_vertex(&q, &vertices[3]->N, vertices[3]->type) == NULL); assert(isis_vertex_queue_pop(&q) == vertices[0]); - assert(isis_find_vertex(&q, vertices[0]->N.id, vertices[0]->type) == NULL); + assert(isis_find_vertex(&q, &vertices[0]->N, vertices[0]->type) == NULL); assert(isis_vertex_queue_pop(&q) == vertices[1]); - assert(isis_find_vertex(&q, vertices[1]->N.id, vertices[1]->type) == NULL); + assert(isis_find_vertex(&q, &vertices[1]->N, vertices[1]->type) == NULL); isis_vertex_queue_delete(&q, vertices[4]); - assert(isis_find_vertex(&q, vertices[4]->N.id, vertices[4]->type) == NULL); + assert(isis_find_vertex(&q, &vertices[4]->N, vertices[4]->type) == NULL); assert(isis_vertex_queue_count(&q) == 0); assert(isis_vertex_queue_pop(&q) == NULL); diff --git a/tests/lib/test_srcdest_table.c b/tests/lib/test_srcdest_table.c index 53180564bd..e717da15b3 100644 --- a/tests/lib/test_srcdest_table.c +++ b/tests/lib/test_srcdest_table.c @@ -392,7 +392,8 @@ static void test_state_del_one_route(struct test_state *test, struct prng *prng) } assert(rn); - srcdest_rnode_prefixes(rn, &dst_p, &src_p); + srcdest_rnode_prefixes(rn, (const struct prefix **)&dst_p, + (const struct prefix **)&src_p); memcpy(&dst6_p, dst_p, sizeof(dst6_p)); if (src_p) memcpy(&src6_p, src_p, sizeof(src6_p)); diff --git a/tools/frr-reload.py b/tools/frr-reload.py index 208fb116e6..a9f183ed7b 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -403,7 +403,7 @@ end self.save_contexts(ctx_keys, current_context_lines) new_ctx = True - elif line == "end": + elif line in ["end", "exit-vrf"]: self.save_contexts(ctx_keys, current_context_lines) log.debug('LINE %-50s: exiting old context, %-50s', line, ctx_keys) diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 5c84219418..8943b434d7 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -891,8 +891,12 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) zns = zebra_ns_lookup(ns_id); ifa = NLMSG_DATA(h); - if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) + if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) { + zlog_warn( + "Invalid address family: %d received from kernel interface addr change: %d", + ifa->ifa_family, h->nlmsg_type); return 0; + } if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR) return 0; @@ -986,7 +990,7 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) if (tb[IFA_LABEL]) label = (char *)RTA_DATA(tb[IFA_LABEL]); - if (ifp && label && strcmp(ifp->name, label) == 0) + if (label && strcmp(ifp->name, label) == 0) label = NULL; /* Register interface address to the interface. */ @@ -1114,6 +1118,14 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) return 0; } + if (!(ifi->ifi_family == AF_UNSPEC || ifi->ifi_family == AF_BRIDGE + || ifi->ifi_family == AF_INET6)) { + zlog_warn( + "Invalid address family: %d received from kernel link change: %d", + ifi->ifi_family, h->nlmsg_type); + return 0; + } + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg)); if (len < 0) { zlog_err("%s: Message received from netlink is of a broken size %d %zu", @@ -1218,6 +1230,12 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) /* Update interface information. */ set_ifindex(ifp, ifi->ifi_index, zns); ifp->flags = ifi->ifi_flags & 0x0000fffff; + if (!tb[IFLA_MTU]) { + zlog_warn( + "RTM_NEWLINK for interface %s(%u) without MTU set", + name, ifi->ifi_index); + return 0; + } ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]); ifp->metric = 0; ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; @@ -1267,6 +1285,12 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) bridge_ifindex, ifi->ifi_flags); set_ifindex(ifp, ifi->ifi_index, zns); + if (!tb[IFLA_MTU]) { + zlog_warn( + "RTM_NEWLINK for interface %s(%u) without MTU set", + name, ifi->ifi_index); + return 0; + } ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]); ifp->metric = 0; diff --git a/zebra/main.c b/zebra/main.c index c5246999fa..3e44a41707 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -236,15 +236,15 @@ int main(int argc, char **argv) " -z, --socket Set path of zebra socket\n" " -e, --ecmp Specify ECMP to use.\n" " -l, --label_socket Socket to external label manager\n" - " -k, --keep_kernel Don't delete old routes which installed by zebra.\n" + " -k, --keep_kernel Don't delete old routes which were installed by zebra.\n" " -r, --retain When program terminates, retain added route by zebra.\n" #ifdef HAVE_NETLINK - " -n, --vrfwnetns Set VRF with NetNS\n" + " -n, --vrfwnetns Use NetNS as VRF backend\n" " -s, --nl-bufsize Set netlink receive buffer size\n" " --v6-rr-semantics Use v6 RR semantics\n" #endif /* HAVE_NETLINK */ #if defined(HANDLE_ZAPI_FUZZING) - " -c <file> Bypass normal startup use this file for tetsting of zapi" + " -c <file> Bypass normal startup and use this file for testing of zapi" #endif ); @@ -349,13 +349,6 @@ int main(int argc, char **argv) /* For debug purpose. */ /* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */ -#if defined(HANDLE_ZAPI_FUZZING) - if (fuzzing) { - zserv_read_file(fuzzing); - exit(0); - } -#endif - /* Process the configuration file. Among other configuration * directives we can meet those installing static routes. Such * requests will not be executed immediately, but queued in @@ -391,6 +384,14 @@ int main(int argc, char **argv) /* RNH init */ zebra_rnh_init(); +#if defined(HANDLE_ZAPI_FUZZING) + if (fuzzing) { + zserv_read_file(fuzzing); + exit(0); + } +#endif + + frr_run(zebrad.master); /* Not reached... */ diff --git a/zebra/rt.h b/zebra/rt.h index 57e62e4f6e..e40bae3a3e 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -122,7 +122,7 @@ extern int kernel_del_mac(struct interface *ifp, vlanid_t vid, int local); extern int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, - struct ethaddr *mac); + struct ethaddr *mac, uint8_t flags); extern int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip); /* diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 485abc3f12..80841b6ac1 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -387,8 +387,15 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, memcpy(&p.u.prefix4, dest, 4); p.prefixlen = rtm->rtm_dst_len; - src_p.prefixlen = - 0; // Forces debug below to not display anything + if (rtm->rtm_src_len != 0) { + char buf[PREFIX_STRLEN]; + zlog_warn("unsupported IPv4 sourcedest route (dest %s vrf %u)", + prefix2str(&p, buf, sizeof(buf)), vrf_id); + return 0; + } + + /* Force debug below to not display anything for source */ + src_p.prefixlen = 0; } else if (rtm->rtm_family == AF_INET6) { p.family = AF_INET6; memcpy(&p.u.prefix6, dest, 16); @@ -399,14 +406,6 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, src_p.prefixlen = rtm->rtm_src_len; } - if (rtm->rtm_src_len != 0) { - char buf[PREFIX_STRLEN]; - zlog_warn( - "unsupported IPv[4|6] sourcedest route (dest %s vrf %u)", - prefix2str(&p, buf, sizeof(buf)), vrf_id); - return 0; - } - /* * For ZEBRA_ROUTE_KERNEL types: * @@ -492,7 +491,7 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, nh.vrf_id = nh_vrf_id; rib_add(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p, - NULL, &nh, table, metric, mtu, distance, tag); + &src_p, &nh, table, metric, mtu, distance, tag); } else { /* This is a multipath route */ @@ -581,6 +580,9 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, route_entry_nexthop_ifindex_add( re, index, nh_vrf_id); + if (rtnh->rtnh_len == 0) + break; + len -= NLMSG_ALIGN(rtnh->rtnh_len); rtnh = RTNH_NEXT(rtnh); } @@ -591,8 +593,8 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, if (re->nexthop_num == 0) XFREE(MTYPE_RE, re); else - rib_add_multipath(afi, SAFI_UNICAST, &p, NULL, - re); + rib_add_multipath(afi, SAFI_UNICAST, &p, + &src_p, re); } } else { if (!tb[RTA_MULTIPATH]) { @@ -624,12 +626,12 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, if (gate) memcpy(&nh.gate, gate, sz); rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, - &p, NULL, &nh, table, metric, true); + &p, &src_p, &nh, table, metric, true); } else { /* XXX: need to compare the entire list of nexthops * here for NLM_F_APPEND stupidity */ rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, - &p, NULL, NULL, table, metric, true); + &p, &src_p, NULL, table, metric, true); } } @@ -701,6 +703,9 @@ static int netlink_route_change_read_multicast(struct nlmsghdr *h, oif[oif_count] = rtnh->rtnh_ifindex; oif_count++; + if (rtnh->rtnh_len == 0) + break; + len -= NLMSG_ALIGN(rtnh->rtnh_len); rtnh = RTNH_NEXT(rtnh); } @@ -740,6 +745,15 @@ int netlink_route_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) return 0; } + if (!(rtm->rtm_family == AF_INET || rtm->rtm_family == AF_INET6 + || rtm->rtm_family == AF_ETHERNET + || rtm->rtm_family == AF_MPLS)) { + zlog_warn( + "Invalid address family: %d received from kernel route change: %d", + rtm->rtm_family, h->nlmsg_type); + return 0; + } + /* Connected route. */ if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("%s %s %s proto %s NS %u", @@ -2151,6 +2165,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) char buf2[INET6_ADDRSTRLEN]; int mac_present = 0; uint8_t ext_learned; + uint8_t router_flag; ndm = NLMSG_DATA(h); @@ -2241,6 +2256,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) } ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0; + router_flag = (ndm->ndm_flags & NTF_ROUTER) ? 1 : 0; if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( @@ -2263,7 +2279,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) if (ndm->ndm_state & NUD_VALID) return zebra_vxlan_handle_kernel_neigh_update( ifp, link_if, &ip, &mac, ndm->ndm_state, - ext_learned); + ext_learned, router_flag); return zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip); } @@ -2386,12 +2402,19 @@ int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id) if (ndm->ndm_family == AF_INET || ndm->ndm_family == AF_INET6) return netlink_ipneigh_change(h, len, ns_id); + else { + zlog_warn( + "Invalid address family: %d received from kernel neighbor change: %d", + ndm->ndm_family, h->nlmsg_type); + return 0; + } return 0; } static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip, - struct ethaddr *mac, uint32_t flags, int cmd) + struct ethaddr *mac, uint8_t flags, + uint16_t state, int cmd) { struct { struct nlmsghdr n; @@ -2414,11 +2437,10 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip, req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE); req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6; - req.ndm.ndm_state = flags; + req.ndm.ndm_state = state; req.ndm.ndm_ifindex = ifp->ifindex; req.ndm.ndm_type = RTN_UNICAST; - req.ndm.ndm_flags = NTF_EXT_LEARNED; - + req.ndm.ndm_flags = flags; ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN; addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len); @@ -2426,12 +2448,12 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip, addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6); if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s", + zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s flags 0x%x", nl_msg_type_to_str(cmd), nl_family_to_str(req.ndm.ndm_family), ifp->name, ifp->ifindex, ipaddr2str(ip, buf, sizeof(buf)), mac ? prefix_mac2str(mac, buf2, sizeof(buf2)) - : "null"); + : "null", flags); return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); @@ -2452,14 +2474,15 @@ int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, } int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, - struct ethaddr *mac) + struct ethaddr *mac, uint8_t flags) { - return netlink_neigh_update2(ifp, ip, mac, NUD_NOARP, RTM_NEWNEIGH); + return netlink_neigh_update2(ifp, ip, mac, flags, + NUD_NOARP, RTM_NEWNEIGH); } int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip) { - return netlink_neigh_update2(ifp, ip, NULL, 0, RTM_DELNEIGH); + return netlink_neigh_update2(ifp, ip, NULL, 0, 0, RTM_DELNEIGH); } /* diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index cba0376300..346699198f 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -88,7 +88,8 @@ static int kernel_rtm_add_labels(struct mpls_label_stack *nh_label, #endif /* Interface between zebra message and rtm message. */ -static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re) +static int kernel_rtm_ipv4(int cmd, const struct prefix *p, + struct route_entry *re) { struct sockaddr_in *mask = NULL; @@ -272,7 +273,8 @@ static int sin6_masklen(struct in6_addr mask) #endif /* SIN6_LEN */ /* Interface between zebra message and rtm message. */ -static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re) +static int kernel_rtm_ipv6(int cmd, const struct prefix *p, + struct route_entry *re) { struct sockaddr_in6 *mask; struct sockaddr_in6 sin_dest, sin_mask, sin_gate; @@ -374,7 +376,7 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re) return 0; /*XXX*/ } -static int kernel_rtm(int cmd, struct prefix *p, struct route_entry *re) +static int kernel_rtm(int cmd, const struct prefix *p, struct route_entry *re) { switch (PREFIX_FAMILY(p)) { case AF_INET: @@ -460,7 +462,7 @@ int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, } int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, - struct ethaddr *mac) + struct ethaddr *mac, uint8_t flags) { return 0; } diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c index c7a8517e17..d683e92bcc 100644 --- a/zebra/rule_netlink.c +++ b/zebra/rule_netlink.c @@ -204,8 +204,12 @@ int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) } frh = NLMSG_DATA(h); - if (frh->family != AF_INET && frh->family != AF_INET6) + if (frh->family != AF_INET && frh->family != AF_INET6) { + zlog_warn( + "Invalid address family: %d received from kernel rule change: %d", + frh->family, h->nlmsg_type); return 0; + } if (frh->action != FR_ACT_TO_TBL) return 0; diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c index d0ea661403..2dd686fd0d 100644 --- a/zebra/zebra_netns_notify.c +++ b/zebra/zebra_netns_notify.c @@ -80,6 +80,8 @@ static void zebra_ns_notify_create_context_from_entry_name(const char *name) ns_id = zebra_ns_id_get(netnspath); if (zserv_privs.change(ZPRIVS_LOWER)) zlog_err("Can't lower privileges"); + if (ns_id == NS_UNKNOWN) + return; ns_id_external = ns_map_nsid_with_external(ns_id, true); /* if VRF with NS ID already present */ vrf = vrf_lookup_by_id((vrf_id_t)ns_id_external); @@ -103,6 +105,7 @@ static void zebra_ns_notify_create_context_from_entry_name(const char *name) if (ret != CMD_SUCCESS) { zlog_warn("NS notify : failed to create NS %s", netnspath); ns_map_nsid_with_external(ns_id, false); + vrf_delete(vrf); return; } zlog_info("NS notify : created VRF %s NS %s", name, netnspath); diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index 8c23bf34cf..5975c4058b 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -615,7 +615,7 @@ static int zebra_ptm_handle_msg_cb(void *arg, void *in_ctxt) int zebra_ptm_sock_read(struct thread *thread) { - int sock, done = 0; + int sock; int rc; errno = 0; @@ -625,28 +625,24 @@ int zebra_ptm_sock_read(struct thread *thread) return -1; /* PTM communicates in CSV format */ - while (!done) { + do { rc = ptm_lib_process_msg(ptm_hdl, sock, ptm_cb.in_data, ZEBRA_PTM_MAX_SOCKBUF, NULL); - if (rc <= 0) - break; - } + } while (rc > 0); - if (rc <= 0) { - if (((rc == 0) && !errno) - || (errno && (errno != EWOULDBLOCK) && (errno != EAGAIN))) { - zlog_warn("%s routing socket error: %s(%d) bytes %d", - __func__, safe_strerror(errno), errno, rc); - - close(ptm_cb.ptm_sock); - ptm_cb.ptm_sock = -1; - zebra_ptm_reset_status(0); - ptm_cb.t_timer = NULL; - thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, - ptm_cb.reconnect_time, - &ptm_cb.t_timer); - return (-1); - } + if (((rc == 0) && !errno) + || (errno && (errno != EWOULDBLOCK) && (errno != EAGAIN))) { + zlog_warn("%s routing socket error: %s(%d) bytes %d", + __func__, safe_strerror(errno), errno, rc); + + close(ptm_cb.ptm_sock); + ptm_cb.ptm_sock = -1; + zebra_ptm_reset_status(0); + ptm_cb.t_timer = NULL; + thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, + ptm_cb.reconnect_time, + &ptm_cb.t_timer); + return (-1); } ptm_cb.t_read = NULL; diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 9bf6bfa22f..71d48632c1 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2331,7 +2331,7 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, if (!re) return 0; - assert(!src_p || afi == AFI_IP6); + assert(!src_p || !src_p->prefixlen || afi == AFI_IP6); /* Lookup table. */ table = zebra_vrf_table_with_table_id(afi, safi, re->vrf_id, re->table); @@ -2421,7 +2421,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, char buf2[INET6_ADDRSTRLEN]; rib_dest_t *dest; - assert(!src_p || afi == AFI_IP6); + assert(!src_p || !src_p->prefixlen || afi == AFI_IP6); /* Lookup table. */ table = zebra_vrf_table_with_table_id(afi, safi, vrf_id, table_id); diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index bf6718164f..0b48e87b1b 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -137,7 +137,8 @@ static int zebra_route_match_delete(struct vty *vty, const char *command, /* 'match tag TAG' * Match function return 1 if match is success else return 0 */ -static route_map_result_t route_match_tag(void *rule, struct prefix *prefix, +static route_map_result_t route_match_tag(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { route_tag_t *tag; @@ -163,7 +164,7 @@ static struct route_map_rule_cmd route_match_tag_cmd = { /* `match interface IFNAME' */ /* Match function return 1 if match is success else return zero. */ static route_map_result_t route_match_interface(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -879,7 +880,7 @@ DEFUN (show_ipv6_protocol_nht, /* Match function return 1 if match is success else return zero. */ static route_map_result_t route_match_ip_next_hop(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -937,7 +938,7 @@ static struct route_map_rule_cmd route_match_ip_next_hop_cmd = { /* `match ip next-hop prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -993,7 +994,7 @@ static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { /* Match function should return 1 if match is success else return zero. */ static route_map_result_t route_match_ip_address(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1032,7 +1033,7 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = { /* `match ip address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -1068,7 +1069,7 @@ static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { /* `match ip address prefix-len PREFIXLEN' */ static route_map_result_t -route_match_address_prefix_len(void *rule, struct prefix *prefix, +route_match_address_prefix_len(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { uint32_t *prefixlen = (uint32_t *)rule; @@ -1122,7 +1123,7 @@ static struct route_map_rule_cmd route_match_ipv6_address_prefix_len_cmd = { /* `match ip nexthop prefix-len PREFIXLEN' */ static route_map_result_t -route_match_ip_nexthop_prefix_len(void *rule, struct prefix *prefix, +route_match_ip_nexthop_prefix_len(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { uint32_t *prefixlen = (uint32_t *)rule; @@ -1162,7 +1163,7 @@ static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd = { /* `match source-protocol PROTOCOL' */ static route_map_result_t route_match_source_protocol(void *rule, - struct prefix *prefix, + const struct prefix *p, route_map_object_t type, void *object) { @@ -1204,7 +1205,7 @@ static struct route_map_rule_cmd route_match_source_protocol_cmd = { /* `source-instance` */ static route_map_result_t route_match_source_instance(void *rule, - struct prefix *prefix, + const struct prefix *p, route_map_object_t type, void *object) { @@ -1246,7 +1247,7 @@ static struct route_map_rule_cmd route_match_source_instance_cmd = { /* `set src A.B.C.D' */ /* Set src. */ -static route_map_result_t route_set_src(void *rule, struct prefix *prefix, +static route_map_result_t route_set_src(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct nh_rmap_obj *nh_data; @@ -1359,8 +1360,7 @@ route_map_result_t zebra_route_map_check(int family, int rib_type, rmap = route_map_lookup_by_name( proto_rm[family][ZEBRA_ROUTE_MAX]); if (rmap) { - ret = route_map_apply(rmap, (struct prefix *)p, - RMAP_ZEBRA, &nh_obj); + ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); } return (ret); @@ -1385,7 +1385,8 @@ void zebra_del_import_table_route_map(afi_t afi, uint32_t table) route_map_result_t zebra_import_table_route_map_check(int family, int re_type, uint8_t instance, - struct prefix *p, struct nexthop *nexthop, + const struct prefix *p, + struct nexthop *nexthop, vrf_id_t vrf_id, route_tag_t tag, const char *rmap_name) { @@ -1410,7 +1411,7 @@ zebra_import_table_route_map_check(int family, int re_type, uint8_t instance, } route_map_result_t zebra_nht_route_map_check(int family, int client_proto, - struct prefix *p, + const struct prefix *p, struct route_entry *re, struct nexthop *nexthop) { @@ -1430,11 +1431,10 @@ route_map_result_t zebra_nht_route_map_check(int family, int client_proto, if (!rmap && nht_rm[family][ZEBRA_ROUTE_MAX]) rmap = route_map_lookup_by_name( nht_rm[family][ZEBRA_ROUTE_MAX]); - if (rmap) { + if (rmap) ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); - } - return (ret); + return ret; } static void zebra_route_map_mark_update(const char *rmap_name) diff --git a/zebra/zebra_routemap.h b/zebra/zebra_routemap.h index 688c8b7203..d33487d7af 100644 --- a/zebra/zebra_routemap.h +++ b/zebra/zebra_routemap.h @@ -35,7 +35,8 @@ extern void zebra_route_map_write_delay_timer(struct vty *); extern route_map_result_t zebra_import_table_route_map_check(int family, int rib_type, uint8_t instance, - struct prefix *p, struct nexthop *nexthop, + const struct prefix *p, + struct nexthop *nexthop, vrf_id_t vrf_id, route_tag_t tag, const char *rmap_name); extern route_map_result_t @@ -43,7 +44,7 @@ zebra_route_map_check(int family, int rib_type, uint8_t instance, const struct prefix *p, struct nexthop *nexthop, vrf_id_t vrf_id, route_tag_t tag); extern route_map_result_t -zebra_nht_route_map_check(int family, int client_proto, struct prefix *p, +zebra_nht_route_map_check(int family, int client_proto, const struct prefix *p, struct route_entry *, struct nexthop *nexthop); diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 55c4f6e916..8ee47d2f1b 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -1198,7 +1198,8 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, break; } - if (re->vrf_id != nexthop->vrf_id) { + if ((re->vrf_id != nexthop->vrf_id) + && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) { struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id); @@ -1415,7 +1416,8 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, break; } - if (nexthop->vrf_id != re->vrf_id) { + if ((nexthop->vrf_id != re->vrf_id) + && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) { struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id); @@ -1569,7 +1571,8 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, break; } - if (nexthop->vrf_id != re->vrf_id) { + if ((nexthop->vrf_id != re->vrf_id) + && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) { struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id); if (vrf) @@ -1651,7 +1654,7 @@ static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf, json = json_object_new_object(); /* Show all routes. */ - for (rn = route_top(table); rn; rn = route_next(rn)) { + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) { dest = rib_dest_from_rnode(rn); RNODE_FOREACH_RE (rn, re) { diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 59f0cf52f0..06d1b3618c 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -33,6 +33,9 @@ #include "jhash.h" #include "vlan.h" #include "vxlan.h" +#ifdef GNU_LINUX +#include <linux/neighbour.h> +#endif #include "zebra/rib.h" #include "zebra/rt.h" @@ -282,6 +285,7 @@ static void zvni_find_neigh_addr_width(struct hash_backet *backet, void *ctxt) ipaddr2str(&n->ip, buf, sizeof(buf)), width = strlen(buf); if (width > wctx->addr_width) wctx->addr_width = width; + } /* @@ -327,6 +331,10 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json) else json_object_boolean_true_add(json, "defaultGateway"); } + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG)) { + if (!json) + vty_out(vty, " Router"); + } if (json == NULL) vty_out(vty, "\n"); } @@ -432,11 +440,11 @@ static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet, return; } num_neigh = hashcount(zvni->neigh_table); - if (json == NULL) + if (json == NULL) { vty_out(vty, "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n", zvni->vni, num_neigh); - else { + } else { json_vni = json_object_new_object(); json_object_int_add(json_vni, "numArpNd", num_neigh); snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni); @@ -458,9 +466,10 @@ static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet, wctx.json = json_vni; hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx); - if (json == NULL) + if (json == NULL) { vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP", "Type", "MAC", "Remote VTEP"); + } hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); if (json) @@ -581,6 +590,9 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt) if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) vty_out(vty, " Default-gateway Mac "); + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW)) + vty_out(vty, " Remote-gateway Mac "); + vty_out(vty, "\n"); /* print all the associated neigh */ vty_out(vty, " Neighbors:\n"); @@ -1553,6 +1565,9 @@ static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip, if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_DEF_GW)) SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); + /* Set router flag (R-bit) based on local neigh entry add */ + if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_ROUTER_FLAG)) + SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags, ZEBRA_MACIP_ADD); @@ -1576,6 +1591,8 @@ static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n) struct zebra_if *zif; struct zebra_l2info_vxlan *vxl; struct interface *vlan_if; + uint8_t flags; + int ret = 0; if (!(n->flags & ZEBRA_NEIGH_REMOTE)) return 0; @@ -1588,8 +1605,13 @@ static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n) vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if); if (!vlan_if) return -1; - - return kernel_add_neigh(vlan_if, &n->ip, &n->emac); +#ifdef GNU_LINUX + flags = NTF_EXT_LEARNED; + if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG) + flags |= NTF_ROUTER; + ret = kernel_add_neigh(vlan_if, &n->ip, &n->emac, flags); +#endif + return ret; } /* @@ -1811,6 +1833,9 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni, /* Set "local" forwarding info. */ SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); SET_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW); + /* Set Router flag (R-bit) */ + if (ip->ipa_type == IPADDR_V6) + SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); memcpy(&n->emac, macaddr, ETH_ALEN); n->ifindex = ifp->ifindex; @@ -1820,10 +1845,10 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni, if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( - "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP", + "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x", ifp->name, ifp->ifindex, zvni->vni, prefix_mac2str(macaddr, buf, sizeof(buf)), - ipaddr2str(ip, buf2, sizeof(buf2))); + ipaddr2str(ip, buf2, sizeof(buf2)), n->flags); zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags); @@ -1966,7 +1991,8 @@ static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet, static int zvni_local_neigh_update(zebra_vni_t *zvni, struct interface *ifp, struct ipaddr *ip, - struct ethaddr *macaddr) + struct ethaddr *macaddr, + uint8_t router_flag) { char buf[ETHER_ADDR_STRLEN]; char buf2[INET6_ADDRSTRLEN]; @@ -2084,15 +2110,19 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, return 0; } + /*Set router flag (R-bit) */ + if (router_flag) + SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); + /* Inform BGP. */ if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u", + zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u with flags 0x%x", ipaddr2str(ip, buf2, sizeof(buf2)), prefix_mac2str(macaddr, buf, sizeof(buf)), - zvni->vni); + zvni->vni, n->flags); ZEBRA_NEIGH_SET_ACTIVE(n); - return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, 0); + return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags); } static int zvni_remote_neigh_update(zebra_vni_t *zvni, @@ -2534,7 +2564,8 @@ static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac) return -1; vxl = &zif->l2info.vxl; - sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0; + sticky = CHECK_FLAG(mac->flags, + (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW)) ? 1 : 0; return kernel_add_mac(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr, mac->fwd_info.r_vtep_ip, sticky); @@ -3362,14 +3393,22 @@ static int zl3vni_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *n) */ static int zl3vni_nh_install(zebra_l3vni_t *zl3vni, zebra_neigh_t *n) { + uint8_t flags; + int ret = 0; + if (!is_l3vni_oper_up(zl3vni)) return -1; if (!(n->flags & ZEBRA_NEIGH_REMOTE) || !(n->flags & ZEBRA_NEIGH_REMOTE_NH)) return 0; - - return kernel_add_neigh(zl3vni->svi_if, &n->ip, &n->emac); +#ifdef GNU_LINUX + flags = NTF_EXT_LEARNED; + if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG) + flags |= NTF_ROUTER; + ret = kernel_add_neigh(zl3vni->svi_if, &n->ip, &n->emac, flags); +#endif + return ret; } /* @@ -4513,9 +4552,11 @@ void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); wctx.zvni = zvni; wctx.vty = vty; + wctx.addr_width = 15; wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP; wctx.r_vtep_ip = vtep_ip; wctx.json = json; + hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx); hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); if (use_json) { @@ -4944,7 +4985,8 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp, struct ipaddr *ip, struct ethaddr *macaddr, uint16_t state, - uint8_t ext_learned) + uint8_t ext_learned, + uint8_t router_flag) { char buf[ETHER_ADDR_STRLEN]; char buf2[INET6_ADDRSTRLEN]; @@ -4975,7 +5017,8 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp, /* Is this about a local neighbor or a remote one? */ if (!ext_learned) - return zvni_local_neigh_update(zvni, ifp, ip, macaddr); + return zvni_local_neigh_update(zvni, ifp, ip, macaddr, + router_flag); return zvni_remote_neigh_update(zvni, ifp, ip, macaddr, state); } @@ -5152,6 +5195,7 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) char buf[ETHER_ADDR_STRLEN]; char buf1[INET6_ADDRSTRLEN]; uint8_t sticky = 0; + u_char remote_gw = 0; uint8_t flags = 0; struct interface *ifp = NULL; struct zebra_if *zif = NULL; @@ -5193,6 +5237,7 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) /* Get flags - sticky mac and/or gateway mac */ STREAM_GETC(s, flags); sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); + remote_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW); l++; if (IS_ZEBRA_DEBUG_VXLAN) @@ -5266,6 +5311,8 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) || (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0) != sticky + || (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) ? 1 : 0) + != remote_gw || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip)) update_mac = 1; @@ -5297,6 +5344,11 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) else UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY); + if (remote_gw) + SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW); + else + UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW); + zvni_process_neigh_on_remote_mac_add(zvni, mac); /* Install the entry. */ @@ -5353,6 +5405,10 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) n->r_vtep_ip = vtep_ip; SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE); + /* Set router flag (R-bit) to this Neighbor entry */ + if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG)) + SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); + /* Install the entry. */ zvni_neigh_install(zvni, n); } diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index 34d1152751..2732ef72ed 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -124,7 +124,8 @@ extern int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if); extern int zebra_vxlan_handle_kernel_neigh_update( struct interface *ifp, struct interface *link_if, struct ipaddr *ip, - struct ethaddr *macaddr, uint16_t state, uint8_t ext_learned); + struct ethaddr *macaddr, uint16_t state, uint8_t ext_learned, + uint8_t router_flag); extern int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp, struct interface *link_if, struct ipaddr *ip); diff --git a/zebra/zebra_vxlan_private.h b/zebra/zebra_vxlan_private.h index fa7075f2de..e86967041b 100644 --- a/zebra/zebra_vxlan_private.h +++ b/zebra/zebra_vxlan_private.h @@ -247,6 +247,8 @@ struct zebra_mac_t_ { #define ZEBRA_MAC_STICKY 0x08 /* Static MAC */ #define ZEBRA_MAC_REMOTE_RMAC 0x10 /* remote router mac */ #define ZEBRA_MAC_DEF_GW 0x20 +/* remote VTEP advertised MAC as default GW */ +#define ZEBRA_MAC_REMOTE_DEF_GW 0x40 /* Local or remote info. */ union { @@ -329,6 +331,7 @@ struct zebra_neigh_t_ { #define ZEBRA_NEIGH_REMOTE 0x02 #define ZEBRA_NEIGH_REMOTE_NH 0x04 /* neigh entry for remote vtep */ #define ZEBRA_NEIGH_DEF_GW 0x08 +#define ZEBRA_NEIGH_ROUTER_FLAG 0x10 enum zebra_neigh_state state; diff --git a/zebra/zserv.c b/zebra/zserv.c index b08da9cebd..725cc9229c 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -640,7 +640,7 @@ static int zserv_handle_client_close(struct thread *thread) * sock * client's socket file descriptor */ -static void zserv_client_create(int sock) +static struct zserv *zserv_client_create(int sock) { struct zserv *client; int i; @@ -696,6 +696,8 @@ static void zserv_client_create(int sock) /* start pthread */ frr_pthread_run(client->pthread, NULL); + + return client; } /* @@ -1022,23 +1024,12 @@ DEFUN (show_zebra_client_summary, void zserv_read_file(char *input) { int fd; - struct zserv *client = NULL; struct thread t; - zserv_client_create(-1); - - frr_pthread_stop(client->pthread, NULL); - frr_pthread_destroy(client->pthread); - client->pthread = NULL; - - t.arg = client; - fd = open(input, O_RDONLY | O_NONBLOCK); t.u.fd = fd; - zserv_read(&t); - - close(fd); + zserv_client_create(fd); } #endif |
