changelogs: https://github.com/FRRouting/frr/releases/tag/frr-7.4 Signed-off-by: Lucian Cristian <lucian.cristian@gmail.com>lilik-openwrt-22.03
@ -0,0 +1,69 @@ | |||
From 34f6d0c67a48e2117c061f6ccdcf1f512982fe8f Mon Sep 17 00:00:00 2001 | |||
From: Donald Sharp <sharpd@cumulusnetworks.com> | |||
Date: Tue, 2 Jun 2020 16:10:48 -0400 | |||
Subject: [PATCH] bgpd: Actually find the sequence number for `bgp | |||
extcommunity-list...` | |||
The code in the bgp extcommunity-list function was using | |||
argv_find to get the correct idx. The problem was that | |||
we had already done argv_finds before and idx was non-zero | |||
thus having us always set the seq pointer to what was last | |||
looked up. This causes us to pass in a value to the | |||
underlying function and it would just wisely ignore it | |||
causing a seq number of 0. | |||
We would then write this seq number of 0 and then immediately | |||
reject it on read in again. BOO! | |||
Actually handle argv_find the way it was meant to be. | |||
Ticket:CM-29926 | |||
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com> | |||
--- | |||
bgpd/bgp_vty.c | 12 ++++-------- | |||
1 file changed, 4 insertions(+), 8 deletions(-) | |||
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c | |||
index 3669205ee3..9c8f1e1def 100644 | |||
--- a/bgpd/bgp_vty.c | |||
+++ b/bgpd/bgp_vty.c | |||
@@ -17617,8 +17617,7 @@ DEFUN (extcommunity_list_standard, | |||
argv_find(argv, argc, "WORD", &idx); | |||
cl_number_or_name = argv[idx]->arg; | |||
- argv_find(argv, argc, "(1-4294967295)", &idx); | |||
- if (idx) | |||
+ if (argv_find(argv, argc, "(1-4294967295)", &idx)) | |||
seq = argv[idx]->arg; | |||
direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT | |||
@@ -17663,8 +17662,7 @@ DEFUN (extcommunity_list_name_expanded, | |||
argv_find(argv, argc, "WORD", &idx); | |||
cl_number_or_name = argv[idx]->arg; | |||
- argv_find(argv, argc, "(1-4294967295)", &idx); | |||
- if (idx) | |||
+ if (argv_find(argv, argc, "(1-4294967295)", &idx)) | |||
seq = argv[idx]->arg; | |||
direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT | |||
@@ -17707,8 +17705,7 @@ DEFUN (no_extcommunity_list_standard_all, | |||
char *seq = NULL; | |||
int idx = 0; | |||
- argv_find(argv, argc, "(1-4294967295)", &idx); | |||
- if (idx) | |||
+ if (argv_find(argv, argc, "(1-4294967295)", &idx)) | |||
seq = argv[idx]->arg; | |||
idx = 0; | |||
@@ -17772,8 +17769,7 @@ DEFUN (no_extcommunity_list_expanded_all, | |||
char *seq = NULL; | |||
int idx = 0; | |||
- argv_find(argv, argc, "(1-4294967295)", &idx); | |||
- if (idx) | |||
+ if (argv_find(argv, argc, "(1-4294967295)", &idx)) | |||
seq = argv[idx]->arg; | |||
idx = 0; |
@ -0,0 +1,83 @@ | |||
From acf6f22d150b0050afbdaf5887b8e25d1614db4c Mon Sep 17 00:00:00 2001 | |||
From: Donatas Abraitis <donatas.abraitis@gmail.com> | |||
Date: Thu, 2 Jul 2020 11:08:29 +0300 | |||
Subject: [PATCH 1/2] bgpd: Return bool type for ecommunity_add_val and | |||
subgroup_announce_check | |||
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com> | |||
--- | |||
bgpd/bgp_ecommunity.c | 6 +++--- | |||
bgpd/bgp_route.c | 2 +- | |||
2 files changed, 4 insertions(+), 4 deletions(-) | |||
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c | |||
index d13da74b04..7d5cac4d62 100644 | |||
--- a/bgpd/bgp_ecommunity.c | |||
+++ b/bgpd/bgp_ecommunity.c | |||
@@ -107,14 +107,14 @@ bool ecommunity_add_val(struct ecommunity *ecom, struct ecommunity_val *eval, | |||
p[1] == eval->val[1]) { | |||
if (overwrite) { | |||
memcpy(p, eval->val, ECOMMUNITY_SIZE); | |||
- return 1; | |||
+ return true; | |||
} | |||
- return 0; | |||
+ return false; | |||
} | |||
} | |||
int ret = memcmp(p, eval->val, ECOMMUNITY_SIZE); | |||
if (ret == 0) | |||
- return 0; | |||
+ return false; | |||
if (ret > 0) { | |||
if (!unique) | |||
break; | |||
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c | |||
index 6ae7a59a14..7bfefde482 100644 | |||
--- a/bgpd/bgp_route.c | |||
+++ b/bgpd/bgp_route.c | |||
@@ -1941,7 +1941,7 @@ bool subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, | |||
/* Codification of AS 0 Processing */ | |||
if (aspath_check_as_zero(attr->aspath)) | |||
- return 0; | |||
+ return false; | |||
if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN)) { | |||
if (peer->sort == BGP_PEER_IBGP | |||
From d5a157b7c377081d23b136b5ba4849abdcbecd97 Mon Sep 17 00:00:00 2001 | |||
From: Donatas Abraitis <donatas.abraitis@gmail.com> | |||
Date: Thu, 2 Jul 2020 11:39:40 +0300 | |||
Subject: [PATCH 2/2] bgpd: Actually find the sequence number for | |||
large-community-list | |||
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com> | |||
--- | |||
bgpd/bgp_vty.c | 6 ++---- | |||
1 file changed, 2 insertions(+), 4 deletions(-) | |||
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c | |||
index 9c8f1e1def..67ff31df8f 100644 | |||
--- a/bgpd/bgp_vty.c | |||
+++ b/bgpd/bgp_vty.c | |||
@@ -17235,8 +17235,7 @@ static int lcommunity_list_set_vty(struct vty *vty, int argc, | |||
char *cl_name; | |||
char *seq = NULL; | |||
- argv_find(argv, argc, "(1-4294967295)", &idx); | |||
- if (idx) | |||
+ if (argv_find(argv, argc, "(1-4294967295)", &idx)) | |||
seq = argv[idx]->arg; | |||
idx = 0; | |||
@@ -17285,8 +17284,7 @@ static int lcommunity_list_unset_vty(struct vty *vty, int argc, | |||
int idx = 0; | |||
char *seq = NULL; | |||
- argv_find(argv, argc, "(1-4294967295)", &idx); | |||
- if (idx) | |||
+ if (argv_find(argv, argc, "(1-4294967295)", &idx)) | |||
seq = argv[idx]->arg; | |||
idx = 0; |
@ -1,26 +0,0 @@ | |||
--- a/zebra/zebra_nhg.c 2019-10-18 01:59:17.582282539 +0300 | |||
+++ b/zebra/zebra_nhg.c 2019-10-18 02:00:17.501997253 +0300 | |||
@@ -1456,20 +1456,9 @@ | |||
while (rn) { | |||
route_unlock_node(rn); | |||
- /* Lookup should halt if we've matched against ourselves ('top', | |||
- * if specified) - i.e., we cannot have a nexthop NH1 is | |||
- * resolved by a route NH1. The exception is if the route is a | |||
- * host route. | |||
- */ | |||
- if (top && rn == top) | |||
- if (((afi == AFI_IP) && (rn->p.prefixlen != 32)) | |||
- || ((afi == AFI_IP6) && (rn->p.prefixlen != 128))) { | |||
- if (IS_ZEBRA_DEBUG_RIB_DETAILED) | |||
- zlog_debug( | |||
- "\t%s: Matched against ourself and prefix length is not max bit length", | |||
- __PRETTY_FUNCTION__); | |||
- return 0; | |||
- } | |||
+ /* If lookup self prefix return immediately. */ | |||
+ if (rn == top) | |||
+ return 0; | |||
/* Pick up selected route. */ | |||
/* However, do not resolve over default route unless explicitly |
@ -0,0 +1,29 @@ | |||
From cc45875e0d2af0b53100ec78364dc51b39a12ac9 Mon Sep 17 00:00:00 2001 | |||
From: Rafael Zalamena <rzalamena@opensourcerouting.org> | |||
Date: Mon, 6 Jul 2020 11:39:27 -0300 | |||
Subject: [PATCH] lib: fix route map description memory leak | |||
Route map entries are not getting a chance to call `description` string | |||
deallocation on shutdown or when the parent entry is destroyed, so lets | |||
add a code to handle this in the `route_map_index_delete` function. | |||
Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org> | |||
(cherry picked from commit f0951335830203426074ddca4317f84b477e4afb) | |||
--- | |||
lib/routemap.c | 3 +++ | |||
1 file changed, 3 insertions(+) | |||
diff --git a/lib/routemap.c b/lib/routemap.c | |||
index 3d69a3495a..3b45133450 100644 | |||
--- a/lib/routemap.c | |||
+++ b/lib/routemap.c | |||
@@ -971,6 +971,9 @@ void route_map_index_delete(struct route_map_index *index, int notify) | |||
zlog_debug("Deleting route-map %s sequence %d", | |||
index->map->name, index->pref); | |||
+ /* Free route map entry description. */ | |||
+ XFREE(MTYPE_TMP, index->description); | |||
+ | |||
/* Free route map northbound hook contexts. */ | |||
while ((rhc = TAILQ_FIRST(&index->rhclist)) != NULL) | |||
routemap_hook_context_free(rhc); |
@ -0,0 +1,288 @@ | |||
From 2939f712d152f7e3ae438cc0f1d96dd9485e7487 Mon Sep 17 00:00:00 2001 | |||
From: Donatas Abraitis <donatas.abraitis@gmail.com> | |||
Date: Thu, 9 Jul 2020 16:00:27 +0300 | |||
Subject: [PATCH 1/2] bgpd: Add command to show only established sessions | |||
``` | |||
exit1-debian-9# show bgp summary | |||
IPv4 Unicast Summary: | |||
BGP router identifier 192.168.0.1, local AS number 100 vrf-id 0 | |||
BGP table version 8 | |||
RIB entries 15, using 2880 bytes of memory | |||
Peers 2, using 43 KiB of memory | |||
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt | |||
192.168.0.2 4 200 10 6 0 0 0 00:00:35 8 8 | |||
2a02:4780::2 4 0 0 1 0 0 0 never Active 0 | |||
Total number of neighbors 2 | |||
exit1-debian-9# show bgp summary established | |||
IPv4 Unicast Summary: | |||
BGP router identifier 192.168.0.1, local AS number 100 vrf-id 0 | |||
BGP table version 8 | |||
RIB entries 15, using 2880 bytes of memory | |||
Peers 2, using 43 KiB of memory | |||
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt | |||
192.168.0.2 4 200 10 6 0 0 0 00:00:39 8 8 | |||
Total number of neighbors 2 | |||
exit1-debian-9# show bgp summary failed | |||
IPv4 Unicast Summary: | |||
BGP router identifier 192.168.0.1, local AS number 100 vrf-id 0 | |||
BGP table version 8 | |||
RIB entries 15, using 2880 bytes of memory | |||
Peers 2, using 43 KiB of memory | |||
Neighbor EstdCnt DropCnt ResetTime Reason | |||
2a02:4780::2 0 0 never Waiting for peer OPEN | |||
Total number of neighbors 2 | |||
exit1-debian-9# | |||
``` | |||
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com> | |||
--- | |||
bgpd/bgp_evpn_vty.c | 11 ++++++++--- | |||
bgpd/bgp_vty.c | 43 +++++++++++++++++++++++++++++++------------ | |||
bgpd/bgp_vty.h | 3 ++- | |||
3 files changed, 41 insertions(+), 16 deletions(-) | |||
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c | |||
index 85604d856d..42987117d4 100644 | |||
--- a/bgpd/bgp_evpn_vty.c | |||
+++ b/bgpd/bgp_evpn_vty.c | |||
@@ -4077,7 +4077,7 @@ DEFUN(show_bgp_l2vpn_evpn_es, | |||
*/ | |||
DEFUN(show_bgp_l2vpn_evpn_summary, | |||
show_bgp_l2vpn_evpn_summary_cmd, | |||
- "show bgp [vrf VRFNAME] l2vpn evpn summary [failed] [json]", | |||
+ "show bgp [vrf VRFNAME] l2vpn evpn summary [established|failed] [json]", | |||
SHOW_STR | |||
BGP_STR | |||
"bgp vrf\n" | |||
@@ -4085,6 +4085,7 @@ DEFUN(show_bgp_l2vpn_evpn_summary, | |||
L2VPN_HELP_STR | |||
EVPN_HELP_STR | |||
"Summary of BGP neighbor status\n" | |||
+ "Show only sessions in Established state\n" | |||
"Show only sessions not in Established state\n" | |||
JSON_STR) | |||
{ | |||
@@ -4092,13 +4093,17 @@ DEFUN(show_bgp_l2vpn_evpn_summary, | |||
bool uj = use_json(argc, argv); | |||
char *vrf = NULL; | |||
bool show_failed = false; | |||
+ bool show_established = false; | |||
if (argv_find(argv, argc, "vrf", &idx_vrf)) | |||
vrf = argv[++idx_vrf]->arg; | |||
if (argv_find(argv, argc, "failed", &idx_vrf)) | |||
show_failed = true; | |||
- return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN, | |||
- show_failed, uj); | |||
+ if (argv_find(argv, argc, "established", &idx_vrf)) | |||
+ show_established = true; | |||
+ | |||
+ return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN, show_failed, | |||
+ show_established, uj); | |||
} | |||
/* | |||
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c | |||
index 67ff31df8f..78521457fd 100644 | |||
--- a/bgpd/bgp_vty.c | |||
+++ b/bgpd/bgp_vty.c | |||
@@ -8772,7 +8772,8 @@ static void bgp_show_failed_summary(struct vty *vty, struct bgp *bgp, | |||
/* Show BGP peer's summary information. */ | |||
static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, | |||
- bool show_failed, bool use_json) | |||
+ bool show_failed, bool show_established, | |||
+ bool use_json) | |||
{ | |||
struct peer *peer; | |||
struct listnode *node, *nnode; | |||
@@ -9104,6 +9105,10 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, | |||
bgp_show_failed_summary(vty, bgp, peer, | |||
json_peer, 0, use_json); | |||
} else if (!show_failed) { | |||
+ if (show_established | |||
+ && bgp_has_peer_failed(peer, afi, safi)) | |||
+ continue; | |||
+ | |||
json_peer = json_object_new_object(); | |||
if (peer_dynamic_neighbor(peer)) { | |||
json_object_boolean_true_add(json_peer, | |||
@@ -9193,6 +9198,10 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, | |||
max_neighbor_width, | |||
use_json); | |||
} else if (!show_failed) { | |||
+ if (show_established | |||
+ && bgp_has_peer_failed(peer, afi, safi)) | |||
+ continue; | |||
+ | |||
memset(dn_flag, '\0', sizeof(dn_flag)); | |||
if (peer_dynamic_neighbor(peer)) { | |||
dn_flag[0] = '*'; | |||
@@ -9315,7 +9324,8 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, | |||
} | |||
static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi, | |||
- int safi, bool show_failed, bool use_json) | |||
+ int safi, bool show_failed, | |||
+ bool show_established, bool use_json) | |||
{ | |||
int is_first = 1; | |||
int afi_wildcard = (afi == AFI_MAX); | |||
@@ -9358,7 +9368,8 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi, | |||
false)); | |||
} | |||
} | |||
- bgp_show_summary(vty, bgp, afi, safi, show_failed, | |||
+ bgp_show_summary(vty, bgp, afi, safi, | |||
+ show_failed, show_established, | |||
use_json); | |||
} | |||
safi++; | |||
@@ -9382,6 +9393,7 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi, | |||
static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi, | |||
safi_t safi, bool show_failed, | |||
+ bool show_established, | |||
bool use_json) | |||
{ | |||
struct listnode *node, *nnode; | |||
@@ -9411,7 +9423,7 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi, | |||
: bgp->name); | |||
} | |||
bgp_show_summary_afi_safi(vty, bgp, afi, safi, show_failed, | |||
- use_json); | |||
+ show_established, use_json); | |||
} | |||
if (use_json) | |||
@@ -9421,15 +9433,16 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi, | |||
} | |||
int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, | |||
- safi_t safi, bool show_failed, bool use_json) | |||
+ safi_t safi, bool show_failed, bool show_established, | |||
+ bool use_json) | |||
{ | |||
struct bgp *bgp; | |||
if (name) { | |||
if (strmatch(name, "all")) { | |||
- bgp_show_all_instances_summary_vty(vty, afi, safi, | |||
- show_failed, | |||
- use_json); | |||
+ bgp_show_all_instances_summary_vty( | |||
+ vty, afi, safi, show_failed, show_established, | |||
+ use_json); | |||
return CMD_SUCCESS; | |||
} else { | |||
bgp = bgp_lookup_by_name(name); | |||
@@ -9444,7 +9457,8 @@ int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, | |||
} | |||
bgp_show_summary_afi_safi(vty, bgp, afi, safi, | |||
- show_failed, use_json); | |||
+ show_failed, show_established, | |||
+ use_json); | |||
return CMD_SUCCESS; | |||
} | |||
} | |||
@@ -9453,7 +9467,7 @@ int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, | |||
if (bgp) | |||
bgp_show_summary_afi_safi(vty, bgp, afi, safi, show_failed, | |||
- use_json); | |||
+ show_established, use_json); | |||
else { | |||
if (use_json) | |||
vty_out(vty, "{}\n"); | |||
@@ -9468,7 +9482,7 @@ int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, | |||
/* `show [ip] bgp summary' commands. */ | |||
DEFUN (show_ip_bgp_summary, | |||
show_ip_bgp_summary_cmd, | |||
- "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] summary [failed] [json]", | |||
+ "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] summary [established|failed] [json]", | |||
SHOW_STR | |||
IP_STR | |||
BGP_STR | |||
@@ -9476,6 +9490,7 @@ DEFUN (show_ip_bgp_summary, | |||
BGP_AFI_HELP_STR | |||
BGP_SAFI_WITH_LABEL_HELP_STR | |||
"Summary of BGP neighbor status\n" | |||
+ "Show only sessions in Established state\n" | |||
"Show only sessions not in Established state\n" | |||
JSON_STR) | |||
{ | |||
@@ -9483,6 +9498,7 @@ DEFUN (show_ip_bgp_summary, | |||
afi_t afi = AFI_MAX; | |||
safi_t safi = SAFI_MAX; | |||
bool show_failed = false; | |||
+ bool show_established = false; | |||
int idx = 0; | |||
@@ -9504,10 +9520,13 @@ DEFUN (show_ip_bgp_summary, | |||
if (argv_find(argv, argc, "failed", &idx)) | |||
show_failed = true; | |||
+ if (argv_find(argv, argc, "established", &idx)) | |||
+ show_established = true; | |||
bool uj = use_json(argc, argv); | |||
- return bgp_show_summary_vty(vty, vrf, afi, safi, show_failed, uj); | |||
+ return bgp_show_summary_vty(vty, vrf, afi, safi, show_failed, | |||
+ show_established, uj); | |||
} | |||
const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json) | |||
diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h | |||
index d6ca198d09..95eefbc36f 100644 | |||
--- a/bgpd/bgp_vty.h | |||
+++ b/bgpd/bgp_vty.h | |||
@@ -178,6 +178,7 @@ extern int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty, | |||
int bgp_vty_find_and_parse_bgp(struct vty *vty, struct cmd_token **argv, | |||
int argc, struct bgp **bgp, bool use_json); | |||
extern int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, | |||
- safi_t safi, bool show_failed, bool use_json); | |||
+ safi_t safi, bool show_failed, | |||
+ bool show_established, bool use_json); | |||
#endif /* _QUAGGA_BGP_VTY_H */ | |||
From 2600443342d8e21d30df2b6ca095a5f2d0d4de2d Mon Sep 17 00:00:00 2001 | |||
From: Donatas Abraitis <donatas.abraitis@gmail.com> | |||
Date: Thu, 9 Jul 2020 16:05:08 +0300 | |||
Subject: [PATCH 2/2] doc: Add 'show bgp summary established' command | |||
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com> | |||
--- | |||
doc/user/bgp.rst | 6 ++++++ | |||
1 file changed, 6 insertions(+) | |||
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst | |||
index cb343e8dad..36227db604 100644 | |||
--- a/doc/user/bgp.rst | |||
+++ b/doc/user/bgp.rst | |||
@@ -2710,6 +2710,12 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`. | |||
Show a bgp peer summary for peers that are not succesfully exchanging routes | |||
for the specified address family, and subsequent address-family. | |||
+.. index:: show bgp [afi] [safi] summary established [json] | |||
+.. clicmd:: show bgp [afi] [safi] summary established [json] | |||
+ | |||
+ Show a bgp peer summary for peers that are succesfully exchanging routes | |||
+ for the specified address family, and subsequent address-family. | |||
+ | |||
.. index:: show bgp [afi] [safi] neighbor [PEER] | |||
.. clicmd:: show bgp [afi] [safi] neighbor [PEER] | |||
@ -0,0 +1,57 @@ | |||
From 692ce87393de9497a7821e9e0856ff70a7973ff6 Mon Sep 17 00:00:00 2001 | |||
From: Paul Manley <paul.manley@wholefoods.com> | |||
Date: Thu, 9 Jul 2020 11:21:16 -0500 | |||
Subject: [PATCH 1/2] tools: create sub-context for bfd peers | |||
add lines starting with 'peer' to the list of sub-contexts that are handled by frr-reload.py. | |||
https://github.com/FRRouting/frr/issues/6511#issuecomment-655163833 | |||
Signed-off-by: Paul Manley <paul.manley@wholefoods.com> | |||
(cherry picked from commit 1c23a0aaa1c5d20af50af75b070e93e1eff21222) | |||
--- | |||
tools/frr-reload.py | 1 + | |||
1 file changed, 1 insertion(+) | |||
diff --git a/tools/frr-reload.py b/tools/frr-reload.py | |||
index d4020cdfc9..e9641b2b13 100755 | |||
--- a/tools/frr-reload.py | |||
+++ b/tools/frr-reload.py | |||
@@ -496,6 +496,7 @@ def load_contexts(self): | |||
line.startswith("vnc defaults") or | |||
line.startswith("vnc l2-group") or | |||
line.startswith("vnc nve-group") or | |||
+ line.startswith("peer") or | |||
line.startswith("member pseudowire")): | |||
main_ctx_key = [] | |||
From 2604086c3d9face0aca2497a982782c865bb2b59 Mon Sep 17 00:00:00 2001 | |||
From: Paul Manley <paul.manley@wholefoods.com> | |||
Date: Thu, 9 Jul 2020 11:25:34 -0500 | |||
Subject: [PATCH 2/2] vtysh: properly exit BFD_PEER_NODE when marking file | |||
vtysh needs to be aware of how to properly exit a bfd peer when subsequent commands only succeed in a higher context. | |||
https://github.com/FRRouting/frr/issues/6511#issuecomment-656166206 | |||
Signed-off-by: Paul Manley <paul.manley@wholefoods.com> | |||
(cherry picked from commit b727c12aabf1afc2b6e33f8590c9786e349e4fcb) | |||
--- | |||
vtysh/vtysh.c | 3 +++ | |||
1 file changed, 3 insertions(+) | |||
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c | |||
index 15ec866fc9..4fdf68c0e6 100644 | |||
--- a/vtysh/vtysh.c | |||
+++ b/vtysh/vtysh.c | |||
@@ -809,6 +809,9 @@ int vtysh_mark_file(const char *filename) | |||
} else if ((prev_node == KEYCHAIN_KEY_NODE) | |||
&& (tried == 1)) { | |||
vty_out(vty, "exit\n"); | |||
+ } else if ((prev_node == BFD_PEER_NODE) | |||
+ && (tried == 1)) { | |||
+ vty_out(vty, "exit\n"); | |||
} else if (tried) { | |||
vty_out(vty, "end\n"); | |||
} |
@ -0,0 +1,120 @@ | |||
From cc5934ed5939315ba5d95bfaf052625762107205 Mon Sep 17 00:00:00 2001 | |||
From: Donald Sharp <sharpd@cumulusnetworks.com> | |||
Date: Tue, 30 Jun 2020 08:59:46 -0400 | |||
Subject: [PATCH 1/2] vtysh: master is a non-sorted list | |||
The commit: | |||
a798241265a5808083a06b14ce1637d1ddf6a45a | |||
attempted to use sorted master lists to do faster lookups | |||
by using a RB Tree. Unfortunately the original code | |||
was creating a list->cmp function *but* never using it. | |||
If you look at the commit, it clearly shows that the | |||
function listnode_add is used to insert but when you | |||
look at that function it is a tail push. | |||
Fixes: #6573 | |||
Namely now this ordering is preserved: | |||
bgp as-path access-list originate-only permit ^$ | |||
bgp as-path access-list originate-only deny .* | |||
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com> | |||
--- | |||
vtysh/vtysh_config.c | 21 ++++++++++----------- | |||
1 file changed, 10 insertions(+), 11 deletions(-) | |||
diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c | |||
index abbb111f9d..2ab9dd5a9a 100644 | |||
--- a/vtysh/vtysh_config.c | |||
+++ b/vtysh/vtysh_config.c | |||
@@ -34,7 +34,7 @@ DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CONFIG_LINE, "Vtysh configuration line") | |||
vector configvec; | |||
-PREDECL_RBTREE_UNIQ(config_master); | |||
+PREDECL_LIST(config_master); | |||
struct config { | |||
/* Configuration node name. */ | |||
@@ -72,11 +72,6 @@ static struct config *config_new(void) | |||
return config; | |||
} | |||
-static int config_cmp(const struct config *c1, const struct config *c2) | |||
-{ | |||
- return strcmp(c1->name, c2->name); | |||
-} | |||
- | |||
static void config_del(struct config *config) | |||
{ | |||
list_delete(&config->line); | |||
@@ -84,13 +79,15 @@ static void config_del(struct config *config) | |||
XFREE(MTYPE_VTYSH_CONFIG, config); | |||
} | |||
-DECLARE_RBTREE_UNIQ(config_master, struct config, rbt_item, config_cmp) | |||
+DECLARE_LIST(config_master, struct config, rbt_item) | |||
static struct config *config_get(int index, const char *line) | |||
{ | |||
- struct config *config; | |||
+ struct config *config, *config_loop; | |||
struct config_master_head *master; | |||
+ config = config_loop = NULL; | |||
+ | |||
master = vector_lookup_ensure(configvec, index); | |||
if (!master) { | |||
@@ -99,8 +96,10 @@ static struct config *config_get(int index, const char *line) | |||
vector_set_index(configvec, index, master); | |||
} | |||
- const struct config config_ref = { .name = (char *)line }; | |||
- config = config_master_find(master, &config_ref); | |||
+ frr_each (config_master, master, config_loop) { | |||
+ if (strcmp(config_loop->name, line) == 0) | |||
+ config = config_loop; | |||
+ } | |||
if (!config) { | |||
config = config_new(); | |||
@@ -109,7 +108,7 @@ static struct config *config_get(int index, const char *line) | |||
config->line->cmp = (int (*)(void *, void *))line_cmp; | |||
config->name = XSTRDUP(MTYPE_VTYSH_CONFIG_LINE, line); | |||
config->index = index; | |||
- config_master_add(master, config); | |||
+ config_master_add_tail(master, config); | |||
} | |||
return config; | |||
} | |||
From 3e4d90ec556649e11954f2f56b5282f95e7e013b Mon Sep 17 00:00:00 2001 | |||
From: Donald Sharp <sharpd@cumulusnetworks.com> | |||
Date: Tue, 30 Jun 2020 09:03:55 -0400 | |||
Subject: [PATCH 2/2] vtysh: Improve lookup performance | |||
When we find the line we are interested in, stop looking. | |||
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com> | |||
--- | |||
vtysh/vtysh_config.c | 4 +++- | |||
1 file changed, 3 insertions(+), 1 deletion(-) | |||
diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c | |||
index 2ab9dd5a9a..61bcf3b658 100644 | |||
--- a/vtysh/vtysh_config.c | |||
+++ b/vtysh/vtysh_config.c | |||
@@ -97,8 +97,10 @@ static struct config *config_get(int index, const char *line) | |||
} | |||
frr_each (config_master, master, config_loop) { | |||
- if (strcmp(config_loop->name, line) == 0) | |||
+ if (strcmp(config_loop->name, line) == 0) { | |||
config = config_loop; | |||
+ break; | |||
+ } | |||
} | |||
if (!config) { |
@ -0,0 +1,835 @@ | |||
From c6a5994609deec62c8aefa1fa15c517e32575ca3 Mon Sep 17 00:00:00 2001 | |||
From: Donatas Abraitis <donatas.abraitis@gmail.com> | |||
Date: Wed, 6 May 2020 17:45:31 +0300 | |||
Subject: [PATCH 1/4] tests: Remove bgp_show_ip_bgp_fqdn test | |||
Not really relevant for now. | |||
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com> | |||
--- | |||
.../bgp_show_ip_bgp_fqdn/__init__.py | 0 | |||
.../bgp_show_ip_bgp_fqdn/r1/bgpd.conf | 5 - | |||
.../bgp_show_ip_bgp_fqdn/r1/zebra.conf | 9 -- | |||
.../bgp_show_ip_bgp_fqdn/r2/bgpd.conf | 5 - | |||
.../bgp_show_ip_bgp_fqdn/r2/zebra.conf | 12 -- | |||
.../bgp_show_ip_bgp_fqdn/r3/bgpd.conf | 3 - | |||
.../bgp_show_ip_bgp_fqdn/r3/zebra.conf | 6 - | |||
.../test_bgp_show_ip_bgp_fqdn.py | 133 ------------------ | |||
8 files changed, 173 deletions(-) | |||
delete mode 100644 tests/topotests/bgp_show_ip_bgp_fqdn/__init__.py | |||
delete mode 100644 tests/topotests/bgp_show_ip_bgp_fqdn/r1/bgpd.conf | |||
delete mode 100644 tests/topotests/bgp_show_ip_bgp_fqdn/r1/zebra.conf | |||
delete mode 100644 tests/topotests/bgp_show_ip_bgp_fqdn/r2/bgpd.conf | |||
delete mode 100644 tests/topotests/bgp_show_ip_bgp_fqdn/r2/zebra.conf | |||
delete mode 100644 tests/topotests/bgp_show_ip_bgp_fqdn/r3/bgpd.conf | |||
delete mode 100644 tests/topotests/bgp_show_ip_bgp_fqdn/r3/zebra.conf | |||
delete mode 100644 tests/topotests/bgp_show_ip_bgp_fqdn/test_bgp_show_ip_bgp_fqdn.py | |||
diff --git a/tests/topotests/bgp_show_ip_bgp_fqdn/__init__.py b/tests/topotests/bgp_show_ip_bgp_fqdn/__init__.py | |||
deleted file mode 100644 | |||
index e69de29bb2..0000000000 | |||
diff --git a/tests/topotests/bgp_show_ip_bgp_fqdn/r1/bgpd.conf b/tests/topotests/bgp_show_ip_bgp_fqdn/r1/bgpd.conf | |||
deleted file mode 100644 | |||
index f0df56e947..0000000000 | |||
--- a/tests/topotests/bgp_show_ip_bgp_fqdn/r1/bgpd.conf | |||
+++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
-router bgp 65000 | |||
- no bgp ebgp-requires-policy | |||
- neighbor 192.168.255.2 remote-as 65001 | |||
- address-family ipv4 unicast | |||
- redistribute connected | |||
diff --git a/tests/topotests/bgp_show_ip_bgp_fqdn/r1/zebra.conf b/tests/topotests/bgp_show_ip_bgp_fqdn/r1/zebra.conf | |||
deleted file mode 100644 | |||
index 0a283c06d5..0000000000 | |||
--- a/tests/topotests/bgp_show_ip_bgp_fqdn/r1/zebra.conf | |||
+++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
-! | |||
-interface lo | |||
- ip address 172.16.255.254/32 | |||
-! | |||
-interface r1-eth0 | |||
- ip address 192.168.255.1/24 | |||
-! | |||
-ip forwarding | |||
-! | |||
diff --git a/tests/topotests/bgp_show_ip_bgp_fqdn/r2/bgpd.conf b/tests/topotests/bgp_show_ip_bgp_fqdn/r2/bgpd.conf | |||
deleted file mode 100644 | |||
index 422a7345f9..0000000000 | |||
--- a/tests/topotests/bgp_show_ip_bgp_fqdn/r2/bgpd.conf | |||
+++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
-router bgp 65001 | |||
- no bgp ebgp-requires-policy | |||
- bgp default show-hostname | |||
- neighbor 192.168.255.1 remote-as 65000 | |||
- neighbor 192.168.254.1 remote-as 65001 | |||
diff --git a/tests/topotests/bgp_show_ip_bgp_fqdn/r2/zebra.conf b/tests/topotests/bgp_show_ip_bgp_fqdn/r2/zebra.conf | |||
deleted file mode 100644 | |||
index e9e2e4391f..0000000000 | |||
--- a/tests/topotests/bgp_show_ip_bgp_fqdn/r2/zebra.conf | |||
+++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
-! | |||
-interface lo | |||
- ip address 172.16.255.253/32 | |||
-! | |||
-interface r2-eth0 | |||
- ip address 192.168.255.2/24 | |||
-! | |||
-interface r2-eth1 | |||
- ip address 192.168.254.2/24 | |||
-! | |||
-ip forwarding | |||
-! | |||
diff --git a/tests/topotests/bgp_show_ip_bgp_fqdn/r3/bgpd.conf b/tests/topotests/bgp_show_ip_bgp_fqdn/r3/bgpd.conf | |||
deleted file mode 100644 | |||
index 8fcf6a736d..0000000000 | |||
--- a/tests/topotests/bgp_show_ip_bgp_fqdn/r3/bgpd.conf | |||
+++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
-router bgp 65001 | |||
- bgp default show-hostname | |||
- neighbor 192.168.254.2 remote-as 65001 | |||
diff --git a/tests/topotests/bgp_show_ip_bgp_fqdn/r3/zebra.conf b/tests/topotests/bgp_show_ip_bgp_fqdn/r3/zebra.conf | |||
deleted file mode 100644 | |||
index a8b8bc38c5..0000000000 | |||
--- a/tests/topotests/bgp_show_ip_bgp_fqdn/r3/zebra.conf | |||
+++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
-! | |||
-interface r3-eth0 | |||
- ip address 192.168.254.1/24 | |||
-! | |||
-ip forwarding | |||
-! | |||
diff --git a/tests/topotests/bgp_show_ip_bgp_fqdn/test_bgp_show_ip_bgp_fqdn.py b/tests/topotests/bgp_show_ip_bgp_fqdn/test_bgp_show_ip_bgp_fqdn.py | |||
deleted file mode 100644 | |||
index e8ad180935..0000000000 | |||
--- a/tests/topotests/bgp_show_ip_bgp_fqdn/test_bgp_show_ip_bgp_fqdn.py | |||
+++ /dev/null | |||
@@ -1,133 +0,0 @@ | |||
-#!/usr/bin/env python | |||
- | |||
-# | |||
-# test_bgp_show_ip_bgp_fqdn.py | |||
-# Part of NetDEF Topology Tests | |||
-# | |||
-# Copyright (c) 2019 by | |||
-# Donatas Abraitis <donatas.abraitis@gmail.com> | |||
-# | |||
-# Permission to use, copy, modify, and/or distribute this software | |||
-# for any purpose with or without fee is hereby granted, provided | |||
-# that the above copyright notice and this permission notice appear | |||
-# in all copies. | |||
-# | |||
-# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES | |||
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR | |||
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY | |||
-# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |||
-# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS | |||
-# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
-# OF THIS SOFTWARE. | |||
-# | |||
- | |||
-""" | |||
-test_bgp_show_ip_bgp_fqdn.py: | |||
-Test if FQND is visible in `show [ip] bgp` output if | |||
-`bgp default show-hostname` is toggled. | |||
- | |||
-Topology: | |||
-r1 <-- eBGP --> r2 <-- iBGP --> r3 | |||
- | |||
-1. Check if both hostname and ip are added to JSON output | |||
-for 172.16.255.254/32 on r2. | |||
-2. Check if only ip is added to JSON output for 172.16.255.254/32 on r3. | |||
-""" | |||
- | |||
-import os | |||
-import sys | |||
-import json | |||
-import time | |||
-import pytest | |||
-import functools | |||
- | |||
-CWD = os.path.dirname(os.path.realpath(__file__)) | |||
-sys.path.append(os.path.join(CWD, "../")) | |||
- | |||
-# pylint: disable=C0413 | |||
-from lib import topotest | |||
-from lib.topogen import Topogen, TopoRouter, get_topogen | |||
-from lib.topolog import logger | |||
-from mininet.topo import Topo | |||
- | |||
- | |||
-class TemplateTopo(Topo): | |||
- def build(self, *_args, **_opts): | |||
- tgen = get_topogen(self) | |||
- | |||
- for routern in range(1, 4): | |||
- tgen.add_router("r{}".format(routern)) | |||
- | |||
- switch = tgen.add_switch("s1") | |||
- switch.add_link(tgen.gears["r1"]) | |||
- switch.add_link(tgen.gears["r2"]) | |||
- | |||
- switch = tgen.add_switch("s2") | |||
- switch.add_link(tgen.gears["r2"]) | |||
- switch.add_link(tgen.gears["r3"]) | |||
- | |||
- | |||
-def setup_module(mod): | |||
- tgen = Topogen(TemplateTopo, mod.__name__) | |||
- tgen.start_topology() | |||
- | |||
- router_list = tgen.routers() | |||
- | |||
- for i, (rname, router) in enumerate(router_list.iteritems(), 1): | |||
- router.load_config( | |||
- TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) | |||
- ) | |||
- router.load_config( | |||
- TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) | |||
- ) | |||
- | |||
- tgen.start_router() | |||
- | |||
- | |||
-def teardown_module(mod): | |||
- tgen = get_topogen() | |||
- tgen.stop_topology() | |||
- | |||
- | |||
-def test_bgp_show_ip_bgp_hostname(): | |||
- tgen = get_topogen() | |||
- | |||
- if tgen.routers_have_failure(): | |||
- pytest.skip(tgen.errors) | |||
- | |||
- def _bgp_converge(router): | |||
- output = json.loads(router.vtysh_cmd("show ip bgp 172.16.255.254/32 json")) | |||
- expected = {"prefix": "172.16.255.254/32"} | |||
- return topotest.json_cmp(output, expected) | |||
- | |||
- def _bgp_show_nexthop_hostname_and_ip(router): | |||
- output = json.loads(router.vtysh_cmd("show ip bgp json")) | |||
- for nh in output["routes"]["172.16.255.254/32"][0]["nexthops"]: | |||
- if "hostname" in nh and "ip" in nh: | |||
- return True | |||
- return False | |||
- | |||
- def _bgp_show_nexthop_ip_only(router): | |||
- output = json.loads(router.vtysh_cmd("show ip bgp json")) | |||
- for nh in output["routes"]["172.16.255.254/32"][0]["nexthops"]: | |||
- if "ip" in nh and not "hostname" in nh: | |||
- return True | |||
- return False | |||
- | |||
- test_func = functools.partial(_bgp_converge, tgen.gears["r2"]) | |||
- success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) | |||
- | |||
- test_func = functools.partial(_bgp_converge, tgen.gears["r3"]) | |||
- success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) | |||
- | |||
- assert result is None, 'Failed bgp convergence in "{}"'.format(tgen.gears["r2"]) | |||
- assert _bgp_show_nexthop_hostname_and_ip(tgen.gears["r2"]) == True | |||
- | |||
- assert result is None, 'Failed bgp convergence in "{}"'.format(tgen.gears["r3"]) | |||
- assert _bgp_show_nexthop_ip_only(tgen.gears["r3"]) == True | |||
- | |||
- | |||
-if __name__ == "__main__": | |||
- args = ["-s"] + sys.argv[1:] | |||
- sys.exit(pytest.main(args)) | |||
From e7cc3d21452bd771a97bc46ab5a1e4853c46f944 Mon Sep 17 00:00:00 2001 | |||
From: Donatas Abraitis <donatas.abraitis@gmail.com> | |||
Date: Wed, 6 May 2020 17:46:10 +0300 | |||
Subject: [PATCH 2/4] bgpd: Show the real next-hop address in addition to | |||
hostname in `show bgp` | |||
It's hard to cope with cases when next-hop is changed/unchanged or | |||
peers are non-direct. | |||
It would be better to show the hostname and nexthop IP address (both) | |||
under `show bgp` to quickly identify the source and the real next-hop | |||
of the route. | |||
If `bgp default show-nexthop-hostname` is toggled the output looks like: | |||
``` | |||
spine1-debian-9# show bgp | |||
BGP table version is 1, local router ID is 2.2.2.2, vrf id 0 | |||
Default local pref 100, local AS 65002 | |||
Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, | |||
i internal, r RIB-failure, S Stale, R Removed | |||
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self | |||
Origin codes: i - IGP, e - EGP, ? - incomplete | |||
Network Next Hop Metric LocPrf Weight Path | |||
* 2a02:4780::/64 fe80::a00:27ff:fe09:f8a3(exit1-debian-9) | |||
0 0 65001 ? | |||
spine1-debian-9# show ip bgp | |||
BGP table version is 5, local router ID is 2.2.2.2, vrf id 0 | |||
Default local pref 100, local AS 65002 | |||
Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, | |||
i internal, r RIB-failure, S Stale, R Removed | |||
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self | |||
Origin codes: i - IGP, e - EGP, ? - incomplete | |||
Network Next Hop Metric LocPrf Weight Path | |||
*> 10.255.255.0/24 192.168.0.1(exit1-debian-9) | |||
0 0 65001 ? | |||
``` | |||
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com> | |||
--- | |||
bgpd/bgp_route.c | 161 ++++++++++++++++++++++++++++++----------------- | |||
bgpd/bgp_vty.c | 45 +++++++++++++ | |||
bgpd/bgpd.h | 1 + | |||
3 files changed, 149 insertions(+), 58 deletions(-) | |||
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c | |||
index 7bfefde482..f033f525e5 100644 | |||
--- a/bgpd/bgp_route.c | |||
+++ b/bgpd/bgp_route.c | |||
@@ -7559,8 +7559,7 @@ static char *bgp_nexthop_hostname(struct peer *peer, | |||
struct bgp_nexthop_cache *bnc) | |||
{ | |||
if (peer->hostname | |||
- && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME) && bnc | |||
- && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) | |||
+ && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME)) | |||
return peer->hostname; | |||
return NULL; | |||
} | |||
@@ -7570,6 +7569,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, | |||
struct bgp_path_info *path, int display, safi_t safi, | |||
json_object *json_paths) | |||
{ | |||
+ int len; | |||
struct attr *attr = path->attr; | |||
json_object *json_path = NULL; | |||
json_object *json_nexthops = NULL; | |||
@@ -7681,10 +7681,19 @@ void route_vty_out(struct vty *vty, const struct prefix *p, | |||
: "ipv6"); | |||
json_object_boolean_true_add(json_nexthop_global, | |||
"used"); | |||
- } else | |||
- vty_out(vty, "%s%s", | |||
- nexthop_hostname ? nexthop_hostname : nexthop, | |||
- vrf_id_str); | |||
+ } else { | |||
+ if (nexthop_hostname) | |||
+ len = vty_out(vty, "%s(%s)%s", nexthop, | |||
+ nexthop_hostname, vrf_id_str); | |||
+ else | |||
+ len = vty_out(vty, "%s%s", nexthop, vrf_id_str); | |||
+ | |||
+ len = 16 - len; | |||
+ if (len < 1) | |||
+ vty_out(vty, "\n%*s", 36, " "); | |||
+ else | |||
+ vty_out(vty, "%*s", len, " "); | |||
+ } | |||
} else if (safi == SAFI_EVPN) { | |||
if (json_paths) { | |||
json_nexthop_global = json_object_new_object(); | |||
@@ -7701,11 +7710,20 @@ void route_vty_out(struct vty *vty, const struct prefix *p, | |||
"ipv4"); | |||
json_object_boolean_true_add(json_nexthop_global, | |||
"used"); | |||
- } else | |||
- vty_out(vty, "%-16s%s", | |||
- nexthop_hostname ? nexthop_hostname | |||
- : inet_ntoa(attr->nexthop), | |||
- vrf_id_str); | |||
+ } else { | |||
+ if (nexthop_hostname) | |||
+ len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop, | |||
+ nexthop_hostname, vrf_id_str); | |||
+ else | |||
+ len = vty_out(vty, "%pI4%s", &attr->nexthop, | |||
+ vrf_id_str); | |||
+ | |||
+ len = 16 - len; | |||
+ if (len < 1) | |||
+ vty_out(vty, "\n%*s", 36, " "); | |||
+ else | |||
+ vty_out(vty, "%*s", len, " "); | |||
+ } | |||
} else if (safi == SAFI_FLOWSPEC) { | |||
if (attr->nexthop.s_addr != INADDR_ANY) { | |||
if (json_paths) { | |||
@@ -7726,10 +7744,21 @@ void route_vty_out(struct vty *vty, const struct prefix *p, | |||
json_nexthop_global, | |||
"used"); | |||
} else { | |||
- vty_out(vty, "%-16s", | |||
- nexthop_hostname | |||
- ? nexthop_hostname | |||
- : inet_ntoa(attr->nexthop)); | |||
+ if (nexthop_hostname) | |||
+ len = vty_out(vty, "%pI4(%s)%s", | |||
+ &attr->nexthop, | |||
+ nexthop_hostname, | |||
+ vrf_id_str); | |||
+ else | |||
+ len = vty_out(vty, "%pI4%s", | |||
+ &attr->nexthop, | |||
+ vrf_id_str); | |||
+ | |||
+ len = 16 - len; | |||
+ if (len < 1) | |||
+ vty_out(vty, "\n%*s", 36, " "); | |||
+ else | |||
+ vty_out(vty, "%*s", len, " "); | |||
} | |||
} | |||
} else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) { | |||
@@ -7749,19 +7778,23 @@ void route_vty_out(struct vty *vty, const struct prefix *p, | |||
json_object_boolean_true_add(json_nexthop_global, | |||
"used"); | |||
} else { | |||
- char buf[BUFSIZ]; | |||
+ if (nexthop_hostname) | |||
+ len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop, | |||
+ nexthop_hostname, vrf_id_str); | |||
+ else | |||
+ len = vty_out(vty, "%pI4%s", &attr->nexthop, | |||
+ vrf_id_str); | |||
- snprintf(buf, sizeof(buf), "%s%s", | |||
- nexthop_hostname ? nexthop_hostname | |||
- : inet_ntoa(attr->nexthop), | |||
- vrf_id_str); | |||
- vty_out(vty, "%-16s", buf); | |||
+ len = 16 - len; | |||
+ if (len < 1) | |||
+ vty_out(vty, "\n%*s", 36, " "); | |||
+ else | |||
+ vty_out(vty, "%*s", len, " "); | |||
} | |||
} | |||
/* IPv6 Next Hop */ | |||
else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) { | |||
- int len; | |||
char buf[BUFSIZ]; | |||
if (json_paths) { | |||
@@ -7835,15 +7868,18 @@ void route_vty_out(struct vty *vty, const struct prefix *p, | |||
else | |||
vty_out(vty, "%*s", len, " "); | |||
} else { | |||
- len = vty_out( | |||
- vty, "%s%s", | |||
- nexthop_hostname | |||
- ? nexthop_hostname | |||
- : inet_ntop( | |||
- AF_INET6, | |||
- &attr->mp_nexthop_local, | |||
- buf, BUFSIZ), | |||
- vrf_id_str); | |||
+ if (nexthop_hostname) | |||
+ len = vty_out( | |||
+ vty, "%pI6(%s)%s", | |||
+ &attr->mp_nexthop_local, | |||
+ nexthop_hostname, | |||
+ vrf_id_str); | |||
+ else | |||
+ len = vty_out( | |||
+ vty, "%pI6%s", | |||
+ &attr->mp_nexthop_local, | |||
+ vrf_id_str); | |||
+ | |||
len = 16 - len; | |||
if (len < 1) | |||
@@ -7852,15 +7888,16 @@ void route_vty_out(struct vty *vty, const struct prefix *p, | |||
vty_out(vty, "%*s", len, " "); | |||
} | |||
} else { | |||
- len = vty_out( | |||
- vty, "%s%s", | |||
- nexthop_hostname | |||
- ? nexthop_hostname | |||
- : inet_ntop( | |||
- AF_INET6, | |||
- &attr->mp_nexthop_global, | |||
- buf, BUFSIZ), | |||
- vrf_id_str); | |||
+ if (nexthop_hostname) | |||
+ len = vty_out(vty, "%pI6(%s)%s", | |||
+ &attr->mp_nexthop_global, | |||
+ nexthop_hostname, | |||
+ vrf_id_str); | |||
+ else | |||
+ len = vty_out(vty, "%pI6%s", | |||
+ &attr->mp_nexthop_global, | |||
+ vrf_id_str); | |||
+ | |||
len = 16 - len; | |||
if (len < 1) | |||
@@ -7986,6 +8023,7 @@ void route_vty_out_tmp(struct vty *vty, const struct prefix *p, | |||
{ | |||
json_object *json_status = NULL; | |||
json_object *json_net = NULL; | |||
+ int len; | |||
char buff[BUFSIZ]; | |||
/* Route status display. */ | |||
@@ -8079,7 +8117,6 @@ void route_vty_out_tmp(struct vty *vty, const struct prefix *p, | |||
inet_ntoa(attr->nexthop)); | |||
} else if (p->family == AF_INET6 | |||
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr)) { | |||
- int len; | |||
char buf[BUFSIZ]; | |||
len = vty_out( | |||
@@ -8823,12 +8860,15 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, | |||
json_object_string_add( | |||
json_nexthop_global, "hostname", | |||
nexthop_hostname); | |||
- } else | |||
- vty_out(vty, " %s", | |||
- nexthop_hostname | |||
- ? nexthop_hostname | |||
- : inet_ntoa( | |||
- attr->mp_nexthop_global_in)); | |||
+ } else { | |||
+ if (nexthop_hostname) | |||
+ vty_out(vty, " %pI4(%s)", | |||
+ &attr->mp_nexthop_global_in, | |||
+ nexthop_hostname); | |||
+ else | |||
+ vty_out(vty, " %pI4", | |||
+ &attr->mp_nexthop_global_in); | |||
+ } | |||
} else { | |||
if (json_paths) { | |||
json_object_string_add( | |||
@@ -8839,11 +8879,15 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, | |||
json_object_string_add( | |||
json_nexthop_global, "hostname", | |||
nexthop_hostname); | |||
- } else | |||
- vty_out(vty, " %s", | |||
- nexthop_hostname | |||
- ? nexthop_hostname | |||
- : inet_ntoa(attr->nexthop)); | |||
+ } else { | |||
+ if (nexthop_hostname) | |||
+ vty_out(vty, " %pI4(%s)", | |||
+ &attr->nexthop, | |||
+ nexthop_hostname); | |||
+ else | |||
+ vty_out(vty, " %pI4", | |||
+ &attr->nexthop); | |||
+ } | |||
} | |||
if (json_paths) | |||
@@ -8866,12 +8910,13 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, | |||
json_object_string_add(json_nexthop_global, "scope", | |||
"global"); | |||
} else { | |||
- vty_out(vty, " %s", | |||
- nexthop_hostname | |||
- ? nexthop_hostname | |||
- : inet_ntop(AF_INET6, | |||
- &attr->mp_nexthop_global, | |||
- buf, INET6_ADDRSTRLEN)); | |||
+ if (nexthop_hostname) | |||
+ vty_out(vty, " %pI6(%s)", | |||
+ &attr->mp_nexthop_global, | |||
+ nexthop_hostname); | |||
+ else | |||
+ vty_out(vty, " %pI6", | |||
+ &attr->mp_nexthop_global); | |||
} | |||
} | |||
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c | |||
index 78521457fd..7f00ff3fbe 100644 | |||
--- a/bgpd/bgp_vty.c | |||
+++ b/bgpd/bgp_vty.c | |||
@@ -84,6 +84,10 @@ FRR_CFG_DEFAULT_BOOL(BGP_SHOW_HOSTNAME, | |||
{ .val_bool = true, .match_profile = "datacenter", }, | |||
{ .val_bool = false }, | |||
) | |||
+FRR_CFG_DEFAULT_BOOL(BGP_SHOW_NEXTHOP_HOSTNAME, | |||
+ { .val_bool = true, .match_profile = "datacenter", }, | |||
+ { .val_bool = false }, | |||
+) | |||
FRR_CFG_DEFAULT_BOOL(BGP_LOG_NEIGHBOR_CHANGES, | |||
{ .val_bool = true, .match_profile = "datacenter", }, | |||
{ .val_bool = false }, | |||
@@ -422,6 +426,8 @@ int bgp_get_vty(struct bgp **bgp, as_t *as, const char *name, | |||
SET_FLAG((*bgp)->flags, BGP_FLAG_IMPORT_CHECK); | |||
if (DFLT_BGP_SHOW_HOSTNAME) | |||
SET_FLAG((*bgp)->flags, BGP_FLAG_SHOW_HOSTNAME); | |||
+ if (DFLT_BGP_SHOW_NEXTHOP_HOSTNAME) | |||
+ SET_FLAG((*bgp)->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME); | |||
if (DFLT_BGP_LOG_NEIGHBOR_CHANGES) | |||
SET_FLAG((*bgp)->flags, BGP_FLAG_LOG_NEIGHBOR_CHANGES); | |||
if (DFLT_BGP_DETERMINISTIC_MED) | |||
@@ -3100,6 +3106,32 @@ DEFUN (no_bgp_default_show_hostname, | |||
return CMD_SUCCESS; | |||
} | |||
+/* Display hostname in certain command outputs */ | |||
+DEFUN (bgp_default_show_nexthop_hostname, | |||
+ bgp_default_show_nexthop_hostname_cmd, | |||
+ "bgp default show-nexthop-hostname", | |||
+ "BGP specific commands\n" | |||
+ "Configure BGP defaults\n" | |||
+ "Show hostname for nexthop in certain command outputs\n") | |||
+{ | |||
+ VTY_DECLVAR_CONTEXT(bgp, bgp); | |||
+ SET_FLAG(bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME); | |||
+ return CMD_SUCCESS; | |||
+} | |||
+ | |||
+DEFUN (no_bgp_default_show_nexthop_hostname, | |||
+ no_bgp_default_show_nexthop_hostname_cmd, | |||
+ "no bgp default show-nexthop-hostname", | |||
+ NO_STR | |||
+ "BGP specific commands\n" | |||
+ "Configure BGP defaults\n" | |||
+ "Show hostname for nexthop in certain command outputs\n") | |||
+{ | |||
+ VTY_DECLVAR_CONTEXT(bgp, bgp); | |||
+ UNSET_FLAG(bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME); | |||
+ return CMD_SUCCESS; | |||
+} | |||
+ | |||
/* "bgp network import-check" configuration. */ | |||
DEFUN (bgp_network_import_check, | |||
bgp_network_import_check_cmd, | |||
@@ -15190,6 +15222,15 @@ int bgp_config_write(struct vty *vty) | |||
? "" | |||
: "no "); | |||
+ /* BGP default show-nexthop-hostname */ | |||
+ if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME) | |||
+ != SAVE_BGP_SHOW_HOSTNAME) | |||
+ vty_out(vty, " %sbgp default show-nexthop-hostname\n", | |||
+ CHECK_FLAG(bgp->flags, | |||
+ BGP_FLAG_SHOW_NEXTHOP_HOSTNAME) | |||
+ ? "" | |||
+ : "no "); | |||
+ | |||
/* BGP default subgroup-pkt-queue-max. */ | |||
if (bgp->default_subgroup_pkt_queue_max | |||
!= BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX) | |||
@@ -15815,6 +15856,10 @@ void bgp_vty_init(void) | |||
install_element(BGP_NODE, &bgp_default_show_hostname_cmd); | |||
install_element(BGP_NODE, &no_bgp_default_show_hostname_cmd); | |||
+ /* bgp default show-nexthop-hostname */ | |||
+ install_element(BGP_NODE, &bgp_default_show_nexthop_hostname_cmd); | |||
+ install_element(BGP_NODE, &no_bgp_default_show_nexthop_hostname_cmd); | |||
+ | |||
/* "bgp default subgroup-pkt-queue-max" commands. */ | |||
install_element(BGP_NODE, &bgp_default_subgroup_pkt_queue_max_cmd); | |||
install_element(BGP_NODE, &no_bgp_default_subgroup_pkt_queue_max_cmd); | |||
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h | |||
index 4a5772a53b..4efc068dea 100644 | |||
--- a/bgpd/bgpd.h | |||
+++ b/bgpd/bgpd.h | |||
@@ -447,6 +447,7 @@ struct bgp { | |||
#define BGP_FLAG_SELECT_DEFER_DISABLE (1 << 23) | |||
#define BGP_FLAG_GR_DISABLE_EOR (1 << 24) | |||
#define BGP_FLAG_EBGP_REQUIRES_POLICY (1 << 25) | |||
+#define BGP_FLAG_SHOW_NEXTHOP_HOSTNAME (1 << 26) | |||
enum global_mode GLOBAL_GR_FSM[BGP_GLOBAL_GR_MODE] | |||
[BGP_GLOBAL_GR_EVENT_CMD]; | |||
From 104dfe5258cbeb0443fa4d6577794a1e5a5dafd3 Mon Sep 17 00:00:00 2001 | |||
From: Donatas Abraitis <donatas.abraitis@gmail.com> | |||
Date: Wed, 6 May 2020 17:50:04 +0300 | |||
Subject: [PATCH 3/4] bgpd: Add "hostname" in JSON output for `show bgp` family | |||
outputs | |||
This adds hostname regardless if `bgp default show-hostname` enabled or not. | |||
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com> | |||
--- | |||
bgpd/bgp_route.c | 40 ++++++++++++++++++++-------------------- | |||
1 file changed, 20 insertions(+), 20 deletions(-) | |||
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c | |||
index f033f525e5..5f645fa871 100644 | |||
--- a/bgpd/bgp_route.c | |||
+++ b/bgpd/bgp_route.c | |||
@@ -7671,10 +7671,10 @@ void route_vty_out(struct vty *vty, const struct prefix *p, | |||
json_object_string_add(json_nexthop_global, "ip", | |||
nexthop); | |||
- if (nexthop_hostname) | |||
+ if (path->peer->hostname) | |||
json_object_string_add(json_nexthop_global, | |||
"hostname", | |||
- nexthop_hostname); | |||
+ path->peer->hostname); | |||
json_object_string_add(json_nexthop_global, "afi", | |||
(af == AF_INET) ? "ipv4" | |||
@@ -7701,10 +7701,10 @@ void route_vty_out(struct vty *vty, const struct prefix *p, | |||
json_object_string_add(json_nexthop_global, "ip", | |||
inet_ntoa(attr->nexthop)); | |||
- if (nexthop_hostname) | |||
+ if (path->peer->hostname) | |||
json_object_string_add(json_nexthop_global, | |||
"hostname", | |||
- nexthop_hostname); | |||
+ path->peer->hostname); | |||
json_object_string_add(json_nexthop_global, "afi", | |||
"ipv4"); | |||
@@ -7735,10 +7735,10 @@ void route_vty_out(struct vty *vty, const struct prefix *p, | |||
json_nexthop_global, "ip", | |||
inet_ntoa(attr->nexthop)); | |||
- if (nexthop_hostname) | |||
+ if (path->peer->hostname) | |||
json_object_string_add( | |||
json_nexthop_global, "hostname", | |||
- nexthop_hostname); | |||
+ path->peer->hostname); | |||
json_object_boolean_true_add( | |||
json_nexthop_global, | |||
@@ -7768,10 +7768,10 @@ void route_vty_out(struct vty *vty, const struct prefix *p, | |||
json_object_string_add(json_nexthop_global, "ip", | |||
inet_ntoa(attr->nexthop)); | |||
- if (nexthop_hostname) | |||
+ if (path->peer->hostname) | |||
json_object_string_add(json_nexthop_global, | |||
"hostname", | |||
- nexthop_hostname); | |||
+ path->peer->hostname); | |||
json_object_string_add(json_nexthop_global, "afi", | |||
"ipv4"); | |||
@@ -7804,10 +7804,10 @@ void route_vty_out(struct vty *vty, const struct prefix *p, | |||
inet_ntop(AF_INET6, &attr->mp_nexthop_global, | |||
buf, BUFSIZ)); | |||
- if (nexthop_hostname) | |||
+ if (path->peer->hostname) | |||
json_object_string_add(json_nexthop_global, | |||
"hostname", | |||
- nexthop_hostname); | |||
+ path->peer->hostname); | |||
json_object_string_add(json_nexthop_global, "afi", | |||
"ipv6"); | |||
@@ -7826,10 +7826,10 @@ void route_vty_out(struct vty *vty, const struct prefix *p, | |||
&attr->mp_nexthop_local, buf, | |||
BUFSIZ)); | |||
- if (nexthop_hostname) | |||
+ if (path->peer->hostname) | |||
json_object_string_add( | |||
json_nexthop_ll, "hostname", | |||
- nexthop_hostname); | |||
+ path->peer->hostname); | |||
json_object_string_add(json_nexthop_ll, "afi", | |||
"ipv6"); | |||
@@ -8856,10 +8856,10 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, | |||
json_nexthop_global, "ip", | |||
inet_ntoa(attr->mp_nexthop_global_in)); | |||
- if (nexthop_hostname) | |||
+ if (path->peer->hostname) | |||
json_object_string_add( | |||
json_nexthop_global, "hostname", | |||
- nexthop_hostname); | |||
+ path->peer->hostname); | |||
} else { | |||
if (nexthop_hostname) | |||
vty_out(vty, " %pI4(%s)", | |||
@@ -8875,10 +8875,10 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, | |||
json_nexthop_global, "ip", | |||
inet_ntoa(attr->nexthop)); | |||
- if (nexthop_hostname) | |||
+ if (path->peer->hostname) | |||
json_object_string_add( | |||
json_nexthop_global, "hostname", | |||
- nexthop_hostname); | |||
+ path->peer->hostname); | |||
} else { | |||
if (nexthop_hostname) | |||
vty_out(vty, " %pI4(%s)", | |||
@@ -8900,10 +8900,10 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, | |||
inet_ntop(AF_INET6, &attr->mp_nexthop_global, | |||
buf, INET6_ADDRSTRLEN)); | |||
- if (nexthop_hostname) | |||
+ if (path->peer->hostname) | |||
json_object_string_add(json_nexthop_global, | |||
"hostname", | |||
- nexthop_hostname); | |||
+ path->peer->hostname); | |||
json_object_string_add(json_nexthop_global, "afi", | |||
"ipv6"); | |||
@@ -9094,10 +9094,10 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, | |||
inet_ntop(AF_INET6, &attr->mp_nexthop_local, | |||
buf, INET6_ADDRSTRLEN)); | |||
- if (nexthop_hostname) | |||
+ if (path->peer->hostname) | |||
json_object_string_add(json_nexthop_ll, | |||
"hostname", | |||
- nexthop_hostname); | |||
+ path->peer->hostname); | |||
json_object_string_add(json_nexthop_ll, "afi", "ipv6"); | |||
json_object_string_add(json_nexthop_ll, "scope", | |||
From 8df39282ea64e2a65a7910012627f78d080833b1 Mon Sep 17 00:00:00 2001 | |||
From: Donatas Abraitis <donatas.abraitis@gmail.com> | |||
Date: Wed, 24 Jun 2020 17:26:27 +0300 | |||
Subject: [PATCH 4/4] doc: Add some words about `bgp default | |||
show-[nexthop]-hostname` | |||
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com> | |||
--- | |||
doc/user/bgp.rst | 13 +++++++++++++ | |||
1 file changed, 13 insertions(+) | |||
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst | |||
index 36227db604..a6c29724b0 100644 | |||
--- a/doc/user/bgp.rst | |||
+++ b/doc/user/bgp.rst | |||
@@ -1366,6 +1366,19 @@ Configuring Peers | |||
on by default or not. This command defaults to on and is not displayed. | |||
The `no bgp default ipv4-unicast` form of the command is displayed. | |||
+.. index:: [no] bgp default show-hostname | |||
+.. clicmd:: [no] bgp default show-hostname | |||
+ | |||
+ This command shows the hostname of the peer in certain BGP commands | |||
+ outputs. It's easier to troubleshoot if you have a number of BGP peers. | |||
+ | |||
+.. index:: [no] bgp default show-nexthop-hostname | |||
+.. clicmd:: [no] bgp default show-nexthop-hostname | |||
+ | |||
+ This command shows the hostname of the next-hop in certain BGP commands | |||
+ outputs. It's easier to troubleshoot if you have a number of BGP peers | |||
+ and a number of routes to check. | |||
+ | |||
.. index:: [no] neighbor PEER advertisement-interval (0-600) | |||
.. clicmd:: [no] neighbor PEER advertisement-interval (0-600) | |||
@ -0,0 +1,30 @@ | |||
From 2bbe7133eb5cb97ba4b745cd251a8615cd2bd008 Mon Sep 17 00:00:00 2001 | |||
From: Richard Wu <wutong23@baidu.com> | |||
Date: Fri, 5 Jun 2020 17:54:57 +0800 | |||
Subject: [PATCH] bgpd: Fix the bug that BGP MRAI does not work. | |||
Issue: bgp_process_writes will be called when the fd is writable. | |||
And it will bgp_generate_updgrp_packets to generate the | |||
update packets no matter MRAI is set or not. | |||
Fix: bgp_generate_updgrp_packets thread will return without sending | |||
any update when MRAI timer is still running. | |||
Signed-off-by: Richard Wu <wutong23@baidu.com> | |||
--- | |||
bgpd/bgp_packet.c | 3 +++ | |||
1 file changed, 3 insertions(+) | |||
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c | |||
index 29c03f4014..6f1c033f2a 100644 | |||
--- a/bgpd/bgp_packet.c | |||
+++ b/bgpd/bgp_packet.c | |||
@@ -408,6 +408,9 @@ int bgp_generate_updgrp_packets(struct thread *thread) | |||
if (peer->bgp->main_peers_update_hold) | |||
return 0; | |||
+ if (peer->t_routeadv) | |||
+ return 0; | |||
+ | |||
do { | |||
s = NULL; | |||
FOREACH_AFI_SAFI (afi, safi) { |
@ -1,385 +0,0 @@ | |||
From 2332428d3c80ac3d3b4e1c0bdba830b098ef440f Mon Sep 17 00:00:00 2001 | |||
From: Rafael Zalamena <rzalamena@opensourcerouting.org> | |||
Date: Fri, 5 Jul 2019 11:07:30 -0300 | |||
Subject: [PATCH] yang: initial filter YANG model import | |||
This model contains the description of access-list, prefix-list and | |||
other lists used by route map and other filtering interfaces. | |||
Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org> | |||
--- | |||
yang/frr-filter.yang | 365 +++++++++++++++++++++++++++++++++++++++++++ | |||
1 file changed, 365 insertions(+) | |||
create mode 100644 yang/frr-filter.yang | |||
diff --git a/yang/frr-filter.yang b/yang/frr-filter.yang | |||
new file mode 100644 | |||
index 0000000000..92af6aebfd | |||
--- /dev/null | |||
+++ b/yang/frr-filter.yang | |||
@@ -0,0 +1,365 @@ | |||
+module frr-filter { | |||
+ yang-version 1.1; | |||
+ namespace "http://frrouting.org/yang/filter"; | |||
+ prefix frr-filter; | |||
+ | |||
+ import ietf-inet-types { | |||
+ prefix inet; | |||
+ } | |||
+ import ietf-yang-types { | |||
+ prefix yang; | |||
+ } | |||
+ | |||
+ organization "Free Range Routing"; | |||
+ contact | |||
+ "FRR Users List: <mailto:frog@lists.frrouting.org> | |||
+ FRR Development List: <mailto:dev@lists.frrouting.org>"; | |||
+ description "This module defines filter settings"; | |||
+ | |||
+ revision 2019-07-04 { | |||
+ description "Initial revision"; | |||
+ } | |||
+ | |||
+ /* | |||
+ * Types. | |||
+ */ | |||
+ typedef access-list-standard { | |||
+ description "Standard IPv4 access list (any, host or a prefix)"; | |||
+ type uint16 { | |||
+ range "1..99 | 1300..1999"; | |||
+ } | |||
+ } | |||
+ | |||
+ typedef access-list-extended { | |||
+ description | |||
+ "Extended IPv4 access list (source / destination any, hosts or prefixes)"; | |||
+ type uint16 { | |||
+ range "100..199 | 2000..2699"; | |||
+ } | |||
+ } | |||
+ | |||
+ typedef access-list-legacy { | |||
+ description "Standard/Extended IPv4 access list"; | |||
+ type uint16 { | |||
+ range "1..199 | 1300..2699"; | |||
+ } | |||
+ } | |||
+ | |||
+ typedef access-list-name { | |||
+ description "Access list name formatting"; | |||
+ type string; | |||
+ } | |||
+ | |||
+ typedef access-list-sequence { | |||
+ description "Access list sequence number"; | |||
+ type uint32 { | |||
+ range "1..4294967295"; | |||
+ } | |||
+ } | |||
+ | |||
+ typedef access-list-action { | |||
+ description "Access list return action on match"; | |||
+ type enumeration { | |||
+ enum deny { | |||
+ description "Deny an entry"; | |||
+ value 0; | |||
+ } | |||
+ enum permit { | |||
+ description "Accept an entry"; | |||
+ value 1; | |||
+ } | |||
+ } | |||
+ } | |||
+ | |||
+ /* | |||
+ * Configuration data. | |||
+ */ | |||
+ container filter-list { | |||
+ list access-list-legacy { | |||
+ description "Access list legacy instance"; | |||
+ | |||
+ key "number sequence"; | |||
+ | |||
+ leaf number { | |||
+ description "Access list sequence value"; | |||
+ type access-list-legacy; | |||
+ } | |||
+ | |||
+ leaf sequence { | |||
+ description "Access list sequence value"; | |||
+ type access-list-sequence; | |||
+ } | |||
+ | |||
+ leaf action { | |||
+ description "Access list action on match"; | |||
+ type access-list-action; | |||
+ mandatory true; | |||
+ } | |||
+ | |||
+ leaf remark { | |||
+ description "Access list remark"; | |||
+ type string; | |||
+ } | |||
+ | |||
+ choice value { | |||
+ description | |||
+ "Standard access list: value to match. | |||
+ Extended access list: source value to match."; | |||
+ mandatory true; | |||
+ | |||
+ case host { | |||
+ leaf host { | |||
+ description "Host to match"; | |||
+ type inet:ipv4-address; | |||
+ } | |||
+ } | |||
+ case network { | |||
+ leaf network { | |||
+ description "Network to match"; | |||
+ type inet:ipv4-prefix; | |||
+ } | |||
+ } | |||
+ case any { | |||
+ leaf any { | |||
+ description "Match any"; | |||
+ type empty; | |||
+ } | |||
+ } | |||
+ } | |||
+ | |||
+ choice extended-value { | |||
+ when "./sequence >= 100 and ./sequence <= 199 or | |||
+ ./sequence >= 2000 and ./sequence <= 2699"; | |||
+ description "Destination value to match"; | |||
+ | |||
+ case destination-host { | |||
+ leaf destination-host { | |||
+ description "Host to match"; | |||
+ type inet:ipv4-address; | |||
+ } | |||
+ } | |||
+ case destination-network { | |||
+ leaf destination-network { | |||
+ description "Network to match"; | |||
+ type inet:ipv4-prefix; | |||
+ } | |||
+ } | |||
+ case destination-any { | |||
+ leaf destination-any { | |||
+ description "Match any"; | |||
+ type empty; | |||
+ } | |||
+ } | |||
+ } | |||
+ } | |||
+ | |||
+ list access-list { | |||
+ description "Access list instance"; | |||
+ | |||
+ key "type identifier sequence"; | |||
+ | |||
+ leaf type { | |||
+ description "Access list content type"; | |||
+ type enumeration { | |||
+ enum ipv4 { | |||
+ description "Internet Protocol address version 4"; | |||
+ value 0; | |||
+ } | |||
+ enum ipv6 { | |||
+ description "Internet Protocol address version 6"; | |||
+ value 1; | |||
+ } | |||
+ enum mac { | |||
+ description "Media Access Control address"; | |||
+ value 2; | |||
+ } | |||
+ | |||
+ /* | |||
+ * Protocol YANG models should augment the parent node to | |||
+ * contain the routing protocol specific value. The protocol | |||
+ * must also augment `value` leaf to include its specific | |||
+ * values or expand the `when` statement on the existing cases. | |||
+ */ | |||
+ enum custom { | |||
+ description "Custom data type"; | |||
+ value 100; | |||
+ } | |||
+ } | |||
+ } | |||
+ | |||
+ leaf identifier { | |||
+ description "Access list identifier"; | |||
+ type access-list-name; | |||
+ } | |||
+ | |||
+ leaf sequence { | |||
+ description "Access list sequence value"; | |||
+ type access-list-sequence; | |||
+ } | |||
+ | |||
+ leaf action { | |||
+ description "Access list action on match"; | |||
+ type access-list-action; | |||
+ mandatory true; | |||
+ } | |||
+ | |||
+ leaf remark { | |||
+ description "Access list remark"; | |||
+ type string; | |||
+ } | |||
+ | |||
+ choice value { | |||
+ description "Access list value to match"; | |||
+ mandatory true; | |||
+ | |||
+ case ipv4-prefix { | |||
+ when "./type = 'ipv4'"; | |||
+ | |||
+ leaf ipv4-prefix { | |||
+ description "Configure IPv4 prefix to match"; | |||
+ type inet:ipv4-prefix; | |||
+ } | |||
+ | |||
+ leaf ipv4-exact-match { | |||
+ description "Exact match of prefix"; | |||
+ type boolean; | |||
+ default false; | |||
+ } | |||
+ } | |||
+ case ipv6-prefix { | |||
+ when "./type = 'ipv6'"; | |||
+ | |||
+ leaf ipv6-prefix { | |||
+ description "Configure IPv6 prefix to match"; | |||
+ type inet:ipv6-prefix; | |||
+ } | |||
+ | |||
+ leaf ipv6-exact-match { | |||
+ description "Exact match of prefix"; | |||
+ type boolean; | |||
+ default false; | |||
+ } | |||
+ } | |||
+ case mac { | |||
+ when "./type = 'mac'"; | |||
+ | |||
+ leaf mac { | |||
+ description "Configure MAC address to match"; | |||
+ type yang:mac-address; | |||
+ } | |||
+ } | |||
+ case any { | |||
+ leaf any { | |||
+ description "Match anything"; | |||
+ type empty; | |||
+ } | |||
+ } | |||
+ } | |||
+ } | |||
+ | |||
+ list prefix-list { | |||
+ description "Prefix list instance"; | |||
+ | |||
+ key "type name sequence"; | |||
+ | |||
+ leaf type { | |||
+ description "Prefix list type"; | |||
+ type enumeration { | |||
+ enum ipv4 { | |||
+ description "Internet Protocol address version 4"; | |||
+ value 0; | |||
+ } | |||
+ enum ipv6 { | |||
+ description "Internet Protocol address version 6"; | |||
+ value 1; | |||
+ } | |||
+ } | |||
+ } | |||
+ | |||
+ leaf name { | |||
+ description "Prefix list name"; | |||
+ type access-list-name; | |||
+ } | |||
+ | |||
+ leaf sequence { | |||
+ description "Access list sequence value"; | |||
+ type access-list-sequence; | |||
+ } | |||
+ | |||
+ leaf action { | |||
+ description "Prefix list action on match"; | |||
+ type access-list-action; | |||
+ mandatory true; | |||
+ } | |||
+ | |||
+ leaf description { | |||
+ description "Prefix list user description"; | |||
+ type string; | |||
+ } | |||
+ | |||
+ choice value { | |||
+ description "Prefix list value to match"; | |||
+ mandatory true; | |||
+ | |||
+ case ipv4-prefix { | |||
+ when "./type = 'ipv4'"; | |||
+ | |||
+ leaf ipv4-prefix { | |||
+ description "Configure IPv4 prefix to match"; | |||
+ type inet:ipv4-prefix; | |||
+ } | |||
+ | |||
+ leaf ipv4-prefix-length-greater-or-equal { | |||
+ description | |||
+ "Specifies if matching prefixes with length greater than | |||
+ or equal to value"; | |||
+ type uint8 { | |||
+ range "0..32"; | |||
+ } | |||
+ } | |||
+ | |||
+ leaf ipv4-prefix-length-lesser-or-equal { | |||
+ description | |||
+ "Specifies if matching prefixes with length lesser than | |||
+ or equal to value"; | |||
+ type uint8 { | |||
+ range "0..32"; | |||
+ } | |||
+ } | |||
+ } | |||
+ case ipv6-prefix { | |||
+ when "./type = 'ipv6'"; | |||
+ | |||
+ leaf ipv6-prefix { | |||
+ description "Configure IPv6 prefix to match"; | |||
+ type inet:ipv6-prefix; | |||
+ } | |||
+ | |||
+ leaf ipv6-prefix-length-greater-or-equal { | |||
+ description | |||
+ "Specifies if matching prefixes with length greater than | |||
+ or equal to value"; | |||
+ type uint8 { | |||
+ range "0..128"; | |||
+ } | |||
+ } | |||
+ | |||
+ leaf ipv6-prefix-length-lesser-or-equal { | |||
+ description | |||
+ "Specifies if matching prefixes with length lesser than | |||
+ or equal to value"; | |||
+ type uint8 { | |||
+ range "0..128"; | |||
+ } | |||
+ } | |||
+ } | |||
+ case any { | |||
+ leaf any { | |||
+ description "Match anything"; | |||
+ type empty; | |||
+ } | |||
+ } | |||
+ } | |||
+ } | |||
+ } | |||
+} |
@ -1,390 +0,0 @@ | |||
--- a/dev/null 2020-04-10 18:48:03.582667900 +0300 | |||
+++ b/yang/frr-route-map.yang 2020-05-02 11:43:04.182956847 +0300 | |||
@@ -0,0 +1,387 @@ | |||
+module frr-route-map { | |||
+ yang-version 1.1; | |||
+ namespace "http://frrouting.org/yang/route-map"; | |||
+ prefix frr-route-map; | |||
+ | |||
+ import ietf-inet-types { | |||
+ prefix inet; | |||
+ } | |||
+ import frr-filter { | |||
+ prefix filter; | |||
+ } | |||
+ import frr-interface { | |||
+ prefix frr-interface; | |||
+ } | |||
+ | |||
+ organization "FRRouting"; | |||
+ contact | |||
+ "FRR Users List: <mailto:frog@lists.frrouting.org> | |||
+ FRR Development List: <mailto:dev@lists.frrouting.org>"; | |||
+ description "This module defines route map settings"; | |||
+ | |||
+ revision 2019-07-01 { | |||
+ description "Initial revision"; | |||
+ } | |||
+ | |||
+ /* | |||
+ * Types. | |||
+ */ | |||
+ typedef route-map-sequence { | |||
+ description "Route map valid sequence numbers"; | |||
+ type uint16 { | |||
+ range "1..65535"; | |||
+ } | |||
+ } | |||
+ | |||
+ typedef route-map-name { | |||
+ description "Route map name format"; | |||
+ type string; | |||
+ } | |||
+ | |||
+ /* | |||
+ * Operational data. | |||
+ */ | |||
+ container lib { | |||
+ list route-map { | |||
+ description "Route map instance"; | |||
+ | |||
+ key "name"; | |||
+ | |||
+ leaf name { | |||
+ description "Route map instance name"; | |||
+ type route-map-name; | |||
+ } | |||
+ | |||
+ list entry { | |||
+ description "Route map entry"; | |||
+ | |||
+ key "sequence"; | |||
+ | |||
+ leaf sequence { | |||
+ description | |||
+ "Route map instance priority (low number means higher priority)"; | |||
+ type route-map-sequence; | |||
+ } | |||
+ | |||
+ leaf description { | |||
+ description "Route map description"; | |||
+ type string; | |||
+ } | |||
+ | |||
+ leaf action { | |||
+ description | |||
+ "Route map actions: permit (executes action), deny (quits evaluation)"; | |||
+ mandatory true; | |||
+ type enumeration { | |||
+ enum permit { | |||
+ description | |||
+ "Executes configured action and permits the prefix/route | |||
+ if the conditions matched. An alternative exit action can | |||
+ be configured to continue processing the route map list | |||
+ or jump to process another route map."; | |||
+ value 0; | |||
+ } | |||
+ enum deny { | |||
+ description | |||
+ "If all conditions are met the prefix/route is denied and | |||
+ route map processing stops."; | |||
+ value 1; | |||
+ } | |||
+ } | |||
+ } | |||
+ | |||
+ leaf call { | |||
+ description | |||
+ "Call another route map before calling `exit-policy`. If the | |||
+ called route map returns deny then this route map will also | |||
+ return deny"; | |||
+ type route-map-name; | |||
+ } | |||
+ | |||
+ leaf exit-policy { | |||
+ description "What do to after route map successful match, set and call"; | |||
+ type enumeration { | |||
+ enum permit-or-deny { | |||
+ description "End route map evaluation and return"; | |||
+ value 0; | |||
+ } | |||
+ enum next { | |||
+ description | |||
+ "Proceed evaluating next route map entry per sequence"; | |||
+ value 1; | |||
+ } | |||
+ enum goto { | |||
+ description | |||
+ "Go to route map entry with the provided sequence number"; | |||
+ value 2; | |||
+ } | |||
+ } | |||
+ default "permit-or-deny"; | |||
+ } | |||
+ | |||
+ leaf goto-value { | |||
+ when "../exit-policy = 'goto'"; | |||
+ description | |||
+ "Sequence number to jump (when using `goto` exit policy)"; | |||
+ mandatory true; | |||
+ type route-map-sequence; | |||
+ } | |||
+ | |||
+ list match-condition { | |||
+ description "Route map match conditions"; | |||
+ | |||
+ key "condition"; | |||
+ | |||
+ leaf condition { | |||
+ description "Match condition"; | |||
+ type enumeration { | |||
+ enum interface { | |||
+ description "Match interface"; | |||
+ value 0; | |||
+ } | |||
+ enum ipv4-address-list { | |||
+ description "Match an IPv4 access-list"; | |||
+ value 1; | |||
+ } | |||
+ enum ipv4-prefix-list { | |||
+ description "Match an IPv4 prefix-list"; | |||
+ value 2; | |||
+ } | |||
+ enum ipv4-next-hop-list { | |||
+ description "Match an IPv4 next-hop"; | |||
+ value 3; | |||
+ } | |||
+ enum ipv4-next-hop-prefix-list { | |||
+ description "Match an IPv4 next-hop prefix list"; | |||
+ value 4; | |||
+ } | |||
+ enum ipv4-next-hop-type { | |||
+ description "Match an IPv4 next-hop type"; | |||
+ value 5; | |||
+ } | |||
+ enum ipv6-address-list { | |||
+ description "Match an IPv6 access-list"; | |||
+ value 6; | |||
+ } | |||
+ enum ipv6-prefix-list { | |||
+ description "Match an IPv6 prefix-list"; | |||
+ value 7; | |||
+ } | |||
+ enum ipv6-next-hop-type { | |||
+ description "Match an IPv6 next-hop type"; | |||
+ value 8; | |||
+ } | |||
+ enum metric { | |||
+ description "Match a route metric"; | |||
+ value 9; | |||
+ } | |||
+ enum tag { | |||
+ description "Match a route tag"; | |||
+ value 10; | |||
+ } | |||
+ /* zebra specific conditions. */ | |||
+ enum ipv4-prefix-length { | |||
+ description "Match IPv4 prefix length"; | |||
+ value 100; | |||
+ } | |||
+ enum ipv6-prefix-length { | |||
+ description "Match IPv6 prefix length"; | |||
+ value 101; | |||
+ } | |||
+ enum ipv4-next-hop-prefix-length { | |||
+ description "Match next-hop prefix length"; | |||
+ value 102; | |||
+ } | |||
+ enum source-protocol { | |||
+ description "Match source protocol"; | |||
+ value 103; | |||
+ } | |||
+ enum source-instance { | |||
+ description "Match source protocol instance"; | |||
+ value 104; | |||
+ } | |||
+ } | |||
+ } | |||
+ | |||
+ choice condition-value { | |||
+ description | |||
+ "Value to match (interpretation depends on condition type)"; | |||
+ mandatory true; | |||
+ case interface { | |||
+ when "./condition = 'interface'"; | |||
+ leaf interface { | |||
+ type string; | |||
+ } | |||
+ } | |||
+ case access-list-num { | |||
+ when "./condition = 'ipv4-address-list' or | |||
+ ./condition = 'ipv4-next-hop-list'"; | |||
+ leaf access-list-num { | |||
+ type filter:access-list-standard; | |||
+ } | |||
+ } | |||
+ case access-list-num-extended { | |||
+ when "./condition = 'ipv4-address-list' or | |||
+ ./condition = 'ipv4-next-hop-list'"; | |||
+ leaf access-list-num-extended { | |||
+ type filter:access-list-extended; | |||
+ } | |||
+ } | |||
+ case list-name { | |||
+ when "./condition = 'ipv4-address-list' or | |||
+ ./condition = 'ipv4-prefix-list' or | |||
+ ./condition = 'ipv4-next-hop-list' or | |||
+ ./condition = 'ipv4-next-hop-prefix-list' or | |||
+ ./condition = 'ipv6-address-list' or | |||
+ ./condition = 'ipv6-prefix-list'"; | |||
+ leaf list-name { | |||
+ type filter:access-list-name; | |||
+ } | |||
+ } | |||
+ case ipv4-next-hop-type { | |||
+ when "./condition = 'ipv4-next-hop-type'"; | |||
+ leaf ipv4-next-hop-type { | |||
+ type enumeration { | |||
+ enum blackhole { | |||
+ value 0; | |||
+ } | |||
+ } | |||
+ } | |||
+ } | |||
+ case ipv6-next-hop-type { | |||
+ when "./condition = 'ipv6-next-hop-type'"; | |||
+ leaf ipv6-next-hop-type { | |||
+ type enumeration { | |||
+ enum blackhole { | |||
+ value 0; | |||
+ } | |||
+ } | |||
+ } | |||
+ } | |||
+ case metric { | |||
+ when "./condition = 'metric'"; | |||
+ leaf metric { | |||
+ type uint32 { | |||
+ range "1..4294967295"; | |||
+ } | |||
+ } | |||
+ } | |||
+ case tag { | |||
+ when "./condition = 'tag'"; | |||
+ leaf tag { | |||
+ type uint32 { | |||
+ range "1..4294967295"; | |||
+ } | |||
+ } | |||
+ } | |||
+ } | |||
+ } | |||
+ | |||
+ list set-action { | |||
+ description "Route map set actions"; | |||
+ | |||
+ key "action"; | |||
+ | |||
+ leaf action { | |||
+ description "Action to do when the route map matches"; | |||
+ type enumeration { | |||
+ enum ipv4-next-hop { | |||
+ description "Set IPv4 address of the next hop"; | |||
+ value 0; | |||
+ } | |||
+ enum ipv6-next-hop { | |||
+ description "Set IPv6 address of the next hop"; | |||
+ value 1; | |||
+ } | |||
+ enum metric { | |||
+ description "Set prefix/route metric"; | |||
+ value 2; | |||
+ } | |||
+ enum tag { | |||
+ description "Set tag"; | |||
+ value 3; | |||
+ } | |||
+ /* zebra specific conditions. */ | |||
+ enum source { | |||
+ description "Set source address for route"; | |||
+ value 100; | |||
+ } | |||
+ } | |||
+ } | |||
+ | |||
+ choice action-value { | |||
+ description | |||
+ "Value to set (interpretation depends on action-type)"; | |||
+ case ipv4-address { | |||
+ when "./action = 'ipv4-next-hop'"; | |||
+ leaf ipv4-address { | |||
+ description "IPv4 address"; | |||
+ type inet:ipv4-address; | |||
+ } | |||
+ } | |||
+ case ipv6-address { | |||
+ when "./action = 'ipv6-next-hop'"; | |||
+ leaf ipv6-address { | |||
+ description "IPv6 address"; | |||
+ type inet:ipv6-address; | |||
+ } | |||
+ } | |||
+ case metric { | |||
+ when "./action = 'metric'"; | |||
+ choice metric-value { | |||
+ description "Metric to set or use"; | |||
+ case value { | |||
+ leaf value { | |||
+ description "Use the following metric value"; | |||
+ type uint32 { | |||
+ range "0..4294967295"; | |||
+ } | |||
+ } | |||
+ } | |||
+ case add-metric { | |||
+ leaf add-metric { | |||
+ description "Add unit to metric"; | |||
+ type boolean; | |||
+ } | |||
+ } | |||
+ case subtract-metric { | |||
+ leaf subtract-metric { | |||
+ description "Subtract unit from metric"; | |||
+ type boolean; | |||
+ } | |||
+ } | |||
+ case use-round-trip-time { | |||
+ leaf use-round-trip-time { | |||
+ description "Use the round trip time as metric"; | |||
+ type boolean; | |||
+ } | |||
+ } | |||
+ case add-round-trip-time { | |||
+ leaf add-round-trip-time { | |||
+ description "Add round trip time to metric"; | |||
+ type boolean; | |||
+ } | |||
+ } | |||
+ case subtract-round-trip-time { | |||
+ leaf subtract-round-trip-time { | |||
+ description "Subtract round trip time to metric"; | |||
+ type boolean; | |||
+ } | |||
+ } | |||
+ } | |||
+ } | |||
+ case tag { | |||
+ when "./action = 'tag'"; | |||
+ leaf tag { | |||
+ description "Tag value"; | |||
+ type uint32 { | |||
+ range "0..4294967295"; | |||
+ } | |||
+ } | |||
+ } | |||
+ } | |||
+ } | |||
+ } | |||
+ } | |||
+ } | |||
+} |
@ -1,83 +0,0 @@ | |||
From bec0aa85b1f404ac9800c7524070fcf8582e82bc Mon Sep 17 00:00:00 2001 | |||
From: Rafael Zalamena <rzalamena@opensourcerouting.org> | |||
Date: Thu, 1 Aug 2019 19:56:46 -0300 | |||
Subject: [PATCH] yang: simplify filter choice by removing cases | |||
Based on @rwestphal feedback, lets remove `case`s where we don't expect | |||
to add more items or items with more than one `leaf`. | |||
Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org> | |||
--- | |||
yang/frr-filter.yang | 48 +++++++++++++++++--------------------------- | |||
1 file changed, 18 insertions(+), 30 deletions(-) | |||
diff --git a/yang/frr-filter.yang b/yang/frr-filter.yang | |||
index 92af6aebfd..e79ede87b7 100644 | |||
--- a/yang/frr-filter.yang | |||
+++ b/yang/frr-filter.yang | |||
@@ -107,23 +107,17 @@ module frr-filter { | |||
Extended access list: source value to match."; | |||
mandatory true; | |||
- case host { | |||
- leaf host { | |||
- description "Host to match"; | |||
- type inet:ipv4-address; | |||
- } | |||
+ leaf host { | |||
+ description "Host to match"; | |||
+ type inet:ipv4-address; | |||
} | |||
- case network { | |||
- leaf network { | |||
- description "Network to match"; | |||
- type inet:ipv4-prefix; | |||
- } | |||
+ leaf network { | |||
+ description "Network to match"; | |||
+ type inet:ipv4-prefix; | |||
} | |||
- case any { | |||
- leaf any { | |||
- description "Match any"; | |||
- type empty; | |||
- } | |||
+ leaf any { | |||
+ description "Match any"; | |||
+ type empty; | |||
} | |||
} | |||
@@ -132,23 +126,17 @@ module frr-filter { | |||
./sequence >= 2000 and ./sequence <= 2699"; | |||
description "Destination value to match"; | |||
- case destination-host { | |||
- leaf destination-host { | |||
- description "Host to match"; | |||
- type inet:ipv4-address; | |||
- } | |||
+ leaf destination-host { | |||
+ description "Host to match"; | |||
+ type inet:ipv4-address; | |||
} | |||
- case destination-network { | |||
- leaf destination-network { | |||
- description "Network to match"; | |||
- type inet:ipv4-prefix; | |||
- } | |||
+ leaf destination-network { | |||
+ description "Network to match"; | |||
+ type inet:ipv4-prefix; | |||
} | |||
- case destination-any { | |||
- leaf destination-any { | |||
- description "Match any"; | |||
- type empty; | |||
- } | |||
+ leaf destination-any { | |||
+ description "Match any"; | |||
+ type empty; | |||
} | |||
} | |||
} |
@ -1,147 +0,0 @@ | |||
From dc397e4c0adc13982fc5d83a1afc42178708f4a5 Mon Sep 17 00:00:00 2001 | |||
From: Renato Westphal <renato@opensourcerouting.org> | |||
Date: Fri, 3 Apr 2020 20:10:04 -0300 | |||
Subject: [PATCH] lib: consolidate flexible array hack in a single place | |||
Old gcc versions (< 5.x) have a bug that prevents C99 flexible | |||
arrays from working properly on shared libraries. | |||
We already have a hack in place to work around this problem, but it | |||
needs to be replicated in every declaration of a frr_yang_module_info | |||
variable within libfrr. This clearly isn't a good solution if we | |||
consider that many more libfrr YANG modules are about to come in | |||
the future. | |||
This commit introduces a different workaround that operates within | |||
the northbound layer itself, such that implementers of libfrr YANG | |||
modules won't need to worry about this problem anymore. | |||
Signed-off-by: Renato Westphal <renato@opensourcerouting.org> | |||
--- | |||
lib/if.c | 24 ------------------------ | |||
lib/northbound.c | 7 +++++++ | |||
lib/northbound.h | 11 +++++++++++ | |||
lib/routemap_northbound.c | 25 ------------------------- | |||
4 files changed, 18 insertions(+), 49 deletions(-) | |||
diff --git a/lib/if.c b/lib/if.c | |||
index dabf66799d..24b103b3ff 100644 | |||
--- a/lib/if.c | |||
+++ b/lib/if.c | |||
@@ -1657,31 +1657,7 @@ static int lib_interface_description_destroy(enum nb_event event, | |||
/* clang-format off */ | |||
-#if defined(__GNUC__) && ((__GNUC__ - 0) < 5) && !defined(__clang__) | |||
-/* gcc versions before 5.x miscalculate the size for structs with variable | |||
- * length arrays (they just count it as size 0) | |||
- */ | |||
-struct frr_yang_module_info_size3 { | |||
- /* YANG module name. */ | |||
- const char *name; | |||
- | |||
- /* Northbound callbacks. */ | |||
- const struct { | |||
- /* Data path of this YANG node. */ | |||
- const char *xpath; | |||
- | |||
- /* Callbacks implemented for this node. */ | |||
- struct nb_callbacks cbs; | |||
- | |||
- /* Priority - lower priorities are processed first. */ | |||
- uint32_t priority; | |||
- } nodes[3]; | |||
-}; | |||
- | |||
-const struct frr_yang_module_info_size3 frr_interface_info_size3 asm("frr_interface_info") = { | |||
-#else | |||
const struct frr_yang_module_info frr_interface_info = { | |||
-#endif | |||
.name = "frr-interface", | |||
.nodes = { | |||
{ | |||
diff --git a/lib/northbound.c b/lib/northbound.c | |||
index cebedcff09..85e723d7cf 100644 | |||
--- a/lib/northbound.c | |||
+++ b/lib/northbound.c | |||
@@ -1866,6 +1866,13 @@ static void nb_load_callbacks(const struct frr_yang_module_info *module) | |||
struct nb_node *nb_node; | |||
uint32_t priority; | |||
+ if (i > YANG_MODULE_MAX_NODES) { | |||
+ zlog_err( | |||
+ "%s: %s.yang has more than %u nodes. Please increase YANG_MODULE_MAX_NODES to fix this problem.", | |||
+ __func__, module->name, YANG_MODULE_MAX_NODES); | |||
+ exit(1); | |||
+ } | |||
+ | |||
nb_node = nb_node_find(module->nodes[i].xpath); | |||
if (!nb_node) { | |||
flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH, | |||
diff --git a/lib/northbound.h b/lib/northbound.h | |||
index 76a11e518c..19a2ba0865 100644 | |||
--- a/lib/northbound.h | |||
+++ b/lib/northbound.h | |||
@@ -403,6 +403,13 @@ struct nb_node { | |||
/* The YANG list doesn't contain key leafs. */ | |||
#define F_NB_NODE_KEYLESS_LIST 0x02 | |||
+/* | |||
+ * HACK: old gcc versions (< 5.x) have a bug that prevents C99 flexible arrays | |||
+ * from working properly on shared libraries. For those compilers, use a fixed | |||
+ * size array to work around the problem. | |||
+ */ | |||
+#define YANG_MODULE_MAX_NODES 1024 | |||
+ | |||
struct frr_yang_module_info { | |||
/* YANG module name. */ | |||
const char *name; | |||
@@ -417,7 +424,11 @@ struct frr_yang_module_info { | |||
/* Priority - lower priorities are processed first. */ | |||
uint32_t priority; | |||
+#if defined(__GNUC__) && ((__GNUC__ - 0) < 5) && !defined(__clang__) | |||
+ } nodes[YANG_MODULE_MAX_NODES + 1]; | |||
+#else | |||
} nodes[]; | |||
+#endif | |||
}; | |||
/* Northbound error codes. */ | |||
diff --git a/lib/routemap_northbound.c b/lib/routemap_northbound.c | |||
index 69cebbd2a1..dd4cbd7d99 100644 | |||
--- a/lib/routemap_northbound.c | |||
+++ b/lib/routemap_northbound.c | |||
@@ -1221,32 +1221,7 @@ lib_route_map_entry_set_action_tag_destroy(enum nb_event event, | |||
} | |||
/* clang-format off */ | |||
-#if defined(__GNUC__) && ((__GNUC__ - 0) < 5) && !defined(__clang__) | |||
-/* | |||
- * gcc versions before 5.x miscalculate the size for structs with variable | |||
- * length arrays (they just count it as size 0) | |||
- */ | |||
-struct frr_yang_module_info_sizen { | |||
- /* YANG module name. */ | |||
- const char *name; | |||
- | |||
- /* Northbound callbacks. */ | |||
- const struct { | |||
- /* Data path of this YANG node. */ | |||
- const char *xpath; | |||
- | |||
- /* Callbacks implemented for this node. */ | |||
- struct nb_callbacks cbs; | |||
- | |||
- /* Priority - lower priorities are processed first. */ | |||
- uint32_t priority; | |||
- } nodes[28]; | |||
-}; | |||
- | |||
-const struct frr_yang_module_info_sizen frr_route_map_info_sizen asm("frr_route_map_info") = { | |||
-#else | |||
const struct frr_yang_module_info frr_route_map_info = { | |||
-#endif | |||
.name = "frr-route-map", | |||
.nodes = { | |||
{ |
@ -1,330 +0,0 @@ | |||
From 97cd849362b45ecbcb20194b5771c5ce777de6bc Mon Sep 17 00:00:00 2001 | |||
From: Renato Westphal <renato@opensourcerouting.org> | |||
Date: Tue, 21 Apr 2020 21:27:47 -0300 | |||
Subject: [PATCH] lib: create a wrapper function for all northbound callbacks | |||
The intention here is to keep the code more organized. These wrappers | |||
should be used by the northbound clients only, and never directly | |||
by any YANG backend code. | |||
Signed-off-by: Renato Westphal <renato@opensourcerouting.org> | |||
--- | |||
lib/northbound.c | 222 +++++++++++++++++++++++----------------- | |||
lib/northbound_grpc.cpp | 3 +- | |||
2 files changed, 131 insertions(+), 94 deletions(-) | |||
diff --git a/lib/northbound.c b/lib/northbound.c | |||
index 85e723d7cf..d10e4713f5 100644 | |||
--- a/lib/northbound.c | |||
+++ b/lib/northbound.c | |||
@@ -62,11 +62,10 @@ static struct { | |||
*/ | |||
static bool transaction_in_progress; | |||
+static int nb_callback_pre_validate(const struct nb_node *nb_node, | |||
+ const struct lyd_node *dnode); | |||
static int nb_callback_configuration(const enum nb_event event, | |||
struct nb_config_change *change); | |||
-static void nb_log_callback(const enum nb_event event, | |||
- enum nb_operation operation, const char *xpath, | |||
- const char *value); | |||
static struct nb_transaction *nb_transaction_new(struct nb_config *config, | |||
struct nb_config_cbs *changes, | |||
enum nb_client client, | |||
@@ -609,18 +608,7 @@ static int nb_candidate_validate_code(struct nb_config *candidate, | |||
if (!nb_node->cbs.pre_validate) | |||
goto next; | |||
- if (DEBUG_MODE_CHECK(&nb_dbg_cbs_config, | |||
- DEBUG_MODE_ALL)) { | |||
- char xpath[XPATH_MAXLEN]; | |||
- | |||
- yang_dnode_get_path(child, xpath, | |||
- sizeof(xpath)); | |||
- nb_log_callback(NB_EV_VALIDATE, | |||
- NB_OP_PRE_VALIDATE, xpath, | |||
- NULL); | |||
- } | |||
- | |||
- ret = (*nb_node->cbs.pre_validate)(child); | |||
+ ret = nb_callback_pre_validate(nb_node, child); | |||
if (ret != NB_OK) | |||
return NB_ERR_VALIDATION; | |||
@@ -791,14 +779,128 @@ int nb_running_lock_check(enum nb_client client, const void *user) | |||
return ret; | |||
} | |||
-static void nb_log_callback(const enum nb_event event, | |||
- enum nb_operation operation, const char *xpath, | |||
- const char *value) | |||
+static void nb_log_config_callback(const enum nb_event event, | |||
+ enum nb_operation operation, | |||
+ const struct lyd_node *dnode) | |||
{ | |||
+ const char *value; | |||
+ char xpath[XPATH_MAXLEN]; | |||
+ | |||
+ if (!DEBUG_MODE_CHECK(&nb_dbg_cbs_config, DEBUG_MODE_ALL)) | |||
+ return; | |||
+ | |||
+ yang_dnode_get_path(dnode, xpath, sizeof(xpath)); | |||
+ if (yang_snode_is_typeless_data(dnode->schema)) | |||
+ value = "(none)"; | |||
+ else | |||
+ value = yang_dnode_get_string(dnode, NULL); | |||
+ | |||
zlog_debug( | |||
"northbound callback: event [%s] op [%s] xpath [%s] value [%s]", | |||
nb_event_name(event), nb_operation_name(operation), xpath, | |||
- value ? value : "(NULL)"); | |||
+ value); | |||
+} | |||
+ | |||
+static int nb_callback_create(const struct nb_node *nb_node, | |||
+ enum nb_event event, const struct lyd_node *dnode, | |||
+ union nb_resource *resource) | |||
+{ | |||
+ nb_log_config_callback(event, NB_OP_CREATE, dnode); | |||
+ | |||
+ return nb_node->cbs.create(event, dnode, resource); | |||
+} | |||
+ | |||
+static int nb_callback_modify(const struct nb_node *nb_node, | |||
+ enum nb_event event, const struct lyd_node *dnode, | |||
+ union nb_resource *resource) | |||
+{ | |||
+ nb_log_config_callback(event, NB_OP_MODIFY, dnode); | |||
+ | |||
+ return nb_node->cbs.modify(event, dnode, resource); | |||
+} | |||
+ | |||
+static int nb_callback_destroy(const struct nb_node *nb_node, | |||
+ enum nb_event event, | |||
+ const struct lyd_node *dnode) | |||
+{ | |||
+ nb_log_config_callback(event, NB_OP_DESTROY, dnode); | |||
+ | |||
+ return nb_node->cbs.destroy(event, dnode); | |||
+} | |||
+ | |||
+static int nb_callback_move(const struct nb_node *nb_node, enum nb_event event, | |||
+ const struct lyd_node *dnode) | |||
+{ | |||
+ nb_log_config_callback(event, NB_OP_MOVE, dnode); | |||
+ | |||
+ return nb_node->cbs.move(event, dnode); | |||
+} | |||
+ | |||
+static int nb_callback_pre_validate(const struct nb_node *nb_node, | |||
+ const struct lyd_node *dnode) | |||
+{ | |||
+ nb_log_config_callback(NB_EV_VALIDATE, NB_OP_PRE_VALIDATE, dnode); | |||
+ | |||
+ return nb_node->cbs.pre_validate(dnode); | |||
+} | |||
+ | |||
+static void nb_callback_apply_finish(const struct nb_node *nb_node, | |||
+ const struct lyd_node *dnode) | |||
+{ | |||
+ nb_log_config_callback(NB_EV_APPLY, NB_OP_APPLY_FINISH, dnode); | |||
+ | |||
+ nb_node->cbs.apply_finish(dnode); | |||
+} | |||
+ | |||
+struct yang_data *nb_callback_get_elem(const struct nb_node *nb_node, | |||
+ const char *xpath, | |||
+ const void *list_entry) | |||
+{ | |||
+ DEBUGD(&nb_dbg_cbs_state, | |||
+ "northbound callback (get_elem): xpath [%s] list_entry [%p]", | |||
+ xpath, list_entry); | |||
+ | |||
+ return nb_node->cbs.get_elem(xpath, list_entry); | |||
+} | |||
+ | |||
+const void *nb_callback_get_next(const struct nb_node *nb_node, | |||
+ const void *parent_list_entry, | |||
+ const void *list_entry) | |||
+{ | |||
+ DEBUGD(&nb_dbg_cbs_state, | |||
+ "northbound callback (get_next): node [%s] parent_list_entry [%p] list_entry [%p]", | |||
+ nb_node->xpath, parent_list_entry, list_entry); | |||
+ | |||
+ return nb_node->cbs.get_next(parent_list_entry, list_entry); | |||
+} | |||
+ | |||
+int nb_callback_get_keys(const struct nb_node *nb_node, const void *list_entry, | |||
+ struct yang_list_keys *keys) | |||
+{ | |||
+ DEBUGD(&nb_dbg_cbs_state, | |||
+ "northbound callback (get_keys): node [%s] list_entry [%p]", | |||
+ nb_node->xpath, list_entry); | |||
+ | |||
+ return nb_node->cbs.get_keys(list_entry, keys); | |||
+} | |||
+ | |||
+const void *nb_callback_lookup_entry(const struct nb_node *nb_node, | |||
+ const void *parent_list_entry, | |||
+ const struct yang_list_keys *keys) | |||
+{ | |||
+ DEBUGD(&nb_dbg_cbs_state, | |||
+ "northbound callback (lookup_entry): node [%s] parent_list_entry [%p]", | |||
+ nb_node->xpath, parent_list_entry); | |||
+ | |||
+ return nb_node->cbs.lookup_entry(parent_list_entry, keys); | |||
+} | |||
+ | |||
+int nb_callback_rpc(const struct nb_node *nb_node, const char *xpath, | |||
+ const struct list *input, struct list *output) | |||
+{ | |||
+ DEBUGD(&nb_dbg_cbs_rpc, "northbound RPC: %s", xpath); | |||
+ | |||
+ return nb_node->cbs.rpc(xpath, input, output); | |||
} | |||
/* | |||
@@ -815,15 +917,6 @@ static int nb_callback_configuration(const enum nb_event event, | |||
union nb_resource *resource; | |||
int ret = NB_ERR; | |||
- if (DEBUG_MODE_CHECK(&nb_dbg_cbs_config, DEBUG_MODE_ALL)) { | |||
- const char *value = "(none)"; | |||
- | |||
- if (dnode && !yang_snode_is_typeless_data(dnode->schema)) | |||
- value = yang_dnode_get_string(dnode, NULL); | |||
- | |||
- yang_dnode_get_path(dnode, xpath, sizeof(xpath)); | |||
- nb_log_callback(event, operation, xpath, value); | |||
- } | |||
if (event == NB_EV_VALIDATE) | |||
resource = NULL; | |||
@@ -832,16 +925,16 @@ static int nb_callback_configuration(const enum nb_event event, | |||
switch (operation) { | |||
case NB_OP_CREATE: | |||
- ret = (*nb_node->cbs.create)(event, dnode, resource); | |||
+ ret = nb_callback_create(nb_node, event, dnode, resource); | |||
break; | |||
case NB_OP_MODIFY: | |||
- ret = (*nb_node->cbs.modify)(event, dnode, resource); | |||
+ ret = nb_callback_modify(nb_node, event, dnode, resource); | |||
break; | |||
case NB_OP_DESTROY: | |||
- ret = (*nb_node->cbs.destroy)(event, dnode); | |||
+ ret = nb_callback_destroy(nb_node, event, dnode); | |||
break; | |||
case NB_OP_MOVE: | |||
- ret = (*nb_node->cbs.move)(event, dnode); | |||
+ ret = nb_callback_move(nb_node, event, dnode); | |||
break; | |||
default: | |||
yang_dnode_get_path(dnode, xpath, sizeof(xpath)); | |||
@@ -890,57 +983,6 @@ static int nb_callback_configuration(const enum nb_event event, | |||
return ret; | |||
} | |||
-struct yang_data *nb_callback_get_elem(const struct nb_node *nb_node, | |||
- const char *xpath, | |||
- const void *list_entry) | |||
-{ | |||
- DEBUGD(&nb_dbg_cbs_state, | |||
- "northbound callback (get_elem): xpath [%s] list_entry [%p]", | |||
- xpath, list_entry); | |||
- | |||
- return nb_node->cbs.get_elem(xpath, list_entry); | |||
-} | |||
- | |||
-const void *nb_callback_get_next(const struct nb_node *nb_node, | |||
- const void *parent_list_entry, | |||
- const void *list_entry) | |||
-{ | |||
- DEBUGD(&nb_dbg_cbs_state, | |||
- "northbound callback (get_next): node [%s] parent_list_entry [%p] list_entry [%p]", | |||
- nb_node->xpath, parent_list_entry, list_entry); | |||
- | |||
- return nb_node->cbs.get_next(parent_list_entry, list_entry); | |||
-} | |||
- | |||
-int nb_callback_get_keys(const struct nb_node *nb_node, const void *list_entry, | |||
- struct yang_list_keys *keys) | |||
-{ | |||
- DEBUGD(&nb_dbg_cbs_state, | |||
- "northbound callback (get_keys): node [%s] list_entry [%p]", | |||
- nb_node->xpath, list_entry); | |||
- | |||
- return nb_node->cbs.get_keys(list_entry, keys); | |||
-} | |||
- | |||
-const void *nb_callback_lookup_entry(const struct nb_node *nb_node, | |||
- const void *parent_list_entry, | |||
- const struct yang_list_keys *keys) | |||
-{ | |||
- DEBUGD(&nb_dbg_cbs_state, | |||
- "northbound callback (lookup_entry): node [%s] parent_list_entry [%p]", | |||
- nb_node->xpath, parent_list_entry); | |||
- | |||
- return nb_node->cbs.lookup_entry(parent_list_entry, keys); | |||
-} | |||
- | |||
-int nb_callback_rpc(const struct nb_node *nb_node, const char *xpath, | |||
- const struct list *input, struct list *output) | |||
-{ | |||
- DEBUGD(&nb_dbg_cbs_rpc, "northbound RPC: %s", xpath); | |||
- | |||
- return nb_node->cbs.rpc(xpath, input, output); | |||
-} | |||
- | |||
static struct nb_transaction * | |||
nb_transaction_new(struct nb_config *config, struct nb_config_cbs *changes, | |||
enum nb_client client, const void *user, const char *comment) | |||
@@ -1058,7 +1100,6 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction) | |||
{ | |||
struct nb_config_cbs cbs; | |||
struct nb_config_cb *cb; | |||
- char xpath[XPATH_MAXLEN]; | |||
/* Initialize tree of 'apply_finish' callbacks. */ | |||
RB_INIT(nb_config_cbs, &cbs); | |||
@@ -1075,6 +1116,8 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction) | |||
* be called though). | |||
*/ | |||
if (change->cb.operation == NB_OP_DESTROY) { | |||
+ char xpath[XPATH_MAXLEN]; | |||
+ | |||
dnode = dnode->parent; | |||
if (!dnode) | |||
break; | |||
@@ -1111,15 +1154,8 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction) | |||
} | |||
/* Call the 'apply_finish' callbacks, sorted by their priorities. */ | |||
- RB_FOREACH (cb, nb_config_cbs, &cbs) { | |||
- if (DEBUG_MODE_CHECK(&nb_dbg_cbs_config, DEBUG_MODE_ALL)) { | |||
- yang_dnode_get_path(cb->dnode, xpath, sizeof(xpath)); | |||
- nb_log_callback(NB_EV_APPLY, NB_OP_APPLY_FINISH, xpath, | |||
- NULL); | |||
- } | |||
- | |||
- (*cb->nb_node->cbs.apply_finish)(cb->dnode); | |||
- } | |||
+ RB_FOREACH (cb, nb_config_cbs, &cbs) | |||
+ nb_callback_apply_finish(cb->nb_node, cb->dnode); | |||
/* Release memory. */ | |||
while (!RB_EMPTY(nb_config_cbs, &cbs)) { | |||
diff --git a/lib/northbound_grpc.cpp b/lib/northbound_grpc.cpp | |||
index b195f1aeca..66bf05c1ab 100644 | |||
--- a/lib/northbound_grpc.cpp | |||
+++ b/lib/northbound_grpc.cpp | |||
@@ -545,7 +545,8 @@ class NorthboundImpl final : public frr::Northbound::Service | |||
} | |||
// Execute callback registered for this XPath. | |||
- if (nb_node->cbs.rpc(xpath, input_list, output_list) != NB_OK) { | |||
+ if (nb_callback_rpc(nb_node, xpath, input_list, output_list) | |||
+ != NB_OK) { | |||
flog_warn(EC_LIB_NB_CB_RPC, | |||
"%s: rpc callback failed: %s", __func__, | |||
xpath); |
@ -1,14 +0,0 @@ | |||
--- a/lib/northbound.h | |||
+++ b/lib/northbound.h | |||
@@ -504,11 +504,7 @@ struct frr_yang_module_info { | |||
/* Priority - lower priorities are processed first. */ | |||
uint32_t priority; | |||
-#if defined(__GNUC__) && ((__GNUC__ - 0) < 5) && !defined(__clang__) | |||
} nodes[YANG_MODULE_MAX_NODES + 1]; | |||
-#else | |||
- } nodes[]; | |||
-#endif | |||
}; | |||
/* Northbound error codes. */ |