summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build-test-docker.yml10
-rw-r--r--bgpd/bgp_advertise.c8
-rw-r--r--bgpd/bgp_advertise.h9
-rw-r--r--bgpd/bgp_attr.c6
-rw-r--r--bgpd/bgp_attr.h6
-rw-r--r--bgpd/bgp_bmp.c26
-rw-r--r--bgpd/bgp_debug.c2
-rw-r--r--bgpd/bgp_debug.h2
-rw-r--r--bgpd/bgp_evpn.c72
-rw-r--r--bgpd/bgp_evpn.h6
-rw-r--r--bgpd/bgp_evpn_mh.c18
-rw-r--r--bgpd/bgp_label.c127
-rw-r--r--bgpd/bgp_label.h24
-rw-r--r--bgpd/bgp_mac.c12
-rw-r--r--bgpd/bgp_main.c3
-rw-r--r--bgpd/bgp_memory.c2
-rw-r--r--bgpd/bgp_memory.h2
-rw-r--r--bgpd/bgp_mplsvpn.c106
-rw-r--r--bgpd/bgp_nht.c12
-rw-r--r--bgpd/bgp_route.c205
-rw-r--r--bgpd/bgp_route.h16
-rw-r--r--bgpd/bgp_routemap.c11
-rw-r--r--bgpd/bgp_rpki.c12
-rw-r--r--bgpd/bgp_updgrp_adv.c10
-rw-r--r--bgpd/bgp_updgrp_packet.c13
-rw-r--r--bgpd/bgp_zebra.c25
-rw-r--r--bgpd/bgp_zebra.h2
-rw-r--r--bgpd/bgpd.c6
-rw-r--r--bgpd/rfapi/rfapi.c8
-rw-r--r--bgpd/rfapi/rfapi_import.c20
-rw-r--r--bgpd/rfapi/rfapi_rib.c5
-rw-r--r--bgpd/rfapi/rfapi_vty.c14
-rw-r--r--bgpd/rfapi/vnc_import_bgp.c127
-rw-r--r--doc/user/bgp.rst4
-rw-r--r--docker/debian/Dockerfile2
-rw-r--r--isisd/isis_lsp.c19
-rw-r--r--isisd/isis_tlvs.c1030
-rw-r--r--isisd/isisd.c15
-rw-r--r--lib/ipaddr.h13
-rw-r--r--lib/prefix.c15
-rw-r--r--lib/prefix.h10
-rw-r--r--lib/stream.c2
-rw-r--r--lib/stream.h2
-rw-r--r--lib/vty.c15
-rw-r--r--lib/vty.h2
-rw-r--r--nhrpd/nhrp_main.c4
-rw-r--r--nhrpd/nhrp_shortcut.c12
-rw-r--r--ospf6d/ospf6_auth_trailer.c9
-rw-r--r--tests/bgpd/test_mp_attr.c2
-rw-r--r--tests/bgpd/test_peer_attr.c2
-rw-r--r--tests/lib/test_printfrr.c12
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_vpn_route_1723101.json50
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py168
-rw-r--r--tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py15
-rw-r--r--tests/topotests/isis_topo1/test_isis_topo1.py2
-rw-r--r--tests/topotests/munet/__main__.py24
-rw-r--r--tests/topotests/munet/base.py60
-rw-r--r--tests/topotests/munet/cleanup.py34
-rw-r--r--tests/topotests/munet/cli.py12
-rw-r--r--tests/topotests/munet/logconf-mutest.yaml5
-rw-r--r--tests/topotests/munet/mucmd.py4
-rw-r--r--tests/topotests/munet/mulog.py26
-rw-r--r--tests/topotests/munet/munet-schema.json9
-rw-r--r--tests/topotests/munet/mutest/__main__.py15
-rw-r--r--tests/topotests/munet/mutest/userapi.py8
-rw-r--r--tests/topotests/munet/native.py216
-rw-r--r--tests/topotests/munet/testing/fixtures.py24
-rw-r--r--tests/topotests/munet/watchlog.py1
-rw-r--r--tests/topotests/ospfv3_basic_functionality/test_ospfv3_authentication.py131
-rw-r--r--zebra/dplane_fpm_nl.c16
-rw-r--r--zebra/zebra_evpn_mh.c2
-rw-r--r--zebra/zebra_netns_notify.c15
-rw-r--r--zebra/zebra_srv6_vty.c12
-rw-r--r--zebra/zebra_vty.c99
-rw-r--r--zebra/zebra_vxlan.c81
75 files changed, 2422 insertions, 704 deletions
diff --git a/.github/workflows/build-test-docker.yml b/.github/workflows/build-test-docker.yml
index de9f620c9..3f53f32d3 100644
--- a/.github/workflows/build-test-docker.yml
+++ b/.github/workflows/build-test-docker.yml
@@ -68,11 +68,13 @@ jobs:
- name: Run topotests
run: |
uname -a
- sudo apt-get install -y linux-modules-extra-azure || true
- sudo apt-get install -y python3-xmltodict || true
+ MODPKGVER=$(uname -r)
+ sudo apt-get update -y
+ # Github is running old kernels but installing newer packages :(
+ sudo apt-get install -y linux-modules-extra-azure linux-modules-${MODPKGVER} linux-modules-extra-${MODPKGVER} python3-xmltodict
sudo modprobe vrf || true
- sudo modprobe mpls-iptunnel || true
- sudo modprobe mpls-router || true
+ sudo modprobe mpls-iptunnel
+ sudo modprobe mpls-router
docker load --input /tmp/frr-ubuntu22.tar
if ! grep CONFIG_IP_MROUTE_MULTIPLE_TABLES=y /boot/config*; then
diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c
index d519749f6..d5c7e1887 100644
--- a/bgpd/bgp_advertise.c
+++ b/bgpd/bgp_advertise.c
@@ -163,7 +163,7 @@ bool bgp_adj_out_lookup(struct peer *peer, struct bgp_dest *dest,
void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr,
- uint32_t addpath_id)
+ uint32_t addpath_id, struct bgp_labels *labels)
{
struct bgp_adj_in *adj;
@@ -173,6 +173,10 @@ void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr,
bgp_attr_unintern(&adj->attr);
adj->attr = bgp_attr_intern(attr);
}
+ if (!bgp_labels_cmp(adj->labels, labels)) {
+ bgp_labels_unintern(&adj->labels);
+ adj->labels = bgp_labels_intern(labels);
+ }
return;
}
}
@@ -181,6 +185,7 @@ void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr,
adj->attr = bgp_attr_intern(attr);
adj->uptime = monotime(NULL);
adj->addpath_rx_id = addpath_id;
+ adj->labels = bgp_labels_intern(labels);
BGP_ADJ_IN_ADD(dest, adj);
peer->stat_pfx_adj_rib_in++;
bgp_dest_lock_node(dest);
@@ -189,6 +194,7 @@ void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr,
void bgp_adj_in_remove(struct bgp_dest **dest, struct bgp_adj_in *bai)
{
bgp_attr_unintern(&bai->attr);
+ bgp_labels_unintern(&bai->labels);
if (bai->peer)
bai->peer->stat_pfx_adj_rib_in--;
BGP_ADJ_IN_DEL(*dest, bai);
diff --git a/bgpd/bgp_advertise.h b/bgpd/bgp_advertise.h
index 49821061b..8c831892b 100644
--- a/bgpd/bgp_advertise.h
+++ b/bgpd/bgp_advertise.h
@@ -75,6 +75,9 @@ struct bgp_adj_out {
/* Advertised attribute. */
struct attr *attr;
+ /* VPN label information */
+ struct bgp_labels *labels;
+
/* Advertisement information. */
struct bgp_advertise *adv;
};
@@ -95,6 +98,9 @@ struct bgp_adj_in {
/* Received attribute. */
struct attr *attr;
+ /* VPN label information */
+ struct bgp_labels *labels;
+
/* timestamp (monotime) */
time_t uptime;
@@ -135,7 +141,8 @@ struct bgp_synchronize {
extern bool bgp_adj_out_lookup(struct peer *peer, struct bgp_dest *dest,
uint32_t addpath_tx_id);
extern void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer,
- struct attr *attr, uint32_t addpath_id);
+ struct attr *attr, uint32_t addpath_id,
+ struct bgp_labels *labels);
extern bool bgp_adj_in_unset(struct bgp_dest **dest, struct peer *peer,
uint32_t addpath_id);
extern void bgp_adj_in_remove(struct bgp_dest **dest, struct bgp_adj_in *bai);
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 71f02a7f8..da4701d06 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -4158,7 +4158,7 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
const struct prefix *p,
const struct prefix_rd *prd, mpls_label_t *label,
- uint32_t num_labels, bool addpath_capable,
+ uint8_t num_labels, bool addpath_capable,
uint32_t addpath_tx_id, struct attr *attr)
{
switch (safi) {
@@ -4434,7 +4434,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
struct bpacket_attr_vec_arr *vecarr,
struct prefix *p, afi_t afi, safi_t safi,
struct peer *from, struct prefix_rd *prd,
- mpls_label_t *label, uint32_t num_labels,
+ mpls_label_t *label, uint8_t num_labels,
bool addpath_capable, uint32_t addpath_tx_id,
struct bgp_path_info *bpi)
{
@@ -4963,7 +4963,7 @@ size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi, safi_t safi)
void bgp_packet_mpunreach_prefix(struct stream *s, const struct prefix *p,
afi_t afi, safi_t safi,
const struct prefix_rd *prd,
- mpls_label_t *label, uint32_t num_labels,
+ mpls_label_t *label, uint8_t num_labels,
bool addpath_capable, uint32_t addpath_tx_id,
struct attr *attr)
{
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index a8ba36d2d..f353e7691 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -393,7 +393,7 @@ extern bgp_size_t bgp_packet_attribute(
struct bgp *bgp, struct peer *peer, struct stream *s, struct attr *attr,
struct bpacket_attr_vec_arr *vecarr, struct prefix *p, afi_t afi,
safi_t safi, struct peer *from, struct prefix_rd *prd,
- mpls_label_t *label, uint32_t num_labels, bool addpath_capable,
+ mpls_label_t *label, uint8_t num_labels, bool addpath_capable,
uint32_t addpath_tx_id, struct bgp_path_info *bpi);
extern void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
const struct prefix *p);
@@ -451,7 +451,7 @@ extern size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer,
extern void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
const struct prefix *p,
const struct prefix_rd *prd,
- mpls_label_t *label, uint32_t num_labels,
+ mpls_label_t *label, uint8_t num_labels,
bool addpath_capable,
uint32_t addpath_tx_id, struct attr *);
extern size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi,
@@ -462,7 +462,7 @@ extern size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi,
safi_t safi);
extern void bgp_packet_mpunreach_prefix(
struct stream *s, const struct prefix *p, afi_t afi, safi_t safi,
- const struct prefix_rd *prd, mpls_label_t *label, uint32_t num_labels,
+ const struct prefix_rd *prd, mpls_label_t *label, uint8_t num_labels,
bool addpath_capable, uint32_t addpath_tx_id, struct attr *attr);
extern void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt);
diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c
index bf08e3050..43f8006e2 100644
--- a/bgpd/bgp_bmp.c
+++ b/bgpd/bgp_bmp.c
@@ -38,6 +38,7 @@
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_trace.h"
#include "bgpd/bgp_network.h"
+#include "bgpd/bgp_label.h"
static void bmp_close(struct bmp *bmp);
static struct bmp_bgp *bmp_bgp_find(struct bgp *bgp);
@@ -1046,6 +1047,7 @@ static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags,
static bool bmp_wrsync(struct bmp *bmp, struct pullwr *pullwr)
{
+ uint8_t bpi_num_labels;
afi_t afi;
safi_t safi;
@@ -1219,14 +1221,16 @@ afibreak:
(safi == SAFI_MPLS_VPN))
prd = (struct prefix_rd *)bgp_dest_get_prefix(bmp->syncrdpos);
+ bpi_num_labels = bgp_path_info_num_labels(bpi);
+
if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_SELECTED) &&
CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_LOC_RIB)) {
bmp_monitor(bmp, bpi->peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE,
bn_p, prd, bpi->attr, afi, safi,
bpi && bpi->extra ? bpi->extra->bgp_rib_uptime
: (time_t)(-1L),
- bpi->extra ? bpi->extra->label : NULL,
- bpi->extra ? bpi->extra->num_labels : 0);
+ bpi_num_labels ? bpi->extra->labels->label : NULL,
+ bpi_num_labels);
}
if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_VALID) &&
@@ -1234,8 +1238,8 @@ afibreak:
bmp_monitor(bmp, bpi->peer, BMP_PEER_FLAG_L,
BMP_PEER_TYPE_GLOBAL_INSTANCE, bn_p, prd, bpi->attr,
afi, safi, bpi->uptime,
- bpi->extra ? bpi->extra->label : NULL,
- bpi->extra ? bpi->extra->num_labels : 0);
+ bpi_num_labels ? bpi->extra->labels->label : NULL,
+ bpi_num_labels);
if (adjin)
/* TODO: set label here when adjin supports labels */
@@ -1292,6 +1296,7 @@ static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr)
struct peer *peer;
struct bgp_dest *bn = NULL;
bool written = false;
+ uint8_t bpi_num_labels;
bqe = bmp_pull_locrib(bmp);
if (!bqe)
@@ -1351,12 +1356,14 @@ static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr)
break;
}
+ bpi_num_labels = bgp_path_info_num_labels(bpi);
+
bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE, &bqe->p, prd,
bpi ? bpi->attr : NULL, afi, safi,
bpi && bpi->extra ? bpi->extra->bgp_rib_uptime
: (time_t)(-1L),
- (bpi && bpi->extra) ? bpi->extra->label : NULL,
- (bpi && bpi->extra) ? bpi->extra->num_labels : 0);
+ bpi_num_labels ? bpi->extra->labels->label : NULL,
+ bpi_num_labels);
written = true;
out:
@@ -1375,6 +1382,7 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
struct peer *peer;
struct bgp_dest *bn = NULL;
bool written = false;
+ uint8_t bpi_num_labels;
bqe = bmp_pull(bmp);
if (!bqe)
@@ -1426,12 +1434,14 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
break;
}
+ bpi_num_labels = bgp_path_info_num_labels(bpi);
+
bmp_monitor(bmp, peer, BMP_PEER_FLAG_L,
BMP_PEER_TYPE_GLOBAL_INSTANCE, &bqe->p, prd,
bpi ? bpi->attr : NULL, afi, safi,
bpi ? bpi->uptime : monotime(NULL),
- (bpi && bpi->extra) ? bpi->extra->label : NULL,
- (bpi && bpi->extra) ? bpi->extra->num_labels : 0);
+ bpi_num_labels ? bpi->extra->labels->label : NULL,
+ bpi_num_labels);
written = true;
}
diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c
index b4651ad0b..6228432bd 100644
--- a/bgpd/bgp_debug.c
+++ b/bgpd/bgp_debug.c
@@ -2713,7 +2713,7 @@ bool bgp_debug_zebra(const struct prefix *p)
const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi,
const struct prefix_rd *prd,
union prefixconstptr pu,
- mpls_label_t *label, uint32_t num_labels,
+ mpls_label_t *label, uint8_t num_labels,
int addpath_valid, uint32_t addpath_id,
struct bgp_route_evpn *overlay_index,
char *str, int size)
diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h
index 673926f24..061d966dc 100644
--- a/bgpd/bgp_debug.h
+++ b/bgpd/bgp_debug.h
@@ -175,7 +175,7 @@ extern bool bgp_debug_zebra(const struct prefix *p);
extern const char *bgp_debug_rdpfxpath2str(
afi_t afi, safi_t safi, const struct prefix_rd *prd,
- union prefixconstptr pu, mpls_label_t *label, uint32_t num_labels,
+ union prefixconstptr pu, mpls_label_t *label, uint8_t num_labels,
int addpath_valid, uint32_t addpath_id,
struct bgp_route_evpn *overlay_index, char *str, int size);
const char *bgp_notify_admin_message(char *buf, size_t bufsz, uint8_t *data,
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index ce9666d61..5ce5b19b1 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -1602,7 +1602,7 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_evpn,
{
struct attr *attr_new = NULL;
struct bgp_path_info *pi = NULL;
- mpls_label_t label = MPLS_INVALID_LABEL;
+ struct bgp_labels bgp_labels = {};
struct bgp_path_info *local_pi = NULL;
struct bgp_path_info *tmp_pi = NULL;
@@ -1630,9 +1630,14 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_evpn,
/* Type-5 routes advertise the L3-VNI */
bgp_path_info_extra_get(pi);
- vni2label(bgp_vrf->l3vni, &label);
- memcpy(&pi->extra->label, &label, sizeof(label));
- pi->extra->num_labels = 1;
+ vni2label(bgp_vrf->l3vni, &bgp_labels.label[0]);
+ bgp_labels.num_labels = 1;
+ if (!bgp_path_info_labels_same(pi, &bgp_labels.label[0],
+ bgp_labels.num_labels)) {
+ bgp_labels_unintern(&pi->extra->labels);
+ pi->extra->labels = bgp_labels_intern(&bgp_labels);
+ }
+
/* add the route entry to route node*/
bgp_path_info_add(dest, pi);
@@ -1930,15 +1935,13 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
struct bgp_path_info *local_pi;
struct attr *attr_new;
struct attr local_attr;
- mpls_label_t label[BGP_MAX_LABELS];
- uint32_t num_labels = 1;
+ struct bgp_labels bgp_labels = {};
int route_change = 1;
uint8_t sticky = 0;
const struct prefix_evpn *evp;
*pi = NULL;
evp = (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
- memset(&label, 0, sizeof(label));
/* See if this is an update of an existing route, or a new add. */
local_pi = bgp_evpn_route_get_local_path(bgp, dest);
@@ -1980,7 +1983,8 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
bgp_path_info_extra_get(tmp_pi);
/* The VNI goes into the 'label' field of the route */
- vni2label(vpn->vni, &label[0]);
+ vni2label(vpn->vni, &bgp_labels.label[0]);
+ bgp_labels.num_labels = 1;
/* Type-2 routes may carry a second VNI - the L3-VNI.
* Only attach second label if we are advertising two labels for
@@ -1992,13 +1996,16 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
l3vni = bgpevpn_get_l3vni(vpn);
if (l3vni) {
- vni2label(l3vni, &label[1]);
- num_labels++;
+ vni2label(l3vni, &bgp_labels.label[1]);
+ bgp_labels.num_labels++;
}
}
- memcpy(&tmp_pi->extra->label, label, sizeof(label));
- tmp_pi->extra->num_labels = num_labels;
+ if (!bgp_path_info_labels_same(tmp_pi, &bgp_labels.label[0],
+ bgp_labels.num_labels)) {
+ bgp_labels_unintern(&tmp_pi->extra->labels);
+ tmp_pi->extra->labels = bgp_labels_intern(&bgp_labels);
+ }
if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
if (mac)
@@ -2022,7 +2029,8 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
* The attributes have changed, type-2 routes needs to
* be advertised with right labels.
*/
- vni2label(vpn->vni, &label[0]);
+ vni2label(vpn->vni, &bgp_labels.label[0]);
+ bgp_labels.num_labels = 1;
if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE
&& CHECK_FLAG(vpn->flags,
VNI_FLAG_USE_TWO_LABELS)) {
@@ -2030,12 +2038,17 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
l3vni = bgpevpn_get_l3vni(vpn);
if (l3vni) {
- vni2label(l3vni, &label[1]);
- num_labels++;
+ vni2label(l3vni, &bgp_labels.label[1]);
+ bgp_labels.num_labels++;
}
}
- memcpy(&tmp_pi->extra->label, label, sizeof(label));
- tmp_pi->extra->num_labels = num_labels;
+ if (!bgp_path_info_labels_same(tmp_pi,
+ &bgp_labels.label[0],
+ bgp_labels.num_labels)) {
+ bgp_labels_unintern(&tmp_pi->extra->labels);
+ tmp_pi->extra->labels =
+ bgp_labels_intern(&bgp_labels);
+ }
if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
if (mac)
@@ -2983,12 +2996,11 @@ bgp_create_evpn_bgp_path_info(struct bgp_path_info *parent_pi,
sizeof(struct bgp_path_info_extra_vrfleak));
pi->extra->vrfleak->parent = bgp_path_info_lock(parent_pi);
bgp_dest_lock_node((struct bgp_dest *)parent_pi->net);
- if (parent_pi->extra) {
- memcpy(&pi->extra->label, &parent_pi->extra->label,
- sizeof(pi->extra->label));
- pi->extra->num_labels = parent_pi->extra->num_labels;
+ if (parent_pi->extra)
pi->extra->igpmetric = parent_pi->extra->igpmetric;
- }
+
+ if (bgp_path_info_num_labels(parent_pi))
+ pi->extra->labels = bgp_labels_intern(parent_pi->extra->labels);
bgp_path_info_add(dest, pi);
@@ -4676,7 +4688,7 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
uint8_t macaddr_len;
/* holds the VNI(s) as in packet */
mpls_label_t label[BGP_MAX_LABELS] = {};
- uint32_t num_labels = 0;
+ uint8_t num_labels = 0;
uint32_t eth_tag;
int ret = 0;
@@ -5019,7 +5031,7 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
static void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p,
const struct prefix_rd *prd,
- mpls_label_t *label, uint32_t num_labels,
+ mpls_label_t *label, uint8_t num_labels,
struct attr *attr)
{
int len;
@@ -5809,7 +5821,7 @@ int bgp_evpn_uninstall_routes(struct bgp *bgp, struct bgpevpn *vpn)
/*
* TODO: Hardcoded for a maximum of 2 VNIs right now
*/
-char *bgp_evpn_label2str(mpls_label_t *label, uint32_t num_labels, char *buf,
+char *bgp_evpn_label2str(mpls_label_t *label, uint8_t num_labels, char *buf,
int len)
{
vni_t vni1, vni2;
@@ -5893,7 +5905,7 @@ void bgp_evpn_route2json(const struct prefix_evpn *p, json_object *json)
*/
void bgp_evpn_encode_prefix(struct stream *s, const struct prefix *p,
const struct prefix_rd *prd, mpls_label_t *label,
- uint32_t num_labels, struct attr *attr,
+ uint8_t num_labels, struct attr *attr,
bool addpath_capable, uint32_t addpath_tx_id)
{
struct prefix_evpn *evp = (struct prefix_evpn *)p;
@@ -7737,7 +7749,7 @@ void bgp_evpn_handle_resolve_overlay_index_unset(struct hash_bucket *bucket,
*
*/
mpls_label_t *bgp_evpn_path_info_labels_get_l3vni(mpls_label_t *labels,
- uint32_t num_labels)
+ uint8_t num_labels)
{
if (!labels)
return NULL;
@@ -7756,8 +7768,10 @@ vni_t bgp_evpn_path_info_get_l3vni(const struct bgp_path_info *pi)
if (!pi->extra)
return 0;
- return label2vni(bgp_evpn_path_info_labels_get_l3vni(
- pi->extra->label, pi->extra->num_labels));
+ return label2vni(
+ bgp_evpn_path_info_labels_get_l3vni(pi->extra->labels->label,
+ pi->extra->labels
+ ->num_labels));
}
/*
diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h
index 11a6f45dd..223f18a17 100644
--- a/bgpd/bgp_evpn.h
+++ b/bgpd/bgp_evpn.h
@@ -115,12 +115,12 @@ extern void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi,
safi_t safi);
extern void bgp_evpn_vrf_delete(struct bgp *bgp_vrf);
extern void bgp_evpn_handle_router_id_update(struct bgp *bgp, int withdraw);
-extern char *bgp_evpn_label2str(mpls_label_t *label, uint32_t num_labels,
+extern char *bgp_evpn_label2str(mpls_label_t *label, uint8_t num_labels,
char *buf, int len);
extern void bgp_evpn_route2json(const struct prefix_evpn *p, json_object *json);
extern void bgp_evpn_encode_prefix(struct stream *s, const struct prefix *p,
const struct prefix_rd *prd,
- mpls_label_t *label, uint32_t num_labels,
+ mpls_label_t *label, uint8_t num_labels,
struct attr *attr, bool addpath_capable,
uint32_t addpath_tx_id);
extern int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
@@ -177,7 +177,7 @@ extern void
bgp_evpn_handle_resolve_overlay_index_unset(struct hash_bucket *bucket,
void *arg);
extern mpls_label_t *bgp_evpn_path_info_labels_get_l3vni(mpls_label_t *labels,
- uint32_t num_labels);
+ uint8_t num_labels);
extern vni_t bgp_evpn_path_info_get_l3vni(const struct bgp_path_info *pi);
extern bool bgp_evpn_mpath_has_dvni(const struct bgp *bgp_vrf,
struct bgp_path_info *mpinfo);
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index d63e01156..d723a2b1b 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -358,6 +358,7 @@ int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
struct bgp_path_info *tmp_pi = NULL;
struct bgp_path_info *local_pi = NULL; /* local route entry if any */
struct bgp_path_info *remote_pi = NULL; /* remote route entry if any */
+ struct bgp_labels bgp_labels = {};
struct attr *attr_new = NULL;
struct prefix_evpn *evp;
@@ -404,11 +405,16 @@ int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
if (evp->prefix.route_type == BGP_EVPN_AD_ROUTE) {
bgp_path_info_extra_get(tmp_pi);
- tmp_pi->extra->num_labels = 1;
+ bgp_labels.num_labels = 1;
if (vpn)
- vni2label(vpn->vni, &tmp_pi->extra->label[0]);
- else
- tmp_pi->extra->label[0] = 0;
+ vni2label(vpn->vni, &bgp_labels.label[0]);
+ if (!bgp_path_info_labels_same(tmp_pi,
+ &bgp_labels.label[0],
+ bgp_labels.num_labels)) {
+ bgp_labels_unintern(&tmp_pi->extra->labels);
+ tmp_pi->extra->labels =
+ bgp_labels_intern(&bgp_labels);
+ }
}
/* add the newly created path to the route-node */
@@ -2455,7 +2461,7 @@ static void bgp_evpn_es_frag_show_detail(struct vty *vty,
}
static char *bgp_evpn_es_vteps_str(char *vtep_str, struct bgp_evpn_es *es,
- uint8_t vtep_str_size)
+ size_t vtep_str_size)
{
char vtep_flag_str[BGP_EVPN_FLAG_STR_SZ];
struct listnode *node;
@@ -3956,7 +3962,7 @@ void bgp_evpn_vni_es_cleanup(struct bgpevpn *vpn)
static char *bgp_evpn_es_evi_vteps_str(char *vtep_str,
struct bgp_evpn_es_evi *es_evi,
- uint8_t vtep_str_size)
+ size_t vtep_str_size)
{
char vtep_flag_str[BGP_EVPN_FLAG_STR_SZ];
struct listnode *node;
diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c
index 68104967b..839437e12 100644
--- a/bgpd/bgp_label.c
+++ b/bgpd/bgp_label.c
@@ -15,6 +15,7 @@
#include "memory.h"
#include "nexthop.h"
#include "mpls.h"
+#include "jhash.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
@@ -27,6 +28,124 @@
extern struct zclient *zclient;
+
+/* MPLS Labels hash routines. */
+static struct hash *labels_hash;
+
+static void *bgp_labels_hash_alloc(void *p)
+{
+ const struct bgp_labels *labels = p;
+ struct bgp_labels *new;
+ uint8_t i;
+
+ new = XMALLOC(MTYPE_BGP_LABELS, sizeof(struct bgp_labels));
+
+ new->num_labels = labels->num_labels;
+ for (i = 0; i < labels->num_labels; i++)
+ new->label[i] = labels->label[i];
+
+ return new;
+}
+
+static uint32_t bgp_labels_hash_key_make(const void *p)
+{
+ const struct bgp_labels *labels = p;
+ uint32_t key = 0;
+
+ if (labels->num_labels)
+ key = jhash(&labels->label,
+ labels->num_labels * sizeof(mpls_label_t), key);
+
+ return key;
+}
+
+static bool bgp_labels_hash_cmp(const void *p1, const void *p2)
+{
+ return bgp_labels_cmp(p1, p2);
+}
+
+void bgp_labels_init(void)
+{
+ labels_hash = hash_create(bgp_labels_hash_key_make, bgp_labels_hash_cmp,
+ "BGP Labels hash");
+}
+
+/*
+ * special for hash_clean below
+ */
+static void bgp_labels_free(void *labels)
+{
+ XFREE(MTYPE_BGP_LABELS, labels);
+}
+
+void bgp_labels_finish(void)
+{
+ hash_clean_and_free(&labels_hash, bgp_labels_free);
+}
+
+struct bgp_labels *bgp_labels_intern(struct bgp_labels *labels)
+{
+ struct bgp_labels *find;
+
+ if (!labels)
+ return NULL;
+
+ if (!labels->num_labels)
+ /* do not intern void labels structure */
+ return NULL;
+
+ find = (struct bgp_labels *)hash_get(labels_hash, labels,
+ bgp_labels_hash_alloc);
+ find->refcnt++;
+
+ return find;
+}
+
+void bgp_labels_unintern(struct bgp_labels **plabels)
+{
+ struct bgp_labels *labels = *plabels;
+ struct bgp_labels *ret;
+
+ if (!*plabels)
+ return;
+
+ /* Decrement labels reference. */
+ labels->refcnt--;
+
+ /* If reference becomes zero then free labels object. */
+ if (labels->refcnt == 0) {
+ ret = hash_release(labels_hash, labels);
+ assert(ret != NULL);
+ bgp_labels_free(labels);
+ *plabels = NULL;
+ }
+}
+
+bool bgp_labels_cmp(const struct bgp_labels *labels1,
+ const struct bgp_labels *labels2)
+{
+ uint8_t i;
+
+ if (!labels1 && !labels2)
+ return true;
+
+ if (!labels1 && labels2)
+ return false;
+
+ if (labels1 && !labels2)
+ return false;
+
+ if (labels1->num_labels != labels2->num_labels)
+ return false;
+
+ for (i = 0; i < labels1->num_labels; i++) {
+ if (labels1->label[i] != labels2->label[i])
+ return false;
+ }
+
+ return true;
+}
+
int bgp_parse_fec_update(void)
{
struct stream *s;
@@ -89,7 +208,9 @@ mpls_label_t bgp_adv_label(struct bgp_dest *dest, struct bgp_path_info *pi,
if (!dest || !pi || !to)
return MPLS_INVALID_LABEL;
- remote_label = pi->extra ? pi->extra->label[0] : MPLS_INVALID_LABEL;
+ remote_label = bgp_path_info_num_labels(pi)
+ ? pi->extra->labels->label[0]
+ : MPLS_INVALID_LABEL;
from = pi->peer;
reflect =
((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP));
@@ -471,8 +592,8 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
return BGP_NLRI_PARSE_OK;
}
-bool bgp_labels_same(const mpls_label_t *tbl_a, const uint32_t num_labels_a,
- const mpls_label_t *tbl_b, const uint32_t num_labels_b)
+bool bgp_labels_same(const mpls_label_t *tbl_a, const uint8_t num_labels_a,
+ const mpls_label_t *tbl_b, const uint8_t num_labels_b)
{
uint32_t i;
diff --git a/bgpd/bgp_label.h b/bgpd/bgp_label.h
index b54403ee8..2ffd5b699 100644
--- a/bgpd/bgp_label.h
+++ b/bgpd/bgp_label.h
@@ -15,6 +15,26 @@ struct bgp_dest;
struct bgp_path_info;
struct peer;
+/* Maximum number of labels we can process or send with a prefix. We
+ * really do only 1 for MPLS (BGP-LU) but we can do 2 for EVPN-VxLAN.
+ */
+#define BGP_MAX_LABELS 2
+
+/* MPLS label(s) - VNI(s) for EVPN-VxLAN */
+struct bgp_labels {
+ mpls_label_t label[BGP_MAX_LABELS];
+ uint8_t num_labels;
+
+ unsigned long refcnt;
+};
+
+extern void bgp_labels_init(void);
+extern void bgp_labels_finish(void);
+extern struct bgp_labels *bgp_labels_intern(struct bgp_labels *labels);
+extern void bgp_labels_unintern(struct bgp_labels **plabels);
+extern bool bgp_labels_cmp(const struct bgp_labels *labels1,
+ const struct bgp_labels *labels2);
+
extern int bgp_reg_for_label_callback(mpls_label_t new_label, void *labelid,
bool allocated);
extern void bgp_reg_dereg_for_label(struct bgp_dest *dest,
@@ -27,9 +47,9 @@ extern mpls_label_t bgp_adv_label(struct bgp_dest *dest,
extern int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
struct bgp_nlri *packet);
extern bool bgp_labels_same(const mpls_label_t *tbl_a,
- const uint32_t num_labels_a,
+ const uint8_t num_labels_a,
const mpls_label_t *tbl_b,
- const uint32_t num_labels_b);
+ const uint8_t num_labels_b);
static inline int bgp_labeled_safi(safi_t safi)
{
diff --git a/bgpd/bgp_mac.c b/bgpd/bgp_mac.c
index e629732c7..31e84d13c 100644
--- a/bgpd/bgp_mac.c
+++ b/bgpd/bgp_mac.c
@@ -14,6 +14,7 @@
#include "bgpd/bgpd.h"
#include "bgpd/bgp_mac.h"
#include "bgpd/bgp_memory.h"
+#include "bgpd/bgp_label.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_packet.h"
#include "bgpd/bgp_rd.h"
@@ -125,6 +126,8 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
{
struct bgp_dest *pdest, *dest;
struct bgp_path_info *pi;
+ uint8_t num_labels;
+ mpls_label_t *label_pnt;
for (pdest = bgp_table_top(table); pdest;
pdest = bgp_route_next(pdest)) {
@@ -140,8 +143,6 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
const struct prefix *p = bgp_dest_get_prefix(dest);
struct prefix_evpn *pevpn = (struct prefix_evpn *)dest;
struct prefix_rd prd;
- uint32_t num_labels = 0;
- mpls_label_t *label_pnt = NULL;
struct bgp_route_evpn *evpn;
if (pevpn->family == AF_EVPN
@@ -169,10 +170,9 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
&& !dest_affected)
continue;
- if (pi->extra)
- num_labels = pi->extra->num_labels;
- if (num_labels)
- label_pnt = &pi->extra->label[0];
+ num_labels = bgp_path_info_num_labels(pi);
+ label_pnt = num_labels ? &pi->extra->labels->label[0]
+ : NULL;
prd.family = AF_UNSPEC;
prd.prefixlen = 64;
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index 2bbd3a4b1..97658d340 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -225,6 +225,9 @@ static __attribute__((__noreturn__)) void bgp_exit(int status)
/* reverse bgp_attr_init */
bgp_attr_finish();
+ /* reverse bgp_labels_init */
+ bgp_labels_finish();
+
/* stop pthreads */
bgp_pthreads_finish();
diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c
index 53c03d810..c1804fb70 100644
--- a/bgpd/bgp_memory.c
+++ b/bgpd/bgp_memory.c
@@ -102,6 +102,8 @@ DEFINE_MTYPE(BGPD, BGP_FILTER_NAME, "BGP Filter Information");
DEFINE_MTYPE(BGPD, BGP_DUMP_STR, "BGP Dump String Information");
DEFINE_MTYPE(BGPD, ENCAP_TLV, "ENCAP TLV");
+DEFINE_MTYPE(BGPD, BGP_LABELS, "BGP LABELS");
+
DEFINE_MTYPE(BGPD, BGP_TEA_OPTIONS, "BGP TEA Options");
DEFINE_MTYPE(BGPD, BGP_TEA_OPTIONS_VALUE, "BGP TEA Options Value");
diff --git a/bgpd/bgp_memory.h b/bgpd/bgp_memory.h
index 865c5880d..4ae49a2c1 100644
--- a/bgpd/bgp_memory.h
+++ b/bgpd/bgp_memory.h
@@ -98,6 +98,8 @@ DECLARE_MTYPE(BGP_FILTER_NAME);
DECLARE_MTYPE(BGP_DUMP_STR);
DECLARE_MTYPE(ENCAP_TLV);
+DECLARE_MTYPE(BGP_LABELS);
+
DECLARE_MTYPE(BGP_TEA_OPTIONS);
DECLARE_MTYPE(BGP_TEA_OPTIONS_VALUE);
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 39f8f84a0..90881621b 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -964,50 +964,6 @@ void transpose_sid(struct in6_addr *sid, uint32_t label, uint8_t offset,
}
}
-static bool labels_same(struct bgp_path_info *bpi, mpls_label_t *label,
- uint32_t n)
-{
- if (!bpi->extra) {
- if (!n)
- return true;
- else
- return false;
- }
-
- return bgp_labels_same((const mpls_label_t *)bpi->extra->label,
- bpi->extra->num_labels,
- (const mpls_label_t *)label, n);
-}
-
-/*
- * make encoded route labels match specified encoded label set
- */
-static void setlabels(struct bgp_path_info *bpi,
- mpls_label_t *label, /* array of labels */
- uint32_t num_labels)
-{
- if (num_labels)
- assert(label);
- assert(num_labels <= BGP_MAX_LABELS);
-
- if (!num_labels) {
- if (bpi->extra)
- bpi->extra->num_labels = 0;
- return;
- }
-
- struct bgp_path_info_extra *extra = bgp_path_info_extra_get(bpi);
- uint32_t i;
-
- for (i = 0; i < num_labels; ++i) {
- extra->label[i] = label[i];
- if (!bgp_is_valid_label(&label[i])) {
- bgp_set_valid_label(&extra->label[i]);
- }
- }
- extra->num_labels = num_labels;
-}
-
static bool leak_update_nexthop_valid(struct bgp *to_bgp, struct bgp_dest *bn,
struct attr *new_attr, afi_t afi,
safi_t safi,
@@ -1086,7 +1042,7 @@ static struct bgp_path_info *
leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
struct attr *new_attr, /* already interned */
afi_t afi, safi_t safi, struct bgp_path_info *source_bpi,
- mpls_label_t *label, uint32_t num_labels, struct bgp *bgp_orig,
+ mpls_label_t *label, uint8_t num_labels, struct bgp *bgp_orig,
struct prefix *nexthop_orig, int nexthop_self_flag, int debug)
{
const struct prefix *p = bgp_dest_get_prefix(bn);
@@ -1094,6 +1050,9 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
struct bgp_path_info *new;
struct bgp_path_info_extra *extra;
struct bgp_path_info *parent = source_bpi;
+ struct bgp_labels bgp_labels = {};
+ bool labelssame;
+ uint8_t i;
if (debug)
zlog_debug(
@@ -1128,8 +1087,15 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
break;
}
+ bgp_labels.num_labels = num_labels;
+ for (i = 0; i < num_labels; i++) {
+ bgp_labels.label[i] = label[i];
+ bgp_set_valid_label(&bgp_labels.label[i]);
+ }
+
if (bpi) {
- bool labelssame = labels_same(bpi, label, num_labels);
+ labelssame = bgp_path_info_labels_same(bpi, bgp_labels.label,
+ bgp_labels.num_labels);
if (CHECK_FLAG(source_bpi->flags, BGP_PATH_REMOVED)
&& CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
@@ -1187,11 +1153,13 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
bpi->uptime = monotime(NULL);
/*
- * rewrite labels
+ * update labels
*/
- if (!labelssame)
- setlabels(bpi, label, num_labels);
-
+ if (!labelssame) {
+ bgp_path_info_extra_get(bpi);
+ bgp_labels_unintern(&bpi->extra->labels);
+ bpi->extra->labels = bgp_labels_intern(&bgp_labels);
+ }
if (nexthop_self_flag)
bgp_path_info_set_flag(bn, bpi, BGP_PATH_ANNC_NH_SELF);
@@ -1249,8 +1217,8 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
if (CHECK_FLAG(source_bpi->flags, BGP_PATH_ACCEPT_OWN))
bgp_path_info_set_flag(bn, new, BGP_PATH_ACCEPT_OWN);
- if (num_labels)
- setlabels(new, label, num_labels);
+ if (bgp_labels.num_labels)
+ new->extra->labels = bgp_labels_intern(&bgp_labels);
new->extra->vrfleak->parent = bgp_path_info_lock(parent);
bgp_dest_lock_node(
@@ -2102,8 +2070,8 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
safi_t safi = SAFI_UNICAST;
const char *debugmsg;
struct prefix nexthop_orig;
- mpls_label_t *pLabels = NULL;
- uint32_t num_labels = 0;
+ mpls_label_t *label_pnt = NULL;
+ uint8_t num_labels = 0;
int nexthop_self_flag = 1;
struct bgp_path_info *bpi_ultimate = NULL;
struct bgp_path_info *bpi;
@@ -2349,21 +2317,16 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
origin_local = 1;
}
- /* copy labels */
- if (!origin_local && path_vpn->extra
- && path_vpn->extra->num_labels) {
- num_labels = path_vpn->extra->num_labels;
- if (num_labels > BGP_MAX_LABELS)
- num_labels = BGP_MAX_LABELS;
- pLabels = path_vpn->extra->label;
- }
+ num_labels = origin_local ? 0
+ : bgp_path_info_num_labels(path_vpn);
+ label_pnt = num_labels ? path_vpn->extra->labels->label : NULL;
}
if (debug)
zlog_debug("%s: pfx %pBD: num_labels %d", __func__,
path_vpn->net, num_labels);
- if (!leak_update(to_bgp, bn, new_attr, afi, safi, path_vpn, pLabels,
+ if (!leak_update(to_bgp, bn, new_attr, afi, safi, path_vpn, label_pnt,
num_labels, src_vrf, &nexthop_orig, nexthop_self_flag,
debug))
bgp_dest_unlock_node(bn);
@@ -3995,7 +3958,7 @@ static void bgp_mplsvpn_nh_label_bind_send_nexthop_label(
struct bgp_mplsvpn_nh_label_bind_cache *bmnc, int cmd)
{
struct prefix pfx_nh, *p = NULL;
- uint32_t num_labels = 0, lsp_num_labels;
+ uint8_t num_labels = 0, lsp_num_labels;
mpls_label_t label[MPLS_MAX_LABELS];
struct nexthop *nh;
ifindex_t ifindex = IFINDEX_INTERNAL;
@@ -4130,7 +4093,7 @@ bool bgp_mplsvpn_path_uses_valid_mpls_label(struct bgp_path_info *pi)
/* prefix_sid attribute */
return false;
- if (!pi->extra || !bgp_is_valid_label(&pi->extra->label[0]))
+ if (!bgp_path_info_has_valid_label(pi))
/* invalid MPLS label */
return false;
return true;
@@ -4237,14 +4200,17 @@ void bgp_mplsvpn_nh_label_bind_register_local_label(struct bgp *bgp,
{
struct bgp_mplsvpn_nh_label_bind_cache *bmnc;
struct bgp_mplsvpn_nh_label_bind_cache_head *tree;
+ mpls_label_t label;
+
+ label = bgp_path_info_num_labels(pi)
+ ? decode_label(&pi->extra->labels->label[0])
+ : MPLS_INVALID_LABEL;
tree = &bgp->mplsvpn_nh_label_bind;
- bmnc = bgp_mplsvpn_nh_label_bind_find(
- tree, &pi->nexthop->prefix, decode_label(&pi->extra->label[0]));
+ bmnc = bgp_mplsvpn_nh_label_bind_find(tree, &pi->nexthop->prefix, label);
if (!bmnc) {
- bmnc = bgp_mplsvpn_nh_label_bind_new(
- tree, &pi->nexthop->prefix,
- decode_label(&pi->extra->label[0]));
+ bmnc = bgp_mplsvpn_nh_label_bind_new(tree, &pi->nexthop->prefix,
+ label);
bmnc->bgp_vpn = bgp;
bmnc->allocation_in_progress = true;
bgp_lp_get(LP_TYPE_BGP_L3VPN_BIND, bmnc,
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index 79f62ef60..8ce45558e 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -499,8 +499,8 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
if (bgp_route->inst_type == BGP_INSTANCE_TYPE_VIEW)
return 1;
else if (safi == SAFI_UNICAST && pi &&
- pi->sub_type == BGP_ROUTE_IMPORTED && pi->extra &&
- pi->extra->num_labels && !bnc->is_evpn_gwip_nexthop)
+ pi->sub_type == BGP_ROUTE_IMPORTED &&
+ bgp_path_info_num_labels(pi) && !bnc->is_evpn_gwip_nexthop)
return bgp_isvalid_nexthop_for_l3vpn(bnc, pi);
else if (safi == SAFI_MPLS_VPN && pi &&
pi->sub_type != BGP_ROUTE_IMPORTED)
@@ -1301,10 +1301,10 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc)
bool bnc_is_valid_nexthop = false;
bool path_valid = false;
- if (safi == SAFI_UNICAST && path->sub_type == BGP_ROUTE_IMPORTED
- && path->extra && path->extra->num_labels
- && (path->attr->evpn_overlay.type
- != OVERLAY_INDEX_GATEWAY_IP)) {
+ if (safi == SAFI_UNICAST &&
+ path->sub_type == BGP_ROUTE_IMPORTED &&
+ bgp_path_info_num_labels(path) &&
+ (path->attr->evpn_overlay.type != OVERLAY_INDEX_GATEWAY_IP)) {
bnc_is_valid_nexthop =
bgp_isvalid_nexthop_for_l3vpn(bnc, path)
? true
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 2309b710e..94c21e186 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -235,8 +235,6 @@ static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
struct bgp_path_info_extra *new;
new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
sizeof(struct bgp_path_info_extra));
- new->label[0] = MPLS_INVALID_LABEL;
- new->num_labels = 0;
new->flowspec = NULL;
return new;
}
@@ -307,6 +305,9 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
XFREE(MTYPE_BGP_ROUTE_EXTRA_VNC, e->vnc);
#endif
+ if (e->labels)
+ bgp_labels_unintern(&e->labels);
+
XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
}
@@ -324,6 +325,41 @@ struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
return pi->extra;
}
+bool bgp_path_info_has_valid_label(const struct bgp_path_info *path)
+{
+ if (!bgp_path_info_num_labels(path))
+ return false;
+
+ return bgp_is_valid_label(&path->extra->labels->label[0]);
+}
+
+bool bgp_path_info_labels_same(const struct bgp_path_info *bpi,
+ const mpls_label_t *label, uint32_t n)
+{
+ uint8_t bpi_num_labels;
+ const mpls_label_t *bpi_label;
+
+ bpi_num_labels = bgp_path_info_num_labels(bpi);
+ bpi_label = bpi_num_labels ? bpi->extra->labels->label : NULL;
+
+ return bgp_labels_same(bpi_label, bpi_num_labels,
+ (const mpls_label_t *)label, n);
+}
+
+uint8_t bgp_path_info_num_labels(const struct bgp_path_info *pi)
+{
+ if (!pi)
+ return 0;
+
+ if (!pi->extra)
+ return 0;
+
+ if (!pi->extra->labels)
+ return 0;
+
+ return pi->extra->labels->num_labels;
+}
+
/* Free bgp route information. */
void bgp_path_info_free_with_caller(const char *name,
struct bgp_path_info *path)
@@ -1359,25 +1395,18 @@ int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
/* If one path has a label but the other does not, do not treat
* them as equals for multipath
*/
- int newl, existl;
-
- newl = existl = 0;
-
- if (new->extra)
- newl = new->extra->num_labels;
- if (exist->extra)
- existl = exist->extra->num_labels;
- if (((new->extra &&bgp_is_valid_label(&new->extra->label[0])) !=
- (exist->extra &&
- bgp_is_valid_label(&exist->extra->label[0]))) ||
- (newl != existl)) {
+ bool new_label_valid, exist_label_valid;
+
+ new_label_valid = bgp_path_info_has_valid_label(new);
+ exist_label_valid = bgp_path_info_has_valid_label(exist);
+
+ if (new_label_valid != exist_label_valid) {
if (debug)
zlog_debug(
"%s: %s and %s cannot be multipath, one has a label while the other does not",
pfx_buf, new_buf, exist_buf);
} else if (CHECK_FLAG(bgp->flags,
BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
-
/*
* For the two paths, all comparison steps till IGP
* metric
@@ -1843,11 +1872,12 @@ static bool bgp_check_role_applicability(afi_t afi, safi_t safi)
static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
struct attr *attr, afi_t afi, safi_t safi,
const char *rmap_name, mpls_label_t *label,
- uint32_t num_labels, struct bgp_dest *dest)
+ uint8_t num_labels, struct bgp_dest *dest)
{
struct bgp_filter *filter;
struct bgp_path_info rmap_path = { 0 };
struct bgp_path_info_extra extra = { 0 };
+ struct bgp_labels bgp_labels = {};
route_map_result_t ret;
struct route_map *rmap = NULL;
@@ -1879,11 +1909,12 @@ static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
rmap_path.attr = attr;
rmap_path.extra = &extra;
rmap_path.net = dest;
+ extra.labels = &bgp_labels;
- extra.num_labels = num_labels;
+ bgp_labels.num_labels = num_labels;
if (label && num_labels && num_labels <= BGP_MAX_LABELS)
- memcpy(extra.label, label,
- num_labels * sizeof(mpls_label_t));
+ memcpy(bgp_labels.label, label,
+ num_labels * sizeof(mpls_label_t));
SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
@@ -2218,8 +2249,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
* off box as that the RT and RD created are localy
* significant and globaly useless.
*/
- if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
- && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
+ if (safi == SAFI_MPLS_VPN && bgp_path_info_num_labels(pi) &&
+ pi->extra->labels->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
return false;
/* If it's labeled safi, make sure the route has a valid label. */
@@ -3455,8 +3486,7 @@ static bool bgp_lu_need_null_label(struct bgp *bgp,
|| new_select->sub_type == BGP_ROUTE_AGGREGATE
|| new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
goto need_null_label;
- else if (new_select->extra &&
- bgp_is_valid_label(&new_select->extra->label[0]))
+ else if (bgp_path_info_has_valid_label(new_select))
return false;
need_null_label:
if (label == NULL)
@@ -4506,7 +4536,7 @@ static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
struct attr *attr, afi_t afi, safi_t safi, int type,
int sub_type, struct prefix_rd *prd, mpls_label_t *label,
- uint32_t num_labels, int soft_reconfig,
+ uint8_t num_labels, int soft_reconfig,
struct bgp_route_evpn *evpn)
{
int ret;
@@ -4517,16 +4547,16 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
struct attr *attr_new;
struct bgp_path_info *pi;
struct bgp_path_info *new = NULL;
- struct bgp_path_info_extra *extra;
const char *reason;
char pfx_buf[BGP_PRD_PATH_STRLEN];
int connected = 0;
int do_loop_check = 1;
- int has_valid_label = 0;
afi_t nh_afi;
bool force_evpn_import = false;
safi_t orig_safi = safi;
int allowas_in = 0;
+ struct bgp_labels bgp_labels = {};
+ uint8_t i;
if (frrtrace_enabled(frr_bgp, process_update)) {
char pfxprint[PREFIX2STR_BUFFER];
@@ -4548,15 +4578,12 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp = peer->bgp;
dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
- /* TODO: Check to see if we can get rid of "is_valid_label" */
- if (afi == AFI_L2VPN && safi == SAFI_EVPN)
- has_valid_label = (num_labels > 0) ? 1 : 0;
- else
- has_valid_label = bgp_is_valid_label(label);
-
- if (has_valid_label)
- assert(label != NULL);
+ if ((afi == AFI_L2VPN && safi == SAFI_EVPN) ||
+ bgp_is_valid_label(&label[0]))
+ bgp_labels.num_labels = num_labels;
+ for (i = 0; i < bgp_labels.num_labels; i++)
+ bgp_labels.label[i] = label[i];
/* When peer's soft reconfiguration enabled. Record input packet in
Adj-RIBs-In. */
@@ -4573,7 +4600,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
memcpy(&attr->evpn_overlay, evpn,
sizeof(struct bgp_route_evpn));
}
- bgp_adj_in_set(dest, peer, attr, addpath_id);
+ bgp_adj_in_set(dest, peer, attr, addpath_id, &bgp_labels);
}
/* Update permitted loop count */
@@ -4850,11 +4877,9 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
/* Same attribute comes in. */
if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED) && same_attr &&
- (!has_valid_label ||
- (bgp_path_info_extra_get(pi) &&
- bgp_labels_same((const mpls_label_t *)pi->extra->label,
- pi->extra->num_labels, label,
- num_labels)))) {
+ (!bgp_labels.num_labels ||
+ bgp_path_info_labels_same(pi, bgp_labels.label,
+ bgp_labels.num_labels))) {
if (get_active_bdc_from_pi(pi, afi, safi) &&
peer->sort == BGP_PEER_EBGP &&
CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
@@ -5036,17 +5061,11 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
pi->attr = attr_new;
/* Update MPLS label */
- if (has_valid_label) {
- extra = bgp_path_info_extra_get(pi);
- if (!bgp_labels_same((const mpls_label_t *)extra->label,
- extra->num_labels, label,
- num_labels)) {
- memcpy(&extra->label, label,
- num_labels * sizeof(mpls_label_t));
- extra->num_labels = num_labels;
- }
- if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
- bgp_set_valid_label(&extra->label[0]);
+ if (!bgp_path_info_labels_same(pi, &bgp_labels.label[0],
+ bgp_labels.num_labels)) {
+ bgp_path_info_extra_get(pi);
+ bgp_labels_unintern(&pi->extra->labels);
+ pi->extra->labels = bgp_labels_intern(&bgp_labels);
}
#ifdef ENABLE_BGP_VNC
@@ -5237,17 +5256,8 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
new = info_make(type, sub_type, 0, peer, attr_new, dest);
/* Update MPLS label */
- if (has_valid_label) {
- extra = bgp_path_info_extra_get(new);
- if (!bgp_labels_same((const mpls_label_t *)extra->label,
- extra->num_labels, label, num_labels)) {
- memcpy(&extra->label, label,
- num_labels * sizeof(mpls_label_t));
- extra->num_labels = num_labels;
- }
- if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
- bgp_set_valid_label(&extra->label[0]);
- }
+ bgp_path_info_extra_get(new);
+ new->extra->labels = bgp_labels_intern(&bgp_labels);
/* Nexthop reachability check. */
if (((afi == AFI_IP || afi == AFI_IP6) &&
@@ -5428,7 +5438,7 @@ filtered:
void bgp_withdraw(struct peer *peer, const struct prefix *p,
uint32_t addpath_id, afi_t afi, safi_t safi, int type,
int sub_type, struct prefix_rd *prd, mpls_label_t *label,
- uint32_t num_labels, struct bgp_route_evpn *evpn)
+ uint8_t num_labels, struct bgp_route_evpn *evpn)
{
struct bgp *bgp;
char pfx_buf[BGP_PRD_PATH_STRLEN];
@@ -5655,18 +5665,16 @@ static void bgp_soft_reconfig_table_update(struct peer *peer,
safi_t safi, struct prefix_rd *prd)
{
struct bgp_path_info *pi;
- uint32_t num_labels = 0;
- mpls_label_t *label_pnt = NULL;
+ uint8_t num_labels;
+ mpls_label_t *label_pnt;
struct bgp_route_evpn evpn;
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
if (pi->peer == peer)
break;
- if (pi && pi->extra)
- num_labels = pi->extra->num_labels;
- if (num_labels)
- label_pnt = &pi->extra->label[0];
+ num_labels = ain->labels ? ain->labels->num_labels : 0;
+ label_pnt = num_labels ? &ain->labels->label[0] : NULL;
if (pi)
memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
sizeof(evpn));
@@ -6678,10 +6686,11 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
route_map_result_t ret;
#ifdef ENABLE_BGP_VNC
int vnc_implicit_withdraw = 0;
- mpls_label_t label = 0;
+ mpls_label_t label = MPLS_INVALID_LABEL;
#endif
- uint32_t num_labels = 0;
+ uint8_t num_labels = 0;
struct bgp *bgp_nexthop = bgp;
+ struct bgp_labels labels = {};
assert(bgp_static);
@@ -6831,9 +6840,9 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
bgp, p, pi);
}
} else {
- if (pi->extra)
+ if (bgp_path_info_num_labels(pi))
label = decode_label(
- &pi->extra->label[0]);
+ &pi->extra->labels->label[0]);
}
#endif
if (pi->extra && pi->extra->vrfleak->bgp_orig)
@@ -6882,8 +6891,9 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
SET_FLAG(new->flags, BGP_PATH_VALID);
bgp_path_info_extra_get(new);
if (num_labels) {
- new->extra->label[0] = bgp_static->label;
- new->extra->num_labels = num_labels;
+ labels.num_labels = num_labels;
+ labels.label[0] = bgp_static->label;
+ new->extra->labels = bgp_labels_intern(&labels);
}
#ifdef ENABLE_BGP_VNC
label = decode_label(&bgp_static->label);
@@ -10069,8 +10079,8 @@ void route_vty_out_tag(struct vty *vty, const struct prefix *p,
}
}
- if (bgp_is_valid_label(&path->extra->label[0])) {
- label = decode_label(&path->extra->label[0]);
+ if (bgp_path_info_has_valid_label(path)) {
+ label = decode_label(&path->extra->labels->label[0]);
if (json) {
json_object_int_add(json_out, "notag", label);
json_object_array_add(json, json_out);
@@ -10460,7 +10470,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
json_object *json_paths)
{
char buf[INET6_ADDRSTRLEN];
- char tag_buf[30];
+ char vni_buf[30] = {};
struct attr *attr = path->attr;
time_t tbuf;
char timebuf[32];
@@ -10493,7 +10503,6 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
uint32_t bos = 0;
uint32_t exp = 0;
mpls_label_t label = MPLS_INVALID_LABEL;
- tag_buf[0] = '\0';
struct bgp_path_info *bpi_ultimate =
bgp_get_imported_bpi_ultimate(path);
@@ -10503,26 +10512,22 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
json_nexthop_global = json_object_new_object();
}
+ if (bgp_path_info_num_labels(path)) {
+ bgp_evpn_label2str(path->extra->labels->label,
+ path->extra->labels->num_labels, vni_buf,
+ sizeof(vni_buf));
+ }
+
if (safi == SAFI_EVPN) {
if (!json_paths)
vty_out(vty, " Route %pFX", p);
- }
- if (path->extra) {
- if (path->extra && path->extra->num_labels) {
- bgp_evpn_label2str(path->extra->label,
- path->extra->num_labels, tag_buf,
- sizeof(tag_buf));
- }
- if (safi == SAFI_EVPN) {
- if (!json_paths) {
- if (tag_buf[0] != '\0')
- vty_out(vty, " VNI %s", tag_buf);
- } else {
- if (tag_buf[0])
- json_object_string_add(json_path, "vni",
- tag_buf);
- }
+ if (vni_buf[0]) {
+ if (json_paths)
+ json_object_string_add(json_path, "vni",
+ vni_buf);
+ else
+ vty_out(vty, " VNI %s", vni_buf);
}
}
@@ -10562,7 +10567,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
vty_out(vty, ":%pFX, VNI %s",
(struct prefix_evpn *)
bgp_dest_get_prefix(dest),
- tag_buf);
+ vni_buf);
if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
vty_out(vty, ", L3NHG %s",
CHECK_FLAG(
@@ -11274,10 +11279,10 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path);
/* Remote Label */
- if (path->extra && bgp_is_valid_label(&path->extra->label[0])
- && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
- mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
- &bos);
+ if (bgp_path_info_has_valid_label(path) &&
+ (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
+ mpls_lse_decode(path->extra->labels->label[0], &label, &ttl,
+ &exp, &bos);
if (json_paths)
json_object_int_add(json_path, "remoteLabel", label);
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 25fc327a1..89449ac5b 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -69,11 +69,6 @@ enum bgp_show_adj_route_type {
#define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf Weight Path\n"
#define BGP_SHOW_HEADER_WIDE " Network Next Hop Metric LocPrf Weight Path\n"
-/* Maximum number of labels we can process or send with a prefix. We
- * really do only 1 for MPLS (BGP-LU) but we can do 2 for EVPN-VxLAN.
- */
-#define BGP_MAX_LABELS 2
-
/* Maximum number of sids we can process or send with a prefix. */
#define BGP_MAX_SIDS 6
@@ -237,8 +232,7 @@ struct bgp_path_info_extra {
uint32_t igpmetric;
/* MPLS label(s) - VNI(s) for EVPN-VxLAN */
- mpls_label_t label[BGP_MAX_LABELS];
- uint32_t num_labels;
+ struct bgp_labels *labels;
/* timestamp of the rib installation */
time_t bgp_rib_uptime;
@@ -753,12 +747,16 @@ extern void bgp_path_info_delete(struct bgp_dest *dest,
struct bgp_path_info *pi);
extern struct bgp_path_info_extra *
bgp_path_info_extra_get(struct bgp_path_info *path);
+extern bool bgp_path_info_has_valid_label(const struct bgp_path_info *path);
+extern uint8_t bgp_path_info_num_labels(const struct bgp_path_info *pi);
extern void bgp_path_info_set_flag(struct bgp_dest *dest,
struct bgp_path_info *path, uint32_t flag);
extern void bgp_path_info_unset_flag(struct bgp_dest *dest,
struct bgp_path_info *path, uint32_t flag);
extern void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi,
char *buf, size_t buf_len);
+extern bool bgp_path_info_labels_same(const struct bgp_path_info *bpi,
+ const mpls_label_t *label, uint32_t n);
extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *);
@@ -795,12 +793,12 @@ extern void bgp_update(struct peer *peer, const struct prefix *p,
uint32_t addpath_id, struct attr *attr, afi_t afi,
safi_t safi, int type, int sub_type,
struct prefix_rd *prd, mpls_label_t *label,
- uint32_t num_labels, int soft_reconfig,
+ uint8_t num_labels, int soft_reconfig,
struct bgp_route_evpn *evpn);
extern void bgp_withdraw(struct peer *peer, const struct prefix *p,
uint32_t addpath_id, afi_t afi, safi_t safi, int type,
int sub_type, struct prefix_rd *prd,
- mpls_label_t *label, uint32_t num_labels,
+ mpls_label_t *label, uint8_t num_labels,
struct bgp_route_evpn *evpn);
/* for bgp_nexthop and bgp_damp */
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index dc26a1f5d..9b0ca72e4 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -1056,7 +1056,7 @@ static enum route_map_cmd_result_t
route_match_vni(void *rule, const struct prefix *prefix, void *object)
{
vni_t vni = 0;
- unsigned int label_cnt = 0;
+ unsigned int label_cnt;
struct bgp_path_info *path = NULL;
struct prefix_evpn *evp = (struct prefix_evpn *) prefix;
@@ -1081,13 +1081,10 @@ route_match_vni(void *rule, const struct prefix *prefix, void *object)
&& evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE))
return RMAP_NOOP;
- if (path->extra == NULL)
- return RMAP_NOMATCH;
-
- for (;
- label_cnt < BGP_MAX_LABELS && label_cnt < path->extra->num_labels;
+ for (label_cnt = 0; label_cnt < BGP_MAX_LABELS &&
+ label_cnt < bgp_path_info_num_labels(path);
label_cnt++) {
- if (vni == label2vni(&path->extra->label[label_cnt]))
+ if (vni == label2vni(&path->extra->labels->label[label_cnt]))
return RMAP_MATCH;
}
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index f5508a0a7..a487f49e6 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -29,6 +29,7 @@
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
#include "bgp_advertise.h"
+#include "bgp_label.h"
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_aspath.h"
@@ -656,17 +657,16 @@ static void revalidate_bgp_node(struct bgp_dest *bgp_dest, afi_t afi,
safi_t safi)
{
struct bgp_adj_in *ain;
+ mpls_label_t *label;
+ uint8_t num_labels;
for (ain = bgp_dest->adj_in; ain; ain = ain->next) {
struct bgp_path_info *path =
bgp_dest_get_bgp_path_info(bgp_dest);
- mpls_label_t *label = NULL;
- uint32_t num_labels = 0;
- if (path && path->extra) {
- label = path->extra->label;
- num_labels = path->extra->num_labels;
- }
+ num_labels = bgp_path_info_num_labels(path);
+ label = num_labels ? path->extra->labels->label : NULL;
+
(void)bgp_update(ain->peer, bgp_dest_get_prefix(bgp_dest),
ain->addpath_rx_id, ain->attr, afi, safi,
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, label,
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index 0a852c75d..250378af6 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -78,6 +78,8 @@ static inline struct bgp_adj_out *adj_lookup(struct bgp_dest *dest,
static void adj_free(struct bgp_adj_out *adj)
{
+ bgp_labels_unintern(&adj->labels);
+
TAILQ_REMOVE(&(adj->subgroup->adjq), adj, subgrp_adj_train);
SUBGRP_DECR_STAT(adj->subgroup, adj_count);
@@ -572,7 +574,9 @@ bool bgp_adj_out_set_subgroup(struct bgp_dest *dest,
attr_hash = attrhash_key_make(attr);
if (!CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES) &&
- attr_hash && adj->attr_hash == attr_hash) {
+ attr_hash && adj->attr_hash == attr_hash &&
+ bgp_labels_cmp(path->extra ? path->extra->labels : NULL,
+ adj->labels)) {
if (BGP_DEBUG(update, UPDATE_OUT)) {
char attr_str[BUFSIZ] = {0};
@@ -614,6 +618,10 @@ bool bgp_adj_out_set_subgroup(struct bgp_dest *dest,
adv->baa = bgp_advertise_attr_intern(subgrp->hash, attr);
adv->adj = adj;
adj->attr_hash = attr_hash;
+ if (path->extra)
+ adj->labels = bgp_labels_intern(path->extra->labels);
+ else
+ adj->labels = NULL;
/* Add new advertisement to advertisement attribute list. */
bgp_advertise_add(adv->baa, adv);
diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c
index 1f691b6a9..6e30d4f84 100644
--- a/bgpd/bgp_updgrp_packet.c
+++ b/bgpd/bgp_updgrp_packet.c
@@ -667,7 +667,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
uint32_t addpath_tx_id = 0;
struct prefix_rd *prd = NULL;
mpls_label_t label = MPLS_INVALID_LABEL, *label_pnt = NULL;
- uint32_t num_labels = 0;
+ uint8_t num_labels = 0;
if (!subgrp)
return NULL;
@@ -814,9 +814,12 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
path);
label_pnt = &label;
num_labels = 1;
- } else if (path && path->extra) {
- label_pnt = &path->extra->label[0];
- num_labels = path->extra->num_labels;
+ } else {
+ num_labels = bgp_path_info_num_labels(path);
+ label_pnt =
+ num_labels
+ ? &path->extra->labels->label[0]
+ : NULL;
}
if (stream_empty(snlri))
@@ -1083,7 +1086,7 @@ void subgroup_default_update_packet(struct update_subgroup *subgrp,
struct bpacket_attr_vec_arr vecarr;
bool addpath_capable = false;
mpls_label_t label = MPLS_LABEL_IMPLICIT_NULL;
- uint32_t num_labels = 0;
+ uint8_t num_labels = 0;
if (DISABLE_BGP_ANNOUNCE)
return;
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 1c2f08465..8fab0d1c0 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1273,7 +1273,7 @@ static void bgp_zebra_announce_parse_nexthop(
struct bgp_path_info local_info;
struct bgp_path_info *mpinfo_cp = &local_info;
mpls_label_t *labels;
- uint32_t num_labels = 0;
+ uint8_t num_labels = 0;
mpls_label_t nh_label;
int nh_othervrf = 0;
bool nh_updated = false;
@@ -1301,8 +1301,6 @@ static void bgp_zebra_announce_parse_nexthop(
}
for (; mpinfo; mpinfo = bgp_path_info_mpath_next(mpinfo)) {
- labels = NULL;
- num_labels = 0;
uint64_t nh_weight;
bool is_evpn;
bool is_parent_evpn;
@@ -1341,15 +1339,14 @@ static void bgp_zebra_announce_parse_nexthop(
api_nh->srte_color = bgp_attr_get_color(info->attr);
if (bgp_debug_zebra(&api->prefix)) {
- if (mpinfo->extra) {
+ if (bgp_path_info_num_labels(mpinfo)) {
zlog_debug("%s: p=%pFX, bgp_is_valid_label: %d",
__func__, p,
bgp_is_valid_label(
- &mpinfo->extra->label[0]));
+ &mpinfo->extra->labels
+ ->label[0]));
} else {
- zlog_debug(
- "%s: p=%pFX, extra is NULL, no label",
- __func__, p);
+ zlog_debug("%s: p=%pFX, no label", __func__, p);
}
}
@@ -1415,13 +1412,10 @@ static void bgp_zebra_announce_parse_nexthop(
mpinfo->peer->sort == BGP_PEER_CONFED))
*allow_recursion = true;
- if (mpinfo->extra) {
- labels = mpinfo->extra->label;
- num_labels = mpinfo->extra->num_labels;
- }
+ num_labels = bgp_path_info_num_labels(mpinfo);
+ labels = num_labels ? mpinfo->extra->labels->label : NULL;
- if (labels && (num_labels > 0) &&
- (is_evpn || bgp_is_valid_label(&labels[0]))) {
+ if (num_labels && (is_evpn || bgp_is_valid_label(&labels[0]))) {
enum lsp_types_t nh_label_type = ZEBRA_LSP_NONE;
if (is_evpn) {
@@ -4112,8 +4106,7 @@ int bgp_zebra_srv6_manager_release_locator_chunk(const char *name)
void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
ifindex_t ifindex, vrf_id_t vrf_id,
enum lsp_types_t ltype, struct prefix *p,
- uint32_t num_labels,
- mpls_label_t out_labels[])
+ uint8_t num_labels, mpls_label_t out_labels[])
{
struct zapi_labels zl = {};
struct zapi_nexthop *znh;
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
index ef296b963..55a4185bd 100644
--- a/bgpd/bgp_zebra.h
+++ b/bgpd/bgp_zebra.h
@@ -120,7 +120,7 @@ extern int bgp_zebra_srv6_manager_release_locator_chunk(const char *name);
extern void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
ifindex_t index, vrf_id_t vrfid,
enum lsp_types_t ltype,
- struct prefix *p, uint32_t num_labels,
+ struct prefix *p, uint8_t num_labels,
mpls_label_t out_labels[]);
extern bool bgp_zebra_request_label_range(uint32_t base, uint32_t chunk_size,
bool label_auto);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index d8eba0ab2..81506f441 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -3620,10 +3620,13 @@ struct bgp *bgp_lookup_by_name(const char *name)
struct bgp *bgp;
struct listnode *node, *nnode;
- for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
+ continue;
if ((bgp->name == NULL && name == NULL)
|| (bgp->name && name && strcmp(bgp->name, name) == 0))
return bgp;
+ }
return NULL;
}
@@ -8547,6 +8550,7 @@ void bgp_init(unsigned short instance)
/* BGP inits. */
bgp_attr_init();
+ bgp_labels_init();
bgp_debug_init();
bgp_community_alias_init();
bgp_dump_init();
diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c
index ae899daf8..23e3eb482 100644
--- a/bgpd/rfapi/rfapi.c
+++ b/bgpd/rfapi/rfapi.c
@@ -549,6 +549,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
int flags)
{
afi_t afi; /* of the VN address */
+ struct bgp_labels bgp_labels = {};
struct bgp_path_info *new;
struct bgp_path_info *bpi;
struct bgp_dest *bn;
@@ -592,7 +593,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
}
}
- if (label)
+ if (label && *label != MPLS_INVALID_LABEL)
label_val = *label;
else
label_val = MPLS_LABEL_IMPLICIT_NULL;
@@ -1020,7 +1021,10 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
new->extra->vnc = XCALLOC(MTYPE_BGP_ROUTE_EXTRA_VNC,
sizeof(struct bgp_path_info_extra_vnc));
new->extra->vnc->vnc.export.rfapi_handle = (void *)rfd;
- encode_label(label_val, &new->extra->label[0]);
+
+ encode_label(label_val, &bgp_labels.label[0]);
+ bgp_labels.num_labels = 1;
+ new->extra->labels = bgp_labels_intern(&bgp_labels);
/* debug */
diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c
index 168b8e4c1..2afcb2f45 100644
--- a/bgpd/rfapi/rfapi_import.c
+++ b/bgpd/rfapi/rfapi_import.c
@@ -442,6 +442,7 @@ static struct bgp_path_info *rfapiBgpInfoCreate(struct attr *attr,
uint32_t *label)
{
struct bgp_path_info *new;
+ struct bgp_labels bgp_labels = {};
new = info_make(type, sub_type, 0, peer, attr, NULL);
@@ -454,8 +455,11 @@ static struct bgp_path_info *rfapiBgpInfoCreate(struct attr *attr,
new->extra->vnc->vnc.import.rd = *prd;
new->extra->vnc->vnc.import.create_time = monotime(NULL);
}
- if (label)
- encode_label(*label, &new->extra->label[0]);
+ if (label && *label != MPLS_INVALID_LABEL) {
+ encode_label(*label, &bgp_labels.label[0]);
+ bgp_labels.num_labels = 1;
+ new->extra->labels = bgp_labels_intern(&bgp_labels);
+ }
peer_lock(peer);
@@ -1267,7 +1271,10 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix,
bpi->extra->vnc->vnc.import.rd.val[1];
/* label comes from MP_REACH_NLRI label */
- vo->v.l2addr.label = decode_label(&bpi->extra->label[0]);
+ vo->v.l2addr.label =
+ bgp_path_info_num_labels(bpi)
+ ? decode_label(&bpi->extra->labels->label[0])
+ : MPLS_INVALID_LABEL;
new->vn_options = vo;
@@ -4154,15 +4161,16 @@ static void rfapiBgpTableFilteredImport(struct bgp *bgp,
for (bpi = bgp_dest_get_bgp_path_info(dest2);
bpi; bpi = bpi->next) {
- uint32_t label = 0;
+ uint32_t label = MPLS_INVALID_LABEL;
if (CHECK_FLAG(bpi->flags,
BGP_PATH_REMOVED))
continue;
- if (bpi->extra)
+ if (bgp_path_info_num_labels(bpi))
label = decode_label(
- &bpi->extra->label[0]);
+ &bpi->extra->labels
+ ->label[0]);
(*rfapiBgpInfoFilteredImportFunction(
safi))(
it, /* which import table */
diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c
index 316904e45..a0bdf4961 100644
--- a/bgpd/rfapi/rfapi_rib.c
+++ b/bgpd/rfapi/rfapi_rib.c
@@ -691,7 +691,10 @@ static void rfapiRibBi2Ri(struct bgp_path_info *bpi, struct rfapi_info *ri,
bpi->extra->vnc->vnc.import.rd.val[1];
/* label comes from MP_REACH_NLRI label */
- vo->v.l2addr.label = decode_label(&bpi->extra->label[0]);
+ vo->v.l2addr.label =
+ bgp_path_info_num_labels(bpi)
+ ? decode_label(&bpi->extra->labels->label[0])
+ : MPLS_INVALID_LABEL;
rfapi_vn_options_free(
ri->vn_options); /* maybe free old version */
diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c
index 5da99dbc4..9bfb6c4b4 100644
--- a/bgpd/rfapi/rfapi_vty.c
+++ b/bgpd/rfapi/rfapi_vty.c
@@ -413,12 +413,12 @@ void rfapi_vty_out_vncinfo(struct vty *vty, const struct prefix *p,
XFREE(MTYPE_ECOMMUNITY_STR, s);
}
- if (bpi->extra != NULL) {
- if (bpi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
+ if (bgp_path_info_num_labels(bpi)) {
+ if (bpi->extra->labels->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
vty_out(vty, " label=VRF2VRF");
else
vty_out(vty, " label=%u",
- decode_label(&bpi->extra->label[0]));
+ decode_label(&bpi->extra->labels->label[0]));
}
if (bpi->attr->srv6_l3vpn || bpi->attr->srv6_vpn) {
@@ -1052,8 +1052,8 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
snprintf(buf_un, sizeof(buf_un), "%s",
inet_ntop(pfx_vn.family, &pfx_vn.u.prefix, buf_ntop,
sizeof(buf_ntop)));
- if (bpi->extra) {
- uint32_t l = decode_label(&bpi->extra->label[0]);
+ if (bgp_path_info_num_labels(bpi)) {
+ uint32_t l = decode_label(&bpi->extra->labels->label[0]);
snprintf(buf_vn, sizeof(buf_vn), "Label: %d", l);
} else /* should never happen */
{
@@ -1161,8 +1161,8 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
}
}
}
- if (tun_type != BGP_ENCAP_TYPE_MPLS && bpi->extra) {
- uint32_t l = decode_label(&bpi->extra->label[0]);
+ if (tun_type != BGP_ENCAP_TYPE_MPLS && bgp_path_info_num_labels(bpi)) {
+ uint32_t l = decode_label(&bpi->extra->labels->label[0]);
if (!MPLS_LABEL_IS_NULL(l)) {
fp(out, " Label: %d", l);
diff --git a/bgpd/rfapi/vnc_import_bgp.c b/bgpd/rfapi/vnc_import_bgp.c
index c067b7a61..2bb7c1b16 100644
--- a/bgpd/rfapi/vnc_import_bgp.c
+++ b/bgpd/rfapi/vnc_import_bgp.c
@@ -414,7 +414,7 @@ static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
uint32_t lifetime;
uint32_t *plifetime;
struct bgp_attr_encap_subtlv *encaptlvs;
- uint32_t label = 0;
+ uint32_t label;
struct rfapi_un_option optary[3];
struct rfapi_un_option *opt = NULL;
@@ -470,16 +470,19 @@ static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
if (bgp_attr_get_ecommunity(bpi->attr))
ecommunity_merge(new_ecom, bgp_attr_get_ecommunity(bpi->attr));
- if (bpi->extra)
- label = decode_label(&bpi->extra->label[0]);
+ if (bgp_path_info_num_labels(bpi))
+ label = decode_label(&bpi->extra->labels->label[0]);
+ else
+ label = MPLS_INVALID_LABEL;
add_vnc_route(&vncHDResolveNve, bgp, SAFI_MPLS_VPN,
- prefix, /* unicast route prefix */
+ prefix, /* unicast route prefix */
prd, &nexthop_h, /* new nexthop */
local_pref, plifetime,
(struct bgp_tea_options *)encaptlvs, /* RFP options */
opt, NULL, new_ecom, med, /* NULL => don't set med */
- (label ? &label : NULL), /* NULL= default */
+ ((label != MPLS_INVALID_LABEL) ? &label
+ : NULL), /* NULL= default */
ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
RFAPI_AHR_RFPOPT_IS_VNCTLV); /* flags */
@@ -1678,7 +1681,7 @@ static void vnc_import_bgp_exterior_add_route_it(
bpi_interior = bpi_interior->next) {
struct prefix_rd *prd;
struct attr new_attr;
- uint32_t label = 0;
+ uint32_t label;
if (!is_usable_interior_route(bpi_interior))
continue;
@@ -1695,14 +1698,19 @@ static void vnc_import_bgp_exterior_add_route_it(
*/
have_usable_route = 1;
- if (bpi_interior->extra) {
+ if (bpi_interior->extra)
prd = &bpi_interior->extra->vnc->vnc
.import.rd;
- label = decode_label(
- &bpi_interior->extra->label[0]);
- } else
+ else
prd = NULL;
+ if (bgp_path_info_num_labels(bpi_interior))
+ label = decode_label(
+ &bpi_interior->extra->labels
+ ->label[0]);
+ else
+ label = MPLS_INVALID_LABEL;
+
/* use local_pref from unicast route */
memset(&new_attr, 0, sizeof(new_attr));
new_attr = *bpi_interior->attr;
@@ -1851,7 +1859,7 @@ void vnc_import_bgp_exterior_del_route(
for (bpi_interior = rn->info; bpi_interior;
bpi_interior = bpi_interior->next) {
struct prefix_rd *prd;
- uint32_t label = 0;
+ uint32_t label;
if (!is_usable_interior_route(bpi_interior))
continue;
@@ -1864,14 +1872,19 @@ void vnc_import_bgp_exterior_del_route(
*/
have_usable_route = 1;
- if (bpi_interior->extra) {
+ if (bpi_interior->extra)
prd = &bpi_interior->extra->vnc->vnc
.import.rd;
- label = decode_label(
- &bpi_interior->extra->label[0]);
- } else
+ else
prd = NULL;
+ if (bgp_path_info_num_labels(bpi_interior))
+ label = decode_label(
+ &bpi_interior->extra->labels
+ ->label[0]);
+ else
+ label = MPLS_INVALID_LABEL;
+
rfapiBgpInfoFilteredImportVPN(
it, FIF_ACTION_KILL, bpi_interior->peer,
NULL, /* rfd */
@@ -2007,18 +2020,22 @@ void vnc_import_bgp_exterior_add_route_interior(
struct prefix_rd *prd;
struct attr new_attr;
- uint32_t label = 0;
+ uint32_t label;
assert(bpi_exterior);
assert(pfx_exterior);
- if (bpi_interior->extra) {
+ if (bpi_interior->extra)
prd = &bpi_interior->extra->vnc->vnc.import.rd;
- label = decode_label(
- &bpi_interior->extra->label[0]);
- } else
+ else
prd = NULL;
+ if (bgp_path_info_num_labels(bpi_interior))
+ label = decode_label(
+ &bpi_interior->extra->labels->label[0]);
+ else
+ label = MPLS_INVALID_LABEL;
+
/* use local_pref from unicast route */
memset(&new_attr, 0, sizeof(struct attr));
new_attr = *bpi_interior->attr;
@@ -2097,7 +2114,7 @@ void vnc_import_bgp_exterior_add_route_interior(
struct bgp_path_info *bpi;
struct prefix_rd *prd;
struct attr new_attr;
- uint32_t label = 0;
+ uint32_t label;
/* do pull-down */
@@ -2124,15 +2141,19 @@ void vnc_import_bgp_exterior_add_route_interior(
* parent routes.
*/
for (bpi = par->info; bpi; bpi = bpi->next) {
-
- if (bpi->extra) {
+ if (bpi->extra)
prd = &bpi->extra->vnc->vnc
.import.rd;
- label = decode_label(
- &bpi->extra->label[0]);
- } else
+ else
prd = NULL;
+ if (bgp_path_info_num_labels(bpi))
+ label = decode_label(
+ &bpi->extra->labels
+ ->label[0]);
+ else
+ label = MPLS_INVALID_LABEL;
+
rfapiBgpInfoFilteredImportVPN(
it, FIF_ACTION_KILL, bpi->peer,
NULL, /* rfd */
@@ -2147,14 +2168,19 @@ void vnc_import_bgp_exterior_add_route_interior(
* Add constructed exterior routes based on
* the new interior route at longer prefix.
*/
- if (bpi_interior->extra) {
+ if (bpi_interior->extra)
prd = &bpi_interior->extra->vnc->vnc
.import.rd;
- label = decode_label(
- &bpi_interior->extra->label[0]);
- } else
+ else
prd = NULL;
+ if (bgp_path_info_num_labels(bpi_interior))
+ label = decode_label(
+ &bpi_interior->extra->labels
+ ->label[0]);
+ else
+ label = MPLS_INVALID_LABEL;
+
/* use local_pref from unicast route */
memset(&new_attr, 0, sizeof(struct attr));
new_attr = *bpi_interior->attr;
@@ -2237,7 +2263,7 @@ void vnc_import_bgp_exterior_add_route_interior(
struct prefix_rd *prd;
struct attr new_attr;
- uint32_t label = 0;
+ uint32_t label;
/* do pull-down */
@@ -2266,13 +2292,17 @@ void vnc_import_bgp_exterior_add_route_interior(
* Add constructed exterior routes based on the
* new interior route at the longer prefix.
*/
- if (bpi_interior->extra) {
+ if (bpi_interior->extra)
prd = &bpi_interior->extra->vnc->vnc.import.rd;
- label = decode_label(
- &bpi_interior->extra->label[0]);
- } else
+ else
prd = NULL;
+ if (bgp_path_info_num_labels(bpi_interior))
+ label = decode_label(
+ &bpi_interior->extra->labels->label[0]);
+ else
+ label = MPLS_INVALID_LABEL;
+
/* use local_pref from unicast route */
memset(&new_attr, 0, sizeof(struct attr));
new_attr = *bpi_interior->attr;
@@ -2372,14 +2402,19 @@ void vnc_import_bgp_exterior_del_route_interior(
&cursor)) {
struct prefix_rd *prd;
- uint32_t label = 0;
+ uint32_t label;
- if (bpi_interior->extra) {
+ if (bpi_interior->extra)
prd = &bpi_interior->extra->vnc->vnc.import.rd;
- label = decode_label(&bpi_interior->extra->label[0]);
- } else
+ else
prd = NULL;
+ if (bgp_path_info_num_labels(bpi_interior))
+ label = decode_label(
+ &bpi_interior->extra->labels->label[0]);
+ else
+ label = MPLS_INVALID_LABEL;
+
rfapiBgpInfoFilteredImportVPN(
it, FIF_ACTION_KILL, bpi_interior->peer, NULL, /* rfd */
pfx_exterior, NULL, afi, prd, bpi_interior->attr,
@@ -2446,18 +2481,22 @@ void vnc_import_bgp_exterior_del_route_interior(
struct prefix_rd *prd;
struct attr new_attr;
- uint32_t label = 0;
+ uint32_t label;
if (bpi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT)
continue;
- if (bpi->extra) {
+ if (bpi->extra)
prd = &bpi->extra->vnc->vnc.import.rd;
- label = decode_label(
- &bpi->extra->label[0]);
- } else
+ else
prd = NULL;
+ if (bgp_path_info_num_labels(bpi))
+ label = decode_label(
+ &bpi->extra->labels->label[0]);
+ else
+ label = MPLS_INVALID_LABEL;
+
/* use local_pref from unicast route */
memset(&new_attr, 0, sizeof(new_attr));
new_attr = *bpi->attr;
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 58fdbf969..150a915e3 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -4102,6 +4102,10 @@ The following are available in the top level *enable* mode:
Clear all peers.
+.. clicmd:: clear bgp ipv4|ipv6 ASNUM
+
+ Clear peers with the AS number in plain or dotted format.
+
.. clicmd:: clear bgp ipv4|ipv6 \*
Clear all peers with this address-family activated.
diff --git a/docker/debian/Dockerfile b/docker/debian/Dockerfile
index d136538c7..b317b0598 100644
--- a/docker/debian/Dockerfile
+++ b/docker/debian/Dockerfile
@@ -24,5 +24,5 @@ RUN chown -R frr:frr /etc/frr /var/run/frr
ENTRYPOINT ["/usr/bin/tini", "--"]
# Default CMD starts watchfrr
-COPY docker-start /usr/lib/frr/docker-start
+COPY --chmod=0755 docker-start /usr/lib/frr/docker-start
CMD ["/usr/lib/frr/docker-start"]
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index 9e875ff6e..c98cee06a 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -705,6 +705,10 @@ void lsp_print_common(struct isis_lsp *lsp, struct vty *vty, struct json_object
}
}
+#if CONFDATE > 20240916
+CPP_NOTICE("Remove JSON in '-' format")
+#endif
+
void lsp_print_json(struct isis_lsp *lsp, struct json_object *json,
char dynhost, struct isis *isis)
{
@@ -718,10 +722,20 @@ void lsp_print_json(struct isis_lsp *lsp, struct json_object *json,
own_json = json_object_new_object();
json_object_object_add(json, "lsp", own_json);
json_object_string_add(own_json, "id", LSPid);
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove own key")
+#endif
json_object_string_add(own_json, "own", lsp->own_lsp ? "*" : " ");
+ if (lsp->own_lsp)
+ json_object_boolean_add(own_json, "ownLSP", true);
json_object_int_add(json, "pdu-len", lsp->hdr.pdu_len);
+ json_object_int_add(json, "pduLen", lsp->hdr.pdu_len);
snprintfrr(buf, sizeof(buf), "0x%08x", lsp->hdr.seqno);
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove seq-number key")
+#endif
json_object_string_add(json, "seq-number", buf);
+ json_object_string_add(json, "seqNumber", buf);
snprintfrr(buf, sizeof(buf), "0x%04hx", lsp->hdr.checksum);
json_object_string_add(json, "chksum", buf);
if (lsp->hdr.rem_lifetime == 0) {
@@ -731,8 +745,13 @@ void lsp_print_json(struct isis_lsp *lsp, struct json_object *json,
} else {
json_object_int_add(json, "holdtime", lsp->hdr.rem_lifetime);
}
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove att-p-ol key")
+#endif
json_object_string_add(
json, "att-p-ol", lsp_bits2string(lsp->hdr.lsp_bits, b, sizeof(b)));
+ json_object_string_add(json, "attPOl",
+ lsp_bits2string(lsp->hdr.lsp_bits, b, sizeof(b)));
}
void lsp_print_vty(struct isis_lsp *lsp, struct vty *vty,
diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c
index 93ae8c6cb..3bb8a4824 100644
--- a/isisd/isis_tlvs.c
+++ b/isisd/isis_tlvs.c
@@ -348,9 +348,120 @@ copy_item_ext_subtlvs(struct isis_ext_subtlvs *exts, uint16_t mtid)
}
static void format_item_asla_subtlvs(struct isis_asla_subtlvs *asla,
+ struct json_object *ext_json,
struct sbuf *buf, int indent)
{
char admin_group_buf[ADMIN_GROUP_PRINT_MAX_SIZE];
+ struct json_object *json;
+ char cnt_buf[255];
+ size_t i;
+ int j;
+
+ if (ext_json) {
+ json = json_object_new_object();
+ json_object_object_add(ext_json, "asla", json);
+ json_object_boolean_add(json, "legacyFlag", asla->legacy);
+ json_object_string_addf(json, "standardApp", "0x%02x",
+ asla->standard_apps);
+ if (IS_SUBTLV(asla, EXT_ADM_GRP))
+ json_object_string_addf(json, "adminGroup", "0x%x",
+ asla->admin_group);
+ if (IS_SUBTLV(asla, EXT_EXTEND_ADM_GRP) &&
+ admin_group_nb_words(&asla->ext_admin_group) != 0) {
+ struct json_object *ext_adm_grp_json;
+
+ ext_adm_grp_json = json_object_new_object();
+ json_object_object_add(json, "extendedAdminGroup",
+ ext_adm_grp_json);
+ for (i = 0;
+ i < admin_group_nb_words(&asla->ext_admin_group);
+ i++) {
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%lu",
+ (unsigned long)i);
+ json_object_string_addf(ext_adm_grp_json,
+ cnt_buf, "0x%x",
+ asla->ext_admin_group
+ .bitmap.data[i]);
+ }
+ }
+ if (IS_SUBTLV(asla, EXT_MAX_BW))
+ json_object_string_addf(json, "maxBandwithBytesSec",
+ "%g", asla->max_bw);
+ if (IS_SUBTLV(asla, EXT_MAX_RSV_BW))
+ json_object_string_addf(json, "maxResBandwithBytesSec",
+ "%g", asla->max_rsv_bw);
+ if (IS_SUBTLV(asla, EXT_UNRSV_BW)) {
+ struct json_object *unrsv_json =
+ json_object_new_object();
+
+ json_object_object_add(json, "unrsvBandwithBytesSec",
+ unrsv_json);
+ for (j = 0; j < MAX_CLASS_TYPE; j += 1) {
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%d", j);
+ json_object_string_addf(unrsv_json, cnt_buf,
+ "%g", asla->unrsv_bw[j]);
+ }
+ }
+ if (IS_SUBTLV(asla, EXT_TE_METRIC))
+ json_object_int_add(json, "teMetric", asla->te_metric);
+
+ /* Extended metrics */
+ if (IS_SUBTLV(asla, EXT_DELAY)) {
+ struct json_object *avg_json;
+
+ avg_json = json_object_new_object();
+ json_object_object_add(json, "avgDelay", avg_json);
+ json_object_string_add(avg_json, "delay",
+ IS_ANORMAL(asla->delay)
+ ? "Anomalous"
+ : "Normal");
+ json_object_int_add(avg_json, "microSec", asla->delay);
+ }
+ if (IS_SUBTLV(asla, EXT_MM_DELAY)) {
+ struct json_object *avg_json;
+
+ avg_json = json_object_new_object();
+ json_object_object_add(json, "maxMinDelay", avg_json);
+ json_object_string_add(avg_json, "delay",
+ IS_ANORMAL(asla->min_delay)
+ ? "Anomalous"
+ : "Normal");
+ json_object_string_addf(avg_json, "microSec", "%u / %u",
+ asla->min_delay & TE_EXT_MASK,
+ asla->max_delay & TE_EXT_MASK);
+ }
+ if (IS_SUBTLV(asla, EXT_DELAY_VAR))
+ json_object_int_add(json, "delayVariationMicroSec",
+ asla->delay_var & TE_EXT_MASK);
+ if (IS_SUBTLV(asla, EXT_PKT_LOSS)) {
+ struct json_object *link_json;
+
+ link_json = json_object_new_object();
+ json_object_object_add(json, "linkPacketLoss",
+ link_json);
+ json_object_string_add(link_json, "loss",
+ IS_ANORMAL(asla->pkt_loss)
+ ? "Anomalous"
+ : "Normal");
+ json_object_string_addf(link_json, "percentage", "%g",
+ (float)((asla->pkt_loss &
+ TE_EXT_MASK) *
+ LOSS_PRECISION));
+ }
+ if (IS_SUBTLV(asla, EXT_RES_BW))
+ json_object_string_addf(json,
+ "unidirResidualBandBytesSec",
+ "%g", (asla->res_bw));
+ if (IS_SUBTLV(asla, EXT_AVA_BW))
+ json_object_string_addf(json,
+ "unidirAvailableBandBytesSec",
+ "%g", (asla->ava_bw));
+ if (IS_SUBTLV(asla, EXT_USE_BW))
+ json_object_string_addf(json,
+ "unidirUtilizedBandBytesSec",
+ "%g", (asla->use_bw));
+ return;
+ }
sbuf_push(buf, indent, "Application Specific Link Attributes:\n");
sbuf_push(buf, indent + 2,
@@ -454,6 +565,10 @@ static void format_item_asla_subtlvs(struct isis_asla_subtlvs *asla,
asla->use_bw);
}
+#if CONFDATE > 20240916
+CPP_NOTICE("Remove JSON in '-' format")
+#endif
+
/* mtid parameter is used to manage multi-topology i.e. IPv4 / IPv6 */
static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
struct sbuf *buf, struct json_object *json,
@@ -470,7 +585,11 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
snprintfrr(aux_buf, sizeof(aux_buf), "0x%x",
exts->adm_group);
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "adm-group", aux_buf);
+ json_object_string_add(json, "admGroup", aux_buf);
} else {
sbuf_push(buf, indent, "Admin Group: 0x%08x\n",
exts->adm_group);
@@ -484,8 +603,23 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (IS_SUBTLV(exts, EXT_EXTEND_ADM_GRP) &&
admin_group_nb_words(&exts->ext_admin_group) != 0) {
- if (!json) {
- /* TODO json after fix show database detail json */
+ if (json) {
+ struct json_object *ext_adm_grp_json;
+ size_t i;
+ ext_adm_grp_json = json_object_new_object();
+ json_object_object_add(json, "extendedAdminGroup",
+ ext_adm_grp_json);
+ for (i = 0;
+ i < admin_group_nb_words(&exts->ext_admin_group);
+ i++) {
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%lu",
+ (unsigned long)i);
+ json_object_string_addf(ext_adm_grp_json,
+ cnt_buf, "0x%x",
+ exts->ext_admin_group
+ .bitmap.data[i]);
+ }
+ } else {
sbuf_push(buf, indent, "Ext Admin Group: %s\n",
admin_group_string(
admin_group_buf,
@@ -505,10 +639,17 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
}
if (IS_SUBTLV(exts, EXT_LLRI)) {
if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_int_add(json, "link-local-id",
exts->local_llri);
json_object_int_add(json, "link-remote-id",
exts->remote_llri);
+ json_object_int_add(json, "linkLocalId",
+ exts->local_llri);
+ json_object_int_add(json, "linkRemoteId",
+ exts->remote_llri);
} else {
sbuf_push(buf, indent, "Link Local ID: %u\n",
exts->local_llri);
@@ -520,7 +661,11 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
inet_ntop(AF_INET, &exts->local_addr, aux_buf,
sizeof(aux_buf));
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "local-iface-ip", aux_buf);
+ json_object_string_add(json, "localIfaceIp", aux_buf);
} else
sbuf_push(buf, indent,
"Local Interface IP Address(es): %pI4\n",
@@ -530,8 +675,12 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
inet_ntop(AF_INET, &exts->neigh_addr, aux_buf,
sizeof(aux_buf));
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "remote-iface-ip",
aux_buf);
+ json_object_string_add(json, "remoteIfaceIp", aux_buf);
} else
sbuf_push(buf, indent,
"Remote Interface IP Address(es): %pI4\n",
@@ -541,8 +690,12 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
inet_ntop(AF_INET6, &exts->local_addr6, aux_buf,
sizeof(aux_buf));
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "local-iface-ipv6",
aux_buf);
+ json_object_string_add(json, "localIfaceIpv6", aux_buf);
} else
sbuf_push(buf, indent,
"Local Interface IPv6 Address(es): %pI6\n",
@@ -552,8 +705,12 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
inet_ntop(AF_INET6, &exts->neigh_addr6, aux_buf,
sizeof(aux_buf));
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "remote-iface-ipv6",
aux_buf);
+ json_object_string_add(json, "remoteIfaceIpv6", aux_buf);
} else
sbuf_push(buf, indent,
"Remote Interface IPv6 Address(es): %pI6\n",
@@ -563,8 +720,13 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
snprintfrr(aux_buf, sizeof(aux_buf), "%g",
exts->max_bw);
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "max-bandwith-bytes-sec",
aux_buf);
+ json_object_string_add(json, "maxBandwithBytesSec",
+ aux_buf);
} else
sbuf_push(buf, indent,
"Maximum Bandwidth: %g (Bytes/sec)\n",
@@ -574,8 +736,13 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
snprintfrr(aux_buf, sizeof(aux_buf), "%g",
exts->max_rsv_bw);
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(
json, "max-res-bandwith-bytes-sec", aux_buf);
+ json_object_string_add(json, "maxResBandwithBytesSec",
+ aux_buf);
} else
sbuf_push(
buf, indent,
@@ -585,6 +752,22 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (IS_SUBTLV(exts, EXT_UNRSV_BW)) {
if (json) {
struct json_object *unrsv_json;
+
+ unrsv_json = json_object_new_object();
+ json_object_object_add(json, "unrsvBandwithBytesSec",
+ unrsv_json);
+ for (int j = 0; j < MAX_CLASS_TYPE; j += 1) {
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%d", j);
+ snprintfrr(aux_buf, sizeof(aux_buf), "%g",
+ exts->unrsv_bw[j]);
+ json_object_string_add(unrsv_json, cnt_buf,
+ aux_buf);
+ }
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
unrsv_json = json_object_new_object();
json_object_object_add(json, "unrsv-bandwith-bytes-sec",
unrsv_json);
@@ -595,6 +778,7 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
json_object_string_add(unrsv_json, cnt_buf,
aux_buf);
}
+ /* end old deprecated key format */
} else {
sbuf_push(buf, indent, "Unreserved Bandwidth:\n");
for (int j = 0; j < MAX_CLASS_TYPE; j += 2) {
@@ -608,7 +792,11 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
}
if (IS_SUBTLV(exts, EXT_TE_METRIC)) {
if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_int_add(json, "te-metric", exts->te_metric);
+ json_object_int_add(json, "teMetric", exts->te_metric);
} else
sbuf_push(buf, indent,
"Traffic Engineering Metric: %u\n",
@@ -616,8 +804,13 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
}
if (IS_SUBTLV(exts, EXT_RMT_AS)) {
if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_int_add(json, "inter-as-te-remote-as",
exts->remote_as);
+ json_object_int_add(json, "interAsTeRemoteAs",
+ exts->remote_as);
} else
sbuf_push(buf, indent,
"Inter-AS TE Remote AS number: %u\n",
@@ -627,8 +820,13 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
inet_ntop(AF_INET6, &exts->remote_ip, aux_buf,
sizeof(aux_buf));
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(
json, "inter-as-te-remote-asbr-ip", aux_buf);
+ json_object_string_add(json, "interAsTeRemoteAsbrIp",
+ aux_buf);
} else
sbuf_push(buf, indent,
"Inter-AS TE Remote ASBR IP address: %pI4\n",
@@ -639,12 +837,23 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
struct json_object *avg_json;
avg_json = json_object_new_object();
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_object_add(json, "avg-delay", avg_json);
json_object_string_add(avg_json, "delay",
IS_ANORMAL(exts->delay)
? "Anomalous"
: "Normal");
json_object_int_add(avg_json, "micro-sec", exts->delay);
+
+ avg_json = json_object_new_object();
+ json_object_object_add(json, "avgDelay", avg_json);
+ json_object_string_add(avg_json, "delay",
+ IS_ANORMAL(exts->delay)
+ ? "Anomalous"
+ : "Normal");
+ json_object_int_add(avg_json, "microSec", exts->delay);
} else
sbuf_push(buf, indent,
"%s Average Link Delay: %u (micro-sec)\n",
@@ -656,6 +865,9 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
struct json_object *avg_json;
avg_json = json_object_new_object();
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_object_add(json, "max-min-delay", avg_json);
json_object_string_add(avg_json, "delay",
IS_ANORMAL(exts->min_delay)
@@ -666,6 +878,17 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
exts->max_delay & TE_EXT_MASK);
json_object_string_add(avg_json, "micro-sec", aux_buf);
+ avg_json = json_object_new_object();
+ json_object_object_add(json, "maxMinDelay", avg_json);
+ json_object_string_add(avg_json, "delay",
+ IS_ANORMAL(exts->min_delay)
+ ? "Anomalous"
+ : "Normal");
+ snprintfrr(aux_buf, sizeof(aux_buf), "%u / %u",
+ exts->min_delay & TE_EXT_MASK,
+ exts->max_delay & TE_EXT_MASK);
+ json_object_string_add(avg_json, "microSec", aux_buf);
+
} else
sbuf_push(
buf, indent,
@@ -677,8 +900,13 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
}
if (IS_SUBTLV(exts, EXT_DELAY_VAR)) {
if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_int_add(json, "delay-variation-micro-sec",
exts->delay_var & TE_EXT_MASK);
+ json_object_int_add(json, "delayVariationMicroSec",
+ exts->delay_var & TE_EXT_MASK);
} else
sbuf_push(buf, indent,
"Delay Variation: %u (micro-sec)\n",
@@ -690,6 +918,10 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
(float)((exts->pkt_loss & TE_EXT_MASK) *
LOSS_PRECISION));
struct json_object *link_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
link_json = json_object_new_object();
json_object_object_add(json, "link-packet-loss",
link_json);
@@ -697,8 +929,18 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
IS_ANORMAL(exts->pkt_loss)
? "Anomalous"
: "Normal");
+ /* typo */
json_object_string_add(link_json, "percentaje",
aux_buf);
+
+ link_json = json_object_new_object();
+ json_object_object_add(json, "linkPacketLoss",
+ link_json);
+ json_object_string_add(link_json, "loss",
+ IS_ANORMAL(exts->pkt_loss)
+ ? "Anomalous"
+ : "Normal");
+ json_object_string_add(link_json, "percentage", aux_buf);
} else
sbuf_push(buf, indent, "%s Link Packet Loss: %g (%%)\n",
IS_ANORMAL(exts->pkt_loss) ? "Anomalous"
@@ -710,9 +952,15 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
snprintfrr(aux_buf, sizeof(aux_buf), "%g",
(exts->res_bw));
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json,
"unidir-residual-band-bytes-sec",
aux_buf);
+ json_object_string_add(json,
+ "unidirResidualBandBytesSec",
+ aux_buf);
} else
sbuf_push(
buf, indent,
@@ -723,9 +971,15 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
snprintfrr(aux_buf, sizeof(aux_buf), "%g",
(exts->ava_bw));
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(
json, "unidir-available-band-bytes-sec",
aux_buf);
+ json_object_string_add(json,
+ "unidirAvailableBandBytesSec",
+ aux_buf);
} else
sbuf_push(
buf, indent,
@@ -739,6 +993,12 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
json_object_string_add(json,
"unidir-utilized-band-bytes-sec",
aux_buf);
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ json_object_string_add(json,
+ "unidirUtilizedBandBytesSec",
+ aux_buf);
} else
sbuf_push(
buf, indent,
@@ -751,6 +1011,11 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
struct json_object *arr_adj_json, *flags_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
arr_adj_json = json_object_new_array();
json_object_object_add(json, "adj-sid", arr_adj_json);
for (adj = (struct isis_adj_sid *)exts->adj_sid.head;
@@ -794,6 +1059,44 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
: "0");
json_object_array_add(arr_adj_json, flags_json);
}
+ /* end old deprecated key format */
+
+ arr_adj_json = json_object_new_array();
+ json_object_object_add(json, "adjSid", arr_adj_json);
+ for (adj = (struct isis_adj_sid *)exts->adj_sid.head;
+ adj; adj = adj->next) {
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%d",
+ adj->sid);
+ flags_json = json_object_new_object();
+ json_object_int_add(flags_json, "sid", adj->sid);
+ json_object_int_add(flags_json, "weight",
+ adj->weight);
+ json_object_boolean_add(flags_json, "flagF",
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_FFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagB",
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_BFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagV",
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_VFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagL",
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_LFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagS",
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_SFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagP",
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_PFLG
+ ? true
+ : false);
+ json_object_array_add(arr_adj_json, flags_json);
+ }
} else
for (adj = (struct isis_adj_sid *)exts->adj_sid.head;
adj; adj = adj->next) {
@@ -826,6 +1129,11 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
struct isis_lan_adj_sid *lan;
if (json) {
struct json_object *arr_adj_json, *flags_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
arr_adj_json = json_object_new_array();
json_object_object_add(json, "lan-adj-sid",
arr_adj_json);
@@ -876,6 +1184,49 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
: "0");
json_object_array_add(arr_adj_json, flags_json);
}
+ /* end old deprecated key format */
+
+ arr_adj_json = json_object_new_array();
+ json_object_object_add(json, "lanAdjSid", arr_adj_json);
+ for (lan = (struct isis_lan_adj_sid *)exts->adj_sid.head;
+ lan; lan = lan->next) {
+ if (((mtid == ISIS_MT_IPV4_UNICAST) &&
+ (lan->family != AF_INET)) ||
+ ((mtid == ISIS_MT_IPV6_UNICAST) &&
+ (lan->family != AF_INET6)))
+ continue;
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%d",
+ lan->sid);
+ flags_json = json_object_new_object();
+ json_object_int_add(flags_json, "sid", lan->sid);
+ json_object_int_add(flags_json, "weight",
+ lan->weight);
+ json_object_boolean_add(flags_json, "flagF",
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_FFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagB",
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_BFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagV",
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_VFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagL",
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_LFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagS",
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_SFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagP",
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_PFLG
+ ? true
+ : false);
+ json_object_array_add(arr_adj_json, flags_json);
+ }
} else
for (lan = (struct isis_lan_adj_sid *)
@@ -918,6 +1269,11 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
struct json_object *arr_adj_json, *flags_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
arr_adj_json = json_object_new_array();
json_object_object_add(json, "srv6-endx-sid",
arr_adj_json);
@@ -955,7 +1311,47 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
json_object_array_add(arr_adj_json, flags_json);
if (adj->subsubtlvs)
isis_format_subsubtlvs(adj->subsubtlvs,
- NULL, json,
+ NULL,
+ arr_adj_json,
+ indent + 4);
+ }
+ /* end old deprecated key format */
+
+ arr_adj_json = json_object_new_array();
+ json_object_object_add(json, "srv6EndSID", arr_adj_json);
+ for (adj = (struct isis_srv6_endx_sid_subtlv *)
+ exts->srv6_endx_sid.head;
+ adj; adj = adj->next) {
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%pI6",
+ &adj->sid);
+ flags_json = json_object_new_object();
+ json_object_string_addf(flags_json, "sid",
+ "%pI6", &adj->sid);
+ json_object_string_add(flags_json, "algorithm",
+ sr_algorithm_string(
+ adj->algorithm));
+ json_object_int_add(flags_json, "weight",
+ adj->weight);
+ json_object_string_add(flags_json, "behavior",
+ seg6local_action2str(
+ adj->behavior));
+ json_object_boolean_add(
+ flags_json, "flagB",
+ !!(adj->flags &
+ EXT_SUBTLV_LINK_SRV6_ENDX_SID_BFLG));
+ json_object_boolean_add(
+ flags_json, "flagS",
+ !!(adj->flags &
+ EXT_SUBTLV_LINK_SRV6_ENDX_SID_SFLG));
+ json_object_boolean_add(
+ flags_json, "flagP",
+ !!(adj->flags &
+ EXT_SUBTLV_LINK_SRV6_ENDX_SID_PFLG));
+ json_object_array_add(arr_adj_json, flags_json);
+ if (adj->subsubtlvs)
+ isis_format_subsubtlvs(adj->subsubtlvs,
+ NULL,
+ arr_adj_json,
indent + 4);
}
} else
@@ -989,6 +1385,11 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
struct isis_srv6_lan_endx_sid_subtlv *lan;
if (json) {
struct json_object *arr_adj_json, *flags_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
arr_adj_json = json_object_new_array();
json_object_object_add(json, "srv6-lan-endx-sid",
arr_adj_json);
@@ -1031,7 +1432,53 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
json_object_array_add(arr_adj_json, flags_json);
if (lan->subsubtlvs)
isis_format_subsubtlvs(lan->subsubtlvs,
- NULL, json,
+ NULL,
+ arr_adj_json,
+ indent + 4);
+ }
+ /* end old deprecated key format */
+
+ arr_adj_json = json_object_new_array();
+ json_object_object_add(json, "srv6LanEndxSID",
+ arr_adj_json);
+ for (lan = (struct isis_srv6_lan_endx_sid_subtlv *)
+ exts->srv6_lan_endx_sid.head;
+ lan; lan = lan->next) {
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%pI6",
+ &lan->sid);
+ flags_json = json_object_new_object();
+ json_object_string_addf(flags_json, "sid",
+ "%pI6", &lan->sid);
+ json_object_int_add(flags_json, "weight",
+ lan->weight);
+ json_object_string_add(flags_json, "algorithm",
+ sr_algorithm_string(
+ lan->algorithm));
+ json_object_int_add(flags_json, "weight",
+ lan->weight);
+ json_object_string_add(flags_json, "behavior",
+ seg6local_action2str(
+ lan->behavior));
+ json_object_boolean_add(
+ flags_json, "flagB",
+ !!(lan->flags &
+ EXT_SUBTLV_LINK_SRV6_ENDX_SID_BFLG));
+ json_object_boolean_add(
+ flags_json, "flagS",
+ !!(lan->flags &
+ EXT_SUBTLV_LINK_SRV6_ENDX_SID_SFLG));
+ json_object_boolean_add(
+ flags_json, "flagP",
+ !!(lan->flags &
+ EXT_SUBTLV_LINK_SRV6_ENDX_SID_PFLG));
+ json_object_string_addf(flags_json,
+ "neighbor-id", "%pSY",
+ lan->neighbor_id);
+ json_object_array_add(arr_adj_json, flags_json);
+ if (lan->subsubtlvs)
+ isis_format_subsubtlvs(lan->subsubtlvs,
+ NULL,
+ arr_adj_json,
indent + 4);
}
} else
@@ -1063,7 +1510,7 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
}
}
for (ALL_LIST_ELEMENTS_RO(exts->aslas, node, asla))
- format_item_asla_subtlvs(asla, buf, indent);
+ format_item_asla_subtlvs(asla, json, buf, indent);
}
static void free_item_ext_subtlvs(struct isis_ext_subtlvs *exts)
@@ -2127,15 +2574,26 @@ static void format_item_prefix_sid(uint16_t mtid, struct isis_item *i,
struct isis_prefix_sid *sid = (struct isis_prefix_sid *)i;
if (json) {
- struct json_object *sr_json;
+ struct json_object *sr_json, *array_json;
+
sr_json = json_object_new_object();
- json_object_object_add(json, "sr", sr_json);
+ json_object_object_get_ex(json, "sr", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "sr", array_json);
+ }
+ json_object_array_add(array_json, sr_json);
if (sid->flags & ISIS_PREFIX_SID_VALUE) {
json_object_int_add(sr_json, "label", sid->value);
} else {
json_object_int_add(sr_json, "index", sid->value);
}
json_object_int_add(sr_json, "alg", sid->algorithm);
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated non boolean json")
+#endif
+ /* old deprecated keys (no booleans) */
json_object_string_add(
sr_json, "readvertised",
((sid->flags & ISIS_PREFIX_SID_READVERTISED) ? "yes"
@@ -2157,6 +2615,27 @@ static void format_item_prefix_sid(uint16_t mtid, struct isis_item *i,
json_object_string_add(
sr_json, "local",
((sid->flags & ISIS_PREFIX_SID_LOCAL) ? "yes" : ""));
+ /* end deprecated keys (no booleans) */
+
+ struct json_object *flags_json;
+
+ flags_json = json_object_new_object();
+ json_object_object_add(sr_json, "flags", flags_json);
+
+ json_object_boolean_add(flags_json, "readvertised",
+ !!(sid->flags &
+ ISIS_PREFIX_SID_READVERTISED));
+ json_object_boolean_add(flags_json, "node",
+ !!(sid->flags & ISIS_PREFIX_SID_NODE));
+ json_object_boolean_add(flags_json, "noPHP",
+ !!(sid->flags & ISIS_PREFIX_SID_NO_PHP));
+ json_object_boolean_add(flags_json, "explicitNull",
+ !!(sid->flags &
+ ISIS_PREFIX_SID_EXPLICIT_NULL));
+ json_object_boolean_add(flags_json, "value",
+ !!(sid->flags & ISIS_PREFIX_SID_VALUE));
+ json_object_boolean_add(flags_json, "local",
+ !!(sid->flags & ISIS_PREFIX_SID_LOCAL));
} else {
sbuf_push(buf, indent, "SR Prefix-SID ");
@@ -2286,7 +2765,11 @@ static void format_subtlv_ipv6_source_prefix(struct prefix_ipv6 *p,
char prefixbuf[PREFIX2STR_BUFFER];
if (json) {
prefix2str(p, prefixbuf, sizeof(prefixbuf));
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "ipv6-src-prefix", prefixbuf);
+ json_object_string_add(json, "ipv6SrcPrefix", prefixbuf);
} else {
sbuf_push(buf, indent, "IPv6 Source Prefix: %s\n",
prefix2str(p, prefixbuf, sizeof(prefixbuf)));
@@ -2388,6 +2871,11 @@ static void format_subsubtlv_srv6_sid_structure(
if (json) {
struct json_object *sid_struct_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
sid_struct_json = json_object_new_object();
json_object_object_add(json, "srv6-sid-structure",
sid_struct_json);
@@ -2399,6 +2887,19 @@ static void format_subsubtlv_srv6_sid_structure(
sid_struct->func_len);
json_object_int_add(sid_struct_json, "arg-len",
sid_struct->arg_len);
+ /* end old deprecated key format */
+
+ sid_struct_json = json_object_new_object();
+ json_object_object_add(json, "srv6SidStructure",
+ sid_struct_json);
+ json_object_int_add(sid_struct_json, "locBlockLen",
+ sid_struct->loc_block_len);
+ json_object_int_add(sid_struct_json, "locNodeLen",
+ sid_struct->loc_node_len);
+ json_object_int_add(sid_struct_json, "funcLen",
+ sid_struct->func_len);
+ json_object_int_add(sid_struct_json, "argLen",
+ sid_struct->arg_len);
} else {
sbuf_push(buf, indent, "SRv6 SID Structure ");
sbuf_push(buf, 0, "Locator Block length: %hhu, ",
@@ -2680,6 +3181,11 @@ static void format_item_srv6_end_sid(uint16_t mtid, struct isis_item *i,
if (json) {
struct json_object *sid_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
sid_json = json_object_new_object();
json_object_object_add(json, "srv6-end-sid", sid_json);
json_object_string_add(sid_json, "endpoint-behavior",
@@ -2694,6 +3200,21 @@ static void format_item_srv6_end_sid(uint16_t mtid, struct isis_item *i,
isis_format_subsubtlvs(sid->subsubtlvs, NULL,
subtlvs_json, 0);
}
+ /* end old deprecated key format */
+
+ sid_json = json_object_new_object();
+ json_object_object_add(json, "srv6EndSid", sid_json);
+ json_object_string_add(sid_json, "endpointBehavior",
+ seg6local_action2str(sid->behavior));
+ json_object_string_addf(sid_json, "sidValue", "%pI6", &sid->sid);
+ if (sid->subsubtlvs) {
+ struct json_object *subtlvs_json;
+ subtlvs_json = json_object_new_object();
+ json_object_object_add(sid_json, "subsubtlvs",
+ subtlvs_json);
+ isis_format_subsubtlvs(sid->subsubtlvs, NULL,
+ subtlvs_json, 0);
+ }
} else {
sbuf_push(buf, indent, "SRv6 End SID ");
sbuf_push(buf, 0, "Endpoint Behavior: %s, ",
@@ -2841,9 +3362,13 @@ static void format_item_area_address(uint16_t mtid, struct isis_item *i,
memcpy(iso_addr.area_addr, addr->addr, ISO_ADDR_SIZE);
iso_addr.addr_len = addr->len;
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_addf(json, "area-addr", "%pIS", &iso_addr);
- else
+ json_object_string_addf(json, "areaAddr", "%pIS", &iso_addr);
+ } else
sbuf_push(buf, indent, "Area Address: %pIS\n", &iso_addr);
}
@@ -2929,11 +3454,34 @@ static void format_item_oldstyle_reach(uint16_t mtid, struct isis_item *i,
snprintfrr(sys_id, ISO_SYSID_STRLEN, "%pPN", r->id);
if (json) {
- struct json_object *old_json;
+ struct json_object *old_json, *array_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
old_json = json_object_new_object();
- json_object_object_add(json, "old-reach-style", old_json);
+ json_object_object_get_ex(json, "old-reach-style", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "old-reach-style",
+ array_json);
+ }
+ json_object_array_add(array_json, old_json);
json_object_string_add(old_json, "is-reach", sys_id);
json_object_int_add(old_json, "metric", r->metric);
+ /* end old deprecated key format */
+
+ old_json = json_object_new_object();
+ json_object_object_get_ex(json, "oldReachStyle", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "oldReachStyle",
+ array_json);
+ }
+ json_object_array_add(array_json, old_json);
+ json_object_string_add(old_json, "isReach", sys_id);
+ json_object_int_add(old_json, "metric", r->metric);
} else
sbuf_push(buf, indent, "IS Reachability: %s (Metric: %hhu)\n",
sys_id, r->metric);
@@ -3011,9 +3559,13 @@ static void format_item_lan_neighbor(uint16_t mtid, struct isis_item *i,
char sys_id[ISO_SYSID_STRLEN];
snprintfrr(sys_id, ISO_SYSID_STRLEN, "%pSY", n->mac);
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "lan-neighbor", sys_id);
- else
+ json_object_string_add(json, "lanNeighbor", sys_id);
+ } else
sbuf_push(buf, indent, "LAN Neighbor: %s\n", sys_id);
}
@@ -3086,6 +3638,9 @@ static void format_item_lsp_entry(uint16_t mtid, struct isis_item *i,
char buf[255];
struct json_object *lsp_json;
lsp_json = json_object_new_object();
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_object_add(json, "lsp-entry", lsp_json);
json_object_string_add(lsp_json, "id", sys_id);
snprintfrr(buf,sizeof(buf),"0x%08x",e->seqno);
@@ -3093,6 +3648,15 @@ static void format_item_lsp_entry(uint16_t mtid, struct isis_item *i,
snprintfrr(buf,sizeof(buf),"0x%04hx",e->checksum);
json_object_string_add(lsp_json, "chksum", buf);
json_object_int_add(lsp_json, "lifetime", e->checksum);
+
+ lsp_json = json_object_new_object();
+ json_object_object_add(json, "lspEntry", lsp_json);
+ json_object_string_add(lsp_json, "id", sys_id);
+ snprintfrr(buf, sizeof(buf), "0x%08x", e->seqno);
+ json_object_string_add(lsp_json, "seq", buf);
+ snprintfrr(buf, sizeof(buf), "0x%04hx", e->checksum);
+ json_object_string_add(lsp_json, "chksum", buf);
+ json_object_int_add(lsp_json, "lifetime", e->checksum);
} else
sbuf_push(
buf, indent,
@@ -3173,9 +3737,19 @@ static void format_item_extended_reach(uint16_t mtid, struct isis_item *i,
snprintfrr(sys_id, ISO_SYSID_STRLEN, "%pPN", r->id);
if (json) {
- struct json_object *reach_json;
+ struct json_object *reach_json, *array_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
reach_json = json_object_new_object();
- json_object_object_add(json, "ext-reach", reach_json);
+ json_object_object_get_ex(json, "ext-reach", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "ext-reach", array_json);
+ }
+ json_object_array_add(array_json, reach_json);
json_object_string_add(
reach_json, "mt-id",
(mtid == ISIS_MT_IPV4_UNICAST) ? "Extended" : "MT");
@@ -3186,7 +3760,29 @@ static void format_item_extended_reach(uint16_t mtid, struct isis_item *i,
isis_mtid2str(mtid));
if (r->subtlvs)
- format_item_ext_subtlvs(r->subtlvs, NULL, json,
+ format_item_ext_subtlvs(r->subtlvs, NULL, reach_json,
+ indent + 2, mtid);
+ /* end old deprecated key format */
+
+ reach_json = json_object_new_object();
+ json_object_object_get_ex(json, "extReach", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "extReach", array_json);
+ }
+ json_object_array_add(array_json, reach_json);
+ json_object_string_add(reach_json, "mtId",
+ (mtid == ISIS_MT_IPV4_UNICAST)
+ ? "Extended"
+ : "MT");
+ json_object_string_add(reach_json, "id", sys_id);
+ json_object_int_add(reach_json, "metric", r->metric);
+ if (mtid != ISIS_MT_IPV4_UNICAST)
+ json_object_string_add(reach_json, "mtName",
+ isis_mtid2str(mtid));
+
+ if (r->subtlvs)
+ format_item_ext_subtlvs(r->subtlvs, NULL, reach_json,
indent + 2, mtid);
} else {
sbuf_push(buf, indent, "%s Reachability: %s (Metric: %u)",
@@ -3314,13 +3910,40 @@ static void format_item_oldstyle_ip_reach(uint16_t mtid, struct isis_item *i,
char prefixbuf[PREFIX2STR_BUFFER];
if (json) {
- struct json_object *old_json;
+ struct json_object *old_json, *array_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
old_json = json_object_new_object();
- json_object_object_add(json, "old-ip-reach-style", old_json);
+ json_object_object_get_ex(json, "old-ip-reach-style",
+ &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "old-ip-reach-style",
+ old_json);
+ }
+ json_object_array_add(array_json, old_json);
json_object_string_add(old_json, "prefix",
prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)));
json_object_int_add(old_json, "metric", r->metric);
- } else
+ /* end old deprecated key format */
+
+ old_json = json_object_new_object();
+ json_object_object_get_ex(json, "oldIpReachStyle", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "oldIpReachStyle",
+ old_json);
+ }
+ json_object_array_add(array_json, old_json);
+ json_object_string_add(old_json, "prefix",
+ prefix2str(&r->prefix, prefixbuf,
+ sizeof(prefixbuf)));
+ json_object_int_add(old_json, "metric", r->metric);
+ return;
+ }
sbuf_push(buf, indent, "IP Reachability: %s (Metric: %hhu)\n",
prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)),
r->metric);
@@ -3412,6 +4035,10 @@ static void format_tlv_protocols_supported(struct isis_protocols_supported *p,
struct json_object *protocol_json;
char buf[255];
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
protocol_json = json_object_new_object();
json_object_object_add(json, "protocols-supported",
protocol_json);
@@ -3420,6 +4047,16 @@ static void format_tlv_protocols_supported(struct isis_protocols_supported *p,
json_object_string_add(protocol_json, buf,
nlpid2str(p->protocols[i]));
}
+
+ protocol_json = json_object_new_object();
+ json_object_object_add(json, "supportedProtocols",
+ protocol_json);
+ for (uint8_t i = 0; i < p->count; i++) {
+ snprintfrr(buf, sizeof(buf), "%d", i);
+ json_object_string_add(protocol_json, buf,
+ nlpid2str(p->protocols[i]));
+ }
+ /* end old deprecated key format */
} else {
sbuf_push(buf, indent, "Protocols Supported: ");
for (uint8_t i = 0; i < p->count; i++) {
@@ -3635,9 +4272,13 @@ static void format_item_global_ipv6_address(uint16_t mtid, struct isis_item *i,
char addrbuf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &a->addr, addrbuf, sizeof(addrbuf));
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "global-ipv6", addrbuf);
- else
+ json_object_string_add(json, "globalIpv6", addrbuf);
+ } else
sbuf_push(buf, indent, "Global IPv6 Interface Address: %s\n",
addrbuf);
}
@@ -3705,12 +4346,30 @@ static void format_item_mt_router_info(uint16_t mtid, struct isis_item *i,
struct isis_mt_router_info *info = (struct isis_mt_router_info *)i;
if (json) {
- struct json_object *mt_json;
+ struct json_object *mt_json, *array_json;
mt_json = json_object_new_object();
- json_object_object_add(json, "mt", mt_json);
+ json_object_object_get_ex(json, "mt", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "mt", array_json);
+ }
+ json_object_array_add(array_json, mt_json);
json_object_int_add(mt_json, "mtid", info->mtid);
+ json_object_string_add(mt_json, "mt-description",
+ isis_mtid2str_fake(info->mtid));
+ json_object_string_add(mt_json, "mtDescription",
+ isis_mtid2str(mtid));
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated non boolean format")
+#endif
json_object_string_add(mt_json, "overload", info->overload?"true":"false");
json_object_string_add(mt_json, "attached", info->attached?"true":"false");
+
+ json_object_boolean_add(mt_json, "overloadBit",
+ !!info->overload);
+ json_object_boolean_add(mt_json, "attachedbit",
+ !!info->attached);
} else
sbuf_push(buf, indent, "MT Router Info: %s%s%s\n",
isis_mtid2str_fake(info->mtid),
@@ -3793,9 +4452,13 @@ static void format_tlv_te_router_id(const struct in_addr *id, struct sbuf *buf,
char addrbuf[INET_ADDRSTRLEN];
inet_ntop(AF_INET, id, addrbuf, sizeof(addrbuf));
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "te-router-id", addrbuf);
- else
+ json_object_string_add(json, "teRouterId", addrbuf);
+ } else
sbuf_push(buf, indent, "TE Router ID: %s\n", addrbuf);
}
@@ -3866,27 +4529,64 @@ static void format_item_extended_ip_reach(uint16_t mtid, struct isis_item *i,
struct json_object *json, int indent)
{
struct isis_extended_ip_reach *r = (struct isis_extended_ip_reach *)i;
+ struct json_object *ext_json, *array_json;
char prefixbuf[PREFIX2STR_BUFFER];
if (json) {
- struct json_object *ext_json;
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
ext_json = json_object_new_object();
- json_object_object_add(json, "ext-ip-reach", ext_json);
- json_object_string_add(
- json, "mt-id",
- (mtid == ISIS_MT_IPV4_UNICAST) ? "Extended" : "MT");
- json_object_string_add(
- json, "ip-reach",
- prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)));
- json_object_int_add(json, "ip-reach-metric", r->metric);
- json_object_string_add(json, "down", r->down ? "yes" : "");
+ json_object_object_get_ex(json, "ext-ip-reach", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "ext-ip-reach", array_json);
+ }
+ json_object_array_add(array_json, ext_json);
+ json_object_string_add(ext_json, "mt-id",
+ (mtid == ISIS_MT_IPV4_UNICAST)
+ ? "Extended"
+ : "MT");
+ json_object_string_add(ext_json, "ip-reach",
+ prefix2str(&r->prefix, prefixbuf,
+ sizeof(prefixbuf)));
+ json_object_int_add(ext_json, "ip-reach-metric", r->metric);
+ json_object_string_add(ext_json, "down", r->down ? "yes" : "");
if (mtid != ISIS_MT_IPV4_UNICAST)
- json_object_string_add(json, "mt-name",
+ json_object_string_add(ext_json, "mt-name",
isis_mtid2str(mtid));
if (r->subtlvs) {
struct json_object *subtlv_json;
subtlv_json = json_object_new_object();
- json_object_object_add(json, "subtlvs", subtlv_json);
+ json_object_object_add(ext_json, "subtlvs", subtlv_json);
+ format_subtlvs(r->subtlvs, NULL, subtlv_json, 0);
+ }
+ /* end old deprecated key format */
+
+ ext_json = json_object_new_object();
+ json_object_object_get_ex(json, "extIpReach", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "extIpReach", array_json);
+ }
+ json_object_array_add(array_json, ext_json);
+ json_object_string_add(ext_json, "mtId",
+ (mtid == ISIS_MT_IPV4_UNICAST)
+ ? "Extended"
+ : "MT");
+ json_object_string_add(ext_json, "ipReach",
+ prefix2str(&r->prefix, prefixbuf,
+ sizeof(prefixbuf)));
+ json_object_int_add(ext_json, "ipReachMetric", r->metric);
+ json_object_boolean_add(ext_json, "down", !!r->down);
+ if (mtid != ISIS_MT_IPV4_UNICAST)
+ json_object_string_add(ext_json, "mtName",
+ isis_mtid2str(mtid));
+ if (r->subtlvs) {
+ struct json_object *subtlv_json;
+ subtlv_json = json_object_new_object();
+ json_object_object_add(ext_json, "subtlvs", subtlv_json);
format_subtlvs(r->subtlvs, NULL, subtlv_json, 0);
}
} else {
@@ -4146,9 +4846,13 @@ static void format_tlv_te_router_id_ipv6(const struct in6_addr *id,
char addrbuf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, id, addrbuf, sizeof(addrbuf));
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "ipv6-te-router-id", addrbuf);
- else
+ json_object_string_add(json, "ipv6TeRouterId", addrbuf);
+ } else
sbuf_push(buf, indent, "IPv6 TE Router ID: %s\n", addrbuf);
}
@@ -4225,6 +4929,11 @@ static void format_tlv_spine_leaf(const struct isis_spine_leaf *spine_leaf,
if (json) {
struct json_object *spine_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated format */
spine_json = json_object_new_object();
json_object_object_add(json, "spine-leaf-extension",
spine_json);
@@ -4243,6 +4952,25 @@ static void format_tlv_spine_leaf(const struct isis_spine_leaf *spine_leaf,
spine_leaf->is_spine ? "yes" : "");
json_object_string_add(spine_json, "flag-backup",
spine_leaf->is_backup ? "yes" : "");
+ /* end old deprecated format */
+
+ spine_json = json_object_new_object();
+ json_object_object_add(json, "spineLeafExtension", spine_json);
+ if (spine_leaf->has_tier) {
+ snprintfrr(aux_buf, sizeof(aux_buf), "%hhu",
+ spine_leaf->tier);
+ json_object_string_add(spine_json, "tier",
+ (spine_leaf->tier ==
+ ISIS_TIER_UNDEFINED)
+ ? "undefined"
+ : aux_buf);
+ }
+ json_object_boolean_add(spine_json, "flagLeaf",
+ spine_leaf->is_leaf ? true : false);
+ json_object_boolean_add(spine_json, "flagSpine",
+ spine_leaf->is_spine ? true : false);
+ json_object_boolean_add(spine_json, "flagBackup",
+ spine_leaf->is_backup ? true : false);
} else {
sbuf_push(buf, indent, "Spine-Leaf-Extension:\n");
if (spine_leaf->has_tier) {
@@ -4384,6 +5112,11 @@ format_tlv_threeway_adj(const struct isis_threeway_adj *threeway_adj,
snprintfrr(sys_id, ISO_SYSID_STRLEN, "%pSY", threeway_adj->neighbor_id);
if (json) {
struct json_object *three_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
three_json = json_object_new_object();
json_object_object_add(json, "p2p-three-way-adj", three_json);
json_object_string_add(
@@ -4392,11 +5125,28 @@ format_tlv_threeway_adj(const struct isis_threeway_adj *threeway_adj,
json_object_int_add(three_json, "state", threeway_adj->state);
json_object_int_add(three_json, "ext-local-circuit-id",
threeway_adj->local_circuit_id);
- if (!threeway_adj->neighbor_set)
- return;
- json_object_string_add(three_json, "neigh-system-id", sys_id);
- json_object_int_add(three_json, "neigh-ext-circuit-id",
- threeway_adj->neighbor_circuit_id);
+ if (threeway_adj->neighbor_set) {
+ json_object_string_add(three_json, "neigh-system-id",
+ sys_id);
+ json_object_int_add(three_json, "neigh-ext-circuit-id",
+ threeway_adj->neighbor_circuit_id);
+ }
+ /* end old deprecated key format */
+
+ three_json = json_object_new_object();
+ json_object_object_add(json, "p2pThreeWayAdj", three_json);
+ json_object_string_add(three_json, "stateName",
+ isis_threeway_state_name(
+ threeway_adj->state));
+ json_object_int_add(three_json, "state", threeway_adj->state);
+ json_object_int_add(three_json, "extLocalCircuitId",
+ threeway_adj->local_circuit_id);
+ if (threeway_adj->neighbor_set) {
+ json_object_string_add(three_json, "neighSystemId",
+ sys_id);
+ json_object_int_add(three_json, "neighExtCircuitId",
+ threeway_adj->neighbor_circuit_id);
+ }
} else {
sbuf_push(buf, indent, "P2P Three-Way Adjacency:\n");
sbuf_push(buf, indent, " State: %s (%d)\n",
@@ -4500,9 +5250,51 @@ static void format_item_ipv6_reach(uint16_t mtid, struct isis_item *i,
char prefixbuf[PREFIX2STR_BUFFER];
if (json) {
- struct json_object *reach_json;
+ struct json_object *reach_json, *array_json;
+
+ reach_json = json_object_new_object();
+ json_object_object_get_ex(json, "ipv6Reach", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "ipv6Reach", array_json);
+ }
+ json_object_array_add(array_json, reach_json);
+ json_object_string_add(reach_json, "mtId",
+ (mtid == ISIS_MT_IPV4_UNICAST) ? ""
+ : "mt");
+ json_object_string_add(reach_json, "prefix",
+ prefix2str(&r->prefix, prefixbuf,
+ sizeof(prefixbuf)));
+ json_object_int_add(reach_json, "metric", r->metric);
+ json_object_boolean_add(reach_json, "down",
+ r->down ? true : false);
+ json_object_boolean_add(reach_json, "external",
+ r->external ? true : false);
+ if (mtid != ISIS_MT_IPV4_UNICAST) {
+ json_object_string_add(reach_json, "mt-name",
+ isis_mtid2str(mtid));
+ json_object_string_add(reach_json, "mtName",
+ isis_mtid2str(mtid));
+ }
+ if (r->subtlvs) {
+ struct json_object *subtlvs_json;
+ subtlvs_json = json_object_new_object();
+ json_object_object_add(reach_json, "subtlvs",
+ subtlvs_json);
+ format_subtlvs(r->subtlvs, NULL, subtlvs_json, 0);
+ }
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated JSON key format */
reach_json = json_object_new_object();
- json_object_object_add(json, "ipv6-reach", reach_json);
+ json_object_object_get_ex(json, "ipv6-reach", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "ipv6-reach", array_json);
+ }
+ json_object_array_add(array_json, reach_json);
json_object_string_add(reach_json, "mt-id",
(mtid == ISIS_MT_IPV4_UNICAST) ? ""
: "mt");
@@ -4520,9 +5312,11 @@ static void format_item_ipv6_reach(uint16_t mtid, struct isis_item *i,
if (r->subtlvs) {
struct json_object *subtlvs_json;
subtlvs_json = json_object_new_object();
- json_object_object_add(json, "subtlvs", subtlvs_json);
+ json_object_object_add(reach_json, "subtlvs",
+ subtlvs_json);
format_subtlvs(r->subtlvs, NULL, subtlvs_json, 0);
}
+ /* end deprecated key format */
} else {
sbuf_push(buf, indent,
"%sIPv6 Reachability: %s (Metric: %u)%s%s",
@@ -4734,6 +5528,11 @@ static void format_tlv_router_cap_json(const struct isis_router_cap *router_cap,
/* Router ID and Flags */
struct json_object *cap_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* deprecated JSON key format */
cap_json = json_object_new_object();
json_object_object_add(json, "router-capability", cap_json);
inet_ntop(AF_INET, &router_cap->router_id, addrbuf, sizeof(addrbuf));
@@ -4744,10 +5543,26 @@ static void format_tlv_router_cap_json(const struct isis_router_cap *router_cap,
json_object_string_add(
cap_json, "flag-s",
router_cap->flags & ISIS_ROUTER_CAP_FLAG_S ? "1" : "0");
+ /* end deprecated JSON key format */
+
+ cap_json = json_object_new_object();
+ json_object_object_add(json, "routerCapability", cap_json);
+ inet_ntop(AF_INET, &router_cap->router_id, addrbuf, sizeof(addrbuf));
+ json_object_string_add(cap_json, "id", addrbuf);
+ json_object_boolean_add(cap_json, "flagD",
+ !!(router_cap->flags & ISIS_ROUTER_CAP_FLAG_D));
+ json_object_boolean_add(cap_json, "flagS",
+ !!(router_cap->flags & ISIS_ROUTER_CAP_FLAG_S));
+
/* Segment Routing Global Block as per RFC8667 section #3.1 */
if (router_cap->srgb.range_size != 0) {
struct json_object *gb_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* deprecated old key format */
gb_json = json_object_new_object();
json_object_object_add(json, "segment-routing-gb", gb_json);
json_object_string_add(gb_json, "ipv4",
@@ -4760,23 +5575,52 @@ static void format_tlv_router_cap_json(const struct isis_router_cap *router_cap,
router_cap->srgb.lower_bound);
json_object_int_add(gb_json, "global-block-range",
router_cap->srgb.range_size);
+
+ gb_json = json_object_new_object();
+ json_object_object_add(json, "segmentRoutingGb", gb_json);
+ json_object_boolean_add(gb_json, "ipv4",
+ !!IS_SR_IPV4(&router_cap->srgb));
+ json_object_boolean_add(gb_json, "ipv6",
+ !!IS_SR_IPV6(&router_cap->srgb));
+ json_object_int_add(gb_json, "globalBlockBase",
+ router_cap->srgb.lower_bound);
+ json_object_int_add(gb_json, "globalBlockRange",
+ router_cap->srgb.range_size);
}
/* Segment Routing Local Block as per RFC8667 section #3.3 */
if (router_cap->srlb.range_size != 0) {
struct json_object *lb_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
lb_json = json_object_new_object();
json_object_object_add(json, "segment-routing-lb", lb_json);
json_object_int_add(lb_json, "global-block-base",
router_cap->srlb.lower_bound);
json_object_int_add(lb_json, "global-block-range",
router_cap->srlb.range_size);
+ /* end old deprecated key format */
+
+ lb_json = json_object_new_object();
+ json_object_object_add(json, "segmentRoutingLb", lb_json);
+ json_object_int_add(lb_json, "globalBlockBase",
+ router_cap->srlb.lower_bound);
+ json_object_int_add(lb_json, "globalBlockRange",
+ router_cap->srlb.range_size);
}
/* Segment Routing Algorithms as per RFC8667 section #3.2 */
if (router_cap->algo[0] != SR_ALGORITHM_UNSET) {
char buf[255];
struct json_object *alg_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
alg_json = json_object_new_object();
json_object_object_add(json, "segment-routing-algorithm",
alg_json);
@@ -4788,6 +5632,20 @@ static void format_tlv_router_cap_json(const struct isis_router_cap *router_cap,
? "SPF"
: "Strict SPF");
}
+ /* end old deprecated key format */
+
+ alg_json = json_object_new_object();
+ json_object_object_add(json, "segmentRoutingAlgorithm",
+ alg_json);
+ for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
+ if (router_cap->algo[i] != SR_ALGORITHM_UNSET) {
+ snprintfrr(buf, sizeof(buf), "%d", i);
+ json_object_string_add(alg_json, buf,
+ router_cap->algo[i] == 0
+ ? "SPF"
+ : "Strict SPF");
+ }
+ }
}
/* Segment Routing Node MSD as per RFC8491 section #2 */
@@ -5631,16 +6489,24 @@ static void format_item_auth(uint16_t mtid, struct isis_item *i,
struct isis_auth *auth = (struct isis_auth *)i;
char obuf[768];
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "test-auth", "ok");
- else
+ json_object_string_add(json, "testAuth", "ok");
+ } else
sbuf_push(buf, indent, "Authentication:\n");
switch (auth->type) {
case ISIS_PASSWD_TYPE_CLEARTXT:
zlog_sanitize(obuf, sizeof(obuf), auth->value, auth->length);
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "auth-pass", obuf);
- else
+ json_object_string_add(json, "authPass", obuf);
+ } else
sbuf_push(buf, indent, " Password: %s\n", obuf);
break;
case ISIS_PASSWD_TYPE_HMAC_MD5:
@@ -5648,15 +6514,23 @@ static void format_item_auth(uint16_t mtid, struct isis_item *i,
snprintf(obuf + 2 * j, sizeof(obuf) - 2 * j, "%02hhx",
auth->value[j]);
}
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "auth-hmac-md5", obuf);
- else
+ json_object_string_add(json, "authHmacMd5", obuf);
+ } else
sbuf_push(buf, indent, " HMAC-MD5: %s\n", obuf);
break;
default:
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_int_add(json, "auth-unknown", auth->type);
- else
+ json_object_int_add(json, "authUnknown", auth->type);
+ } else
sbuf_push(buf, indent, " Unknown (%hhu)\n",
auth->type);
break;
@@ -5771,12 +6645,25 @@ static void format_tlv_purge_originator(struct isis_purge_originator *poi,
if (json) {
struct json_object *purge_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
purge_json = json_object_new_object();
json_object_object_add(json, "purge_originator", purge_json);
json_object_string_add(purge_json, "id", gen_id);
if (poi->sender_set)
json_object_string_add(purge_json, "rec-from", sen_id);
+ /* end old deprecated key format */
+
+ purge_json = json_object_new_object();
+ json_object_object_add(json, "purgeOriginator", purge_json);
+
+ json_object_string_add(purge_json, "id", gen_id);
+ if (poi->sender_set)
+ json_object_string_add(purge_json, "recFrom", sen_id);
} else {
sbuf_push(buf, indent, "Purge Originator Identification:\n");
sbuf_push(buf, indent, " Generator: %s\n", gen_id);
@@ -6319,6 +7206,11 @@ static void format_item_srv6_locator(uint16_t mtid, struct isis_item *i,
if (json) {
struct json_object *loc_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old json key format */
loc_json = json_object_new_object();
json_object_object_add(json, "srv6-locator", loc_json);
json_object_int_add(loc_json, "mt-id", mtid);
@@ -6340,6 +7232,26 @@ static void format_item_srv6_locator(uint16_t mtid, struct isis_item *i,
subtlvs_json);
format_subtlvs(loc->subtlvs, NULL, subtlvs_json, 0);
}
+ /* old deprecated key format */
+
+ loc_json = json_object_new_object();
+ json_object_object_add(json, "srv6Locator", loc_json);
+ json_object_int_add(loc_json, "mtId", mtid);
+ json_object_string_addf(loc_json, "prefix", "%pFX",
+ &loc->prefix);
+ json_object_int_add(loc_json, "metric", loc->metric);
+ json_object_boolean_add(loc_json, "flagD",
+ !!CHECK_FLAG(loc->flags,
+ ISIS_TLV_SRV6_LOCATOR_FLAG_D));
+ json_object_int_add(loc_json, "algorithm", loc->algorithm);
+ json_object_string_add(loc_json, "MTName", isis_mtid2str(mtid));
+ if (loc->subtlvs) {
+ struct json_object *subtlvs_json;
+ subtlvs_json = json_object_new_object();
+ json_object_object_add(loc_json, "subtlvs",
+ subtlvs_json);
+ format_subtlvs(loc->subtlvs, NULL, subtlvs_json, 0);
+ }
} else {
sbuf_push(buf, indent, "SRv6 Locator: %pFX (Metric: %u)%s",
&loc->prefix, loc->metric,
@@ -6623,9 +7535,13 @@ static void format_tlvs(struct isis_tlvs *tlvs, struct sbuf *buf, struct json_ob
&tlvs->area_addresses, buf, json, indent);
if (tlvs->mt_router_info_empty) {
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "mt-router-info", "none");
- else
+ json_object_object_add(json, "mtRouterInfo", NULL);
+ } else
sbuf_push(buf, indent, "MT Router Info: None\n");
} else {
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_ROUTER_INFO,
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 382a6aa3b..982df0839 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -2649,6 +2649,7 @@ void show_isis_database_lspdb_json(struct json_object *json,
struct lspdb_head *lspdb,
const char *sysid_str, int ui_level)
{
+ struct json_object *array_json, *lsp_json;
struct isis_lsp *lsp;
int lsp_count;
struct json_object *lsp_arr_json;
@@ -2661,11 +2662,19 @@ void show_isis_database_lspdb_json(struct json_object *json,
}
if (lsp) {
+ json_object_object_get_ex(json, "lsps", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "lsps", array_json);
+ }
+ lsp_json = json_object_new_object();
+ json_object_array_add(array_json, lsp_json);
+
if (ui_level == ISIS_UI_LEVEL_DETAIL)
- lsp_print_detail(lsp, NULL, json,
+ lsp_print_detail(lsp, NULL, lsp_json,
area->dynhostname, area->isis);
else
- lsp_print_json(lsp, json, area->dynhostname,
+ lsp_print_json(lsp, lsp_json, area->dynhostname,
area->isis);
} else if (sysid_str == NULL) {
lsp_arr_json = json_object_new_array();
@@ -2739,6 +2748,8 @@ static void show_isis_database_json(struct json_object *json, const char *sysid_
json_object_object_add(area_json,"area",tag_area_json);
json_object_object_add(area_json,"levels",arr_json);
for (level = 0; level < ISIS_LEVELS; level++) {
+ if (lspdb_count(&area->lspdb[level]) == 0)
+ continue;
lsp_json = json_object_new_object();
show_isis_database_lspdb_json(lsp_json, area, level,
&area->lspdb[level],
diff --git a/lib/ipaddr.h b/lib/ipaddr.h
index c86e38c86..888955fba 100644
--- a/lib/ipaddr.h
+++ b/lib/ipaddr.h
@@ -40,8 +40,9 @@ struct ipaddr {
#define IS_IPADDR_V4(p) ((p)->ipa_type == IPADDR_V4)
#define IS_IPADDR_V6(p) ((p)->ipa_type == IPADDR_V6)
-#define SET_IPADDR_V4(p) (p)->ipa_type = IPADDR_V4
-#define SET_IPADDR_V6(p) (p)->ipa_type = IPADDR_V6
+#define SET_IPADDR_NONE(p) ((p)->ipa_type = IPADDR_NONE)
+#define SET_IPADDR_V4(p) ((p)->ipa_type = IPADDR_V4)
+#define SET_IPADDR_V6(p) ((p)->ipa_type = IPADDR_V6)
#define IPADDRSZ(p) \
(IS_IPADDR_V4((p)) ? sizeof(struct in_addr) : sizeof(struct in6_addr))
@@ -165,9 +166,17 @@ static inline bool ipaddr_is_zero(const struct ipaddr *ip)
return true;
}
+static inline bool ipaddr_is_same(const struct ipaddr *ip1,
+ const struct ipaddr *ip2)
+{
+ return ipaddr_cmp(ip1, ip2) == 0;
+}
+
+/* clang-format off */
#ifdef _FRR_ATTRIBUTE_PRINTFRR
#pragma FRR printfrr_ext "%pIA" (struct ipaddr *)
#endif
+/* clang-format on */
#ifdef __cplusplus
}
diff --git a/lib/prefix.c b/lib/prefix.c
index f342c4c1d..2485c3e61 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -1124,6 +1124,15 @@ const char *prefix2str(union prefixconstptr pu, char *str, int size)
return str;
}
+void prefix_mcast_ip_dump(const char *onfail, const struct ipaddr *addr,
+ char *buf, int buf_size)
+{
+ if (ipaddr_is_zero(addr))
+ strlcpy(buf, "*", buf_size);
+ else
+ (void)snprintfrr(buf, buf_size, "%pIA", addr);
+}
+
static ssize_t prefixhost2str(struct fbuf *fbuf, union prefixconstptr pu)
{
const struct prefix *p = pu.p;
@@ -1166,7 +1175,7 @@ const char *prefix_sg2str(const struct prefix_sg *sg, char *sg_str)
char src_str[INET_ADDRSTRLEN];
char grp_str[INET_ADDRSTRLEN];
- prefix_mcast_inet4_dump("<src?>", sg->src, src_str, sizeof(src_str));
+ prefix_mcast_ip_dump("<src?>", &sg->src, src_str, sizeof(src_str));
prefix_mcast_inet4_dump("<grp?>", sg->grp, grp_str, sizeof(grp_str));
snprintf(sg_str, PREFIX_SG_STR_LEN, "(%s,%s)", src_str, grp_str);
@@ -1637,10 +1646,10 @@ static ssize_t printfrr_psg(struct fbuf *buf, struct printfrr_eargs *ea,
if (!sg)
return bputs(buf, "(null)");
- if (sg->src.s_addr == INADDR_ANY)
+ if (ipaddr_is_zero(&sg->src))
ret += bputs(buf, "(*,");
else
- ret += bprintfrr(buf, "(%pI4,", &sg->src);
+ ret += bprintfrr(buf, "(%pIA,", &sg->src);
if (sg->grp.s_addr == INADDR_ANY)
ret += bputs(buf, "*)");
diff --git a/lib/prefix.h b/lib/prefix.h
index 14f269593..2d679d062 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -52,10 +52,10 @@ typedef enum {
/* Maximum number of VTEPs per-ES -
* XXX - temporary limit for allocating strings etc.
*/
-#define ES_VTEP_MAX_CNT 10
-#define ES_VTEP_LIST_STR_SZ (ES_VTEP_MAX_CNT * 16)
+#define ES_VTEP_MAX_CNT 10
+#define ES_VTEP_LIST_STR_SZ (ES_VTEP_MAX_CNT * IPADDR_STRING_SIZE)
-#define ETHER_ADDR_STRLEN (3*ETH_ALEN)
+#define ETHER_ADDR_STRLEN (3 * ETH_ALEN)
/*
* there isn't a portable ethernet address type. We define our
* own to simplify internal handling
@@ -282,7 +282,7 @@ struct prefix_fs {
struct prefix_sg {
uint8_t family;
uint16_t prefixlen;
- struct in_addr src __attribute__((aligned(8)));
+ struct ipaddr src __attribute__((aligned(8)));
struct in_addr grp;
};
@@ -415,6 +415,8 @@ extern int str2prefix(const char *string, struct prefix *prefix);
#define PREFIX2STR_BUFFER PREFIX_STRLEN
+extern void prefix_mcast_ip_dump(const char *onfail, const struct ipaddr *addr,
+ char *buf, int buf_size);
extern void prefix_mcast_inet4_dump(const char *onfail, struct in_addr addr,
char *buf, int buf_size);
extern const char *prefix_sg2str(const struct prefix_sg *sg, char *str);
diff --git a/lib/stream.c b/lib/stream.c
index fa20ebdbe..bb90f3b94 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -921,7 +921,7 @@ int stream_put_in_addr(struct stream *s, const struct in_addr *addr)
return sizeof(uint32_t);
}
-bool stream_put_ipaddr(struct stream *s, struct ipaddr *ip)
+bool stream_put_ipaddr(struct stream *s, const struct ipaddr *ip)
{
stream_putw(s, ip->ipa_type);
diff --git a/lib/stream.h b/lib/stream.h
index 61eaa46c9..e48cedc61 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -175,7 +175,7 @@ extern int stream_putq(struct stream *, uint64_t);
extern int stream_putq_at(struct stream *, size_t, uint64_t);
extern int stream_put_ipv4(struct stream *, uint32_t);
extern int stream_put_in_addr(struct stream *s, const struct in_addr *addr);
-extern bool stream_put_ipaddr(struct stream *s, struct ipaddr *ip);
+extern bool stream_put_ipaddr(struct stream *s, const struct ipaddr *ip);
extern int stream_put_in_addr_at(struct stream *s, size_t putp,
const struct in_addr *addr);
extern int stream_put_in6_addr_at(struct stream *s, size_t putp,
diff --git a/lib/vty.c b/lib/vty.c
index 628c694e9..0dcd118a9 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -390,6 +390,21 @@ int vty_json_no_pretty(struct vty *vty, struct json_object *json)
return vty_json_helper(vty, json, JSON_C_TO_STRING_NOSLASHESCAPE);
}
+
+void vty_json_key(struct vty *vty, const char *key, bool *first_key)
+{
+ vty_out(vty, "%s\"%s\":", *first_key ? "{" : ",", key);
+ *first_key = false;
+}
+
+void vty_json_close(struct vty *vty, bool first_key)
+{
+ if (first_key)
+ /* JSON was not opened */
+ vty_out(vty, "{");
+ vty_out(vty, "}\n");
+}
+
void vty_json_empty(struct vty *vty, struct json_object *json)
{
json_object *jsonobj = json;
diff --git a/lib/vty.h b/lib/vty.h
index a9570ef04..c336a816c 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -378,6 +378,8 @@ extern bool vty_set_include(struct vty *vty, const char *regexp);
*/
extern int vty_json(struct vty *vty, struct json_object *json);
extern int vty_json_no_pretty(struct vty *vty, struct json_object *json);
+void vty_json_key(struct vty *vty, const char *key, bool *first_key);
+void vty_json_close(struct vty *vty, bool first_key);
extern void vty_json_empty(struct vty *vty, struct json_object *json);
/* post fd to be passed to the vtysh client
* fd is owned by the VTY code after this and will be closed when done
diff --git a/nhrpd/nhrp_main.c b/nhrpd/nhrp_main.c
index 5d492249d..adb8be36d 100644
--- a/nhrpd/nhrp_main.c
+++ b/nhrpd/nhrp_main.c
@@ -83,13 +83,13 @@ static void nhrp_request_stop(void)
debugf(NHRP_DEBUG_COMMON, "Exiting...");
frr_early_fini();
- vrf_terminate();
+ nhrp_shortcut_terminate();
nhrp_nhs_terminate();
nhrp_zebra_terminate();
vici_terminate();
evmgr_terminate();
+ vrf_terminate();
nhrp_vc_terminate();
- nhrp_shortcut_terminate();
debugf(NHRP_DEBUG_COMMON, "Done.");
diff --git a/nhrpd/nhrp_shortcut.c b/nhrpd/nhrp_shortcut.c
index 04dad2aea..e83ce7f58 100644
--- a/nhrpd/nhrp_shortcut.c
+++ b/nhrpd/nhrp_shortcut.c
@@ -19,7 +19,8 @@ DEFINE_MTYPE_STATIC(NHRPD, NHRP_SHORTCUT, "NHRP shortcut");
static struct route_table *shortcut_rib[AFI_MAX];
static void nhrp_shortcut_do_purge(struct event *t);
-static void nhrp_shortcut_delete(struct nhrp_shortcut *s);
+static void nhrp_shortcut_delete(struct nhrp_shortcut *s,
+ void *arg __attribute__((__unused__)));
static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s);
static void nhrp_shortcut_check_use(struct nhrp_shortcut *s)
@@ -72,7 +73,7 @@ static void nhrp_shortcut_cache_notify(struct notifier_block *n,
s->route_installed = 0;
}
if (cmd == NOTIFY_CACHE_DELETE)
- nhrp_shortcut_delete(s);
+ nhrp_shortcut_delete(s, NULL);
break;
}
}
@@ -132,7 +133,8 @@ static void nhrp_shortcut_update_binding(struct nhrp_shortcut *s,
}
}
-static void nhrp_shortcut_delete(struct nhrp_shortcut *s)
+static void nhrp_shortcut_delete(struct nhrp_shortcut *s,
+ void *arg __attribute__((__unused__)))
{
struct route_node *rn;
afi_t afi = family2afi(PREFIX_FAMILY(s->p));
@@ -158,7 +160,7 @@ static void nhrp_shortcut_do_purge(struct event *t)
{
struct nhrp_shortcut *s = EVENT_ARG(t);
s->t_timer = NULL;
- nhrp_shortcut_delete(s);
+ nhrp_shortcut_delete(s, NULL);
}
static struct nhrp_shortcut *nhrp_shortcut_get(struct prefix *p)
@@ -469,6 +471,8 @@ void nhrp_shortcut_init(void)
void nhrp_shortcut_terminate(void)
{
+ nhrp_shortcut_foreach(AFI_IP, nhrp_shortcut_delete, NULL);
+ nhrp_shortcut_foreach(AFI_IP6, nhrp_shortcut_delete, NULL);
route_table_finish(shortcut_rib[AFI_IP]);
route_table_finish(shortcut_rib[AFI_IP6]);
}
diff --git a/ospf6d/ospf6_auth_trailer.c b/ospf6d/ospf6_auth_trailer.c
index 8d9eff409..860d27379 100644
--- a/ospf6d/ospf6_auth_trailer.c
+++ b/ospf6d/ospf6_auth_trailer.c
@@ -517,6 +517,15 @@ int ospf6_auth_check_digest(struct ospf6_header *oh, struct ospf6_interface *oi,
}
} else if (CHECK_FLAG(oi->at_data.flags,
OSPF6_AUTH_TRAILER_MANUAL_KEY)) {
+ if (oi->at_data.key_id != ntohs(ospf6_auth->id)) {
+ if (IS_OSPF6_DEBUG_AUTH_RX)
+ zlog_err("RECV[%s]: Auth SA ID mismatch for %s, received %u vs configured %u",
+ oi->interface->name,
+ ospf6_message_type(oh->type),
+ ntohs(ospf6_auth->id),
+ oi->at_data.key_id);
+ return OSPF6_AUTH_VALIDATE_FAILURE;
+ }
auth_str = oi->at_data.auth_key;
hash_algo = oi->at_data.hash_algo;
}
diff --git a/tests/bgpd/test_mp_attr.c b/tests/bgpd/test_mp_attr.c
index cebdda9e5..44a210403 100644
--- a/tests/bgpd/test_mp_attr.c
+++ b/tests/bgpd/test_mp_attr.c
@@ -23,6 +23,7 @@
#include "bgpd/bgp_nexthop.h"
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_network.h"
+#include "bgpd/bgp_label.h"
#define VT100_RESET "\x1b[0m"
#define VT100_RED "\x1b[31m"
@@ -1075,6 +1076,7 @@ int main(void)
vrf_init(NULL, NULL, NULL, NULL);
bgp_option_set(BGP_OPT_NO_LISTEN);
bgp_attr_init();
+ bgp_labels_init();
if (fileno(stdout) >= 0)
tty = isatty(fileno(stdout));
diff --git a/tests/bgpd/test_peer_attr.c b/tests/bgpd/test_peer_attr.c
index 12c2f1103..767c41cfe 100644
--- a/tests/bgpd/test_peer_attr.c
+++ b/tests/bgpd/test_peer_attr.c
@@ -18,6 +18,7 @@
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_zebra.h"
#include "bgpd/bgp_network.h"
+#include "bgpd/bgp_label.h"
#ifdef ENABLE_BGP_VNC
#include "bgpd/rfapi/rfapi_backend.h"
@@ -1374,6 +1375,7 @@ static void bgp_shutdown(void)
bgp_route_finish();
bgp_route_map_terminate();
bgp_attr_finish();
+ bgp_labels_finish();
bgp_pthreads_finish();
access_list_add_hook(NULL);
access_list_delete_hook(NULL);
diff --git a/tests/lib/test_printfrr.c b/tests/lib/test_printfrr.c
index cefa07ec7..a81ebcdbc 100644
--- a/tests/lib/test_printfrr.c
+++ b/tests/lib/test_printfrr.c
@@ -230,19 +230,25 @@ int main(int argc, char **argv)
printchk("02:ca:fe:f0:0d:1e", "%pFXh", &pfx);
struct prefix_sg sg;
- sg.src.s_addr = INADDR_ANY;
+ SET_IPADDR_V4(&sg.src);
+ sg.src.ipaddr_v4.s_addr = INADDR_ANY;
sg.grp.s_addr = INADDR_ANY;
printchk("(*,*)", "%pPSG4", &sg);
- inet_aton("192.168.1.2", &sg.src);
+ inet_aton("192.168.1.2", &sg.src.ipaddr_v4);
printchk("(192.168.1.2,*)", "%pPSG4", &sg);
inet_aton("224.1.2.3", &sg.grp);
printchk("(192.168.1.2,224.1.2.3)", "%pPSG4", &sg);
- sg.src.s_addr = INADDR_ANY;
+ SET_IPADDR_NONE(&sg.src);
+ sg.src.ipaddr_v4.s_addr = INADDR_ANY;
printchk("(*,224.1.2.3)", "%pPSG4", &sg);
+ SET_IPADDR_V6(&sg.src);
+ inet_pton(AF_INET6, "1:2:3:4::5", &sg.src.ipaddr_v6);
+ printchk("(1:2:3:4::5,224.1.2.3)", "%pPSG4", &sg);
+
uint8_t randhex[] = { 0x12, 0x34, 0x00, 0xca, 0xfe, 0x00, 0xaa, 0x55 };
FMT_NSTD(printchk("12 34 00 ca fe 00 aa 55", "%.8pHX", randhex));
diff --git a/tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_vpn_route_1723101.json b/tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_vpn_route_1723101.json
new file mode 100644
index 000000000..2ed76314b
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_vpn_route_1723101.json
@@ -0,0 +1,50 @@
+{
+ "444:1":{
+ "prefix":"172.31.0.1/32",
+ "advertisedTo":{
+ "192.168.0.1":{
+ }
+ },
+ "paths":[
+ {
+ "aspath":{
+ "string":"65500",
+ "segments":[
+ {
+ "type":"as-sequence",
+ "list":[
+ 65500
+ ]
+ }
+ ],
+ "length":1
+ },
+ "origin":"incomplete",
+ "metric":0,
+ "valid":true,
+ "bestpath":{
+ "overall":true,
+ "selectionReason":"First path received"
+ },
+ "extendedCommunity":{
+ "string":"RT:52:101"
+ },
+ "remoteLabel":102,
+ "nexthops":[
+ {
+ "ip":"192.168.0.1",
+ "afi":"ipv4",
+ "metric":0,
+ "accessible":true,
+ "used":true
+ }
+ ],
+ "peer":{
+ "peerId":"192.168.0.1",
+ "routerId":"192.0.2.1",
+ "type":"external"
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py b/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py
index 8b2e674aa..189824311 100644
--- a/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py
+++ b/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py
@@ -228,7 +228,12 @@ def test_export_route_target_empty():
router = tgen.gears["r1"]
logger.info("r1, Remove 'rt vpn export 52:100' command")
router.vtysh_cmd(
- "configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv4 unicast\nno rt vpn export 52:100\n"
+ """
+configure terminal
+router bgp 65500 vrf vrf1
+ address-family ipv4 unicast
+ no rt vpn export 52:100
+"""
)
prefix = "172.31.0.1/32"
@@ -254,10 +259,15 @@ def test_export_route_target_with_routemap_with_export_route_target():
router = tgen.gears["r1"]
logger.info("r1, configuring route target with route-map with export route target")
router.vtysh_cmd(
- "configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv4 unicast\nroute-map vpn export rmap\n"
- )
- router.vtysh_cmd(
- "configure terminal\nroute-map rmap permit 1\nset extcommunity rt 52:100\n"
+ """
+configure terminal
+router bgp 65500 vrf vrf1
+ address-family ipv4 unicast
+ route-map vpn export RMAP
+!
+route-map RMAP permit 1
+ set extcommunity rt 52:100
+"""
)
prefix = "172.31.0.1/32"
@@ -283,7 +293,11 @@ def test_export_route_target_with_routemap_without_export_route_target():
router = tgen.gears["r1"]
logger.info("r1, removing 'set extcommunity rt 52:100.")
router.vtysh_cmd(
- "configure terminal\nroute-map rmap permit 1\nno set extcommunity rt\n"
+ """
+configure terminal
+route-map RMAP permit 1
+ no set extcommunity rt
+"""
)
prefix = "172.31.0.1/32"
@@ -309,7 +323,12 @@ def test_export_route_target_with_default_command():
router = tgen.gears["r1"]
logger.info("r1, detach route-map and re-add route target vpn export")
router.vtysh_cmd(
- "configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv4 unicast\nrt vpn export 52:100\n"
+ """
+configure terminal
+router bgp 65500 vrf vrf1
+ address-family ipv4 unicast
+ rt vpn export 52:100
+"""
)
prefix = "172.31.0.1/32"
logger.info("r1, check that exported prefix {} is added back".format(prefix))
@@ -334,9 +353,14 @@ def test_export_suppress_route_target_with_route_map_command():
router = tgen.gears["r1"]
logger.info("r1, add an extended comm-list to delete 52:100")
- router.vtysh_cmd("configure terminal\nbgp extcommunity-list 1 permit rt 52:100\n")
router.vtysh_cmd(
- "configure terminal\nroute-map rmap permit 1\nset extended-comm-list 1 delete\n"
+ """
+configure terminal
+bgp extcommunity-list 1 permit rt 52:100
+!
+route-map RMAP permit 1
+ set extended-comm-list 1 delete
+"""
)
prefix = "172.31.0.1/32"
logger.info("r1, check that exported prefix {} is removed".format(prefix))
@@ -361,7 +385,11 @@ def test_export_add_route_target_to_route_map_command():
router = tgen.gears["r1"]
logger.info("r1, add an additional set extcommunity 52:101")
router.vtysh_cmd(
- "configure terminal\nroute-map rmap permit 1\nset extcommunity rt 52:101\n"
+ """
+configure terminal
+route-map RMAP permit 1
+ set extcommunity rt 52:101
+"""
)
prefix = "172.31.0.1/32"
logger.info("r1, check that exported prefix {} is added back".format(prefix))
@@ -376,6 +404,126 @@ def test_export_add_route_target_to_route_map_command():
assert success, "{}, vpnv4 update {} still not present".format(router.name, prefix)
+def test_adj_rib_out_label_change():
+ """
+ Check that changing the VPN label on r1
+ is propagated on r2
+ """
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Changing VPN label value to export")
+ dump = tgen.gears["r1"].vtysh_cmd(
+ """
+configure terminal
+ router bgp 65500 vrf vrf1
+ address-family ipv4 unicast
+ label vpn export 102
+"""
+ )
+ # Check BGP IPv4 route entry for 172.31.0.1 on r1
+ logger.info("Checking BGP IPv4 routes for convergence on r1")
+ router = tgen.gears["r2"]
+ json_file = "{}/{}/bgp_ipv4_vpn_route_1723101.json".format(CWD, router.name)
+ expected = json.loads(open(json_file).read())
+ test_func = partial(
+ topotest.router_json_cmp,
+ router,
+ "show bgp ipv4 vpn 172.31.0.1/32 json",
+ expected,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+
+def test_adj_rib_in_label_change():
+ """
+ Check that syncinig with ADJ-RIB-in on r2
+ permits restoring the initial label value
+ """
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Enable soft-reconfiguration inbound on r2")
+
+ r2 = tgen.gears["r2"]
+ r2.vtysh_cmd(
+ """
+configure terminal
+router bgp 65501
+ address-family ipv4 vpn
+ neighbor 192.168.0.1 soft-reconfiguration inbound
+"""
+ )
+
+ logger.info("Applying a deny-all route-map to input on r2")
+ r2.vtysh_cmd(
+ """
+configure terminal
+route-map DENY-ALL deny 1
+!
+router bgp 65501
+ address-family ipv4 vpn
+ neighbor 192.168.0.1 route-map DENY-ALL in
+"""
+ )
+
+ # check that 172.31.0.1 should not be present
+ logger.info("Check that received update 172.31.0.1 is not present")
+
+ expected = {}
+ test_func = partial(
+ topotest.router_json_cmp,
+ r2,
+ "show bgp ipv4 vpn 172.31.0.1/32 json",
+ expected,
+ exact=True,
+ )
+ success, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assert success, "r2, vpnv4 update 172.31.0.1 still present"
+
+
+def test_adj_rib_in_label_change_remove_rmap():
+ """
+ Check that syncinig with ADJ-RIB-in on r2
+ permits restoring the initial label value
+ """
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Removing the deny-all route-map from input on r2")
+
+ r2 = tgen.gears["r2"]
+ r2.vtysh_cmd(
+ """
+configure terminal
+router bgp 65501
+ address-family ipv4 vpn
+ no neighbor 192.168.0.1 route-map DENY-ALL in
+"""
+ )
+ # Check BGP IPv4 route entry for 172.31.0.1 on r1
+ logger.info(
+ "Checking that 172.31.0.1 BGP update is present and has valid label on r2"
+ )
+ json_file = "{}/{}/bgp_ipv4_vpn_route_1723101.json".format(CWD, r2.name)
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(
+ topotest.router_json_cmp,
+ r2,
+ "show bgp ipv4 vpn 172.31.0.1/32 json",
+ expected,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assertmsg = '"{}" JSON output mismatches'.format(r2.name)
+ assert result is None, assertmsg
+
+
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
diff --git a/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py b/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py
index 3938a966e..6d4b436bc 100644
--- a/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py
+++ b/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py
@@ -338,6 +338,21 @@ interface EVA
result, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
assert result, "BGP VRF DONNA check failed:\n{}".format(diff)
+ """
+ Check that "show ip route vrf DONNA json" and the JSON at key "DONNA" of
+ "show ip route vrf all json" gives the same result.
+ """
+
+ def check_vrf_table(router, vrf, expect):
+ output = router.vtysh_cmd("show ip route vrf all json", isjson=True)
+ vrf_table = output.get(vrf, {})
+
+ return topotest.json_cmp(vrf_table, expect)
+
+ test_func = partial(check_vrf_table, r1, "DONNA", expect)
+ result, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assert result, "BGP VRF DONNA check failed:\n{}".format(diff)
+
def test_vrf_route_leak_donna_after_eva_up():
logger.info("Ensure that route states change after EVA interface goes up")
diff --git a/tests/topotests/isis_topo1/test_isis_topo1.py b/tests/topotests/isis_topo1/test_isis_topo1.py
index 532e70859..b388f52bd 100644
--- a/tests/topotests/isis_topo1/test_isis_topo1.py
+++ b/tests/topotests/isis_topo1/test_isis_topo1.py
@@ -685,7 +685,7 @@ def _check_lsp_overload_bit(router, overloaded_router_lsp, att_p_ol_expected):
)
database_json = json.loads(isis_database_output)
- att_p_ol = database_json["areas"][0]["levels"][1]["att-p-ol"]
+ att_p_ol = database_json["areas"][0]["levels"][1]["lsps"][0]["attPOl"]
if att_p_ol == att_p_ol_expected:
return True
return "{} peer with expected att_p_ol {} got {} ".format(
diff --git a/tests/topotests/munet/__main__.py b/tests/topotests/munet/__main__.py
index e50fea691..145eb265a 100644
--- a/tests/topotests/munet/__main__.py
+++ b/tests/topotests/munet/__main__.py
@@ -19,6 +19,7 @@ from . import parser
from .args import add_launch_args
from .base import get_event_loop
from .cleanup import cleanup_previous
+from .cleanup import is_running_in_rundir
from .compat import PytestConfig
@@ -139,10 +140,11 @@ def main(*args):
eap = ap.add_argument_group(title="Uncommon", description="uncommonly used options")
eap.add_argument("--log-config", help="logging config file (yaml, toml, json, ...)")
eap.add_argument(
- "--no-kill",
+ "--kill",
action="store_true",
- help="Do not kill previous running processes",
+ help="Kill previous running processes using same rundir and exit",
)
+ eap.add_argument("--no-kill", action="store_true", help=argparse.SUPPRESS)
eap.add_argument(
"--no-cli", action="store_true", help="Do not run the interactive CLI"
)
@@ -157,7 +159,18 @@ def main(*args):
sys.exit(0)
rundir = args.rundir if args.rundir else "/tmp/munet"
+ rundir = os.path.abspath(rundir)
args.rundir = rundir
+
+ if args.kill:
+ logging.info("Killing any previous run using rundir: {rundir}")
+ cleanup_previous(args.rundir)
+ elif is_running_in_rundir(args.rundir):
+ logging.fatal(
+ "Munet processes using rundir: %s, use `--kill` to cleanup first", rundir
+ )
+ return 1
+
if args.cleanup:
if os.path.exists(rundir):
if not os.path.exists(f"{rundir}/config.json"):
@@ -169,6 +182,10 @@ def main(*args):
sys.exit(1)
else:
subprocess.run(["/usr/bin/rm", "-rf", rundir], check=True)
+
+ if args.kill:
+ return 0
+
subprocess.run(f"mkdir -p {rundir} && chmod 755 {rundir}", check=True, shell=True)
os.environ["MUNET_RUNDIR"] = rundir
@@ -183,9 +200,6 @@ def main(*args):
logger.critical("No nodes defined in config file")
return 1
- if not args.no_kill:
- cleanup_previous()
-
loop = None
status = 4
try:
diff --git a/tests/topotests/munet/base.py b/tests/topotests/munet/base.py
index a4811f179..e77eb15dc 100644
--- a/tests/topotests/munet/base.py
+++ b/tests/topotests/munet/base.py
@@ -469,6 +469,8 @@ class Commander: # pylint: disable=R0904
env = {**(kwargs["env"] if "env" in kwargs else os.environ)}
if "MUNET_NODENAME" not in env:
env["MUNET_NODENAME"] = self.name
+ if "MUNET_PID" not in env and "MUNET_PID" in os.environ:
+ env["MUNET_PID"] = os.environ["MUNET_PID"]
kwargs["env"] = env
defaults.update(kwargs)
@@ -780,8 +782,14 @@ class Commander: # pylint: disable=R0904
ps1 = re.escape(ps1)
ps2 = re.escape(ps2)
-
- extra = "PAGER=cat; export PAGER; TERM=dumb; unset HISTFILE; set +o emacs +o vi"
+ extra = [
+ "TERM=dumb",
+ "set +o emacs",
+ "set +o vi",
+ "unset HISTFILE",
+ "PAGER=cat",
+ "export PAGER",
+ ]
pchg = "PS1='{0}' PS2='{1}' PROMPT_COMMAND=''\n".format(ps1p, ps2p)
p.send(pchg)
return ShellWrapper(p, ps1, ps2, extra_init_cmd=extra, will_echo=will_echo)
@@ -934,15 +942,25 @@ class Commander: # pylint: disable=R0904
def _cmd_status(self, cmds, raises=False, warn=True, stdin=None, **kwargs):
"""Execute a command."""
+ timeout = None
+ if "timeout" in kwargs:
+ timeout = kwargs["timeout"]
+ del kwargs["timeout"]
+
pinput, stdin = Commander._cmd_status_input(stdin)
p, actual_cmd = self._popen("cmd_status", cmds, stdin=stdin, **kwargs)
- o, e = p.communicate(pinput)
+ o, e = p.communicate(pinput, timeout=timeout)
return self._cmd_status_finish(p, cmds, actual_cmd, o, e, raises, warn)
async def _async_cmd_status(
self, cmds, raises=False, warn=True, stdin=None, text=None, **kwargs
):
"""Execute a command."""
+ timeout = None
+ if "timeout" in kwargs:
+ timeout = kwargs["timeout"]
+ del kwargs["timeout"]
+
pinput, stdin = Commander._cmd_status_input(stdin)
p, actual_cmd = await self._async_popen(
"async_cmd_status", cmds, stdin=stdin, **kwargs
@@ -955,7 +973,12 @@ class Commander: # pylint: disable=R0904
if encoding is not None and isinstance(pinput, str):
pinput = pinput.encode(encoding)
- o, e = await p.communicate(pinput)
+ try:
+ o, e = await asyncio.wait_for(p.communicate(), timeout=timeout)
+ except (TimeoutError, asyncio.TimeoutError) as error:
+ raise subprocess.TimeoutExpired(
+ cmd=actual_cmd, timeout=timeout, output=None, stderr=None
+ ) from error
if encoding is not None:
o = o.decode(encoding) if o is not None else o
e = e.decode(encoding) if e is not None else e
@@ -1220,7 +1243,13 @@ class Commander: # pylint: disable=R0904
if self.is_vm and self.use_ssh and not ns_only: # pylint: disable=E1101
if isinstance(cmd, str):
cmd = shlex.split(cmd)
- cmd = ["/usr/bin/env", f"MUNET_NODENAME={self.name}"] + cmd
+ cmd = [
+ "/usr/bin/env",
+ f"MUNET_NODENAME={self.name}",
+ ]
+ if "MUNET_PID" in os.environ:
+ cmd.append(f"MUNET_PID={os.environ.get('MUNET_PID')}")
+ cmd += cmd
# get the ssh cmd
cmd = self._get_pre_cmd(False, True, ns_only=ns_only) + [shlex.join(cmd)]
@@ -1240,6 +1269,8 @@ class Commander: # pylint: disable=R0904
envvars = f"MUNET_NODENAME={self.name} NODENAME={self.name}"
if hasattr(self, "rundir"):
envvars += f" RUNDIR={self.rundir}"
+ if "MUNET_PID" in os.environ:
+ envvars += f" MUNET_PID={os.environ.get('MUNET_PID')}"
if hasattr(self.unet, "config_dirname") and self.unet.config_dirname:
envvars += f" CONFIGDIR={self.unet.config_dirname}"
elif "CONFIGDIR" in os.environ:
@@ -2520,7 +2551,7 @@ class Bridge(SharedNamespace, InterfaceMixin):
self.logger.debug("Bridge: Creating")
- assert len(self.name) <= 16 # Make sure fits in IFNAMSIZE
+ # assert len(self.name) <= 16 # Make sure fits in IFNAMSIZE
self.cmd_raises(f"ip link delete {name} || true")
self.cmd_raises(f"ip link add {name} type bridge")
if self.mtu:
@@ -2644,10 +2675,6 @@ class BaseMunet(LinuxNamespace):
self.cfgopt = munet_config.ConfigOptionsProxy(pytestconfig)
- super().__init__(
- name, mount=True, net=isolated, uts=isolated, pid=pid, unet=None, **kwargs
- )
-
# This allows us to cleanup any leftover running munet's
if "MUNET_PID" in os.environ:
if os.environ["MUNET_PID"] != str(our_pid):
@@ -2658,6 +2685,10 @@ class BaseMunet(LinuxNamespace):
)
os.environ["MUNET_PID"] = str(our_pid)
+ super().__init__(
+ name, mount=True, net=isolated, uts=isolated, pid=pid, unet=None, **kwargs
+ )
+
# this is for testing purposes do not use
if not BaseMunet.g_unet:
BaseMunet.g_unet = self
@@ -2765,7 +2796,7 @@ class BaseMunet(LinuxNamespace):
self.logger.error('"%s" len %s > 16', nsif1, len(nsif1))
elif len(nsif2) > 16:
self.logger.error('"%s" len %s > 16', nsif2, len(nsif2))
- assert len(nsif1) <= 16 and len(nsif2) <= 16 # Make sure fits in IFNAMSIZE
+ assert len(nsif1) < 16 and len(nsif2) < 16 # Make sure fits in IFNAMSIZE
self.logger.debug("%s: Creating veth pair for link %s", self, lname)
@@ -2993,8 +3024,11 @@ if True: # pylint: disable=using-constant-test
self._expectf = self.child.expect
if extra_init_cmd:
- self.expect_prompt()
- self.child.sendline(extra_init_cmd)
+ if isinstance(extra_init_cmd, str):
+ extra_init_cmd = [extra_init_cmd]
+ for ecmd in extra_init_cmd:
+ self.expect_prompt()
+ self.child.sendline(ecmd)
self.expect_prompt()
def expect_prompt(self, timeout=-1):
diff --git a/tests/topotests/munet/cleanup.py b/tests/topotests/munet/cleanup.py
index c641cda68..12ea6e284 100644
--- a/tests/topotests/munet/cleanup.py
+++ b/tests/topotests/munet/cleanup.py
@@ -59,25 +59,33 @@ def _get_our_pids():
return {}
-def _get_other_pids():
- piddict = get_pids_with_env("MUNET_PID")
- unet_pids = {d["MUNET_PID"] for d in piddict.values()}
+def _get_other_pids(rundir):
+ if rundir:
+ # get only munet pids using the given rundir
+ piddict = get_pids_with_env("MUNET_RUNDIR", str(rundir))
+ else:
+ # Get all munet pids
+ piddict = get_pids_with_env("MUNET_PID")
+ unet_pids = {d["MUNET_PID"] for d in piddict.values() if "MUNET_PID" in d}
pids_by_upid = {p: set() for p in unet_pids}
for pid, envdict in piddict.items():
+ if "MUNET_PID" not in envdict:
+ continue
unet_pid = envdict["MUNET_PID"]
pids_by_upid[unet_pid].add(pid)
# Filter out any child pid sets whos munet pid is still running
return {x: y for x, y in pids_by_upid.items() if x not in y}
-def _get_pids_by_upid(ours):
+def _get_pids_by_upid(ours, rundir):
if ours:
+ assert rundir is None
return _get_our_pids()
- return _get_other_pids()
+ return _get_other_pids(rundir)
-def _cleanup_pids(ours):
- pids_by_upid = _get_pids_by_upid(ours).items()
+def _cleanup_pids(ours, rundir):
+ pids_by_upid = _get_pids_by_upid(ours, rundir).items()
if not pids_by_upid:
return
@@ -94,7 +102,7 @@ def _cleanup_pids(ours):
# return
# time.sleep(1)
- pids_by_upid = _get_pids_by_upid(ours).items()
+ pids_by_upid = _get_pids_by_upid(ours, rundir).items()
_kill_piddict(pids_by_upid, signal.SIGKILL)
@@ -103,12 +111,16 @@ def cleanup_current():
Currently this only scans for old processes.
"""
- _cleanup_pids(True)
+ _cleanup_pids(True, None)
-def cleanup_previous():
+def cleanup_previous(rundir=None):
"""Attempt to cleanup preview runs.
Currently this only scans for old processes.
"""
- _cleanup_pids(False)
+ _cleanup_pids(False, rundir)
+
+
+def is_running_in_rundir(rundir):
+ return bool(get_pids_with_env("MUNET_RUNDIR", str(rundir)))
diff --git a/tests/topotests/munet/cli.py b/tests/topotests/munet/cli.py
index 133644e85..01a709151 100644
--- a/tests/topotests/munet/cli.py
+++ b/tests/topotests/munet/cli.py
@@ -106,9 +106,13 @@ def is_host_regex(restr):
def get_host_regex(restr):
- if len(restr) < 3 or restr[0] != "/" or restr[-1] != "/":
+ try:
+ if len(restr) < 3 or restr[0] != "/" or restr[-1] != "/":
+ return None
+ return re.compile(restr[1:-1])
+ except re.error:
+ logging.error("Invalid regex")
return None
- return re.compile(restr[1:-1])
def host_in(restr, names):
@@ -126,8 +130,8 @@ def expand_host(restr, names):
hosts = []
regexp = get_host_regex(restr)
if not regexp:
- assert restr in names
- hosts.append(restr)
+ if restr in names:
+ hosts.append(restr)
else:
for name in names:
if regexp.fullmatch(name):
diff --git a/tests/topotests/munet/logconf-mutest.yaml b/tests/topotests/munet/logconf-mutest.yaml
index b450fb938..c0b636cd6 100644
--- a/tests/topotests/munet/logconf-mutest.yaml
+++ b/tests/topotests/munet/logconf-mutest.yaml
@@ -1,5 +1,8 @@
version: 1
formatters:
+ result_color:
+ class: munet.mulog.ResultColorFormatter
+ format: '%(levelname)5s: %(message)s'
brief:
format: '%(levelname)5s: %(message)s'
operfmt:
@@ -22,7 +25,7 @@ handlers:
info_console:
level: INFO
class: logging.StreamHandler
- formatter: brief
+ formatter: result_color
stream: ext://sys.stderr
oper_console:
level: DEBUG
diff --git a/tests/topotests/munet/mucmd.py b/tests/topotests/munet/mucmd.py
index d6101e1a5..cd356f38a 100644
--- a/tests/topotests/munet/mucmd.py
+++ b/tests/topotests/munet/mucmd.py
@@ -89,14 +89,14 @@ def main(*args):
ecmd = "/usr/bin/nsenter"
eargs = [ecmd]
- # start mucmd same way base process is started
+ #start mucmd same way base process is started
eargs.append(f"--mount=/proc/{pid}/ns/mnt")
eargs.append(f"--net=/proc/{pid}/ns/net")
eargs.append(f"--pid=/proc/{pid}/ns/pid_for_children")
eargs.append(f"--uts=/proc/{pid}/ns/uts")
eargs.append(f"--wd={rundir}")
eargs += args.shellcmd
- # print("Using ", eargs)
+ #print("Using ", eargs)
return os.execvpe(ecmd, eargs, {**env, **envcfg})
diff --git a/tests/topotests/munet/mulog.py b/tests/topotests/munet/mulog.py
index f840eae2d..968acd9d1 100644
--- a/tests/topotests/munet/mulog.py
+++ b/tests/topotests/munet/mulog.py
@@ -12,6 +12,9 @@ import logging
from pathlib import Path
+do_color = True
+
+
class MultiFileHandler(logging.FileHandler):
"""A logging handler that logs to new files based on the logger name.
@@ -118,5 +121,28 @@ class ColorFormatter(logging.Formatter):
super().__init__(fmt, datefmt, style, **kwargs)
def format(self, record):
+ if not do_color:
+ return super().format(record)
formatter = self.formatters.get(record.levelno)
return formatter.format(record)
+
+
+class ResultColorFormatter(logging.Formatter):
+ """A formatter that colorizes PASS/FAIL strings based on level."""
+
+ green = "\x1b[32m"
+ red = "\x1b[31m"
+ reset = "\x1b[0m"
+
+ def format(self, record):
+ s = super().format(record)
+ if not do_color:
+ return s
+ idx = s.find("FAIL")
+ if idx >= 0 and record.levelno > logging.INFO:
+ s = s[:idx] + self.red + "FAIL" + self.reset + s[idx + 4 :]
+ elif record.levelno == logging.INFO:
+ idx = s.find("PASS")
+ if idx >= 0:
+ s = s[:idx] + self.green + "PASS" + self.reset + s[idx + 4 :]
+ return s
diff --git a/tests/topotests/munet/munet-schema.json b/tests/topotests/munet/munet-schema.json
index 7d577e63b..6ebc368dc 100644
--- a/tests/topotests/munet/munet-schema.json
+++ b/tests/topotests/munet/munet-schema.json
@@ -93,6 +93,9 @@
"image": {
"type": "string"
},
+ "hostnet": {
+ "type": "boolean"
+ },
"server": {
"type": "string"
},
@@ -383,6 +386,9 @@
},
"ipv6": {
"type": "string"
+ },
+ "external": {
+ "type": "boolean"
}
}
}
@@ -422,6 +428,9 @@
"image": {
"type": "string"
},
+ "hostnet": {
+ "type": "boolean"
+ },
"server": {
"type": "string"
},
diff --git a/tests/topotests/munet/mutest/__main__.py b/tests/topotests/munet/mutest/__main__.py
index d94e702c5..a78c69e26 100644
--- a/tests/topotests/munet/mutest/__main__.py
+++ b/tests/topotests/munet/mutest/__main__.py
@@ -20,6 +20,7 @@ from copy import deepcopy
from pathlib import Path
from typing import Union
+from munet import mulog
from munet import parser
from munet.args import add_testing_args
from munet.base import Bridge
@@ -380,8 +381,10 @@ async def run_tests(args):
for result in results:
test_name, passed, failed, e = result
tnum += 1
- s = "FAIL" if failed or e else "PASS"
- reslog.info(" %s %s:%s", s, tnum, test_name)
+ if failed or e:
+ reslog.warning(" FAIL %s:%s", tnum, test_name)
+ else:
+ reslog.info(" PASS %s:%s", tnum, test_name)
reslog.info("-" * 70)
reslog.info(
@@ -447,8 +450,9 @@ def main():
sys.exit(0)
rundir = args.rundir if args.rundir else "/tmp/mutest"
- args.rundir = Path(rundir)
- os.environ["MUNET_RUNDIR"] = rundir
+ rundir = Path(rundir).absolute()
+ args.rundir = rundir
+ os.environ["MUNET_RUNDIR"] = str(rundir)
subprocess.run(f"mkdir -p {rundir} && chmod 755 {rundir}", check=True, shell=True)
config = parser.setup_logging(args, config_base="logconf-mutest")
@@ -459,6 +463,9 @@ def main():
fconfig.get("format"), fconfig.get("datefmt")
)
+ if not hasattr(sys.stderr, "isatty") or not sys.stderr.isatty():
+ mulog.do_color = False
+
loop = None
status = 4
try:
diff --git a/tests/topotests/munet/mutest/userapi.py b/tests/topotests/munet/mutest/userapi.py
index f42fbc189..abc63af36 100644
--- a/tests/topotests/munet/mutest/userapi.py
+++ b/tests/topotests/munet/mutest/userapi.py
@@ -544,7 +544,9 @@ class TestCase:
"""
js = self._command_json(target, cmd)
if js is None:
- return expect_fail, {}
+ # Always fail on bad json, even if user expected failure
+ # return expect_fail, {}
+ return False, {}
try:
# Convert to string to validate the input is valid JSON
@@ -556,7 +558,9 @@ class TestCase:
self.olog.warning(
"JSON load failed. Check match value is in JSON format: %s", error
)
- return expect_fail, {}
+ # Always fail on bad json, even if user expected failure
+ # return expect_fail, {}
+ return False, {}
if exact_match:
deep_diff = json_cmp(expect, js)
diff --git a/tests/topotests/munet/native.py b/tests/topotests/munet/native.py
index de0f0ffc6..5747d5e1d 100644
--- a/tests/topotests/munet/native.py
+++ b/tests/topotests/munet/native.py
@@ -28,8 +28,10 @@ from . import cli
from .base import BaseMunet
from .base import Bridge
from .base import Commander
+from .base import InterfaceMixin
from .base import LinuxNamespace
from .base import MunetError
+from .base import SharedNamespace
from .base import Timeout
from .base import _async_get_exec_path
from .base import _get_exec_path
@@ -132,6 +134,22 @@ def convert_ranges_to_bitmask(ranges):
return bitmask
+class ExternalNetwork(SharedNamespace, InterfaceMixin):
+ """A network external to munet."""
+
+ def __init__(self, name=None, unet=None, logger=None, mtu=None, config=None):
+ """Create an external network."""
+ del logger # avoid linter
+ del mtu # avoid linter
+ # Do we want to use os.getpid() rather than unet.pid?
+ super().__init__(name, pid=unet.pid, nsflags=unet.nsflags, unet=unet)
+ self.config = config if config else {}
+
+ async def _async_delete(self):
+ self.logger.debug("%s: deleting", self)
+ await super()._async_delete()
+
+
class L2Bridge(Bridge):
"""A linux bridge with no IP network address."""
@@ -555,17 +573,38 @@ class NodeMixin:
await super()._async_delete()
+class HostnetNode(NodeMixin, LinuxNamespace):
+ """A node for running commands in the host network namespace."""
+
+ def __init__(self, name, pid=True, **kwargs):
+ if "net" in kwargs:
+ del kwargs["net"]
+ super().__init__(name, pid=pid, net=False, **kwargs)
+
+ self.logger.debug("%s: creating", self)
+
+ self.mgmt_ip = None
+ self.mgmt_ip6 = None
+ self.set_ns_cwd(self.rundir)
+
+ super().pytest_hook_open_shell()
+ self.logger.info("%s: created", self)
+
+ def get_ifname(self, netname): # pylint: disable=useless-return
+ del netname
+ return None
+
+ async def _async_delete(self):
+ self.logger.debug("%s: deleting", self)
+ await super()._async_delete()
+
+
class SSHRemote(NodeMixin, Commander):
"""SSHRemote a node representing an ssh connection to something."""
def __init__(
self,
name,
- server,
- port=22,
- user=None,
- password=None,
- idfile=None,
**kwargs,
):
super().__init__(name, **kwargs)
@@ -580,32 +619,33 @@ class SSHRemote(NodeMixin, Commander):
self.mgmt_ip = None
self.mgmt_ip6 = None
- self.port = port
-
- if user:
- self.user = user
- elif "SUDO_USER" in os.environ:
- self.user = os.environ["SUDO_USER"]
- else:
+ self.server = self.config["server"]
+ self.port = int(self.config.get("server-port", 22))
+ self.sudo_user = os.environ.get("SUDO_USER")
+ self.user = self.config.get("ssh-user")
+ if not self.user:
+ self.user = self.sudo_user
+ if not self.user:
self.user = getpass.getuser()
- self.password = password
- self.idfile = idfile
-
- self.server = f"{self.user}@{server}"
+ self.password = self.config.get("ssh-password")
+ self.idfile = self.config.get("ssh-identity-file")
+ self.use_host_network = None
# Setup our base `pre-cmd` values
#
# We maybe should add environment variable transfer here in particular
# MUNET_NODENAME. The problem is the user has to explicitly approve
# of SendEnv variables.
- self.__base_cmd = [
- get_exec_path_host("sudo"),
- "-E",
- f"-u{self.user}",
- get_exec_path_host("ssh"),
- ]
- if port != 22:
- self.__base_cmd.append(f"-p{port}")
+ self.__base_cmd = []
+ if self.idfile and self.sudo_user:
+ self.__base_cmd += [
+ get_exec_path_host("sudo"),
+ "-E",
+ f"-u{self.sudo_user}",
+ ]
+ self.__base_cmd.append(get_exec_path_host("ssh"))
+ if self.port != 22:
+ self.__base_cmd.append(f"-p{self.port}")
self.__base_cmd.append("-q")
self.__base_cmd.append("-oStrictHostKeyChecking=no")
self.__base_cmd.append("-oUserKnownHostsFile=/dev/null")
@@ -615,15 +655,34 @@ class SSHRemote(NodeMixin, Commander):
# self.__base_cmd.append("-oSendVar='TEST'")
self.__base_cmd_pty = list(self.__base_cmd)
self.__base_cmd_pty.append("-t")
- self.__base_cmd.append(self.server)
- self.__base_cmd_pty.append(self.server)
+ server_str = f"{self.user}@{self.server}"
+ self.__base_cmd.append(server_str)
+ self.__base_cmd_pty.append(server_str)
# self.set_pre_cmd(pre_cmd, pre_cmd_tty)
self.logger.info("%s: created", self)
def _get_pre_cmd(self, use_str, use_pty, ns_only=False, **kwargs):
- pre_cmd = []
- if self.unet:
+ # None on first use, set after
+ if self.use_host_network is None:
+ # We have networks now so try and ping the server in the namespace
+ if not self.unet:
+ self.use_host_network = True
+ else:
+ rc, _, _ = self.unet.cmd_status(f"ping -w1 -c1 {self.server}")
+ if rc:
+ self.use_host_network = True
+ else:
+ self.use_host_network = False
+
+ if self.use_host_network:
+ self.logger.debug("Using host namespace for ssh connection")
+ else:
+ self.logger.debug("Using munet namespace for ssh connection")
+
+ if self.use_host_network:
+ pre_cmd = []
+ else:
pre_cmd = self.unet._get_pre_cmd(False, use_pty, ns_only=False, **kwargs)
if ns_only:
return pre_cmd
@@ -979,17 +1038,16 @@ ff02::2\tip6-allrouters
)
self.unet.rootcmd.cmd_status(f"ip link set {dname} name {hname}")
- rc, o, _ = self.unet.rootcmd.cmd_status("ip -o link show")
- m = re.search(rf"\d+:\s+{re.escape(hname)}:.*", o)
- if m:
- self.unet.rootcmd.cmd_nostatus(f"ip link set {hname} down ")
- self.unet.rootcmd.cmd_raises(f"ip link set {hname} netns {self.pid}")
+ # Make sure the interface is there.
+ self.unet.rootcmd.cmd_raises(f"ip -o link show {hname}")
+ self.unet.rootcmd.cmd_nostatus(f"ip link set {hname} down ")
+ self.unet.rootcmd.cmd_raises(f"ip link set {hname} netns {self.pid}")
+
# Wait for interface to show up in namespace
for retry in range(0, 10):
rc, o, _ = self.cmd_status(f"ip -o link show {hname}")
if not rc:
- if re.search(rf"\d+: {re.escape(hname)}:.*", o):
- break
+ break
if retry > 0:
await asyncio.sleep(1)
self.cmd_raises(f"ip link set {hname} name {lname}")
@@ -1001,12 +1059,11 @@ ff02::2\tip6-allrouters
lname = self.host_intfs[hname]
self.cmd_raises(f"ip link set {lname} down")
self.cmd_raises(f"ip link set {lname} name {hname}")
- self.cmd_status(f"ip link set netns 1 dev {hname}")
- # The above is failing sometimes and not sure why
- # logging.error(
- # "XXX after setns %s",
- # self.unet.rootcmd.cmd_nostatus(f"ip link show {hname}"),
- # )
+ # We need to NOT run this command in the new pid namespace so that pid 1 is the
+ # root init process and so the interface gets returned to the root namespace
+ self.unet.rootcmd.cmd_raises(
+ f"nsenter -t {self.pid} -n ip link set netns 1 dev {hname}"
+ )
del self.host_intfs[hname]
async def add_phy_intf(self, devaddr, lname):
@@ -1917,7 +1974,11 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
# InterfaceMixin override
# We need a name unique in the shared namespace.
def get_ns_ifname(self, ifname):
- return self.name + ifname
+ ifname = self.name + ifname
+ ifname = re.sub("gigabitethernet", "GE", ifname, flags=re.I)
+ if len(ifname) >= 16:
+ ifname = ifname[0:7] + ifname[-8:]
+ return ifname
async def add_host_intf(self, hname, lname, mtu=None):
# L3QemuVM needs it's own add_host_intf for macvtap, We need to create the tap
@@ -2093,16 +2154,22 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
)
con.cmd_raises(rf"rm -rf {tmpdir}")
- self.logger.info("Saved coverage data in VM at %s", dest)
+ self.logger.debug("Saved coverage data in VM at %s", dest)
ldest = os.path.join(self.rundir, "gcov-data.tgz")
if self.use_ssh:
self.cmd_raises(["/bin/cat", dest], stdout=open(ldest, "wb"))
- self.logger.info("Saved coverage data on host at %s", ldest)
+ self.logger.debug("Saved coverage data on host at %s", ldest)
else:
output = con.cmd_raises(rf"base64 {dest}")
with open(ldest, "wb") as f:
f.write(base64.b64decode(output))
- self.logger.info("Saved coverage data on host at %s", ldest)
+ self.logger.debug("Saved coverage data on host at %s", ldest)
+ self.logger.info("Extracting coverage for %s into %s", self.name, ldest)
+
+ # We need to place the gcda files where munet expects to find them
+ gcdadir = Path(os.environ["GCOV_PREFIX"]) / self.name
+ self.unet.cmd_raises_nsonly(f"mkdir -p {gcdadir}")
+ self.unet.cmd_raises_nsonly(f"tar -C {gcdadir} -xzf {ldest}")
async def _opencons(
self,
@@ -2878,7 +2945,9 @@ ff02::2\tip6-allrouters
else:
node2.set_lan_addr(node1, c2)
- if "physical" not in c1 and not node1.is_vm:
+ if isinstance(node1, ExternalNetwork):
+ pass
+ elif "physical" not in c1 and not node1.is_vm:
node1.set_intf_constraints(if1, **c1)
if "physical" not in c2 and not node2.is_vm:
node2.set_intf_constraints(if2, **c2)
@@ -2891,14 +2960,8 @@ ff02::2\tip6-allrouters
cls = L3QemuVM
elif config and config.get("server"):
cls = SSHRemote
- kwargs["server"] = config["server"]
- kwargs["port"] = int(config.get("server-port", 22))
- if "ssh-identity-file" in config:
- kwargs["idfile"] = config.get("ssh-identity-file")
- if "ssh-user" in config:
- kwargs["user"] = config.get("ssh-user")
- if "ssh-password" in config:
- kwargs["password"] = config.get("ssh-password")
+ elif config and config.get("hostnet"):
+ cls = HostnetNode
else:
cls = L3NamespaceNode
return super().add_host(name, cls=cls, config=config, **kwargs)
@@ -2908,7 +2971,12 @@ ff02::2\tip6-allrouters
if config is None:
config = {}
- cls = L3Bridge if config.get("ip") else L2Bridge
+ if config.get("external"):
+ cls = ExternalNetwork
+ elif config.get("ip"):
+ cls = L3Bridge
+ else:
+ cls = L2Bridge
mtu = kwargs.get("mtu", config.get("mtu"))
return super().add_switch(name, cls=cls, config=config, mtu=mtu, **kwargs)
@@ -2947,7 +3015,7 @@ ff02::2\tip6-allrouters
bdir = Path(os.environ["GCOV_BUILD_DIR"])
gcdadir = Path(os.environ["GCOV_PREFIX"])
- # Create GCNO symlinks
+ # Create .gcno symlinks if they don't already exist, for kernel they will
self.logger.info("Creating .gcno symlinks from '%s' to '%s'", gcdadir, bdir)
commander.cmd_raises(
f'cd "{gcdadir}"; bdir="{bdir}"'
@@ -2955,9 +3023,11 @@ ff02::2\tip6-allrouters
for f in $(find . -name '*.gcda'); do
f=${f#./};
f=${f%.gcda}.gcno;
- ln -fs $bdir/$f $f;
- touch -h -r $bdir/$f $f;
- echo $f;
+ if [ ! -h "$f" ]; then
+ ln -fs $bdir/$f $f;
+ touch -h -r $bdir/$f $f;
+ echo $f;
+ fi;
done"""
)
@@ -2977,10 +3047,30 @@ done"""
# f"\nCOVERAGE-SUMMARY-START\n{output}\nCOVERAGE-SUMMARY-END\n"
# )
- async def run(self):
+ async def load_images(self, images):
tasks = []
+ for image in images:
+ logging.debug("Checking for image %s", image)
+ rc, _, _ = self.rootcmd.cmd_status(
+ f"podman image inspect {image}", warn=False
+ )
+ if not rc:
+ continue
+ logging.info("Pulling missing image %s", image)
+ aw = self.rootcmd.async_cmd_raises(f"podman pull {image}")
+ tasks.append(asyncio.create_task(aw))
+ if not tasks:
+ return
+ _, pending = await asyncio.wait(tasks, timeout=600)
+ assert not pending, "Failed to pull container images"
+ async def run(self):
+ tasks = []
hosts = self.hosts.values()
+
+ images = {x.container_image for x in hosts if hasattr(x, "container_image")}
+ await self.load_images(images)
+
launch_nodes = [x for x in hosts if hasattr(x, "launch")]
launch_nodes = [x for x in launch_nodes if x.config.get("qemu")]
run_nodes = [x for x in hosts if x.has_run_cmd()]
@@ -3049,10 +3139,10 @@ done"""
await asyncio.sleep(0.25)
logging.debug("%s is ready!", x)
+ tasks = [asyncio.create_task(wait_until_ready(x)) for x in ready_nodes]
+
logging.debug("Waiting for ready on nodes: %s", ready_nodes)
- _, pending = await asyncio.wait(
- [wait_until_ready(x) for x in ready_nodes], timeout=30
- )
+ _, pending = await asyncio.wait(tasks, timeout=30)
if pending:
logging.warning("Timeout waiting for ready: %s", pending)
for nr in pending:
diff --git a/tests/topotests/munet/testing/fixtures.py b/tests/topotests/munet/testing/fixtures.py
index 4150d28b5..3c6ddf9ae 100644
--- a/tests/topotests/munet/testing/fixtures.py
+++ b/tests/topotests/munet/testing/fixtures.py
@@ -25,7 +25,6 @@ from ..base import BaseMunet
from ..base import Bridge
from ..base import get_event_loop
from ..cleanup import cleanup_current
-from ..cleanup import cleanup_previous
from ..native import L3NodeMixin
from ..parser import async_build_topology
from ..parser import get_config
@@ -130,9 +129,12 @@ def session_autouse():
else:
is_worker = True
- if not is_worker:
- # This is unfriendly to multi-instance
- cleanup_previous()
+ # We dont want to kill all munet and we don't have the rundir here yet
+ # This was more useful back when we used to leave processes around a lot
+ # more.
+ # if not is_worker:
+ # # This is unfriendly to multi-instance
+ # cleanup_previous()
# We never pop as we want to keep logging
_push_log_handler("session", "/tmp/unet-test/pytest-session.log")
@@ -150,8 +152,9 @@ def session_autouse():
@pytest.fixture(autouse=True, scope="module")
def module_autouse(request):
+ root_path = os.environ.get("MUNET_RUNDIR", "/tmp/unet-test")
logpath = get_test_logdir(request.node.nodeid, True)
- logpath = os.path.join("/tmp/unet-test", logpath, "pytest-exec.log")
+ logpath = os.path.join(root_path, logpath, "pytest-exec.log")
with log_handler("module", logpath):
sdir = os.path.dirname(os.path.realpath(request.fspath))
with chdir(sdir, "module autouse fixture"):
@@ -174,7 +177,8 @@ def event_loop():
@pytest.fixture(scope="module")
def rundir_module():
- d = os.path.join("/tmp/unet-test", get_test_logdir(module=True))
+ root_path = os.environ.get("MUNET_RUNDIR", "/tmp/unet-test")
+ d = os.path.join(root_path, get_test_logdir(module=True))
logging.debug("conftest: test module rundir %s", d)
return d
@@ -375,7 +379,8 @@ async def astepf(pytestconfig):
@pytest.fixture(scope="function")
def rundir():
- d = os.path.join("/tmp/unet-test", get_test_logdir(module=False))
+ root_path = os.environ.get("MUNET_RUNDIR", "/tmp/unet-test")
+ d = os.path.join(root_path, get_test_logdir(module=False))
logging.debug("conftest: test function rundir %s", d)
return d
@@ -383,9 +388,8 @@ def rundir():
# Configure logging
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_setup(item):
- d = os.path.join(
- "/tmp/unet-test", get_test_logdir(nodeid=item.nodeid, module=False)
- )
+ root_path = os.environ.get("MUNET_RUNDIR", "/tmp/unet-test")
+ d = os.path.join(root_path, get_test_logdir(nodeid=item.nodeid, module=False))
config = item.config
logging_plugin = config.pluginmanager.get_plugin("logging-plugin")
filename = Path(d, "pytest-exec.log")
diff --git a/tests/topotests/munet/watchlog.py b/tests/topotests/munet/watchlog.py
index f764f9dac..27bc3251a 100644
--- a/tests/topotests/munet/watchlog.py
+++ b/tests/topotests/munet/watchlog.py
@@ -15,7 +15,6 @@ from pathlib import Path
class MatchFoundError(Exception):
"""An error raised when a match is not found."""
-
def __init__(self, watchlog, match):
self.watchlog = watchlog
self.match = match
diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_authentication.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_authentication.py
index 58608e249..00c98ac97 100644
--- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_authentication.py
+++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_authentication.py
@@ -175,7 +175,7 @@ def test_ospf6_auth_trailer_tc1_md5(request):
result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r1"
@@ -208,7 +208,7 @@ def test_ospf6_auth_trailer_tc1_md5(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 "
+ "Verify that the neighbor is FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
@@ -266,7 +266,7 @@ def test_ospf6_auth_trailer_tc1_md5(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 using"
+ "Verify that the neighbor is FULL between R1 and R2 using"
" show ip ospf6 neighbor cmd."
)
@@ -283,7 +283,7 @@ def test_ospf6_auth_trailer_tc1_md5(request):
dut = "r2"
step(
- "Verify that the neighbour is not FULL between R1 and R2 using "
+ "Verify that the neighbor is not FULL between R1 and R2 using "
"show ip ospf6 neighbor cmd."
)
ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut, expected=False)
@@ -295,7 +295,7 @@ def test_ospf6_auth_trailer_tc1_md5(request):
shutdown_bringup_interface(tgen, dut, intf, True)
step(
- "Verify that the neighbour is FULL between R1 and R2 using "
+ "Verify that the neighbor is FULL between R1 and R2 using "
"show ip ospf6 neighbor cmd."
)
@@ -341,7 +341,7 @@ def test_ospf6_auth_trailer_tc2_sha256(request):
result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r1"
@@ -374,7 +374,7 @@ def test_ospf6_auth_trailer_tc2_sha256(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 "
+ "Verify that the neighbor is FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
@@ -432,7 +432,7 @@ def test_ospf6_auth_trailer_tc2_sha256(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 using"
+ "Verify that the neighbor is FULL between R1 and R2 using"
" show ip ospf6 neighbor cmd."
)
@@ -449,7 +449,7 @@ def test_ospf6_auth_trailer_tc2_sha256(request):
dut = "r2"
step(
- "Verify that the neighbour is not FULL between R1 and R2 using "
+ "Verify that the neighbor is not FULL between R1 and R2 using "
"show ip ospf6 neighbor cmd."
)
ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut, expected=False)
@@ -461,7 +461,66 @@ def test_ospf6_auth_trailer_tc2_sha256(request):
shutdown_bringup_interface(tgen, dut, intf, True)
step(
- "Verify that the neighbour is FULL between R1 and R2 using "
+ "Verify that the neighbor is FULL between R1 and R2 using "
+ "show ip ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step("Change the key ID on R2 to not match R1")
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "hash-algo": "hmac-sha-256",
+ "key": "ospf6",
+ "key-id": "30",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify on R1 that R2 nbr is deleted due to key-id mismatch "
+ "after dead interval expiry"
+ )
+ # wait till the dead timer expiry
+ sleep(6)
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=5
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step("Correct the key ID on R2 so that it matches R1")
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "hash-algo": "hmac-sha-256",
+ "key": "ospf6",
+ "key-id": "10",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that the neighbor is FULL between R1 and R2 using "
"show ip ospf6 neighbor cmd."
)
@@ -524,7 +583,7 @@ def test_ospf6_auth_trailer_tc3_keychain_md5(request):
result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r1"
@@ -555,7 +614,7 @@ def test_ospf6_auth_trailer_tc3_keychain_md5(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 "
+ "Verify that the neighbor is FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
@@ -600,7 +659,7 @@ def test_ospf6_auth_trailer_tc3_keychain_md5(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 using"
+ "Verify that the neighbor is FULL between R1 and R2 using"
" show ip ospf6 neighbor cmd."
)
@@ -617,7 +676,7 @@ def test_ospf6_auth_trailer_tc3_keychain_md5(request):
dut = "r2"
step(
- "Verify that the neighbour is not FULL between R1 and R2 using "
+ "Verify that the neighbor is not FULL between R1 and R2 using "
"show ip ospf6 neighbor cmd."
)
ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut, expected=False)
@@ -629,7 +688,7 @@ def test_ospf6_auth_trailer_tc3_keychain_md5(request):
shutdown_bringup_interface(tgen, dut, intf, True)
step(
- "Verify that the neighbour is FULL between R1 and R2 using "
+ "Verify that the neighbor is FULL between R1 and R2 using "
"show ip ospf6 neighbor cmd."
)
@@ -692,7 +751,7 @@ def test_ospf6_auth_trailer_tc4_keychain_sha256(request):
result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r1"
@@ -723,7 +782,7 @@ def test_ospf6_auth_trailer_tc4_keychain_sha256(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 "
+ "Verify that the neighbor is FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
@@ -768,7 +827,7 @@ def test_ospf6_auth_trailer_tc4_keychain_sha256(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 using"
+ "Verify that the neighbor is FULL between R1 and R2 using"
" show ip ospf6 neighbor cmd."
)
@@ -785,7 +844,7 @@ def test_ospf6_auth_trailer_tc4_keychain_sha256(request):
dut = "r2"
step(
- "Verify that the neighbour is not FULL between R1 and R2 using "
+ "Verify that the neighbor is not FULL between R1 and R2 using "
"show ip ospf6 neighbor cmd."
)
ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut, expected=False)
@@ -797,7 +856,7 @@ def test_ospf6_auth_trailer_tc4_keychain_sha256(request):
shutdown_bringup_interface(tgen, dut, intf, True)
step(
- "Verify that the neighbour is FULL between R1 and R2 using "
+ "Verify that the neighbor is FULL between R1 and R2 using "
"show ip ospf6 neighbor cmd."
)
@@ -843,7 +902,7 @@ def test_ospf6_auth_trailer_tc5_md5_keymissmatch(request):
result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r1"
@@ -876,11 +935,11 @@ def test_ospf6_auth_trailer_tc5_md5_keymissmatch(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is not FULL between R1 and R2 "
+ "Verify that the neighbor is not FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
- step("Verify that the neighbour is FULL between R1 and R2.")
+ step("Verify that the neighbor is FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r2"
@@ -913,7 +972,7 @@ def test_ospf6_auth_trailer_tc5_md5_keymissmatch(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 "
+ "Verify that the neighbor is FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
@@ -959,7 +1018,7 @@ def test_ospf6_auth_trailer_tc6_sha256_mismatch(request):
result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r1"
@@ -991,7 +1050,7 @@ def test_ospf6_auth_trailer_tc6_sha256_mismatch(request):
result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r2"
@@ -1024,7 +1083,7 @@ def test_ospf6_auth_trailer_tc6_sha256_mismatch(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 "
+ "Verify that the neighbor is FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
@@ -1095,7 +1154,7 @@ def test_ospf6_auth_trailer_tc7_keychain_md5_missmatch(request):
result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r1"
@@ -1125,7 +1184,7 @@ def test_ospf6_auth_trailer_tc7_keychain_md5_missmatch(request):
result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r2"
@@ -1156,7 +1215,7 @@ def test_ospf6_auth_trailer_tc7_keychain_md5_missmatch(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 "
+ "Verify that the neighbor is FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
@@ -1227,7 +1286,7 @@ def test_ospf6_auth_trailer_tc8_keychain_sha256_missmatch(request):
result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r1"
@@ -1257,7 +1316,7 @@ def test_ospf6_auth_trailer_tc8_keychain_sha256_missmatch(request):
result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r2"
@@ -1288,7 +1347,7 @@ def test_ospf6_auth_trailer_tc8_keychain_sha256_missmatch(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 "
+ "Verify that the neighbor is FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
@@ -1335,7 +1394,7 @@ def test_ospf6_auth_trailer_tc9_keychain_not_configured(request):
result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r1"
@@ -1365,7 +1424,7 @@ def test_ospf6_auth_trailer_tc9_keychain_not_configured(request):
result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r2"
@@ -1396,7 +1455,7 @@ def test_ospf6_auth_trailer_tc10_no_auth_trailer(request):
router2 = tgen.gears["r2"]
step(
- "Verify that the neighbour is FULL between R1 and R2 "
+ "Verify that the neighbor is FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c
index 245b799a9..9ad92d626 100644
--- a/zebra/dplane_fpm_nl.c
+++ b/zebra/dplane_fpm_nl.c
@@ -654,14 +654,6 @@ static void fpm_read(struct event *t)
hdr_available_bytes = fpm.msg_len - FPM_MSG_HDR_LEN;
available_bytes -= hdr_available_bytes;
- /* Sanity check: must be at least header size. */
- if (hdr->nlmsg_len < sizeof(*hdr)) {
- zlog_warn(
- "%s: [seq=%u] invalid message length %u (< %zu)",
- __func__, hdr->nlmsg_seq, hdr->nlmsg_len,
- sizeof(*hdr));
- continue;
- }
if (hdr->nlmsg_len > fpm.msg_len) {
zlog_warn(
"%s: Received a inner header length of %u that is greater than the fpm total length of %u",
@@ -691,6 +683,14 @@ static void fpm_read(struct event *t)
switch (hdr->nlmsg_type) {
case RTM_NEWROUTE:
+ /* Sanity check: need at least route msg header size. */
+ if (hdr->nlmsg_len < sizeof(struct rtmsg)) {
+ zlog_warn("%s: [seq=%u] invalid message length %u (< %zu)",
+ __func__, hdr->nlmsg_seq,
+ hdr->nlmsg_len, sizeof(struct rtmsg));
+ break;
+ }
+
ctx = dplane_ctx_alloc();
dplane_ctx_route_init(ctx, DPLANE_OP_ROUTE_NOTIFY, NULL,
NULL);
diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c
index 5c19d226b..75e7e2017 100644
--- a/zebra/zebra_evpn_mh.c
+++ b/zebra/zebra_evpn_mh.c
@@ -3026,7 +3026,7 @@ void zebra_evpn_es_if_oper_state_change(struct zebra_if *zif, bool up)
}
static char *zebra_evpn_es_vtep_str(char *vtep_str, struct zebra_evpn_es *es,
- uint8_t vtep_str_size)
+ size_t vtep_str_size)
{
struct zebra_evpn_es_vtep *zvtep;
struct listnode *node;
diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c
index 617a2225f..fb326b0dd 100644
--- a/zebra/zebra_netns_notify.c
+++ b/zebra/zebra_netns_notify.c
@@ -15,6 +15,7 @@
#include <sched.h>
#endif
#include <dirent.h>
+#include <libgen.h>
#include <sys/inotify.h>
#include <sys/stat.h>
@@ -234,6 +235,7 @@ static void zebra_ns_ready_read(struct event *t)
{
struct zebra_netns_info *zns_info = EVENT_ARG(t);
const char *netnspath;
+ const char *netnspath_basename;
int err, stop_retry = 0;
if (!zns_info)
@@ -261,23 +263,24 @@ static void zebra_ns_ready_read(struct event *t)
zebra_ns_continue_read(zns_info, stop_retry);
return;
}
+ netnspath_basename = basename(strdupa(netnspath));
/* check default name is not already set */
- if (strmatch(VRF_DEFAULT_NAME, basename(netnspath))) {
- zlog_warn("NS notify : NS %s is already default VRF.Cancel VRF Creation", basename(netnspath));
+ if (strmatch(VRF_DEFAULT_NAME, netnspath_basename)) {
+ zlog_warn("NS notify : NS %s is already default VRF.Cancel VRF Creation", netnspath_basename);
zebra_ns_continue_read(zns_info, 1);
return;
}
- if (zebra_ns_notify_is_default_netns(basename(netnspath))) {
+ if (zebra_ns_notify_is_default_netns(netnspath_basename)) {
zlog_warn(
"NS notify : NS %s is default VRF. Ignore VRF creation",
- basename(netnspath));
+ netnspath_basename);
zebra_ns_continue_read(zns_info, 1);
return;
}
/* success : close fd and create zns context */
- zebra_ns_notify_create_context_from_entry_name(basename(netnspath));
+ zebra_ns_notify_create_context_from_entry_name(netnspath_basename);
zebra_ns_continue_read(zns_info, 1);
}
@@ -396,7 +399,7 @@ void zebra_ns_notify_parse(void)
continue;
}
/* check default name is not already set */
- if (strmatch(VRF_DEFAULT_NAME, basename(dent->d_name))) {
+ if (strmatch(VRF_DEFAULT_NAME, basename(strdupa(dent->d_name)))) {
zlog_warn("NS notify : NS %s is already default VRF.Cancel VRF Creation", dent->d_name);
continue;
}
diff --git a/zebra/zebra_srv6_vty.c b/zebra/zebra_srv6_vty.c
index c5b850599..d5cd30e64 100644
--- a/zebra/zebra_srv6_vty.c
+++ b/zebra/zebra_srv6_vty.c
@@ -475,16 +475,24 @@ static int zebra_sr_config(struct vty *vty)
struct listnode *node;
struct srv6_locator *locator;
char str[256];
+ bool display_source_srv6 = false;
+
+ if (srv6 && !IPV6_ADDR_SAME(&srv6->encap_src_addr, &in6addr_any))
+ display_source_srv6 = true;
vty_out(vty, "!\n");
- if (zebra_srv6_is_enable()) {
+ if (display_source_srv6 || zebra_srv6_is_enable()) {
vty_out(vty, "segment-routing\n");
vty_out(vty, " srv6\n");
+ }
+ if (display_source_srv6) {
if (!IPV6_ADDR_SAME(&srv6->encap_src_addr, &in6addr_any)) {
vty_out(vty, " encapsulation\n");
vty_out(vty, " source-address %pI6\n",
&srv6->encap_src_addr);
}
+ }
+ if (zebra_srv6_is_enable()) {
vty_out(vty, " locators\n");
for (ALL_LIST_ELEMENTS_RO(srv6->locators, node, locator)) {
inet_ntop(AF_INET6, &locator->prefix.prefix,
@@ -514,6 +522,8 @@ static int zebra_sr_config(struct vty *vty)
vty_out(vty, " !\n");
vty_out(vty, " exit\n");
vty_out(vty, " !\n");
+ }
+ if (display_source_srv6 || zebra_srv6_is_enable()) {
vty_out(vty, "exit\n");
vty_out(vty, "!\n");
}
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 44720754b..c31218a7c 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -60,8 +60,8 @@ struct route_show_ctx {
};
static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
- safi_t safi, bool use_fib, json_object *vrf_json,
- bool use_json, route_tag_t tag,
+ safi_t safi, bool use_fib, bool use_json,
+ route_tag_t tag,
const struct prefix *longer_prefix_p,
bool supernets_only, int type,
unsigned short ospf_instance_id, uint32_t tableid,
@@ -153,8 +153,8 @@ DEFPY (show_ip_rpf,
};
return do_show_ip_route(vty, VRF_DEFAULT_NAME, ip ? AFI_IP : AFI_IP6,
- SAFI_MULTICAST, false, NULL, uj, 0, NULL, false,
- 0, 0, 0, false, &ctx);
+ SAFI_MULTICAST, false, uj, 0, NULL, false, 0, 0,
+ 0, false, &ctx);
}
DEFPY (show_ip_rpf_addr,
@@ -858,19 +858,20 @@ static void vty_show_ip_route_detail_json(struct vty *vty,
vty_json(vty, json);
}
-static void
-do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
- struct route_table *table, afi_t afi, bool use_fib,
- json_object *vrf_json, route_tag_t tag,
- const struct prefix *longer_prefix_p, bool supernets_only,
- int type, unsigned short ospf_instance_id, bool use_json,
- uint32_t tableid, bool show_ng, struct route_show_ctx *ctx)
+static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
+ struct route_table *table, afi_t afi,
+ bool use_fib, route_tag_t tag,
+ const struct prefix *longer_prefix_p,
+ bool supernets_only, int type,
+ unsigned short ospf_instance_id, bool use_json,
+ uint32_t tableid, bool show_ng,
+ struct route_show_ctx *ctx)
{
struct route_node *rn;
struct route_entry *re;
+ bool first_json = true;
int first = 1;
rib_dest_t *dest;
- json_object *json = NULL;
json_object *json_prefix = NULL;
uint32_t addr;
char buf[BUFSIZ];
@@ -886,9 +887,6 @@ do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
* => display the VRF and table if specific
*/
- if (use_json && !vrf_json)
- json = json_object_new_object();
-
/* Show all routes. */
for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
dest = rib_dest_from_rnode(rn);
@@ -961,28 +959,20 @@ do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
if (json_prefix) {
prefix2str(&rn->p, buf, sizeof(buf));
- if (!vrf_json)
- json_object_object_add(json, buf, json_prefix);
- else
- json_object_object_add(vrf_json, buf,
- json_prefix);
+ vty_json_key(vty, buf, &first_json);
+ vty_json_no_pretty(vty, json_prefix);
+
json_prefix = NULL;
}
}
- /*
- * This is an extremely expensive operation at scale
- * and non-pretty reduces memory footprint significantly.
- */
- if (use_json && !vrf_json) {
- vty_json_no_pretty(vty, json);
- json = NULL;
- }
+ if (use_json)
+ vty_json_close(vty, first_json);
}
static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf,
- afi_t afi, bool use_fib, json_object *vrf_json,
- bool use_json, route_tag_t tag,
+ afi_t afi, bool use_fib, bool use_json,
+ route_tag_t tag,
const struct prefix *longer_prefix_p,
bool supernets_only, int type,
unsigned short ospf_instance_id, bool show_ng,
@@ -1002,15 +992,15 @@ static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf,
continue;
do_show_ip_route(vty, zvrf_name(zvrf), afi, SAFI_UNICAST,
- use_fib, vrf_json, use_json, tag,
- longer_prefix_p, supernets_only, type,
- ospf_instance_id, zrt->tableid, show_ng, ctx);
+ use_fib, use_json, tag, longer_prefix_p,
+ supernets_only, type, ospf_instance_id,
+ zrt->tableid, show_ng, ctx);
}
}
static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
- safi_t safi, bool use_fib, json_object *vrf_json,
- bool use_json, route_tag_t tag,
+ safi_t safi, bool use_fib, bool use_json,
+ route_tag_t tag,
const struct prefix *longer_prefix_p,
bool supernets_only, int type,
unsigned short ospf_instance_id, uint32_t tableid,
@@ -1045,7 +1035,7 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
return CMD_SUCCESS;
}
- do_show_route_helper(vty, zvrf, table, afi, use_fib, vrf_json, tag,
+ do_show_route_helper(vty, zvrf, table, afi, use_fib, tag,
longer_prefix_p, supernets_only, type,
ospf_instance_id, use_json, tableid, show_ng, ctx);
@@ -1744,13 +1734,13 @@ DEFPY (show_route,
"Nexthop Group Information\n")
{
afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
+ bool first_vrf_json = true;
struct vrf *vrf;
int type = 0;
struct zebra_vrf *zvrf;
struct route_show_ctx ctx = {
.multi = vrf_all || table_all,
};
- json_object *root_json = NULL;
if (!vrf_is_backend_netns()) {
if ((vrf_all || vrf_name) && (table || table_all)) {
@@ -1772,43 +1762,30 @@ DEFPY (show_route,
}
if (vrf_all) {
- if (!!json)
- root_json = json_object_new_object();
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
- json_object *vrf_json = NULL;
-
if ((zvrf = vrf->info) == NULL
|| (zvrf->table[afi][SAFI_UNICAST] == NULL))
continue;
-
- if (!!json)
- vrf_json = json_object_new_object();
-
+ if (json)
+ vty_json_key(vty, zvrf_name(zvrf),
+ &first_vrf_json);
if (table_all)
do_show_ip_route_all(vty, zvrf, afi, !!fib,
- vrf_json, !!json, tag,
+ !!json, tag,
prefix_str ? prefix : NULL,
!!supernets_only, type,
ospf_instance_id, !!ng,
&ctx);
else
do_show_ip_route(vty, zvrf_name(zvrf), afi,
- SAFI_UNICAST, !!fib, vrf_json,
- !!json, tag,
- prefix_str ? prefix : NULL,
+ SAFI_UNICAST, !!fib, !!json,
+ tag, prefix_str ? prefix : NULL,
!!supernets_only, type,
ospf_instance_id, table, !!ng,
&ctx);
-
- if (!!json)
- json_object_object_add(root_json,
- zvrf_name(zvrf),
- vrf_json);
- }
- if (!!json) {
- vty_json_no_pretty(vty, root_json);
- root_json = NULL;
}
+ if (json)
+ vty_json_close(vty, first_vrf_json);
} else {
vrf_id_t vrf_id = VRF_DEFAULT;
@@ -1823,13 +1800,13 @@ DEFPY (show_route,
return CMD_SUCCESS;
if (table_all)
- do_show_ip_route_all(vty, zvrf, afi, !!fib, NULL, !!json,
- tag, prefix_str ? prefix : NULL,
+ do_show_ip_route_all(vty, zvrf, afi, !!fib, !!json, tag,
+ prefix_str ? prefix : NULL,
!!supernets_only, type,
ospf_instance_id, !!ng, &ctx);
else
do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST,
- !!fib, NULL, !!json, tag,
+ !!fib, !!json, tag,
prefix_str ? prefix : NULL,
!!supernets_only, type,
ospf_instance_id, table, !!ng, &ctx);
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 65dc6638b..b8c11e186 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -108,10 +108,11 @@ static void zevpn_build_hash_table(void);
static unsigned int zebra_vxlan_sg_hash_key_make(const void *p);
static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2);
static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf,
- struct in_addr sip, struct in_addr mcast_grp);
-static struct zebra_vxlan_sg *zebra_vxlan_sg_do_ref(struct zebra_vrf *vrf,
- struct in_addr sip,
- struct in_addr mcast_grp);
+ const struct ipaddr *sip,
+ const struct in_addr mcast_grp);
+static struct zebra_vxlan_sg *
+zebra_vxlan_sg_do_ref(struct zebra_vrf *vrf, const struct ipaddr *sip,
+ const struct in_addr mcast_grp);
static void zebra_vxlan_cleanup_sg_table(struct zebra_vrf *zvrf);
bool zebra_evpn_do_dup_addr_detect(struct zebra_vrf *zvrf)
@@ -5891,7 +5892,10 @@ static int zebra_vxlan_sg_send(struct zebra_vrf *zvrf,
zclient_create_header(s, cmd, VRF_DEFAULT);
stream_putl(s, IPV4_MAX_BYTELEN);
- stream_put(s, &sg->src.s_addr, IPV4_MAX_BYTELEN);
+ /*
+ * There is currently no support for IPv6 VTEPs with PIM.
+ */
+ stream_put(s, &sg->src.ipaddr_v4, IPV4_MAX_BYTELEN);
stream_put(s, &sg->grp.s_addr, IPV4_MAX_BYTELEN);
/* Write packet size. */
@@ -5914,9 +5918,17 @@ static int zebra_vxlan_sg_send(struct zebra_vrf *zvrf,
static unsigned int zebra_vxlan_sg_hash_key_make(const void *p)
{
const struct zebra_vxlan_sg *vxlan_sg = p;
+ uint32_t hash1;
- return (jhash_2words(vxlan_sg->sg.src.s_addr,
- vxlan_sg->sg.grp.s_addr, 0));
+ if (IS_IPADDR_V4(&vxlan_sg->sg.src)) {
+ return (jhash_2words(vxlan_sg->sg.src.ipaddr_v4.s_addr,
+ vxlan_sg->sg.grp.s_addr, 0));
+ } else {
+ hash1 = jhash_1word(vxlan_sg->sg.grp.s_addr, 0);
+ return jhash2(vxlan_sg->sg.src.ipaddr_v6.s6_addr32,
+ array_size(vxlan_sg->sg.src.ipaddr_v6.s6_addr32),
+ hash1);
+ }
}
static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2)
@@ -5924,8 +5936,8 @@ static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2)
const struct zebra_vxlan_sg *sg1 = p1;
const struct zebra_vxlan_sg *sg2 = p2;
- return ((sg1->sg.src.s_addr == sg2->sg.src.s_addr)
- && (sg1->sg.grp.s_addr == sg2->sg.grp.s_addr));
+ return (ipaddr_is_same(&sg1->sg.src, &sg2->sg.src) &&
+ (sg1->sg.grp.s_addr == sg2->sg.grp.s_addr));
}
static struct zebra_vxlan_sg *zebra_vxlan_sg_new(struct zebra_vrf *zvrf,
@@ -5961,7 +5973,7 @@ static struct zebra_vxlan_sg *zebra_vxlan_sg_add(struct zebra_vrf *zvrf,
{
struct zebra_vxlan_sg *vxlan_sg;
struct zebra_vxlan_sg *parent = NULL;
- struct in_addr sip;
+ struct ipaddr sip;
vxlan_sg = zebra_vxlan_sg_find(zvrf, sg);
if (vxlan_sg)
@@ -5972,9 +5984,9 @@ static struct zebra_vxlan_sg *zebra_vxlan_sg_add(struct zebra_vrf *zvrf,
* 2. the XG entry is used by pimd to setup the
* vxlan-termination-mroute
*/
- if (sg->src.s_addr != INADDR_ANY) {
+ if (!ipaddr_is_zero(&sg->src)) {
memset(&sip, 0, sizeof(sip));
- parent = zebra_vxlan_sg_do_ref(zvrf, sip, sg->grp);
+ parent = zebra_vxlan_sg_do_ref(zvrf, &sip, sg->grp);
if (!parent)
return NULL;
}
@@ -5989,7 +6001,7 @@ static struct zebra_vxlan_sg *zebra_vxlan_sg_add(struct zebra_vrf *zvrf,
static void zebra_vxlan_sg_del(struct zebra_vxlan_sg *vxlan_sg)
{
- struct in_addr sip;
+ struct ipaddr sip;
struct zebra_vrf *zvrf;
zvrf = vrf_info_lookup(VRF_DEFAULT);
@@ -5997,13 +6009,13 @@ static void zebra_vxlan_sg_del(struct zebra_vxlan_sg *vxlan_sg)
/* On SG entry deletion remove the reference to its parent XG
* entry
*/
- if (vxlan_sg->sg.src.s_addr != INADDR_ANY) {
+ if (!ipaddr_is_zero(&vxlan_sg->sg.src)) {
memset(&sip, 0, sizeof(sip));
- zebra_vxlan_sg_do_deref(zvrf, sip, vxlan_sg->sg.grp);
+ zebra_vxlan_sg_do_deref(zvrf, &sip, vxlan_sg->sg.grp);
}
- zebra_vxlan_sg_send(zvrf, &vxlan_sg->sg,
- vxlan_sg->sg_str, ZEBRA_VXLAN_SG_DEL);
+ zebra_vxlan_sg_send(zvrf, &vxlan_sg->sg, vxlan_sg->sg_str,
+ ZEBRA_VXLAN_SG_DEL);
hash_release(vxlan_sg->zvrf->vxlan_sg_table, vxlan_sg);
@@ -6014,14 +6026,15 @@ static void zebra_vxlan_sg_del(struct zebra_vxlan_sg *vxlan_sg)
}
static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf,
- struct in_addr sip, struct in_addr mcast_grp)
+ const struct ipaddr *sip,
+ const struct in_addr mcast_grp)
{
struct zebra_vxlan_sg *vxlan_sg;
struct prefix_sg sg;
sg.family = AF_INET;
sg.prefixlen = IPV4_MAX_BYTELEN;
- sg.src = sip;
+ sg.src = *sip;
sg.grp = mcast_grp;
vxlan_sg = zebra_vxlan_sg_find(zvrf, &sg);
if (!vxlan_sg)
@@ -6034,16 +6047,16 @@ static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf,
zebra_vxlan_sg_del(vxlan_sg);
}
-static struct zebra_vxlan_sg *zebra_vxlan_sg_do_ref(struct zebra_vrf *zvrf,
- struct in_addr sip,
- struct in_addr mcast_grp)
+static struct zebra_vxlan_sg *
+zebra_vxlan_sg_do_ref(struct zebra_vrf *zvrf, const struct ipaddr *sip,
+ const struct in_addr mcast_grp)
{
struct zebra_vxlan_sg *vxlan_sg;
struct prefix_sg sg;
sg.family = AF_INET;
sg.prefixlen = IPV4_MAX_BYTELEN;
- sg.src = sip;
+ sg.src = *sip;
sg.grp = mcast_grp;
vxlan_sg = zebra_vxlan_sg_add(zvrf, &sg);
if (vxlan_sg)
@@ -6052,10 +6065,10 @@ static struct zebra_vxlan_sg *zebra_vxlan_sg_do_ref(struct zebra_vrf *zvrf,
return vxlan_sg;
}
-void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip,
- struct in_addr mcast_grp)
+void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip, struct in_addr mcast_grp)
{
struct zebra_vrf *zvrf;
+ struct ipaddr local_vtep_ipaddr;
if (local_vtep_ip.s_addr == INADDR_ANY
|| mcast_grp.s_addr == INADDR_ANY)
@@ -6063,20 +6076,26 @@ void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip,
zvrf = vrf_info_lookup(VRF_DEFAULT);
- zebra_vxlan_sg_do_deref(zvrf, local_vtep_ip, mcast_grp);
+ SET_IPADDR_V4(&local_vtep_ipaddr);
+ local_vtep_ipaddr.ipaddr_v4 = local_vtep_ip;
+
+ zebra_vxlan_sg_do_deref(zvrf, &local_vtep_ipaddr, mcast_grp);
}
void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip, struct in_addr mcast_grp)
{
struct zebra_vrf *zvrf;
+ struct ipaddr local_vtep_ipaddr;
- if (local_vtep_ip.s_addr == INADDR_ANY
- || mcast_grp.s_addr == INADDR_ANY)
+ if (local_vtep_ip.s_addr == INADDR_ANY || mcast_grp.s_addr == INADDR_ANY)
return;
zvrf = vrf_info_lookup(VRF_DEFAULT);
- zebra_vxlan_sg_do_ref(zvrf, local_vtep_ip, mcast_grp);
+ SET_IPADDR_V4(&local_vtep_ipaddr);
+ local_vtep_ipaddr.ipaddr_v4 = local_vtep_ip;
+
+ zebra_vxlan_sg_do_ref(zvrf, &local_vtep_ipaddr, mcast_grp);
}
static void zebra_vxlan_xg_pre_cleanup(struct hash_bucket *bucket, void *arg)
@@ -6086,7 +6105,7 @@ static void zebra_vxlan_xg_pre_cleanup(struct hash_bucket *bucket, void *arg)
/* increment the ref count against (*,G) to prevent them from being
* deleted
*/
- if (vxlan_sg->sg.src.s_addr == INADDR_ANY)
+ if (ipaddr_is_zero(&vxlan_sg->sg.src))
++vxlan_sg->ref_cnt;
}
@@ -6095,7 +6114,7 @@ static void zebra_vxlan_xg_post_cleanup(struct hash_bucket *bucket, void *arg)
struct zebra_vxlan_sg *vxlan_sg = (struct zebra_vxlan_sg *)bucket->data;
/* decrement the dummy ref count against (*,G) to delete them */
- if (vxlan_sg->sg.src.s_addr == INADDR_ANY) {
+ if (ipaddr_is_zero(&vxlan_sg->sg.src)) {
if (vxlan_sg->ref_cnt)
--vxlan_sg->ref_cnt;
if (!vxlan_sg->ref_cnt)