summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/Makefile.am1
-rw-r--r--bgpd/bgp_debug.c69
-rw-r--r--bgpd/bgp_evpn_vty.c46
-rw-r--r--bgpd/bgp_main.c2
-rw-r--r--bgpd/bgp_mplsvpn.c20
-rw-r--r--bgpd/bgp_nexthop.c42
-rw-r--r--bgpd/bgp_nexthop.h2
-rw-r--r--bgpd/bgp_route.c37
-rw-r--r--bgpd/bgp_routemap.c8
-rw-r--r--bgpd/bgp_vty.c2
-rw-r--r--bgpd/rfapi/bgp_rfapi_cfg.c8
-rw-r--r--bgpd/rfapi/rfapi_vty.c4
-rwxr-xr-xconfigure.ac18
-rw-r--r--eigrpd/eigrp_main.c2
-rw-r--r--lib/command.h1
-rw-r--r--lib/command_lex.l6
-rw-r--r--lib/command_match.c1
-rw-r--r--lib/libfrr.c1
-rw-r--r--lib/pid_output.c3
-rw-r--r--lib/plist.c21
-rw-r--r--lib/plist.h16
-rw-r--r--lib/thread.c2
-rw-r--r--ospf6d/ospf6_intra.c15
-rw-r--r--pimd/pim_cmd.c56
-rw-r--r--pimd/pim_iface.c3
-rw-r--r--pimd/pim_iface.h3
-rw-r--r--pimd/pim_igmp.c24
-rw-r--r--pimd/pim_igmpv3.c19
-rw-r--r--pimd/pim_instance.h4
-rw-r--r--pimd/pim_join.c18
-rw-r--r--pimd/pim_rp.c135
-rw-r--r--pimd/pim_rpf.c8
-rw-r--r--pimd/pim_util.c19
-rw-r--r--pimd/pim_util.h3
-rw-r--r--pimd/pim_vty.c9
-rwxr-xr-xtools/frr-reload.py15
-rw-r--r--vtysh/vtysh.c2
-rw-r--r--watchfrr/watchfrr_vty.c12
-rw-r--r--zebra/connected.c4
-rw-r--r--zebra/debug.c12
-rw-r--r--zebra/kernel_socket.c8
-rw-r--r--zebra/redistribute.c2
-rw-r--r--zebra/rib.h2
-rw-r--r--zebra/rt_netlink.c25
-rw-r--r--zebra/zebra_mpls.h18
-rw-r--r--zebra/zebra_ns.c2
-rw-r--r--zebra/zebra_rib.c156
-rw-r--r--zebra/zebra_vty.c186
-rw-r--r--zebra/zserv.c6
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;