diff options
49 files changed, 757 insertions, 321 deletions
diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index 0ec5a778bb..1f2602c059 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -119,7 +119,6 @@ dist_examples_DATA = bgpd.conf.sample bgpd.conf.sample2 \ bgpd.conf.vnc.sample bgp_vty.o: bgp_vty_clippy.c -bgp_debug.o: bgp_debug_clippy.c EXTRA_DIST = BGP4-MIB.txt diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index c1c4f2b39c..6de9ba3cc6 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -865,39 +865,42 @@ DEFUN (no_debug_bgp_keepalive_peer, return CMD_SUCCESS; } -#ifndef VTYSH_EXTRACT_PL -#include "bgp_debug_clippy.c" -#endif - /* debug bgp bestpath */ -DEFPY (debug_bgp_bestpath_prefix, +DEFUN (debug_bgp_bestpath_prefix, debug_bgp_bestpath_prefix_cmd, - "debug bgp bestpath <A.B.C.D/M|X:X::X:X/M>$bestpath", + "debug bgp bestpath <A.B.C.D/M|X:X::X:X/M>", DEBUG_STR BGP_STR "BGP bestpath\n" "IPv4 prefix\n" "IPv6 prefix\n") { + struct prefix *argv_p; + int idx_ipv4_ipv6_prefixlen = 3; + + argv_p = prefix_new(); + (void)str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); + apply_mask(argv_p); + if (!bgp_debug_bestpath_prefixes) bgp_debug_bestpath_prefixes = list_new(); if (bgp_debug_list_has_entry(bgp_debug_bestpath_prefixes, NULL, - bestpath)) { + argv_p)) { vty_out(vty, "BGP bestpath debugging is already enabled for %s\n", - bestpath_str); + argv[idx_ipv4_ipv6_prefixlen]->arg); return CMD_SUCCESS; } - bgp_debug_list_add_entry(bgp_debug_bestpath_prefixes, NULL, bestpath); + bgp_debug_list_add_entry(bgp_debug_bestpath_prefixes, NULL, argv_p); if (vty->node == CONFIG_NODE) { DEBUG_ON(bestpath, BESTPATH); } else { TERM_DEBUG_ON(bestpath, BESTPATH); vty_out(vty, "BGP bestpath debugging is on for %s\n", - bestpath_str); + argv[idx_ipv4_ipv6_prefixlen]->arg); } return CMD_SUCCESS; @@ -916,15 +919,10 @@ DEFUN (no_debug_bgp_bestpath_prefix, int idx_ipv4_ipv6_prefixlen = 4; struct prefix *argv_p; int found_prefix = 0; - int ret; argv_p = prefix_new(); - ret = str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); - if (!ret) { - prefix_free(argv_p); - vty_out(vty, "%% Malformed Prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } + (void)str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); + apply_mask(argv_p); if (bgp_debug_bestpath_prefixes && !list_isempty(bgp_debug_bestpath_prefixes)) { @@ -1267,16 +1265,10 @@ DEFUN (debug_bgp_update_prefix, { int idx_ipv4_ipv6_prefixlen = 4; struct prefix *argv_p; - int ret; argv_p = prefix_new(); - ret = str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); - if (!ret) { - prefix_free(argv_p); - vty_out(vty, "%% Malformed Prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - + (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(); @@ -1315,15 +1307,10 @@ DEFUN (no_debug_bgp_update_prefix, int idx_ipv4_ipv6_prefixlen = 5; struct prefix *argv_p; int found_prefix = 0; - int ret; argv_p = prefix_new(); - ret = str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); - if (!ret) { - prefix_free(argv_p); - vty_out(vty, "%% Malformed Prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } + (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)) { @@ -1411,15 +1398,10 @@ DEFUN (debug_bgp_zebra_prefix, { int idx_ipv4_ipv6_prefixlen = 4; struct prefix *argv_p; - int ret; argv_p = prefix_new(); - ret = str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); - if (!ret) { - prefix_free(argv_p); - vty_out(vty, "%% Malformed Prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } + (void)str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); + apply_mask(argv_p); if (!bgp_debug_zebra_prefixes) bgp_debug_zebra_prefixes = list_new(); @@ -1476,15 +1458,10 @@ DEFUN (no_debug_bgp_zebra_prefix, int idx_ipv4_ipv6_prefixlen = 5; struct prefix *argv_p; int found_prefix = 0; - int ret; argv_p = prefix_new(); - ret = str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); - if (!ret) { - prefix_free(argv_p); - vty_out(vty, "%% Malformed Prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } + (void)str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); + apply_mask(argv_p); if (bgp_debug_zebra_prefixes && !list_isempty(bgp_debug_zebra_prefixes)) { diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index aa11013fcc..7454aec892 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -723,7 +723,7 @@ DEFUN(show_ip_bgp_l2vpn_evpn, DEFUN(show_ip_bgp_l2vpn_evpn_rd, show_ip_bgp_l2vpn_evpn_rd_cmd, - "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn [json]", + "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]", SHOW_STR IP_STR BGP_STR @@ -736,7 +736,7 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd, int ret; struct prefix_rd prd; - argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community); + argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community); ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); if (!ret) { @@ -764,7 +764,7 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_tags, DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags, show_ip_bgp_l2vpn_evpn_rd_tags_cmd, - "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn tags", + "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags", SHOW_STR IP_STR BGP_STR @@ -777,7 +777,7 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags, int ret; struct prefix_rd prd; - argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community); + argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community); ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); if (!ret) { @@ -847,7 +847,7 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes, DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes, show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd, - "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes [json]", + "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D routes [json]", SHOW_STR IP_STR BGP_STR @@ -867,7 +867,7 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes, struct prefix_rd prd; u_char uj = use_json(argc, argv); - argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community); + argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community); argv_find(argv, argc, "A.B.C.D", &idx_ipv4); ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); @@ -978,7 +978,7 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes, DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes, show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd, - "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes [json]", + "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D advertised-routes [json]", SHOW_STR IP_STR BGP_STR @@ -998,7 +998,7 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes, union sockunion su; u_char uj = use_json(argc, argv); - argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community); + argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community); argv_find(argv, argc, "A.B.C.D", &idx_ipv4); ret = str2sockunion(argv[idx_ipv4]->arg, &su); @@ -1068,7 +1068,7 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay, DEFUN(show_ip_bgp_evpn_rd_overlay, show_ip_bgp_evpn_rd_overlay_cmd, - "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn overlay", + "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay", SHOW_STR IP_STR BGP_STR @@ -1082,7 +1082,7 @@ DEFUN(show_ip_bgp_evpn_rd_overlay, int ret; struct prefix_rd prd; - argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community); + argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community); ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); if (!ret) { @@ -1097,7 +1097,7 @@ DEFUN(show_ip_bgp_evpn_rd_overlay, /* For testing purpose, static route of MPLS-VPN. */ DEFUN(evpnrt5_network, evpnrt5_network_cmd, - "network <A.B.C.D/M|X:X::X:X/M> rd ASN:nn_or_IP-address:nn ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X> routermac WORD [route-map WORD]", + "network <A.B.C.D/M|X:X::X:X/M> rd ASN:NN_OR_IP-ADDRESS:NN ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X> routermac WORD [route-map WORD]", "Specify a network to announce via BGP\n" "IP prefix\n" "IPv6 prefix\n" @@ -1118,17 +1118,17 @@ DEFUN(evpnrt5_network, "Name of the route map\n") { int idx_ipv4_prefixlen = 1; - int idx_ext_community = 3; - int idx_word = 7; + int idx_route_distinguisher = 3; + int idx_label = 7; int idx_esi = 9; int idx_gwip = 11; int idx_ethtag = 5; int idx_routermac = 13; - int idx_rmap = 15; + return bgp_static_set_safi( AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg, - argv[idx_ext_community]->arg, argv[idx_word]->arg, - argv[idx_rmap] ? argv[idx_gwip]->arg : NULL, + argv[idx_route_distinguisher]->arg, argv[idx_label]->arg, + NULL, BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg, argv[idx_gwip]->arg, argv[idx_ethtag]->arg, argv[idx_routermac]->arg); @@ -1137,7 +1137,7 @@ DEFUN(evpnrt5_network, /* For testing purpose, static route of MPLS-VPN. */ DEFUN(no_evpnrt5_network, no_evpnrt5_network_cmd, - "no network <A.B.C.D/M|X:X::X:X/M> rd ASN:nn_or_IP-address:nn ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X>", + "no network <A.B.C.D/M|X:X::X:X/M> rd ASN:NN_OR_IP-ADDRESS:NN ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X>", NO_STR "Specify a network to announce via BGP\n" "IP prefix\n" @@ -2388,7 +2388,7 @@ DEFUN(show_bgp_l2vpn_evpn_route, */ DEFUN(show_bgp_l2vpn_evpn_route_rd, show_bgp_l2vpn_evpn_route_rd_cmd, - "show bgp l2vpn evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>] [json]", + "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>] [json]", SHOW_STR BGP_STR L2VPN_HELP_STR @@ -2456,7 +2456,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_rd, */ DEFUN(show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_l2vpn_evpn_route_rd_macip_cmd, - "show bgp l2vpn evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD] [json]", + "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]", SHOW_STR BGP_STR L2VPN_HELP_STR @@ -2841,7 +2841,7 @@ ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd, ALIAS_HIDDEN( show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd, - "show bgp evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>]", + "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]", SHOW_STR BGP_STR EVPN_HELP_STR "EVPN route information\n" "Route Distinguisher\n" @@ -2852,7 +2852,7 @@ ALIAS_HIDDEN( ALIAS_HIDDEN( show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd, - "show bgp evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD]", + "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]", SHOW_STR BGP_STR EVPN_HELP_STR "EVPN route information\n" "Route Distinguisher\n" @@ -2980,7 +2980,7 @@ DEFUN_NOSH (exit_vni, DEFUN (bgp_evpn_vni_rd, bgp_evpn_vni_rd_cmd, - "rd ASN:nn_or_IP-address:nn", + "rd ASN:NN_OR_IP-ADDRESS:NN", "Route Distinguisher\n" "ASN:XX or A.B.C.D:XX\n") { @@ -3009,7 +3009,7 @@ DEFUN (bgp_evpn_vni_rd, DEFUN (no_bgp_evpn_vni_rd, no_bgp_evpn_vni_rd_cmd, - "no rd ASN:nn_or_IP-address:nn", + "no rd ASN:NN_OR_IP-ADDRESS:NN", NO_STR "Route Distinguisher\n" "ASN:XX or A.B.C.D:XX\n") diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index fa8c45b004..dfd639c92c 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -320,7 +320,7 @@ int main(int argc, char **argv) frr_preinit(&bgpd_di, argc, argv); frr_opt_add( - "p:l:rne:", longopts, + "p:l:rSne:", longopts, " -p, --bgp_port Set bgp protocol's port number\n" " -l, --listenon Listen on specified address (implies -n)\n" " -r, --retain When program terminates, retain added route by bgpd.\n" diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index baf081c815..694cb14790 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -236,7 +236,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr, /* For testing purpose, static route of MPLS-VPN. */ DEFUN (vpnv4_network, vpnv4_network_cmd, - "network A.B.C.D/M rd ASN:nn_or_IP-address:nn <tag|label> (0-1048575)", + "network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)", "Specify a network to announce via BGP\n" "IPv4 prefix\n" "Specify Route Distinguisher\n" @@ -256,7 +256,7 @@ DEFUN (vpnv4_network, DEFUN (vpnv4_network_route_map, vpnv4_network_route_map_cmd, - "network A.B.C.D/M rd ASN:nn_or_IP-address:nn <tag|label> (0-1048575) route-map WORD", + "network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575) route-map WORD", "Specify a network to announce via BGP\n" "IPv4 prefix\n" "Specify Route Distinguisher\n" @@ -280,7 +280,7 @@ DEFUN (vpnv4_network_route_map, /* For testing purpose, static route of MPLS-VPN. */ DEFUN (no_vpnv4_network, no_vpnv4_network_cmd, - "no network A.B.C.D/M rd ASN:nn_or_IP-address:nn <tag|label> (0-1048575)", + "no network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)", NO_STR "Specify a network to announce via BGP\n" "IPv4 prefix\n" @@ -301,7 +301,7 @@ DEFUN (no_vpnv4_network, DEFUN (vpnv6_network, vpnv6_network_cmd, - "network X:X::X:X/M rd ASN:nn_or_IP-address:nn <tag|label> (0-1048575) [route-map WORD]", + "network X:X::X:X/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575) [route-map WORD]", "Specify a network to announce via BGP\n" "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n" "Specify Route Distinguisher\n" @@ -331,7 +331,7 @@ DEFUN (vpnv6_network, /* For testing purpose, static route of MPLS-VPN. */ DEFUN (no_vpnv6_network, no_vpnv6_network_cmd, - "no network X:X::X:X/M rd ASN:nn_or_IP-address:nn <tag|label> (0-1048575)", + "no network X:X::X:X/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)", NO_STR "Specify a network to announce via BGP\n" "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n" @@ -632,7 +632,7 @@ int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd, DEFUN (show_bgp_ip_vpn_all_rd, show_bgp_ip_vpn_all_rd_cmd, - "show bgp "BGP_AFI_CMD_STR" vpn all [rd ASN:nn_or_IP-address:nn] [json]", + "show bgp "BGP_AFI_CMD_STR" vpn all [rd ASN:NN_OR_IP-ADDRESS:NN] [json]", SHOW_STR IP_STR BGP_STR @@ -670,7 +670,7 @@ DEFUN (show_bgp_ip_vpn_all_rd, DEFUN (show_ip_bgp_vpn_rd, show_ip_bgp_vpn_rd_cmd, - "show [ip] bgp "BGP_AFI_CMD_STR" vpn rd ASN:nn_or_IP-address:nn", + "show [ip] bgp "BGP_AFI_CMD_STR" vpn rd ASN:NN_OR_IP-ADDRESS:NN", SHOW_STR IP_STR BGP_STR @@ -736,7 +736,7 @@ DEFUN (show_ip_bgp_vpn_all_tags, DEFUN (show_ip_bgp_vpn_rd_tags, show_ip_bgp_vpn_rd_tags_cmd, - "show [ip] bgp <vpnv4|vpnv6> rd ASN:nn_or_IP-address:nn tags", + "show [ip] bgp <vpnv4|vpnv6> rd ASN:NN_OR_IP-ADDRESS:NN tags", SHOW_STR IP_STR BGP_STR @@ -826,7 +826,7 @@ DEFUN (show_ip_bgp_vpn_all_neighbor_routes, DEFUN (show_ip_bgp_vpn_rd_neighbor_routes, show_ip_bgp_vpn_rd_neighbor_routes_cmd, - "show [ip] bgp <vpnv4|vpnv6> rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes [json]", + "show [ip] bgp <vpnv4|vpnv6> rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D routes [json]", SHOW_STR IP_STR BGP_STR @@ -966,7 +966,7 @@ DEFUN (show_ip_bgp_vpn_all_neighbor_advertised_routes, DEFUN (show_ip_bgp_vpn_rd_neighbor_advertised_routes, show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd, - "show [ip] bgp <vpnv4|vpnv6> rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes [json]", + "show [ip] bgp <vpnv4|vpnv6> rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D advertised-routes [json]", SHOW_STR IP_STR BGP_STR diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 2d05a9e194..870da22d20 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -430,6 +430,48 @@ int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer) return (ret); } +int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop, + struct update_subgroup *subgrp) +{ + struct bgp_node *rn1, *rn2; + struct peer_af *paf; + struct prefix p, np; + struct bgp *bgp = NULL; + + np.family = AF_INET; + np.prefixlen = IPV4_MAX_BITLEN; + np.u.prefix4 = nexthop; + + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + + rn1 = rn2 = NULL; + + bgp = SUBGRP_INST(subgrp); + rn1 = bgp_node_match(bgp->connected_table[AFI_IP], + &np); + if (!rn1) + return 0; + + SUBGRP_FOREACH_PEER(subgrp, paf) { + p.u.prefix4 = paf->peer->su.sin.sin_addr; + + rn2 = bgp_node_match(bgp->connected_table[AFI_IP], + &p); + if (rn1 == rn2) { + bgp_unlock_node(rn1); + bgp_unlock_node(rn2); + return 1; + } + + if (rn2) + bgp_unlock_node(rn2); + } + + bgp_unlock_node(rn1); + return 0; +} + static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp, struct bgp_nexthop_cache *bnc) diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h index b482778fdf..2c5b2ab118 100644 --- a/bgpd/bgp_nexthop.h +++ b/bgpd/bgp_nexthop.h @@ -82,6 +82,8 @@ extern int bgp_nexthop_lookup(afi_t, struct peer *peer, struct bgp_info *, int *, int *); extern void bgp_connected_add(struct bgp *bgp, struct connected *c); extern void bgp_connected_delete(struct bgp *bgp, struct connected *c); +extern int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop, + struct update_subgroup *subgrp); extern int bgp_multiaccess_check_v4(struct in_addr, struct peer *); extern int bgp_config_write_scan_time(struct vty *); extern int bgp_nexthop_self(struct bgp *, struct in_addr); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index a12abd9fd0..b9f23a387e 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1319,7 +1319,6 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, struct peer *onlypeer; struct bgp *bgp; struct attr *riattr; - struct peer_af *paf; char buf[PREFIX_STRLEN]; int ret; int transparent; @@ -1710,16 +1709,12 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, * Note: 3rd party nexthop currently implemented for * IPv4 only. */ - SUBGRP_FOREACH_PEER (subgrp, paf) { - if (bgp_multiaccess_check_v4(riattr->nexthop, - paf->peer)) - break; - } - if (!paf) + if (!bgp_subgrp_multiaccess_check_v4(riattr->nexthop, + subgrp)) subgroup_announce_reset_nhop( (peer_cap_enhe(peer, afi, safi) - ? AF_INET6 - : p->family), + ? AF_INET6 + : p->family), attr); } /* If IPv6/MP and nexthop does not have any override and happens @@ -7846,7 +7841,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, "bestpathFromAs", first_as); } else { if (first_as) - vty_out(vty, ", bestpath-from-AS %d", + vty_out(vty, ", bestpath-from-AS %u", first_as); else vty_out(vty, @@ -10485,7 +10480,7 @@ struct bgp_distance { DEFUN (show_bgp_afi_vpn_rd_route, show_bgp_afi_vpn_rd_route_cmd, - "show bgp "BGP_AFI_CMD_STR" vpn rd ASN:nn_or_IP-address:nn <A.B.C.D/M|X:X::X:X/M> [json]", + "show bgp "BGP_AFI_CMD_STR" vpn rd ASN:NN_OR_IP-ADDRESS:NN <A.B.C.D/M|X:X::X:X/M> [json]", SHOW_STR BGP_STR BGP_AFI_HELP_STR @@ -11129,11 +11124,23 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp, /* "network" configuration display. */ prefix_rd2str(prd, rdbuf, RD_ADDRSTRLEN); + if (p->u.prefix_evpn.route_type == 5) { + char local_buf[PREFIX_STRLEN]; + uint8_t family = IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p) + ? AF_INET + : AF_INET6; + inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr, local_buf, + PREFIX_STRLEN); + sprintf(buf, "%s/%u", local_buf,p->u.prefix_evpn.ip_prefix_length); + } else { + prefix2str(p, buf, sizeof(buf)); + } - inet_ntop(AF_INET, &bgp_static->igpnexthop, buf2, - SU_ADDRSTRLEN); - - prefix2str(p, buf, sizeof(buf)); + if (bgp_static->gatewayIp.family == AF_INET || + bgp_static->gatewayIp.family == AF_INET6) + inet_ntop(bgp_static->gatewayIp.family, + &bgp_static->gatewayIp.u.prefix, buf2, + sizeof(buf2)); vty_out(vty, " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s\n", buf, rdbuf, p->u.prefix_evpn.eth_tag, diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index f5663e9262..bb3def2fbe 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -3972,7 +3972,7 @@ DEFUN (no_set_lcommunity_delete, DEFUN (set_ecommunity_rt, set_ecommunity_rt_cmd, - "set extcommunity rt ASN:nn_or_IP-address:nn...", + "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...", SET_STR "BGP extended community attribute\n" "Route Target extended community\n" @@ -3992,7 +3992,7 @@ DEFUN (set_ecommunity_rt, DEFUN (no_set_ecommunity_rt, no_set_ecommunity_rt_cmd, - "no set extcommunity rt ASN:nn_or_IP-address:nn...", + "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...", NO_STR SET_STR "BGP extended community attribute\n" @@ -4006,7 +4006,7 @@ DEFUN (no_set_ecommunity_rt, DEFUN (set_ecommunity_soo, set_ecommunity_soo_cmd, - "set extcommunity soo ASN:nn_or_IP-address:nn...", + "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...", SET_STR "BGP extended community attribute\n" "Site-of-Origin extended community\n" @@ -4026,7 +4026,7 @@ DEFUN (set_ecommunity_soo, DEFUN (no_set_ecommunity_soo, no_set_ecommunity_soo_cmd, - "no set extcommunity soo ASN:nn_or_IP-address:nn...", + "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...", NO_STR SET_STR "BGP extended community attribute\n" diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index f9105bfaf7..4ddb499821 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -9868,7 +9868,7 @@ static int bgp_show_neighbor_vty(struct vty *vty, const char *name, /* "show [ip] bgp neighbors" commands. */ DEFUN (show_ip_bgp_neighbors, show_ip_bgp_neighbors_cmd, - "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|vpnv4 <all|rd ASN:nn_or_IP-address:nn>>] neighbors [<A.B.C.D|X:X::X:X|WORD>] [json]", + "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|vpnv4 <all|rd ASN:NN_OR_IP-ADDRESS:NN>>] neighbors [<A.B.C.D|X:X::X:X|WORD>] [json]", SHOW_STR IP_STR BGP_STR diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c index 91a3744315..3dffb59d11 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.c +++ b/bgpd/rfapi/bgp_rfapi_cfg.c @@ -385,7 +385,7 @@ DEFUN (vnc_defaults_rt_both, DEFUN (vnc_defaults_rd, vnc_defaults_rd_cmd, - "rd ASN:nn_or_IP-address:nn", + "rd ASN:NN_OR_IP-ADDRESS:NN", "Specify default route distinguisher\n" "Route Distinguisher (<as-number>:<number> | <ip-address>:<number> | auto:vn:<number> )\n") { @@ -2841,7 +2841,7 @@ DEFUN (vnc_nve_group_no_l2rd, DEFUN (vnc_nve_group_rd, vnc_nve_group_rd_cmd, - "rd ASN:nn_or_IP-address:nn", + "rd ASN:NN_OR_IP-ADDRESS:NN", "Specify route distinguisher\n" "Route Distinguisher (<as-number>:<number> | <ip-address>:<number> | auto:vn:<number> )\n") { @@ -3295,7 +3295,7 @@ DEFUN (vnc_vrf_policy_rt_both, DEFUN (vnc_vrf_policy_rd, vnc_vrf_policy_rd_cmd, - "rd ASN:nn_or_IP-address:nn", + "rd ASN:NN_OR_IP-ADDRESS:NN", "Specify default VRF route distinguisher\n" "Route Distinguisher (<as-number>:<number> | <ip-address>:<number> | auto:nh:<number> )\n") { @@ -3562,7 +3562,7 @@ DEFUN (vnc_l2_group_no_labels, DEFUN (vnc_l2_group_rt, vnc_l2_group_rt_cmd, - "rt <both|export|import> ASN:nn_or_IP-address:nn", + "rt <both|export|import> ASN:NN_OR_IP-ADDRESS:NN", "Specify route targets\n" "Export+import filters\n" "Export filters\n" diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index 8d1b2b974e..c6958237a3 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -4791,7 +4791,7 @@ static int vnc_add_vrf_prefix(struct vty *vty, const char *arg_vrf, DEFUN (add_vrf_prefix_rd_label_pref, add_vrf_prefix_rd_label_pref_cmd, - "add vrf NAME prefix <A.B.C.D/M|X:X::X:X/M> [{rd ASN:nn_or_IP-address|label (0-1048575)|preference (0-4294967295)}]", + "add vrf NAME prefix <A.B.C.D/M|X:X::X:X/M> [{rd ASN:NN_OR_IP-ADDRESS|label (0-1048575)|preference (0-4294967295)}]", "Add\n" "To a VRF\n" "VRF name\n" @@ -4914,7 +4914,7 @@ static int vnc_clear_vrf(struct vty *vty, struct bgp *bgp, const char *arg_vrf, DEFUN (clear_vrf_prefix_rd, clear_vrf_prefix_rd_cmd, - "clear vrf NAME [prefix <A.B.C.D/M|X:X::X:X/M>] [rd ASN:nn_or_IP-address]", + "clear vrf NAME [prefix <A.B.C.D/M|X:X::X:X/M>] [rd ASN:NN_OR_IP-ADDRESS]", "Clear stored data\n" "From a VRF\n" "VRF name\n" diff --git a/configure.ac b/configure.ac index 63bde5fcda..2faaa7fc8e 100755 --- a/configure.ac +++ b/configure.ac @@ -185,14 +185,6 @@ CC="${CC% -std=c99}" AC_C_FLAG([-std=gnu11], [CC="$ac_cc"], [CC="$CC -std=gnu11"]) -dnl if the user specified any CFLAGS, we don't add "-g -Os/-O2" here -if test "z$orig_cflags" = "z"; then - AC_C_FLAG([-g]) - AC_C_FLAG([-Os], [ - AC_C_FLAG([-O2]) - ]) -fi - dnl always want these CFLAGS AC_C_FLAG([-fno-omit-frame-pointer]) AC_C_FLAG([-funwind-tables]) @@ -438,6 +430,16 @@ AM_CONDITIONAL([FPM], [test "x$enable_fpm" = "xyes"]) if test "x${enable_dev_build}" = "xyes"; then AC_DEFINE(DEV_BUILD,,Build for development) + AC_C_FLAG([-g]) + AC_C_FLAG([-O0]) +else + dnl if the user specified any CFLAGS, we don't add "-g -Os/-O2" here + if test "z$orig_cflags" = "z"; then + AC_C_FLAG([-g]) + AC_C_FLAG([-Os], [ + AC_C_FLAG([-O2]) + ]) + fi fi AM_CONDITIONAL([DEV_BUILD], [test "x$enable_dev_build" = "xyes"]) diff --git a/eigrpd/eigrp_main.c b/eigrpd/eigrp_main.c index 705e04b34d..c4ca07178c 100644 --- a/eigrpd/eigrp_main.c +++ b/eigrpd/eigrp_main.c @@ -100,6 +100,8 @@ static void sigint(void) { zlog_notice("Terminating on signal"); eigrp_terminate(); + + exit(0); } /* SIGUSR1 handler. */ diff --git a/lib/command.h b/lib/command.h index 1c6938523c..8cccb62de3 100644 --- a/lib/command.h +++ b/lib/command.h @@ -357,6 +357,7 @@ struct cmd_node { #define OSPF_RI_STR "OSPF Router Information specific commands\n" #define PCE_STR "PCE Router Information specific commands\n" #define MPLS_STR "MPLS information\n" +#define WATCHFRR_STR "watchfrr information\n" #define CONF_BACKUP_EXT ".sav" diff --git a/lib/command_lex.l b/lib/command_lex.l index 59d0d840a8..436f3a241d 100644 --- a/lib/command_lex.l +++ b/lib/command_lex.l @@ -35,14 +35,14 @@ } } while(0) %} -WORD (\-|\+)?[a-z0-9\*][-+_a-zA-Z0-9\*]* IPV4 A\.B\.C\.D IPV4_PREFIX A\.B\.C\.D\/M IPV6 X:X::X:X IPV6_PREFIX X:X::X:X\/M MAC M:A:C MAC_PREFIX M:A:C\/M -VARIABLE [A-Z][-_a-zA-Z:0-9]+ +VARIABLE [A-Z][-_A-Z:0-9]+ +WORD (\-|\+)?[a-zA-Z0-9\*][-+_a-zA-Z0-9\*]* NUMBER (\-|\+)?[0-9]{1,20} RANGE \({NUMBER}[ ]?\-[ ]?{NUMBER}\) @@ -64,7 +64,6 @@ RANGE \({NUMBER}[ ]?\-[ ]?{NUMBER}\) %} [ \t]+ LOC_STEP /* ignore whitespace */; -{WORD} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return WORD;} {IPV4} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return IPV4;} {IPV4_PREFIX} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return IPV4_PREFIX;} {IPV6} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return IPV6;} @@ -72,6 +71,7 @@ RANGE \({NUMBER}[ ]?\-[ ]?{NUMBER}\) {MAC} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return MAC;} {MAC_PREFIX} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return MAC_PREFIX;} {VARIABLE} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return VARIABLE;} +{WORD} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return WORD;} {RANGE} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return RANGE;} . {return yytext[0];} %% diff --git a/lib/command_match.c b/lib/command_match.c index 62e7c63068..6384abe5ce 100644 --- a/lib/command_match.c +++ b/lib/command_match.c @@ -214,6 +214,7 @@ static enum matcher_rv command_match_r(struct graph_node *start, vector vline, fprintf(stdout, "\"%-20s\" matches \"%-30s\" ? ", input_token, token->text); enum match_type mt = match_token(token, input_token); + fprintf(stdout, "type: %d ", token->type); fprintf(stdout, "min: %d - ", minmatch); switch (mt) { case trivial_match: diff --git a/lib/libfrr.c b/lib/libfrr.c index 3e2e008223..d5078f98aa 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -886,6 +886,7 @@ void frr_fini(void) zprivs_terminate(di->privs); /* signal_init -> nothing needed */ thread_master_free(master); + master = NULL; closezlog(); /* frrmod_init -> nothing needed / hooks */ diff --git a/lib/pid_output.c b/lib/pid_output.c index e2e4434150..9a7307bc4f 100644 --- a/lib/pid_output.c +++ b/lib/pid_output.c @@ -57,7 +57,8 @@ pid_t pid_output(const char *path) lock.l_whence = SEEK_SET; if (fcntl(fd, F_SETLK, &lock) < 0) { - zlog_err("Could not lock pid_file %s, exiting", path); + zlog_err("Could not lock pid_file %s (%s), exiting", + path, safe_strerror(errno)); exit(1); } diff --git a/lib/plist.c b/lib/plist.c index ebd628d724..da6406d334 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -679,7 +679,9 @@ static int prefix_list_entry_match(struct prefix_list_entry *pentry, return 1; } -enum prefix_list_type prefix_list_apply(struct prefix_list *plist, void *object) +enum prefix_list_type prefix_list_apply_which_prefix(struct prefix_list *plist, + struct prefix **which, + void *object) { struct prefix_list_entry *pentry, *pbest = NULL; @@ -689,11 +691,17 @@ enum prefix_list_type prefix_list_apply(struct prefix_list *plist, void *object) size_t validbits = p->prefixlen; struct pltrie_table *table; - if (plist == NULL) + if (plist == NULL) { + if (which) + *which = NULL; return PREFIX_DENY; + } - if (plist->count == 0) + if (plist->count == 0) { + if (which) + *which = NULL; return PREFIX_PERMIT; + } depth = plist->master->trie_depth; table = plist->trie; @@ -729,6 +737,13 @@ enum prefix_list_type prefix_list_apply(struct prefix_list *plist, void *object) break; } + if (which) { + if (pbest) + *which = &pbest->prefix; + else + *which = NULL; + } + if (pbest == NULL) return PREFIX_DENY; diff --git a/lib/plist.h b/lib/plist.h index 3eba3046ae..bf06e74d36 100644 --- a/lib/plist.h +++ b/lib/plist.h @@ -50,7 +50,21 @@ extern void prefix_list_delete_hook(void (*func)(struct prefix_list *)); extern const char *prefix_list_name(struct prefix_list *); extern afi_t prefix_list_afi(struct prefix_list *); extern struct prefix_list *prefix_list_lookup(afi_t, const char *); -extern enum prefix_list_type prefix_list_apply(struct prefix_list *, void *); + +/* + * prefix_list_apply_which_prefix + * + * Allow calling function to learn which prefix + * caused the DENY or PERMIT. + * + * If no pointer is sent in, do not return anything. + * 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); +#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 *); extern struct stream *prefix_bgp_orf_entry(struct stream *, diff --git a/lib/thread.c b/lib/thread.c index d8be32e2bd..a69bd2f0d5 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -567,9 +567,11 @@ void thread_master_free(struct thread_master *m) thread_list_free(m, &m->ready); thread_list_free(m, &m->unuse); pthread_mutex_destroy(&m->mtx); + pthread_cond_destroy(&m->cancel_cond); close(m->io_pipe[0]); close(m->io_pipe[1]); list_delete(m->cancel_req); + m->cancel_req = NULL; hash_clean(m->cpu_record, cpu_record_hash_free); hash_free(m->cpu_record); diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index 015776a174..e4644bb09f 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -1555,7 +1555,20 @@ void ospf6_intra_brouter_calculation(struct ospf6_area *oa) for (brouter = ospf6_route_head(oa->ospf6->brouter_table); brouter; brouter = nbrouter) { - nbrouter = ospf6_route_next(brouter); + /* + * brouter may have been "deleted" in the last loop iteration. + * If this is the case there is still 1 final refcount lock + * taken by ospf6_route_next, that will be released by the same + * call and result in deletion. To avoid heap UAF we must then + * skip processing the deleted route. + */ + if (brouter->lock == 1) { + nbrouter = ospf6_route_next(brouter); + continue; + } else { + nbrouter = ospf6_route_next(brouter); + } + brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix); inet_ntop(AF_INET, &brouter_id, brouter_name, sizeof(brouter_name)); diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index f330807b22..1ebe9c9aba 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -5068,7 +5068,7 @@ static int pim_rp_cmd_worker(struct pim_instance *pim, struct vty *vty, } if (result == PIM_GROUP_OVERLAP) { - vty_out(vty, "%% Group range specified cannot overlap\n"); + vty_out(vty, "%% Group range specified cannot exact match another\n"); return CMD_WARNING_CONFIG_FAILED; } @@ -6462,6 +6462,58 @@ DEFUN (interface_no_ip_pim_sm, return CMD_SUCCESS; } +/* boundaries */ +DEFUN(interface_ip_pim_boundary_oil, + interface_ip_pim_boundary_oil_cmd, + "ip multicast boundary oil WORD", + IP_STR + "Generic multicast configuration options\n" + "Define multicast boundary\n" + "Filter OIL by group using prefix list\n" + "Prefix list to filter OIL with") +{ + VTY_DECLVAR_CONTEXT(interface, iif); + struct pim_interface *pim_ifp; + int idx = 0; + + argv_find(argv, argc, "WORD", &idx); + + PIM_GET_PIM_INTERFACE(pim_ifp, iif); + + if (pim_ifp->boundary_oil_plist) + XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist); + + pim_ifp->boundary_oil_plist = + XSTRDUP(MTYPE_PIM_INTERFACE, argv[idx]->arg); + + /* Interface will be pruned from OIL on next Join */ + return CMD_SUCCESS; +} + +DEFUN(interface_no_ip_pim_boundary_oil, + interface_no_ip_pim_boundary_oil_cmd, + "no ip multicast boundary oil [WORD]", + NO_STR + IP_STR + "Generic multicast configuration options\n" + "Define multicast boundary\n" + "Filter OIL by group using prefix list\n" + "Prefix list to filter OIL with") +{ + VTY_DECLVAR_CONTEXT(interface, iif); + struct pim_interface *pim_ifp; + int idx; + + argv_find(argv, argc, "WORD", &idx); + + PIM_GET_PIM_INTERFACE(pim_ifp, iif); + + if (pim_ifp->boundary_oil_plist) + XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist); + + return CMD_SUCCESS; +} + DEFUN (interface_ip_mroute, interface_ip_mroute_cmd, "ip mroute INTERFACE A.B.C.D", @@ -8564,6 +8616,8 @@ void pim_cmd_init(void) install_element(INTERFACE_NODE, &interface_no_ip_pim_drprio_cmd); install_element(INTERFACE_NODE, &interface_ip_pim_hello_cmd); install_element(INTERFACE_NODE, &interface_no_ip_pim_hello_cmd); + install_element(INTERFACE_NODE, &interface_ip_pim_boundary_oil_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_pim_boundary_oil_cmd); // Static mroutes NEB install_element(INTERFACE_NODE, &interface_ip_mroute_cmd); diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index d98e5f1f66..b8cbed7f93 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -246,6 +246,9 @@ void pim_if_delete(struct interface *ifp) list_delete(pim_ifp->upstream_switch_list); list_delete(pim_ifp->sec_addr_list); + if (pim_ifp->boundary_oil_plist) + XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist); + while ((ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) != NULL) pim_ifchannel_delete(ch); diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index 2f27a14010..09bd2b06e4 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -122,6 +122,9 @@ struct pim_interface { uint32_t pim_dr_priority; /* config */ int pim_dr_num_nondrpri_neighbors; /* neighbors without dr_pri */ + /* boundary prefix-list */ + char *boundary_oil_plist; + int64_t pim_ifstat_start; /* start timestamp for stats */ uint32_t pim_ifstat_hello_sent; uint32_t pim_ifstat_hello_sendfail; diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 3a870374c0..f6c8db7acb 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -299,22 +299,19 @@ static int igmp_recv_query(struct igmp_sock *igmp, int query_version, return -1; } - /* RFC 3376 defines some guidelines on operating in backwards - * compatibility - * with older versions of IGMP but there are some gaps in the logic: + /* + * RFC 3376 defines some guidelines on operating in backwards + * compatibility with older versions of IGMP but there are some gaps in + * the logic: * * - once we drop from say version 3 to version 2 we will never go back - * to - * version 3 even if the node that TXed an IGMP v2 query upgrades to - * v3 + * to version 3 even if the node that TXed an IGMP v2 query upgrades + * to v3 * * - The node with the lowest IP is the querier so we will only know to - * drop - * from v3 to v2 if the node that is the querier is also the one that - * is - * running igmp v2. If a non-querier only supports igmp v2 we will - * have - * no way of knowing. + * drop from v3 to v2 if the node that is the querier is also the one + * that is running igmp v2. If a non-querier only supports igmp v2 + * we will have no way of knowing. * * For now we will simplify things and inform the user that they need to * configure all PIM routers to use the same version of IGMP. @@ -403,6 +400,9 @@ static int igmp_v1_recv_report(struct igmp_sock *igmp, struct in_addr from, memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); + if (pim_is_group_filtered(ifp->info, &group_addr)) + return -1; + /* non-existant group is created as INCLUDE {empty} */ group = igmp_add_group_by_addr(igmp, group_addr); if (!group) { diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index 1fc7517e05..ecde546c06 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -671,6 +671,9 @@ void igmpv3_report_isex(struct igmp_sock *igmp, struct in_addr from, on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources, sources); + if (pim_is_group_filtered(ifp->info, &group_addr)) + return; + /* non-existant group is created as INCLUDE {empty} */ group = igmp_add_group_by_addr(igmp, group_addr); if (!group) { @@ -1869,6 +1872,9 @@ int igmp_v3_recv_report(struct igmp_sock *igmp, struct in_addr from, struct interface *ifp = igmp->interface; int i; int local_ncb = 0; + struct pim_interface *pim_ifp; + + pim_ifp = igmp->interface->info; if (igmp_msg_len < IGMP_V3_MSG_MIN_SIZE) { zlog_warn( @@ -1920,6 +1926,7 @@ int igmp_v3_recv_report(struct igmp_sock *igmp, struct in_addr from, int j; struct prefix lncb; struct prefix g; + bool filtered = false; if ((group_record + IGMP_V3_GROUP_RECORD_MIN_SIZE) > report_pastend) { @@ -1983,6 +1990,16 @@ int igmp_v3_recv_report(struct igmp_sock *igmp, struct in_addr from, g.family = AF_INET; g.u.prefix4 = rec_group; g.prefixlen = 32; + + /* determine filtering status for group */ + filtered = pim_is_group_filtered(ifp->info, &rec_group); + + if (PIM_DEBUG_IGMP_PACKETS && filtered) + zlog_debug( + "Filtering IGMPv3 group record %s from %s on %s per prefix-list %s", + inet_ntoa(rec_group), from_str, ifp->name, + pim_ifp->boundary_oil_plist); + /* * If we receive a igmp report with the group in 224.0.0.0/24 * then we should ignore it @@ -1990,7 +2007,7 @@ int igmp_v3_recv_report(struct igmp_sock *igmp, struct in_addr from, if (prefix_match(&lncb, &g)) local_ncb = 1; - if (!local_ncb) + if (!local_ncb && !filtered) switch (rec_type) { case IGMP_GRP_REC_TYPE_MODE_IS_INCLUDE: igmpv3_report_isin(igmp, from, rec_group, diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h index 0e91b4ca01..5422e8fe0d 100644 --- a/pimd/pim_instance.h +++ b/pimd/pim_instance.h @@ -76,7 +76,11 @@ struct pim_instance { struct hash *upstream_hash; struct timer_wheel *upstream_sg_wheel; + /* + * RP information + */ struct list *rp_list; + struct route_table *rp_table; int iface_vif_index[MAXVIFS]; diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 4f5e534010..ae5032be73 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -38,6 +38,7 @@ #include "pim_rpf.h" #include "pim_rp.h" #include "pim_jp_agg.h" +#include "pim_util.h" static void on_trace(const char *label, struct interface *ifp, struct in_addr src) @@ -153,6 +154,7 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, int tlv_buf_size) { struct prefix msg_upstream_addr; + struct pim_interface *pim_ifp; uint8_t msg_num_groups; uint16_t msg_holdtime; int addr_offset; @@ -163,6 +165,7 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, buf = tlv_buf; pastend = tlv_buf + tlv_buf_size; + pim_ifp = ifp->info; /* Parse ucast addr @@ -231,6 +234,7 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, uint16_t msg_num_pruned_sources; int source; struct pim_ifchannel *starg_ch = NULL, *sg_ch = NULL; + bool filtered = false; memset(&sg, 0, sizeof(struct prefix_sg)); addr_offset = pim_parse_addr_group(&sg, buf, pastend - buf); @@ -273,6 +277,9 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, src_str, ifp->name); } + /* boundary check */ + filtered = pim_is_group_filtered(pim_ifp, &sg.grp); + /* Scan joined sources */ for (source = 0; source < msg_num_joined_sources; ++source) { addr_offset = pim_parse_addr_source( @@ -283,6 +290,10 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, buf += addr_offset; + /* if we are filtering this group, skip the join */ + if (filtered) + continue; + recv_join(ifp, neigh, msg_holdtime, msg_upstream_addr.u.prefix4, &sg, msg_source_flags); @@ -304,6 +315,11 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, } buf += addr_offset; + + /* if we are filtering this group, skip the prune */ + if (filtered) + continue; + recv_prune(ifp, neigh, msg_holdtime, msg_upstream_addr.u.prefix4, &sg, msg_source_flags); @@ -335,7 +351,7 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, } } } - if (starg_ch) + if (starg_ch && !filtered) pim_ifchannel_set_star_g_join_state(starg_ch, 1, 0); starg_ch = NULL; } /* scan groups */ diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 851a861a95..5c7561f586 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -30,6 +30,7 @@ #include "vrf.h" #include "plist.h" #include "nexthop.h" +#include "table.h" #include "pimd.h" #include "pim_vty.h" @@ -96,17 +97,36 @@ int pim_rp_list_cmp(void *v1, void *v2) void pim_rp_init(struct pim_instance *pim) { struct rp_info *rp_info; + struct route_node *rn; pim->rp_list = list_new(); + if (!pim->rp_list) { + zlog_err("Unable to alloc rp_list"); + return; + } pim->rp_list->del = (void (*)(void *))pim_rp_info_free; pim->rp_list->cmp = pim_rp_list_cmp; + pim->rp_table = route_table_init(); + if (!pim->rp_table) { + zlog_err("Unable to alloc rp_table"); + list_delete(pim->rp_list); + return; + } + rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info)); - if (!rp_info) + if (!rp_info) { + zlog_err("Unable to alloc rp_info"); + route_table_finish(pim->rp_table); + list_delete(pim->rp_list); return; + } if (!str2prefix("224.0.0.0/4", &rp_info->group)) { + zlog_err("Unable to convert 224.0.0.0/4 to prefix"); + list_delete(pim->rp_list); + route_table_finish(pim->rp_table); XFREE(MTYPE_PIM_RP, rp_info); return; } @@ -116,6 +136,20 @@ void pim_rp_init(struct pim_instance *pim) rp_info->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; listnode_add(pim->rp_list, rp_info); + + rn = route_node_get(pim->rp_table, &rp_info->group); + if (!rn) { + zlog_err("Failure to get route node for pim->rp_table"); + list_delete(pim->rp_list); + route_table_finish(pim->rp_table); + XFREE(MTYPE_PIM_RP, rp_info); + return; + } + + rn->info = rp_info; + if (PIM_DEBUG_TRACE) + zlog_debug("Allocated: %p for rp_info: %p(224.0.0.0/4) Lock: %d", + rn, rp_info, rn->lock); } void pim_rp_free(struct pim_instance *pim) @@ -189,23 +223,58 @@ static struct rp_info *pim_rp_find_match_group(struct pim_instance *pim, struct prefix *group) { struct listnode *node; + struct rp_info *best = NULL; struct rp_info *rp_info; struct prefix_list *plist; + struct prefix *p, *bp; + struct route_node *rn; + bp = NULL; for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) { if (rp_info->plist) { plist = prefix_list_lookup(AFI_IP, rp_info->plist); - if (plist - && prefix_list_apply(plist, group) == PREFIX_PERMIT) - return rp_info; - } else { - if (prefix_match(&rp_info->group, group)) - return rp_info; + if (prefix_list_apply_which_prefix(plist, &p, group) == PREFIX_DENY) + continue; + + if (!best) { + best = rp_info; + bp = p; + continue; + } + + if (bp && bp->prefixlen < p->prefixlen) { + best = rp_info; + bp = p; + } } } - return NULL; + rn = route_node_match(pim->rp_table, group); + if (!rn) { + zlog_err("%s: BUG We should have found default group information\n", + __PRETTY_FUNCTION__); + return best; + } + + rp_info = rn->info; + if (PIM_DEBUG_TRACE) { + char buf[PREFIX_STRLEN]; + + route_unlock_node(rn); + zlog_debug("Lookedup: %p for rp_info: %p(%s) Lock: %d", + rn, rp_info, + prefix2str(&rp_info->group, buf, sizeof(buf)), + rn->lock); + } + + if (!best) + return rp_info; + + if (rp_info->group.prefixlen < best->group.prefixlen) + best = rp_info; + + return best; } /* @@ -293,6 +362,7 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, char buffer[BUFSIZ]; struct prefix nht_p; struct pim_nexthop_cache pnc; + struct route_node *rn; rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info)); if (!rp_info) @@ -357,6 +427,7 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, rp_info->plist = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist); } else { + if (!str2prefix("224.0.0.0/4", &group_all)) { XFREE(MTYPE_PIM_RP, rp_info); return PIM_GROUP_BAD_ADDRESS; @@ -452,8 +523,8 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, * For all others * though we must return PIM_GROUP_OVERLAP */ - if (!prefix_same(&group_all, - &tmp_rp_info->group)) { + if (prefix_same(&rp_info->group, + &tmp_rp_info->group)) { XFREE(MTYPE_PIM_RP, rp_info); return PIM_GROUP_OVERLAP; } @@ -462,6 +533,23 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, } listnode_add_sort(pim->rp_list, rp_info); + rn = route_node_get(pim->rp_table, &rp_info->group); + if (!rn) { + char buf[PREFIX_STRLEN]; + zlog_err("Failure to get route node for pim->rp_table: %s", + prefix2str(&rp_info->group, buf, sizeof(buf))); + return PIM_MALLOC_FAIL; + } + rn->info = rp_info; + + if (PIM_DEBUG_TRACE) { + char buf[PREFIX_STRLEN]; + + zlog_debug("Allocated: %p for rp_info: %p(%s) Lock: %d", + rn, rp_info, + prefix2str(&rp_info->group, buf, sizeof(buf)), + rn->lock); + } /* Register addr with Zebra NHT */ nht_p.family = AF_INET; @@ -504,6 +592,8 @@ int pim_rp_del(struct pim_instance *pim, const char *rp, struct rp_info *rp_all; int result; struct prefix nht_p; + struct route_node *rn; + bool was_plist = false; if (group_range == NULL) result = str2prefix("224.0.0.0/4", &group); @@ -528,6 +618,7 @@ int pim_rp_del(struct pim_instance *pim, const char *rp, if (rp_info->plist) { XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist); rp_info->plist = NULL; + was_plist = true; } /* Deregister addr with Zebra NHT */ @@ -555,7 +646,31 @@ int pim_rp_del(struct pim_instance *pim, const char *rp, } listnode_delete(pim->rp_list, rp_info); + + if (!was_plist) { + rn = route_node_get(pim->rp_table, &rp_info->group); + if (rn) { + if (rn->info != rp_info) + zlog_err("WTF matey"); + + if (PIM_DEBUG_TRACE) { + char buf[PREFIX_STRLEN]; + + zlog_debug("%s:Found for Freeing: %p for rp_info: %p(%s) Lock: %d", + __PRETTY_FUNCTION__, + rn, rp_info, + prefix2str(&rp_info->group, buf, sizeof(buf)), + rn->lock); + } + rn->info = NULL; + route_unlock_node(rn); + route_unlock_node(rn); + } + } + pim_rp_refresh_group_to_rp_mapping(pim); + + XFREE(MTYPE_PIM_RP, rp_info); return PIM_SUCCESS; } diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 36c6c894ef..fd09b04b8a 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -61,6 +61,14 @@ int pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop, int found = 0; int i = 0; + /* + * We should not attempt to lookup a + * 255.255.255.255 address, since + * it will never work + */ + if (addr.s_addr == INADDR_NONE) + return -1; + if ((nexthop->last_lookup.s_addr == addr.s_addr) && (nexthop->last_lookup_time > last_route_change_time)) { if (PIM_DEBUG_TRACE) { diff --git a/pimd/pim_util.c b/pimd/pim_util.c index 820117a03a..15bde256da 100644 --- a/pimd/pim_util.c +++ b/pimd/pim_util.c @@ -21,6 +21,7 @@ #include "log.h" #include "prefix.h" +#include "plist.h" #include "pim_util.h" @@ -114,7 +115,7 @@ int pim_is_group_224_0_0_0_24(struct in_addr group_addr) group.family = AF_INET; group.u.prefix4 = group_addr; - group.prefixlen = 32; + group.prefixlen = IPV4_MAX_PREFIXLEN; return prefix_match(&group_224, &group); } @@ -137,3 +138,19 @@ int pim_is_group_224_4(struct in_addr group_addr) return prefix_match(&group_all, &group); } + +bool pim_is_group_filtered(struct pim_interface *pim_ifp, struct in_addr *grp) +{ + struct prefix grp_pfx; + struct prefix_list *pl; + + if (!pim_ifp->boundary_oil_plist) + return false; + + grp_pfx.family = AF_INET; + grp_pfx.prefixlen = 32; + grp_pfx.u.prefix4 = *grp; + + pl = prefix_list_lookup(AFI_IP, pim_ifp->boundary_oil_plist); + return pl ? prefix_list_apply(pl, &grp_pfx) == PREFIX_DENY : false; +} diff --git a/pimd/pim_util.h b/pimd/pim_util.h index 1b319cfe4c..c66dd7b660 100644 --- a/pimd/pim_util.h +++ b/pimd/pim_util.h @@ -25,6 +25,8 @@ #include <zebra.h> #include "checksum.h" +#include "pimd.h" +#include "pim_iface.h" uint8_t igmp_msg_encode16to8(uint16_t value); uint16_t igmp_msg_decode8to16(uint8_t code); @@ -33,4 +35,5 @@ void pim_pkt_dump(const char *label, const uint8_t *buf, int size); int pim_is_group_224_0_0_0_24(struct in_addr group_addr); int pim_is_group_224_4(struct in_addr group_addr); +bool pim_is_group_filtered(struct pim_interface *pim_ifp, struct in_addr *grp); #endif /* PIM_UTIL_H */ diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 3da092541d..c1adbcc915 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -285,6 +285,7 @@ int pim_interface_config_write(struct vty *vty) vty_out(vty, " %d", pim_ifp->pim_default_holdtime); vty_out(vty, "\n"); + ++writes; } /* update source */ @@ -358,6 +359,14 @@ int pim_interface_config_write(struct vty *vty) } } + /* boundary */ + if (pim_ifp->boundary_oil_plist) { + vty_out(vty, + " ip pim boundary oil %s\n", + pim_ifp->boundary_oil_plist); + ++writes; + } + writes += pim_static_write_mroute(pim, vty, ifp); pim_bfd_write_config(vty, ifp); diff --git a/tools/frr-reload.py b/tools/frr-reload.py index 8f34b4cb3f..afe66b6eaf 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -557,7 +557,15 @@ def line_for_vtysh_file(ctx_keys, line, delete): for ctx_key in ctx_keys: cmd.append(ctx_key) - return '\n' + '\n'.join(cmd) + cmd = '\n' + '\n'.join(cmd) + + # There are some commands that are on by default so their "no" form will be + # displayed in the config. "no bgp default ipv4-unicast" is one of these. + # If we need to remove this line we do so by adding "bgp default ipv4-unicast", + # not by doing a "no no bgp default ipv4-unicast" + cmd = cmd.replace('no no ', '') + + return cmd def get_normalized_ipv6_line(line): @@ -931,6 +939,7 @@ def compare_context_objects(newconf, running): return (lines_to_add, lines_to_del) + if __name__ == '__main__': # Command line options parser = argparse.ArgumentParser(description='Dynamically apply diff in frr configs') @@ -1143,7 +1152,7 @@ if __name__ == '__main__': while True: try: - _ = subprocess.check_output(cmd) + _ = subprocess.check_output(cmd, stderr=subprocess.STDOUT) except subprocess.CalledProcessError: @@ -1188,7 +1197,7 @@ if __name__ == '__main__': fh.write(line + '\n') try: - subprocess.check_output(['/usr/bin/vtysh', '-f', filename]) + subprocess.check_output(['/usr/bin/vtysh', '-f', filename], stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: log.warning("frr-reload.py failed due to\n%s" % e.output) reload_ok = False diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 78e64c1509..3f86f3c929 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -1896,7 +1896,7 @@ DEFUN (vtysh_show_debugging, DEBUG_STR) { return show_per_daemon("do show debugging\n", - "Debugging Information for %s:\n"); + ""); } DEFUN (vtysh_show_debugging_hashtable, diff --git a/watchfrr/watchfrr_vty.c b/watchfrr/watchfrr_vty.c index 9cfdab44ab..1f872c91ff 100644 --- a/watchfrr/watchfrr_vty.c +++ b/watchfrr/watchfrr_vty.c @@ -101,6 +101,16 @@ DEFUN(config_write_integrated, exit(1); } +DEFUN_NOSH (show_debugging_watchfrr, + show_debugging_watchfrr_cmd, + "show debugging [watchfrr]", + SHOW_STR + DEBUG_STR + WATCHFRR_STR) +{ + return CMD_SUCCESS; +} + void integrated_write_sigchld(int status) { uint8_t reply[4] = {0, 0, 0, CMD_WARNING}; @@ -134,4 +144,6 @@ void watchfrr_vty_init(void) { integrated_write_pid = -1; install_element(ENABLE_NODE, &config_write_integrated_cmd); + install_element(ENABLE_NODE, &show_debugging_watchfrr_cmd); + install_element(CONFIG_NODE, &show_debugging_watchfrr_cmd); } diff --git a/zebra/connected.c b/zebra/connected.c index 77a560c6bd..18dc6a970b 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -396,10 +396,10 @@ void connected_down(struct interface *ifp, struct connected *ifc) * head. */ rib_delete(afi, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, - &p, NULL, &nh, 0, 0); + &p, NULL, &nh, 0, 0, false); rib_delete(afi, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, - 0, &p, NULL, &nh, 0, 0); + 0, &p, NULL, &nh, 0, 0, false); if (IS_ZEBRA_DEBUG_RIB_DETAILED) { char buf[PREFIX_STRLEN]; diff --git a/zebra/debug.c b/zebra/debug.c index afeba1c6de..ac96051abd 100644 --- a/zebra/debug.c +++ b/zebra/debug.c @@ -83,6 +83,8 @@ DEFUN_NOSH (show_debugging_zebra, vty_out(vty, " Zebra next-hop tracking debugging is on\n"); if (IS_ZEBRA_DEBUG_MPLS) vty_out(vty, " Zebra MPLS debugging is on\n"); + if (IS_ZEBRA_DEBUG_VXLAN) + vty_out(vty, " Zebra VXLAN debugging is on\n"); if (IS_ZEBRA_DEBUG_PW) vty_out(vty, " Zebra pseudowire debugging is on\n"); @@ -97,7 +99,7 @@ DEFUN (debug_zebra_events, "Debug option set for zebra events\n") { zebra_debug_event = ZEBRA_DEBUG_EVENT; - return CMD_WARNING_CONFIG_FAILED; + return CMD_SUCCESS; } DEFUN (debug_zebra_nht, @@ -108,7 +110,7 @@ DEFUN (debug_zebra_nht, "Debug option set for zebra next hop tracking\n") { zebra_debug_nht = ZEBRA_DEBUG_NHT; - return CMD_WARNING_CONFIG_FAILED; + return CMD_SUCCESS; } DEFUN (debug_zebra_mpls, @@ -119,7 +121,7 @@ DEFUN (debug_zebra_mpls, "Debug option set for zebra MPLS LSPs\n") { zebra_debug_mpls = ZEBRA_DEBUG_MPLS; - return CMD_WARNING_CONFIG_FAILED; + return CMD_SUCCESS; } DEFUN (debug_zebra_vxlan, @@ -130,7 +132,7 @@ DEFUN (debug_zebra_vxlan, "Debug option set for zebra VxLAN (EVPN)\n") { zebra_debug_vxlan = ZEBRA_DEBUG_VXLAN; - return CMD_WARNING; + return CMD_SUCCESS; } DEFUN (debug_zebra_pw, @@ -145,7 +147,7 @@ DEFUN (debug_zebra_pw, UNSET_FLAG(zebra_debug_pw, ZEBRA_DEBUG_PW); else SET_FLAG(zebra_debug_pw, ZEBRA_DEBUG_PW); - return CMD_WARNING; + return CMD_SUCCESS; } DEFUN (debug_zebra_packet, diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index df8cdb3ab3..9907ef5b79 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -1042,7 +1042,7 @@ void rtm_read(struct rt_msghdr *rtm) if (rtm->rtm_type == RTM_CHANGE) rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, - NULL, 0, 0); + NULL, 0, 0, true); if (!nh.type) { nh.type = NEXTHOP_TYPE_IPV4; @@ -1057,7 +1057,7 @@ void rtm_read(struct rt_msghdr *rtm) else rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, - &nh, 0, 0); + &nh, 0, 0, true); } if (dest.sa.sa_family == AF_INET6) { /* One day we might have a debug section here like one in the @@ -1088,7 +1088,7 @@ void rtm_read(struct rt_msghdr *rtm) if (rtm->rtm_type == RTM_CHANGE) rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, - NULL, 0, 0); + NULL, 0, 0, true); if (!nh.type) { nh.type = ifindex ? NEXTHOP_TYPE_IPV6_IFINDEX @@ -1105,7 +1105,7 @@ void rtm_read(struct rt_msghdr *rtm) else rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, - &nh, 0, 0); + &nh, 0, 0, true); } } diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 76e0df40b9..890ad887da 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -558,7 +558,7 @@ int zebra_del_import_table_entry(struct route_node *rn, struct route_entry *re) rib_delete(afi, SAFI_UNICAST, re->vrf_id, ZEBRA_ROUTE_TABLE, re->table, re->flags, &p, NULL, NULL, - zebrad.rtm_table_default, re->metric); + zebrad.rtm_table_default, re->metric, false); return 0; } diff --git a/zebra/rib.h b/zebra/rib.h index fec5c2aacf..e3ed6210ca 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -304,7 +304,7 @@ extern int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *, extern void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, int flags, struct prefix *p, struct prefix_ipv6 *src_p, const struct nexthop *nh, - u_int32_t table_id, u_int32_t metric); + u_int32_t table_id, u_int32_t metric, bool fromkernel); extern struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t, union g_addr *, diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 039fac4e67..573f60f4ca 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -526,7 +526,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, if (re->nexthop_num == 0) XFREE(MTYPE_RE, re); else - rib_add_multipath(AFI_IP, SAFI_UNICAST, &p, + rib_add_multipath(afi, SAFI_UNICAST, &p, NULL, re); } } else { @@ -560,13 +560,13 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, memcpy(&nh.gate, gate, sz); rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p, NULL, &nh, - table, metric); + 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); + table, metric, true); } } @@ -1446,8 +1446,8 @@ static int netlink_route_multipath(int cmd, struct prefix *p, && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))) { routedesc = nexthop->rparent - ? "recursive, 1 hop" - : "single hop"; + ? "recursive, single-path" + : "single-path"; _netlink_route_debug(cmd, p, nexthop, routedesc, family, zvrf); @@ -1529,8 +1529,8 @@ static int netlink_route_multipath(int cmd, struct prefix *p, && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))) { routedesc = nexthop->rparent - ? "recursive, multihop" - : "multihop"; + ? "recursive, multipath" + : "multipath"; nexthop_num++; _netlink_route_debug(cmd, p, nexthop, routedesc, @@ -2349,6 +2349,7 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) unsigned int nexthop_num; const char *routedesc; struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + int route_type; struct { struct nlmsghdr n; @@ -2382,9 +2383,11 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) } } - if (nexthop_num == 0) // unexpected + if (nexthop_num == 0 || !lsp->best_nhlfe) // unexpected return 0; + route_type = re_type_from_lsp_type(lsp->best_nhlfe->type); + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; req.n.nlmsg_type = cmd; @@ -2393,7 +2396,7 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) req.r.rtm_family = AF_MPLS; req.r.rtm_table = RT_TABLE_MAIN; req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS; - req.r.rtm_protocol = RTPROT_ZEBRA; + req.r.rtm_protocol = zebra2proto(route_type); req.r.rtm_scope = RT_SCOPE_UNIVERSE; req.r.rtm_type = RTN_UNICAST; @@ -2409,7 +2412,7 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) * chosen depend on the operation. */ if (nexthop_num == 1 || multipath_num == 1) { - routedesc = "single hop"; + routedesc = "single-path"; _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); nexthop_num = 0; @@ -2457,7 +2460,7 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) rta->rta_len = RTA_LENGTH(0); rtnh = RTA_DATA(rta); - routedesc = "multihop"; + routedesc = "multipath"; _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); nexthop_num = 0; diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index 51279798a4..22c771c348 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -436,6 +436,24 @@ static inline enum lsp_types_t lsp_type_from_re_type(int re_type) } } +/* + * Map LSP type to RIB type. + */ +static inline int re_type_from_lsp_type(enum lsp_types_t lsp_type) +{ + switch (lsp_type) { + case ZEBRA_LSP_STATIC: + return ZEBRA_ROUTE_STATIC; + case ZEBRA_LSP_LDP: + return ZEBRA_ROUTE_LDP; + case ZEBRA_LSP_BGP: + return ZEBRA_ROUTE_BGP; + case ZEBRA_LSP_NONE: + default: + return ZEBRA_ROUTE_KERNEL; + } +} + /* NHLFE type as printable string. */ static inline const char *nhlfe_type2str(enum lsp_types_t lsp_type) { diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index 7014731e04..78072f43bb 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -32,7 +32,7 @@ DEFINE_MTYPE(ZEBRA, ZEBRA_NS, "Zebra Name Space") -struct zebra_ns *dzns; +static struct zebra_ns *dzns; struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id) { diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 00550fa07d..fab8c3c932 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -261,7 +261,7 @@ struct nexthop *route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re, if (src) nexthop->src.ipv4 = *src; nexthop->ifindex = ifindex; - ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT); + ifp = if_lookup_by_index(nexthop->ifindex, re->vrf_id); /*Pending: need to think if null ifp here is ok during bootup? There was a crash because ifp here was coming to be NULL */ if (ifp) @@ -417,7 +417,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re, * address in the routing table. */ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) { - ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT); + ifp = if_lookup_by_index(nexthop->ifindex, re->vrf_id); if (ifp && connected_is_unnumbered(ifp)) { if (if_is_operative(ifp)) return 1; @@ -2216,23 +2216,18 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, struct route_entry *same; struct nexthop *nexthop; int ret = 0; - int family; if (!re) return 0; - if (p->family == AF_INET) - family = AFI_IP; - else - family = AFI_IP6; - - assert(!src_p || family == AFI_IP6); + assert(!src_p || afi == AFI_IP6); /* Lookup table. */ - table = zebra_vrf_table_with_table_id(family, safi, re->vrf_id, - re->table); - if (!table) + table = zebra_vrf_table_with_table_id(afi, safi, re->vrf_id, re->table); + if (!table) { + XFREE(MTYPE_RE, re); return 0; + } /* Make it sure prefixlen is applied to the prefix. */ apply_mask(p); @@ -2258,8 +2253,18 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED)) continue; - if (same->type == re->type && same->instance == re->instance - && same->table == re->table && !RIB_SYSTEM_ROUTE(same)) + if (same->type != re->type) + continue; + if (same->instance != re->instance) + continue; + if (same->type == ZEBRA_ROUTE_KERNEL && + same->metric != re->metric) + continue; + /* + * We should allow duplicate connected routes because of + * IPv6 link-local routes and unnumbered interfaces on Linux. + */ + if (same->type != ZEBRA_ROUTE_CONNECT) break; } @@ -2294,7 +2299,7 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, int flags, struct prefix *p, struct prefix_ipv6 *src_p, const struct nexthop *nh, - u_int32_t table_id, u_int32_t metric) + u_int32_t table_id, u_int32_t metric, bool fromkernel) { struct route_table *table; struct route_node *rn; @@ -2375,6 +2380,21 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, /* If same type of route can't be found and this message is from kernel. */ if (!same) { + /* + * In the past(HA!) we could get here because + * we were receiving a route delete from the + * kernel and we're not marking the proto + * as coming from it's appropriate originator. + * Now that we are properly noticing the fact + * that the kernel has deleted our route we + * are not going to get called in this path + * I am going to leave this here because + * this might still work this way on non-linux + * platforms as well as some weird state I have + * not properly thought of yet. + * If we can show that this code path is + * dead then we can remove it. + */ if (fib && type == ZEBRA_ROUTE_KERNEL && CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE)) { if (IS_ZEBRA_DEBUG_RIB) { @@ -2423,8 +2443,17 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, } } - if (same) + if (same) { + if (fromkernel && + CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE) && + !allow_delete) { + rib_install_kernel(rn, same, NULL); + route_unlock_node(rn); + + return; + } rib_delnode(rn, same); + } route_unlock_node(rn); return; @@ -2437,70 +2466,10 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, u_int32_t mtu, u_char distance) { struct route_entry *re; - struct route_entry *same = NULL; - struct route_table *table; - struct route_node *rn; - struct nexthop *rtnh; - - assert(!src_p || afi == AFI_IP6); - - /* Lookup table. */ - table = zebra_vrf_table_with_table_id(afi, safi, vrf_id, table_id); - if (!table) - return 0; - - /* Make sure mask is applied. */ - apply_mask(p); - if (src_p) - apply_mask_ipv6(src_p); - - /* Set default distance by route type. */ - if (distance == 0) { - distance = route_distance(type); - - /* iBGP distance is 200. */ - if (type == ZEBRA_ROUTE_BGP - && CHECK_FLAG(flags, ZEBRA_FLAG_IBGP)) - distance = 200; - } - - /* Lookup route node.*/ - rn = srcdest_rnode_get(table, p, src_p); - - /* If same type of route are installed, treat it as a implicit - withdraw. */ - RNODE_FOREACH_RE (rn, re) { - if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) - continue; - - if (re->type != type) - continue; - if (re->instance != instance) - continue; - if (re->type == ZEBRA_ROUTE_KERNEL && - re->metric != metric) - continue; - if (!RIB_SYSTEM_ROUTE(re)) { - same = re; - break; - } - /* Duplicate system route comes in. */ - rtnh = re->nexthop; - if (nexthop_same_no_recurse(rtnh, nh)) - return 0; - /* - * Nexthop is different. Remove the old route unless it's - * a connected route. This exception is necessary because - * of IPv6 link-local routes and unnumbered interfaces on - * Linux. - */ - else if (type != ZEBRA_ROUTE_CONNECT) - same = re; - } + struct nexthop *nexthop; - /* Allocate new re structure. */ + /* Allocate new route_entry structure. */ re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); - re->type = type; re->instance = instance; re->distance = distance; @@ -2512,33 +2481,12 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, re->nexthop_num = 0; re->uptime = time(NULL); - rtnh = nexthop_new(); - *rtnh = *nh; - route_entry_nexthop_add(re, rtnh); - - /* If this route is kernel route, set FIB flag to the route. */ - if (RIB_SYSTEM_ROUTE(re)) - for (rtnh = re->nexthop; rtnh; rtnh = rtnh->next) - SET_FLAG(rtnh->flags, NEXTHOP_FLAG_FIB); - - /* Link new rib to node.*/ - if (IS_ZEBRA_DEBUG_RIB) { - rnode_debug( - rn, vrf_id, - "Inserting route rn %p, re %p (type %d) existing %p", - (void *)rn, (void *)re, re->type, (void *)same); - - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - route_entry_dump(p, src_p, re); - } - rib_addnode(rn, re, 1); - - /* Free implicit route.*/ - if (same) - rib_delnode(rn, same); + /* Add nexthop. */ + nexthop = nexthop_new(); + *nexthop = *nh; + route_entry_nexthop_add(re, nexthop); - route_unlock_node(rn); - return 0; + return rib_add_multipath(afi, safi, p, src_p, re); } /* Schedule routes of a particular table (address-family) based on event. */ diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index df1eef119a..04cd17cedb 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -166,10 +166,13 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi, } /* Null0 static route. */ - if ((ifname != NULL) - && (strncasecmp(ifname, "Null0", strlen(ifname)) == 0)) { - bh_type = STATIC_BLACKHOLE_NULL; - ifname = NULL; + if (ifname != NULL) { + if (strncasecmp(ifname, "Null0", strlen(ifname)) == 0 || + strncasecmp(ifname, "reject", strlen(ifname)) == 0 || + strncasecmp(ifname, "blackhole", strlen(ifname)) == 0) { + vty_out(vty, "%% Nexthop interface cannot be Null0, reject or blackhole\n"); + return CMD_WARNING_CONFIG_FAILED; + } } /* Route flags */ @@ -181,6 +184,9 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi, case 'b': bh_type = STATIC_BLACKHOLE_DROP; break; + case 'N': + bh_type = STATIC_BLACKHOLE_NULL; + break; default: vty_out(vty, "%% Malformed flag %s \n", flag_str); return CMD_WARNING_CONFIG_FAILED; @@ -333,27 +339,22 @@ DEFUN (show_ip_rpf_addr, } /* Static route configuration. */ -DEFPY(ip_route, ip_route_cmd, +DEFPY(ip_route_blackhole, + ip_route_blackhole_cmd, "[no] ip route\ - <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask>\ - <\ - {A.B.C.D$gate|INTERFACE$ifname}\ - |null0$ifname\ - |<reject|blackhole>$flag\ - >\ - [{\ - tag (1-4294967295)\ - |(1-255)$distance\ - |vrf NAME\ - |label WORD\ + <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \ + <Null0|reject|blackhole>$flag \ + [{ \ + tag (1-4294967295) \ + |(1-255)$distance \ + |vrf NAME \ + |label WORD \ }]", NO_STR IP_STR "Establish static routes\n" "IP destination prefix (e.g. 10.0.0.0/8)\n" "IP destination prefix\n" "IP destination prefix mask\n" - "IP gateway address\n" - "IP gateway interface name\n" "Null interface\n" "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n" @@ -364,9 +365,67 @@ DEFPY(ip_route, ip_route_cmd, MPLS_LABEL_HELPSTR) { return zebra_static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix, - mask_str, NULL, gate_str, ifname, flag, + mask_str, NULL, NULL, NULL, flag, + tag_str, distance_str, vrf, label); +} + +DEFPY(ip_route_address_interface, + ip_route_address_interface_cmd, + "[no] ip route\ + <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \ + A.B.C.D$gate \ + INTERFACE$ifname \ + [{ \ + tag (1-4294967295) \ + |(1-255)$distance \ + |vrf NAME \ + |label WORD \ + }]", + NO_STR IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR + MPLS_LABEL_HELPSTR) +{ + return zebra_static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix, + mask_str, NULL, gate_str, ifname, NULL, + tag_str, distance_str, vrf, label); +} + +DEFPY(ip_route, + ip_route_cmd, + "[no] ip route\ + <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \ + <A.B.C.D$gate|INTERFACE$ifname> \ + [{ \ + tag (1-4294967295) \ + |(1-255)$distance \ + |vrf NAME \ + |label WORD \ + }]", + NO_STR IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR + MPLS_LABEL_HELPSTR) +{ + return zebra_static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix, + mask_str, NULL, gate_str, ifname, NULL, tag_str, distance_str, vrf, label); - return 0; } /* New RIB. Detailed information for IPv4 route. */ @@ -1752,19 +1811,75 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi, return write; } +DEFPY(ipv6_route_blackhole, + ipv6_route_blackhole_cmd, + "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \ + <Null0|reject|blackhole>$flag \ + [{ \ + tag (1-4294967295) \ + |(1-255)$distance \ + |vrf NAME \ + |label WORD \ + }]", + NO_STR + IPV6_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 source-dest route\n" + "IPv6 source prefix\n" + "Null interface\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this prefix\n" + VRF_CMD_HELP_STR + MPLS_LABEL_HELPSTR) +{ + return zebra_static_route(vty, AFI_IP6, SAFI_UNICAST, no, prefix_str, + NULL, from_str, NULL, NULL, flag, + tag_str, distance_str, vrf, label); +} + +DEFPY(ipv6_route_address_interface, + ipv6_route_address_interface_cmd, + "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \ + X:X::X:X$gate \ + INTERFACE$ifname \ + [{ \ + tag (1-4294967295) \ + |(1-255)$distance \ + |vrf NAME \ + |label WORD \ + }]", + NO_STR + IPV6_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 source-dest route\n" + "IPv6 source prefix\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this prefix\n" + VRF_CMD_HELP_STR + MPLS_LABEL_HELPSTR) +{ + return zebra_static_route(vty, AFI_IP6, SAFI_UNICAST, no, prefix_str, + NULL, from_str, gate_str, ifname, NULL, + tag_str, distance_str, vrf, label); +} + DEFPY(ipv6_route, ipv6_route_cmd, - "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M]\ - <\ - {X:X::X:X$gate|INTERFACE$ifname}\ - |null0$ifname\ - |<reject|blackhole>$flag\ - >\ - [{\ - tag (1-4294967295)\ - |(1-255)$distance\ - |vrf NAME\ - |label WORD\ + "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \ + <X:X::X:X$gate|INTERFACE$ifname> \ + [{ \ + tag (1-4294967295) \ + |(1-255)$distance \ + |vrf NAME \ + |label WORD \ }]", NO_STR IPV6_STR @@ -1774,9 +1889,6 @@ DEFPY(ipv6_route, "IPv6 source prefix\n" "IPv6 gateway address\n" "IPv6 gateway interface name\n" - "Null interface\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n" "Set tag for this route\n" "Tag value\n" "Distance value for this prefix\n" @@ -1784,7 +1896,7 @@ DEFPY(ipv6_route, MPLS_LABEL_HELPSTR) { return zebra_static_route(vty, AFI_IP6, SAFI_UNICAST, no, prefix_str, - NULL, from_str, gate_str, ifname, flag, + NULL, from_str, gate_str, ifname, NULL, tag_str, distance_str, vrf, label); } @@ -2664,6 +2776,8 @@ void zebra_vty_init(void) install_element(CONFIG_NODE, &ip_mroute_dist_cmd); install_element(CONFIG_NODE, &ip_multicast_mode_cmd); install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd); + install_element(CONFIG_NODE, &ip_route_blackhole_cmd); + install_element(CONFIG_NODE, &ip_route_address_interface_cmd); install_element(CONFIG_NODE, &ip_route_cmd); install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd); install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd); @@ -2687,6 +2801,8 @@ void zebra_vty_init(void) install_element(VIEW_NODE, &show_ip_route_vrf_all_summary_cmd); install_element(VIEW_NODE, &show_ip_route_vrf_all_summary_prefix_cmd); + install_element(CONFIG_NODE, &ipv6_route_blackhole_cmd); + install_element(CONFIG_NODE, &ipv6_route_address_interface_cmd); install_element(CONFIG_NODE, &ipv6_route_cmd); install_element(CONFIG_NODE, &ip_nht_default_route_cmd); install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd); diff --git a/zebra/zserv.c b/zebra/zserv.c index 2c0e1a0200..fd2c5dd97c 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1165,7 +1165,7 @@ static int zread_route_del(struct zserv *client, u_short length, rib_delete(afi, api.safi, zvrf_id(zvrf), api.type, api.instance, api.flags, &api.prefix, src_p, NULL, zvrf->table_id, - api.metric); + api.metric, false); /* Stats */ switch (api.prefix.family) { @@ -1331,7 +1331,7 @@ static int zread_ipv4_delete(struct zserv *client, u_short length, table_id = zvrf->table_id; rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance, - api.flags, &p, NULL, NULL, table_id, 0); + api.flags, &p, NULL, NULL, table_id, 0, false); client->v4_route_del_cnt++; return 0; } @@ -1693,7 +1693,7 @@ static int zread_ipv6_delete(struct zserv *client, u_short length, src_pp = NULL; rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, api.instance, - api.flags, &p, src_pp, NULL, client->rtm_table, 0); + api.flags, &p, src_pp, NULL, client->rtm_table, 0, false); client->v6_route_del_cnt++; return 0; |
