summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/commitlint.config.js3
-rw-r--r--.github/workflows/commitlint.yml6
-rw-r--r--babeld/message.c6
-rw-r--r--bfdd/bfd_packet.c8
-rw-r--r--bgpd/bgp_attr.c88
-rw-r--r--bgpd/bgp_bmp.c4
-rw-r--r--bgpd/bgp_evpn.c47
-rw-r--r--bgpd/bgp_evpn_mh.c4
-rw-r--r--bgpd/bgp_evpn_private.h8
-rw-r--r--bgpd/bgp_evpn_vty.c10
-rw-r--r--bgpd/bgp_fsm.c6
-rw-r--r--bgpd/bgp_label.c15
-rw-r--r--bgpd/bgp_mplsvpn_snmp.c13
-rw-r--r--bgpd/bgp_nht.c2
-rw-r--r--bgpd/bgp_route.c20
-rw-r--r--bgpd/bgp_route.h7
-rw-r--r--bgpd/bgp_updgrp.c21
-rw-r--r--bgpd/bgp_updgrp_adv.c21
-rw-r--r--bgpd/bgp_vty.c35
-rw-r--r--bgpd/bgp_zebra.c52
-rw-r--r--bgpd/bgp_zebra.h3
-rw-r--r--bgpd/rfapi/rfapi_import.c53
-rw-r--r--bgpd/rfapi/vnc_import_bgp.c4
-rw-r--r--doc/developer/cli.rst46
-rw-r--r--doc/developer/workflow.rst3
-rw-r--r--doc/user/bgp.rst2
-rw-r--r--doc/user/isisd.rst6
-rw-r--r--isisd/isis_circuit.c4
-rw-r--r--isisd/isis_cli.c25
-rw-r--r--isisd/isis_nb.c7
-rw-r--r--isisd/isis_nb.h4
-rw-r--r--isisd/isis_nb_config.c18
-rw-r--r--isisd/isis_pfpacket.c27
-rw-r--r--isisd/isisd.c55
-rw-r--r--isisd/isisd.h4
-rw-r--r--lib/log.c20
-rw-r--r--lib/log.h1
-rw-r--r--ospf6d/ospf6_abr.c25
-rw-r--r--ospf6d/ospf6_asbr.c20
-rw-r--r--ospf6d/ospf6_asbr.h2
-rw-r--r--ospf6d/ospf6_flood.c5
-rw-r--r--ospf6d/ospf6_gr.c21
-rw-r--r--ospf6d/ospf6_interface.c12
-rw-r--r--ospf6d/ospf6_lsdb.c27
-rw-r--r--ospf6d/ospf6_lsdb.h3
-rw-r--r--ospf6d/ospf6_route.c3
-rw-r--r--ospf6d/ospf6_route.h2
-rw-r--r--ospf6d/ospf6_zebra.c6
-rw-r--r--ospfd/ospf_packet.c11
-rw-r--r--pimd/pim_util.c2
-rw-r--r--tests/topotests/bgp_ipv6_ll_peering/__init__.py0
-rw-r--r--tests/topotests/bgp_ipv6_ll_peering/r1/bgpd.conf6
-rw-r--r--tests/topotests/bgp_ipv6_ll_peering/r1/zebra.conf4
-rw-r--r--tests/topotests/bgp_ipv6_ll_peering/r2/bgpd.conf6
-rw-r--r--tests/topotests/bgp_ipv6_ll_peering/r2/zebra.conf4
-rw-r--r--tests/topotests/bgp_ipv6_ll_peering/test_bgp_ipv6_ll_peering.py88
-rwxr-xr-xtests/topotests/conftest.py7
-rw-r--r--tests/topotests/isis_advertise_high_metrics/__init__.py0
-rw-r--r--tests/topotests/isis_advertise_high_metrics/r1/isisd.conf19
-rw-r--r--tests/topotests/isis_advertise_high_metrics/r1/zebra.conf5
-rw-r--r--tests/topotests/isis_advertise_high_metrics/r2/isisd.conf18
-rw-r--r--tests/topotests/isis_advertise_high_metrics/r2/zebra.conf5
-rw-r--r--tests/topotests/isis_advertise_high_metrics/r3/isisd.conf20
-rw-r--r--tests/topotests/isis_advertise_high_metrics/r3/zebra.conf5
-rw-r--r--tests/topotests/isis_advertise_high_metrics/r4/isisd.conf19
-rw-r--r--tests/topotests/isis_advertise_high_metrics/r4/zebra.conf5
-rw-r--r--tests/topotests/isis_advertise_high_metrics/test_isis_advertise_high_metrics.py485
-rw-r--r--yang/frr-isisd.yang7
-rw-r--r--zebra/zebra_gr.c104
-rw-r--r--zebra/zebra_mpls.c10
70 files changed, 1323 insertions, 291 deletions
diff --git a/.github/commitlint.config.js b/.github/commitlint.config.js
index bee965b814..2b420b6fbf 100644
--- a/.github/commitlint.config.js
+++ b/.github/commitlint.config.js
@@ -18,10 +18,12 @@ module.exports = {
'isisd',
'ldpd',
'lib',
+ 'mgmtd',
'multi',
'nhrpd',
'ospf6d',
'ospfd',
+ 'pathd',
'pbrd',
'pimd',
'pim6d',
@@ -40,6 +42,5 @@ module.exports = {
],
'subject-empty': [2, 'never'],
'subject-full-stop': [2, 'never', '.'],
- 'subject-case': [2, 'always', 'sentence-case'],
},
};
diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml
index f5a2e7d360..06bf3b3b95 100644
--- a/.github/workflows/commitlint.yml
+++ b/.github/workflows/commitlint.yml
@@ -10,8 +10,9 @@ on:
- unlabeled
jobs:
- lint:
- if: github.repository == 'frrouting/frr'
+ commitlint:
+ if: github.repository == 'frrouting/frr' && github.base_ref == 'refs/heads/master'
+ name: Check if the commits meet the requirements of the guidelines
permissions:
contents: read
pull-requests: read
@@ -26,3 +27,4 @@ jobs:
uses: wagoid/commitlint-github-action@v5
with:
configFile: .github/commitlint.config.js
+ helpURL: 'https://docs.frrouting.org/projects/dev-guide/en/latest/workflow.html#submitting-patches-and-enhancements'
diff --git a/babeld/message.c b/babeld/message.c
index 687f768446..b5c2a58984 100644
--- a/babeld/message.c
+++ b/babeld/message.c
@@ -422,7 +422,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
debugf(BABEL_DEBUG_COMMON,
"Received Hello from %s on %s that does not have all 0's in the unused section of flags, ignoring",
format_address(from), ifp->name);
- continue;
+ goto done;
}
/*
@@ -434,7 +434,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
debugf(BABEL_DEBUG_COMMON,
"Received Unicast Hello from %s on %s that FRR is not prepared to understand yet",
format_address(from), ifp->name);
- continue;
+ goto done;
}
DO_NTOHS(seqno, message + 4);
@@ -452,7 +452,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
debugf(BABEL_DEBUG_COMMON,
"Received hello from %s on %s should be ignored as that this version of FRR does not know how to properly handle interval == 0",
format_address(from), ifp->name);
- continue;
+ goto done;
}
changed = update_neighbour(neigh, seqno, interval);
diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c
index 7be235326c..88a9310bc6 100644
--- a/bfdd/bfd_packet.c
+++ b/bfdd/bfd_packet.c
@@ -140,7 +140,7 @@ int _ptm_bfd_send(struct bfd_session *bs, uint16_t *port, const void *data,
* sizeof(*pkt)
*
* ip
- * IP address that pkt will be transmitted from and too.
+ * IP address that pkt will be transmitted from and to.
*
* Returns:
* Checksum in network byte order.
@@ -481,12 +481,6 @@ ssize_t bfd_recv_ipv4_fp(int sd, uint8_t *msgbuf, size_t msgbuflen,
*ttl = ip->ttl;
if (*ttl != 254) {
- /* Echo should be looped in peer's forwarding plane, but it also
- * comes up to BFD so silently drop it
- */
- if (ip->daddr == ip->saddr)
- return -1;
-
if (bglobal.debug_network)
zlog_debug("%s: invalid TTL: %u", __func__, *ttl);
return -1;
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index de77bd5304..68be9675ca 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -810,55 +810,55 @@ bool attrhash_cmp(const void *p1, const void *p2)
&& attr1->med == attr2->med
&& attr1->local_pref == attr2->local_pref
&& attr1->rmap_change_flags == attr2->rmap_change_flags) {
- if (attr1->aggregator_as == attr2->aggregator_as
- && attr1->aggregator_addr.s_addr
- == attr2->aggregator_addr.s_addr
- && attr1->weight == attr2->weight
- && attr1->tag == attr2->tag
- && attr1->label_index == attr2->label_index
- && attr1->mp_nexthop_len == attr2->mp_nexthop_len
- && bgp_attr_get_ecommunity(attr1)
- == bgp_attr_get_ecommunity(attr2)
- && bgp_attr_get_ipv6_ecommunity(attr1)
- == bgp_attr_get_ipv6_ecommunity(attr2)
- && bgp_attr_get_lcommunity(attr1)
- == bgp_attr_get_lcommunity(attr2)
- && bgp_attr_get_cluster(attr1)
- == bgp_attr_get_cluster(attr2)
- && bgp_attr_get_transit(attr1)
- == bgp_attr_get_transit(attr2)
- && bgp_attr_get_aigp_metric(attr1)
- == bgp_attr_get_aigp_metric(attr2)
- && attr1->rmap_table_id == attr2->rmap_table_id
- && (attr1->encap_tunneltype == attr2->encap_tunneltype)
- && encap_same(attr1->encap_subtlvs, attr2->encap_subtlvs)
+ if (attr1->aggregator_as == attr2->aggregator_as &&
+ attr1->aggregator_addr.s_addr ==
+ attr2->aggregator_addr.s_addr &&
+ attr1->weight == attr2->weight &&
+ attr1->tag == attr2->tag &&
+ attr1->label_index == attr2->label_index &&
+ attr1->mp_nexthop_len == attr2->mp_nexthop_len &&
+ bgp_attr_get_ecommunity(attr1) ==
+ bgp_attr_get_ecommunity(attr2) &&
+ bgp_attr_get_ipv6_ecommunity(attr1) ==
+ bgp_attr_get_ipv6_ecommunity(attr2) &&
+ bgp_attr_get_lcommunity(attr1) ==
+ bgp_attr_get_lcommunity(attr2) &&
+ bgp_attr_get_cluster(attr1) ==
+ bgp_attr_get_cluster(attr2) &&
+ bgp_attr_get_transit(attr1) ==
+ bgp_attr_get_transit(attr2) &&
+ bgp_attr_get_aigp_metric(attr1) ==
+ bgp_attr_get_aigp_metric(attr2) &&
+ attr1->rmap_table_id == attr2->rmap_table_id &&
+ (attr1->encap_tunneltype == attr2->encap_tunneltype) &&
+ encap_same(attr1->encap_subtlvs, attr2->encap_subtlvs)
#ifdef ENABLE_BGP_VNC
&& encap_same(bgp_attr_get_vnc_subtlvs(attr1),
bgp_attr_get_vnc_subtlvs(attr2))
#endif
&& IPV6_ADDR_SAME(&attr1->mp_nexthop_global,
- &attr2->mp_nexthop_global)
- && IPV6_ADDR_SAME(&attr1->mp_nexthop_local,
- &attr2->mp_nexthop_local)
- && IPV4_ADDR_SAME(&attr1->mp_nexthop_global_in,
- &attr2->mp_nexthop_global_in)
- && IPV4_ADDR_SAME(&attr1->originator_id,
- &attr2->originator_id)
- && overlay_index_same(attr1, attr2)
- && !memcmp(&attr1->esi, &attr2->esi, sizeof(esi_t))
- && attr1->es_flags == attr2->es_flags
- && attr1->mm_sync_seqnum == attr2->mm_sync_seqnum
- && attr1->df_pref == attr2->df_pref
- && attr1->df_alg == attr2->df_alg
- && attr1->nh_ifindex == attr2->nh_ifindex
- && attr1->nh_lla_ifindex == attr2->nh_lla_ifindex
- && attr1->distance == attr2->distance
- && srv6_l3vpn_same(attr1->srv6_l3vpn, attr2->srv6_l3vpn)
- && srv6_vpn_same(attr1->srv6_vpn, attr2->srv6_vpn)
- && attr1->srte_color == attr2->srte_color
- && attr1->nh_type == attr2->nh_type
- && attr1->bh_type == attr2->bh_type
- && attr1->otc == attr2->otc)
+ &attr2->mp_nexthop_global) &&
+ IPV6_ADDR_SAME(&attr1->mp_nexthop_local,
+ &attr2->mp_nexthop_local) &&
+ IPV4_ADDR_SAME(&attr1->mp_nexthop_global_in,
+ &attr2->mp_nexthop_global_in) &&
+ IPV4_ADDR_SAME(&attr1->originator_id,
+ &attr2->originator_id) &&
+ overlay_index_same(attr1, attr2) &&
+ !memcmp(&attr1->esi, &attr2->esi, sizeof(esi_t)) &&
+ attr1->es_flags == attr2->es_flags &&
+ attr1->mm_sync_seqnum == attr2->mm_sync_seqnum &&
+ attr1->df_pref == attr2->df_pref &&
+ attr1->df_alg == attr2->df_alg &&
+ attr1->nh_ifindex == attr2->nh_ifindex &&
+ attr1->nh_lla_ifindex == attr2->nh_lla_ifindex &&
+ attr1->distance == attr2->distance &&
+ srv6_l3vpn_same(attr1->srv6_l3vpn, attr2->srv6_l3vpn) &&
+ srv6_vpn_same(attr1->srv6_vpn, attr2->srv6_vpn) &&
+ attr1->srte_color == attr2->srte_color &&
+ attr1->nh_type == attr2->nh_type &&
+ attr1->bh_type == attr2->bh_type &&
+ attr1->otc == attr2->otc)
return true;
}
diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c
index 92d92ada2b..40a27cad70 100644
--- a/bgpd/bgp_bmp.c
+++ b/bgpd/bgp_bmp.c
@@ -1175,8 +1175,8 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
(bqe->safi == SAFI_MPLS_VPN);
struct prefix_rd *prd = is_vpn ? &bqe->rd : NULL;
- bn = bgp_afi_node_lookup(bmp->targets->bgp->rib[afi][safi], afi, safi,
- &bqe->p, prd);
+ bn = bgp_safi_node_lookup(bmp->targets->bgp->rib[afi][safi], safi,
+ &bqe->p, prd);
if (bmp->targets->afimon[afi][safi] & BMP_MON_POSTPOLICY) {
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index a8560ab539..6968558681 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -674,11 +674,9 @@ struct bgp_dest *bgp_evpn_global_node_get(struct bgp_table *table, afi_t afi,
/*
* Wrapper for node lookup in global table.
*/
-struct bgp_dest *
-bgp_evpn_global_node_lookup(struct bgp_table *table, afi_t afi, safi_t safi,
- const struct prefix_evpn *evp,
- struct prefix_rd *prd,
- const struct bgp_path_info *local_pi)
+struct bgp_dest *bgp_evpn_global_node_lookup(
+ struct bgp_table *table, safi_t safi, const struct prefix_evpn *evp,
+ struct prefix_rd *prd, const struct bgp_path_info *local_pi)
{
struct prefix_evpn global_p;
@@ -709,7 +707,7 @@ bgp_evpn_global_node_lookup(struct bgp_table *table, afi_t afi, safi_t safi,
evp = &global_p;
}
- return bgp_afi_node_lookup(table, afi, safi, (struct prefix *)evp, prd);
+ return bgp_safi_node_lookup(table, safi, (struct prefix *)evp, prd);
}
/*
@@ -1358,7 +1356,7 @@ static void evpn_delete_old_local_route(struct bgp *bgp, struct bgpevpn *vpn,
* L3VPN routes.
*/
global_dest = bgp_evpn_global_node_lookup(
- bgp->rib[afi][safi], afi, safi,
+ bgp->rib[afi][safi], safi,
(const struct prefix_evpn *)bgp_dest_get_prefix(dest),
&vpn->prd, old_local);
if (global_dest) {
@@ -1837,6 +1835,7 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
struct bgp_path_info *tmp_pi;
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;
int route_change = 1;
@@ -1870,13 +1869,15 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
add_mac_mobility_to_attr(seq, attr);
if (!local_pi) {
- /* Add (or update) attribute to hash. */
- attr_new = bgp_attr_intern(attr);
+ local_attr = *attr;
/* Extract MAC mobility sequence number, if any. */
- attr_new->mm_seqnum =
- bgp_attr_mac_mobility_seqnum(attr_new, &sticky);
- attr_new->sticky = sticky;
+ local_attr.mm_seqnum =
+ bgp_attr_mac_mobility_seqnum(&local_attr, &sticky);
+ local_attr.sticky = sticky;
+
+ /* Add (or update) attribute to hash. */
+ attr_new = bgp_attr_intern(&local_attr);
/* Create new route with its attribute. */
tmp_pi = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0,
@@ -1952,14 +1953,16 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
/* The attribute has changed. */
/* Add (or update) attribute to hash. */
- attr_new = bgp_attr_intern(attr);
+ local_attr = *attr;
bgp_path_info_set_flag(dest, tmp_pi,
BGP_PATH_ATTR_CHANGED);
/* Extract MAC mobility sequence number, if any. */
- attr_new->mm_seqnum =
- bgp_attr_mac_mobility_seqnum(attr_new, &sticky);
- attr_new->sticky = sticky;
+ local_attr.mm_seqnum = bgp_attr_mac_mobility_seqnum(
+ &local_attr, &sticky);
+ local_attr.sticky = sticky;
+
+ attr_new = bgp_attr_intern(&local_attr);
/* Restore route, if needed. */
if (CHECK_FLAG(tmp_pi->flags, BGP_PATH_REMOVED))
@@ -2255,8 +2258,8 @@ static int delete_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp)
return 0;
/* locate the global route entry for this type-5 prefix */
- dest = bgp_evpn_global_node_lookup(bgp_evpn->rib[afi][safi], afi, safi,
- evp, &bgp_vrf->vrf_prd, NULL);
+ dest = bgp_evpn_global_node_lookup(bgp_evpn->rib[afi][safi], safi, evp,
+ &bgp_vrf->vrf_prd, NULL);
if (!dest)
return 0;
@@ -2292,8 +2295,8 @@ static int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
* this table is a 2-level tree (RD-level + Prefix-level) similar to
* L3VPN routes.
*/
- global_dest = bgp_evpn_global_node_lookup(bgp->rib[afi][safi], afi,
- safi, p, &vpn->prd, NULL);
+ global_dest = bgp_evpn_global_node_lookup(bgp->rib[afi][safi], safi, p,
+ &vpn->prd, NULL);
if (global_dest) {
/* Delete route entry in the global EVPN table. */
delete_evpn_route_entry(bgp, afi, safi, global_dest, &pi);
@@ -4312,8 +4315,8 @@ static int delete_withdraw_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
/* Remove type-3 route for this VNI from global table. */
build_evpn_type3_prefix(&p, vpn->originator_ip);
- global_dest = bgp_evpn_global_node_lookup(bgp->rib[afi][safi], afi,
- safi, &p, &vpn->prd, NULL);
+ global_dest = bgp_evpn_global_node_lookup(bgp->rib[afi][safi], safi, &p,
+ &vpn->prd, NULL);
if (global_dest) {
/* Delete route entry in the global EVPN table. */
delete_evpn_route_entry(bgp, afi, safi, global_dest, &pi);
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index 2f95023aa9..4fd0a67911 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -487,8 +487,8 @@ static int bgp_evpn_mh_route_delete(struct bgp *bgp, struct bgp_evpn_es *es,
/* Next, locate route node in the global EVPN routing table.
* Note that this table is a 2-level tree (RD-level + Prefix-level)
*/
- global_dest = bgp_evpn_global_node_lookup(bgp->rib[afi][safi], afi,
- safi, p, prd, NULL);
+ global_dest = bgp_evpn_global_node_lookup(bgp->rib[afi][safi], safi, p,
+ prd, NULL);
if (global_dest) {
/* Delete route entry in the global EVPN table. */
diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h
index fbf3b19c37..fd8d2c118f 100644
--- a/bgpd/bgp_evpn_private.h
+++ b/bgpd/bgp_evpn_private.h
@@ -712,11 +712,9 @@ extern struct bgp_dest *
bgp_evpn_global_node_get(struct bgp_table *table, afi_t afi, safi_t safi,
const struct prefix_evpn *evp, struct prefix_rd *prd,
const struct bgp_path_info *local_pi);
-extern struct bgp_dest *
-bgp_evpn_global_node_lookup(struct bgp_table *table, afi_t afi, safi_t safi,
- const struct prefix_evpn *evp,
- struct prefix_rd *prd,
- const struct bgp_path_info *local_pi);
+extern struct bgp_dest *bgp_evpn_global_node_lookup(
+ struct bgp_table *table, safi_t safi, const struct prefix_evpn *evp,
+ struct prefix_rd *prd, const struct bgp_path_info *local_pi);
extern struct bgp_dest *
bgp_evpn_vni_ip_node_get(struct bgp_table *const table,
const struct prefix_evpn *evp,
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index e28a8c8057..c1bcbf77ce 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -2716,8 +2716,8 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
/* See if route exists. Look for both non-sticky and sticky. */
build_evpn_type2_prefix(&p, mac, ip);
- dest = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
- (struct prefix *)&p, prd);
+ dest = bgp_safi_node_lookup(bgp->rib[afi][safi], safi,
+ (struct prefix *)&p, prd);
if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {
if (!json)
vty_out(vty, "%% Network not in table\n");
@@ -2946,9 +2946,9 @@ static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp,
* then search the l2vpn evpn table for it.
*/
build_evpn_type2_prefix(&ep, mac, ip);
- dest = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
- (struct prefix *)&ep,
- (struct prefix_rd *)rd_destp);
+ dest = bgp_safi_node_lookup(bgp->rib[afi][safi], safi,
+ (struct prefix *)&ep,
+ (struct prefix_rd *)rd_destp);
if (!dest)
continue;
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 59a8fcb92a..fb7b998777 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -2047,7 +2047,7 @@ static int bgp_start_deferral_timer(struct bgp *bgp, afi_t afi, safi_t safi,
if (gr_info->af_enabled[afi][safi] == false) {
gr_info->af_enabled[afi][safi] = true;
/* Send message to RIB */
- bgp_zebra_update(afi, safi, bgp->vrf_id,
+ bgp_zebra_update(bgp, afi, safi,
ZEBRA_CLIENT_ROUTE_UPDATE_PENDING);
}
if (BGP_DEBUG(update, UPDATE_OUT))
@@ -2194,7 +2194,7 @@ static enum bgp_fsm_state_progress bgp_establish(struct peer *peer)
/* Send route processing complete
message to RIB */
bgp_zebra_update(
- afi, safi, peer->bgp->vrf_id,
+ peer->bgp, afi, safi,
ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
}
} else {
@@ -2206,7 +2206,7 @@ static enum bgp_fsm_state_progress bgp_establish(struct peer *peer)
/* Send route processing complete
message to RIB */
bgp_zebra_update(
- afi, safi, peer->bgp->vrf_id,
+ peer->bgp, afi, safi,
ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
}
}
diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c
index 0cad119af1..414dafebd4 100644
--- a/bgpd/bgp_label.c
+++ b/bgpd/bgp_label.c
@@ -297,6 +297,9 @@ static int bgp_nlri_get_labels(struct peer *peer, uint8_t *pnt, uint8_t plen,
uint8_t llen = 0;
uint8_t label_depth = 0;
+ if (plen < BGP_LABEL_BYTES)
+ return 0;
+
for (; data < lim; data += BGP_LABEL_BYTES) {
memcpy(label, data, BGP_LABEL_BYTES);
llen += BGP_LABEL_BYTES;
@@ -359,6 +362,9 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
addpath_id = ntohl(addpath_id);
pnt += BGP_ADDPATH_ID_LEN;
+
+ if (pnt >= lim)
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
}
/* Fetch prefix length. */
@@ -377,6 +383,13 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
/* Fill in the labels */
llen = bgp_nlri_get_labels(peer, pnt, psize, &label);
+ if (llen == 0) {
+ flog_err(
+ EC_BGP_UPDATE_RCV,
+ "%s [Error] Update packet error (wrong label length 0)",
+ peer->host);
+ return BGP_NLRI_PARSE_ERROR_LABEL_LENGTH;
+ }
p.prefixlen = prefixlen - BSIZE(llen);
/* There needs to be at least one label */
@@ -384,8 +397,6 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
flog_err(EC_BGP_UPDATE_RCV,
"%s [Error] Update packet error (wrong label length %d)",
peer->host, prefixlen);
- bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_INVAL_NETWORK);
return BGP_NLRI_PARSE_ERROR_LABEL_LENGTH;
}
diff --git a/bgpd/bgp_mplsvpn_snmp.c b/bgpd/bgp_mplsvpn_snmp.c
index 9b2ab66806..8453133dff 100644
--- a/bgpd/bgp_mplsvpn_snmp.c
+++ b/bgpd/bgp_mplsvpn_snmp.c
@@ -1124,7 +1124,8 @@ static uint8_t *mplsL3vpnVrfRtTable(struct variable *v, oid name[],
struct bgp *l3vpn_bgp;
uint32_t rt_index = 0;
uint8_t rt_type = 0;
- char *rt_b;
+ char *rt_b = NULL;
+ static char rt_b_str[BUFSIZ] = {};
if (smux_header_table(v, name, length, exact, var_len, write_method)
== MATCH_FAILED)
@@ -1156,14 +1157,16 @@ static uint8_t *mplsL3vpnVrfRtTable(struct variable *v, oid name[],
ECOMMUNITY_ROUTE_TARGET);
break;
default:
- rt_b = NULL;
break;
}
- if (rt_b)
+ if (rt_b) {
*var_len = strnlen(rt_b, ECOMMUNITY_STRLEN);
- else
+ strlcpy(rt_b_str, rt_b, sizeof(rt_b_str));
+ XFREE(MTYPE_ECOMMUNITY_STR, rt_b);
+ } else {
*var_len = 0;
- return (uint8_t *)rt_b;
+ }
+ return (uint8_t *)rt_b_str;
case MPLSL3VPNVRFRTDESCR:
/* since we dont have a description generate one */
memset(rt_description, 0, VRF_NAMSIZ + RT_PREAMBLE_SIZE);
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index 25b458a8e5..473c95071c 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -324,7 +324,7 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
* Gather the ifindex for if up/down events to be
* tagged into this fun
*/
- if (afi == AFI_IP6 &&
+ if (afi == AFI_IP6 && peer->conf_if &&
IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr)) {
ifindex = peer->su.sin6.sin6_scope_id;
if (ifindex == 0) {
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 1e9f9429c5..076e5a6cad 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -151,9 +151,9 @@ struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
return dest;
}
-struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
- safi_t safi, const struct prefix *p,
- struct prefix_rd *prd)
+struct bgp_dest *bgp_safi_node_lookup(struct bgp_table *table, safi_t safi,
+ const struct prefix *p,
+ struct prefix_rd *prd)
{
struct bgp_dest *dest;
struct bgp_dest *pdest = NULL;
@@ -2921,10 +2921,14 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp,
* in FIB, then it is advertised
*/
if (advertise) {
- if (!bgp_check_withdrawal(bgp, dest))
- bgp_adj_out_set_subgroup(
- dest, subgrp, &attr, selected);
- else
+ if (!bgp_check_withdrawal(bgp, dest)) {
+ struct attr *adv_attr =
+ bgp_attr_intern(&attr);
+
+ bgp_adj_out_set_subgroup(dest, subgrp,
+ adv_attr,
+ selected);
+ } else
bgp_adj_out_unset_subgroup(
dest, subgrp, 1, addpath_tx_id);
}
@@ -3401,7 +3405,7 @@ void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
if (!bgp->gr_info[afi][safi].gr_deferred) {
bgp_send_delayed_eor(bgp);
/* Send route processing complete message to RIB */
- bgp_zebra_update(afi, safi, bgp->vrf_id,
+ bgp_zebra_update(bgp, afi, safi,
ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
return;
}
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 66cc62ab09..7755687700 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -819,9 +819,10 @@ extern void bgp_peer_clear_node_queue_drain_immediate(struct peer *peer);
extern void bgp_process_queues_drain_immediate(void);
/* for encap/vpn */
-extern struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
- safi_t safi, const struct prefix *p,
- struct prefix_rd *prd);
+extern struct bgp_dest *bgp_safi_node_lookup(struct bgp_table *table,
+ safi_t safi,
+ const struct prefix *p,
+ struct prefix_rd *prd);
extern void bgp_path_info_restore(struct bgp_dest *dest,
struct bgp_path_info *path);
diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c
index 277492157f..962783b21f 100644
--- a/bgpd/bgp_updgrp.c
+++ b/bgpd/bgp_updgrp.c
@@ -322,6 +322,11 @@ static unsigned int updgrp_hash_key_make(const void *p)
afi_t afi;
safi_t safi;
+ /*
+ * IF YOU ADD AN ADDITION TO THE HASH KEY TO ENSURE
+ * THAT THE UPDATE GROUP CALCULATION IS CORRECT THEN
+ * PLEASE ADD IT TO THE DEBUG OUTPUT TOO AT THE BOTTOM
+ */
#define SEED1 999331
#define SEED2 2147483647
@@ -436,6 +441,10 @@ static unsigned int updgrp_hash_key_make(const void *p)
key = jhash_1word(jhash(soo_str, strlen(soo_str), SEED1), key);
}
+ /*
+ * ANY NEW ITEMS THAT ARE ADDED TO THE key, ENSURE DEBUG
+ * STATEMENT STAYS UP TO DATE
+ */
if (bgp_debug_neighbor_events(peer)) {
zlog_debug(
"%pBP Update Group Hash: sort: %d UpdGrpFlags: %ju UpdGrpAFFlags: %ju",
@@ -457,7 +466,7 @@ static unsigned int updgrp_hash_key_make(const void *p)
ROUTE_MAP_OUT_NAME(filter) ? ROUTE_MAP_OUT_NAME(filter)
: "(NONE)");
zlog_debug(
- "%pBP Update Group Hash: dlist out: %s plist out: %s aslist out: %s usmap out: %s advmap: %s",
+ "%pBP Update Group Hash: dlist out: %s plist out: %s aslist out: %s usmap out: %s advmap: %s %d",
peer,
DISTRIBUTE_OUT_NAME(filter)
? DISTRIBUTE_OUT_NAME(filter)
@@ -472,7 +481,8 @@ static unsigned int updgrp_hash_key_make(const void *p)
? UNSUPPRESS_MAP_NAME(filter)
: "(NONE)",
ADVERTISE_MAP_NAME(filter) ? ADVERTISE_MAP_NAME(filter)
- : "(NONE)");
+ : "(NONE)",
+ filter->advmap.update_type);
zlog_debug(
"%pBP Update Group Hash: default rmap: %s shared network and afi active network: %d",
peer,
@@ -490,6 +500,13 @@ static unsigned int updgrp_hash_key_make(const void *p)
PEER_CAP_ORF_PREFIX_SM_OLD_RCV),
(intmax_t)CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX_OUT));
+ zlog_debug(
+ "%pBP Update Group Hash: local role: %u AIGP: %d SOO: %s",
+ peer, peer->local_role,
+ !!CHECK_FLAG(peer->flags, PEER_FLAG_AIGP),
+ peer->soo[afi][safi]
+ ? ecommunity_str(peer->soo[afi][safi])
+ : "(NONE)");
zlog_debug("%pBP Update Group Hash key: %u", peer, key);
}
return key;
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index d6eb3ff20b..d8e0e7875c 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -497,6 +497,23 @@ void bgp_adj_out_set_subgroup(struct bgp_dest *dest,
zlog_debug("%s suppress UPDATE w/ attr: %s", peer->host,
attr_str);
}
+
+ /*
+ * If BGP is skipping sending this value to it's peers
+ * the version number should be updated just like it
+ * would if it sent the data. Why? Because update
+ * groups will not be coalesced until such time that
+ * the version numbers are the same.
+ *
+ * Imagine a scenario with say 2 peers and they come
+ * up and are placed in the same update group. Then
+ * a new peer comes up a bit later. Then a prefix is
+ * flapped that we decide for the first 2 peers are
+ * mapped to and we decide not to send the data to
+ * it. Then unless more network changes happen we
+ * will never be able to coalesce the 3rd peer down
+ */
+ subgrp->version = MAX(subgrp->version, dest->version);
return;
}
@@ -901,8 +918,8 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
memset(&p, 0, sizeof(p));
p.family = afi2family(afi);
p.prefixlen = 0;
- dest = bgp_afi_node_lookup(bgp->rib[afi][safi_rib], afi, safi_rib, &p,
- NULL);
+ dest = bgp_safi_node_lookup(bgp->rib[afi][safi_rib], safi_rib, &p,
+ NULL);
if (withdraw) {
/* Withdraw the default route advertised using default
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index a1e9a9a8a9..93b412240a 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -11676,37 +11676,22 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
vty_out(vty, "4 ");
vty_out(vty, ASN_FORMAT_SPACE(bgp->asnotation),
&peer->as);
- if (show_wide) {
+ if (show_wide)
vty_out(vty,
ASN_FORMAT_SPACE(
bgp->asnotation),
peer->change_local_as
? &peer->change_local_as
: &peer->local_as);
- vty_out(vty,
- " %9u %9u %8" PRIu64
- " %4zu %4zu %8s",
- PEER_TOTAL_RX(peer),
- PEER_TOTAL_TX(peer),
- peer->version[afi][safi],
- inq_count, outq_count,
- peer_uptime(peer->uptime,
- timebuf,
- BGP_UPTIME_LEN, 0,
- NULL));
- } else {
- vty_out(vty,
- " %9u %9u %8" PRIu64
- " %4zu %4zu %8s",
- PEER_TOTAL_RX(peer),
- PEER_TOTAL_TX(peer),
- peer->version[afi][safi],
- inq_count, outq_count,
- peer_uptime(peer->uptime,
- timebuf,
- BGP_UPTIME_LEN, 0,
- NULL));
- }
+ vty_out(vty,
+ " %9u %9u %8" PRIu64 " %4zu %4zu %8s",
+ PEER_TOTAL_RX(peer),
+ PEER_TOTAL_TX(peer),
+ peer->version[afi][safi], inq_count,
+ outq_count,
+ peer_uptime(peer->uptime, timebuf,
+ BGP_UPTIME_LEN, 0, NULL));
+
if (peer_established(peer)) {
if (peer->afc_recv[afi][safi]) {
if (CHECK_FLAG(
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index d05768da05..da598993d1 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -2596,8 +2596,8 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,
}
/* Find the bgp route node */
- dest = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi, &p,
- &bgp->vrf_prd);
+ dest = bgp_safi_node_lookup(bgp->rib[afi][safi], safi, &p,
+ &bgp->vrf_prd);
if (!dest)
return -1;
@@ -3748,16 +3748,22 @@ int bgp_zebra_send_capabilities(struct bgp *bgp, bool disable)
struct zapi_cap api;
int ret = BGP_GR_SUCCESS;
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: Sending %sable for %s", __func__,
+ disable ? "dis" : "en", bgp->name_pretty);
+
if (zclient == NULL) {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("zclient invalid");
+ zlog_debug("%s: %s zclient invalid", __func__,
+ bgp->name_pretty);
return BGP_GR_FAILURE;
}
/* Check if the client is connected */
if ((zclient->sock < 0) || (zclient->t_connect)) {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("client not connected");
+ zlog_debug("%s: %s client not connected", __func__,
+ bgp->name_pretty);
return BGP_GR_FAILURE;
}
@@ -3776,7 +3782,8 @@ int bgp_zebra_send_capabilities(struct bgp *bgp, bool disable)
if (zclient_capabilities_send(ZEBRA_CLIENT_CAPABILITIES, zclient, &api)
== ZCLIENT_SEND_FAILURE) {
- zlog_err("error sending capability");
+ zlog_err("%s: %s error sending capability", __func__,
+ bgp->name_pretty);
ret = BGP_GR_FAILURE;
} else {
if (disable)
@@ -3785,7 +3792,8 @@ int bgp_zebra_send_capabilities(struct bgp *bgp, bool disable)
bgp->present_zebra_gr_state = ZEBRA_GR_ENABLE;
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("send capabilty success");
+ zlog_debug("%s: %s send capabilty success", __func__,
+ bgp->name_pretty);
ret = BGP_GR_SUCCESS;
}
return ret;
@@ -3794,32 +3802,41 @@ int bgp_zebra_send_capabilities(struct bgp *bgp, bool disable)
/* Send route update pesding or completed status to RIB for the
* specific AFI, SAFI
*/
-int bgp_zebra_update(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type)
+int bgp_zebra_update(struct bgp *bgp, afi_t afi, safi_t safi,
+ enum zserv_client_capabilities type)
{
struct zapi_cap api = {0};
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: %s afi: %u safi: %u Command %s", __func__,
+ bgp->name_pretty, afi, safi,
+ zserv_gr_client_cap_string(type));
+
if (zclient == NULL) {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("zclient == NULL, invalid");
+ zlog_debug("%s: %s zclient == NULL, invalid", __func__,
+ bgp->name_pretty);
return BGP_GR_FAILURE;
}
/* Check if the client is connected */
if ((zclient->sock < 0) || (zclient->t_connect)) {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("client not connected");
+ zlog_debug("%s: %s client not connected", __func__,
+ bgp->name_pretty);
return BGP_GR_FAILURE;
}
api.afi = afi;
api.safi = safi;
- api.vrf_id = vrf_id;
+ api.vrf_id = bgp->vrf_id;
api.cap = type;
if (zclient_capabilities_send(ZEBRA_CLIENT_CAPABILITIES, zclient, &api)
== ZCLIENT_SEND_FAILURE) {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("error sending capability");
+ zlog_debug("%s: %s error sending capability", __func__,
+ bgp->name_pretty);
return BGP_GR_FAILURE;
}
return BGP_GR_SUCCESS;
@@ -3831,6 +3848,10 @@ int bgp_zebra_stale_timer_update(struct bgp *bgp)
{
struct zapi_cap api;
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: %s Timer Update to %u", __func__,
+ bgp->name_pretty, bgp->rib_stale_time);
+
if (zclient == NULL) {
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("zclient invalid");
@@ -3840,7 +3861,8 @@ int bgp_zebra_stale_timer_update(struct bgp *bgp)
/* Check if the client is connected */
if ((zclient->sock < 0) || (zclient->t_connect)) {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("client not connected");
+ zlog_debug("%s: %s client not connected", __func__,
+ bgp->name_pretty);
return BGP_GR_FAILURE;
}
@@ -3851,11 +3873,11 @@ int bgp_zebra_stale_timer_update(struct bgp *bgp)
if (zclient_capabilities_send(ZEBRA_CLIENT_CAPABILITIES, zclient, &api)
== ZCLIENT_SEND_FAILURE) {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("error sending capability");
+ zlog_debug("%s: %s error sending capability", __func__,
+ bgp->name_pretty);
return BGP_GR_FAILURE;
}
- if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("send capabilty success");
+
return BGP_GR_SUCCESS;
}
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
index 8a0203c32d..6f28f7b900 100644
--- a/bgpd/bgp_zebra.h
+++ b/bgpd/bgp_zebra.h
@@ -114,7 +114,8 @@ extern void bgp_send_pbr_iptable(struct bgp_pbr_action *pba,
extern void bgp_zebra_announce_default(struct bgp *bgp, struct nexthop *nh,
afi_t afi, uint32_t table_id, bool announce);
extern int bgp_zebra_send_capabilities(struct bgp *bgp, bool disable);
-extern int bgp_zebra_update(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type);
+extern int bgp_zebra_update(struct bgp *bgp, afi_t afi, safi_t safi,
+ enum zserv_client_capabilities);
extern int bgp_zebra_stale_timer_update(struct bgp *bgp);
extern int bgp_zebra_srv6_manager_get_locator_chunk(const char *name);
extern int bgp_zebra_srv6_manager_release_locator_chunk(const char *name);
diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c
index 5c68545398..25a4403040 100644
--- a/bgpd/rfapi/rfapi_import.c
+++ b/bgpd/rfapi/rfapi_import.c
@@ -874,33 +874,39 @@ static void rfapiImportTableFlush(struct rfapi_import_table *it)
for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
struct agg_node *rn;
+ struct agg_table *at;
- for (rn = agg_route_top(it->imported_vpn[afi]); rn;
- rn = agg_route_next(rn)) {
- /*
- * Each route_node has:
- * aggregate: points to rfapi_it_extra with monitor
- * chain(s)
- * info: points to chain of bgp_path_info
- */
- /* free bgp_path_info and its children */
- rfapiBgpInfoChainFree(rn->info);
- rn->info = NULL;
+ at = it->imported_vpn[afi];
+ if (at) {
+ for (rn = agg_route_top(at); rn;
+ rn = agg_route_next(rn)) {
+ /*
+ * Each route_node has:
+ * aggregate: points to rfapi_it_extra with
+ * monitor chain(s)
+ * info: points to chain of bgp_path_info
+ */
+ /* free bgp_path_info and its children */
+ rfapiBgpInfoChainFree(rn->info);
+ rn->info = NULL;
- rfapiMonitorExtraFlush(SAFI_MPLS_VPN, rn);
+ rfapiMonitorExtraFlush(SAFI_MPLS_VPN, rn);
+ }
+ agg_table_finish(at);
}
- for (rn = agg_route_top(it->imported_encap[afi]); rn;
- rn = agg_route_next(rn)) {
- /* free bgp_path_info and its children */
- rfapiBgpInfoChainFree(rn->info);
- rn->info = NULL;
+ if (at) {
+ at = it->imported_encap[afi];
+ for (rn = agg_route_top(at); rn;
+ rn = agg_route_next(rn)) {
+ /* free bgp_path_info and its children */
+ rfapiBgpInfoChainFree(rn->info);
+ rn->info = NULL;
- rfapiMonitorExtraFlush(SAFI_ENCAP, rn);
+ rfapiMonitorExtraFlush(SAFI_ENCAP, rn);
+ }
+ agg_table_finish(at);
}
-
- agg_table_finish(it->imported_vpn[afi]);
- agg_table_finish(it->imported_encap[afi]);
}
if (it->monitor_exterior_orphans) {
skiplist_free(it->monitor_exterior_orphans);
@@ -4260,10 +4266,7 @@ void bgp_rfapi_destroy(struct bgp *bgp, struct rfapi *h)
h->resolve_nve_nexthop = NULL;
}
- agg_table_finish(h->it_ce->imported_vpn[AFI_IP]);
- agg_table_finish(h->it_ce->imported_vpn[AFI_IP6]);
- agg_table_finish(h->it_ce->imported_encap[AFI_IP]);
- agg_table_finish(h->it_ce->imported_encap[AFI_IP6]);
+ rfapiImportTableFlush(h->it_ce);
if (h->import_mac) {
struct rfapi_import_table *it;
diff --git a/bgpd/rfapi/vnc_import_bgp.c b/bgpd/rfapi/vnc_import_bgp.c
index 7c8e8f35c9..19ac6f353d 100644
--- a/bgpd/rfapi/vnc_import_bgp.c
+++ b/bgpd/rfapi/vnc_import_bgp.c
@@ -834,6 +834,8 @@ static void vnc_import_bgp_add_route_mode_plain(struct bgp *bgp,
if (ecom)
ecommunity_free(&ecom);
+ if (iattr)
+ bgp_attr_unintern(&iattr);
}
static void vnc_import_bgp_add_route_mode_nvegroup(
@@ -1030,6 +1032,8 @@ static void vnc_import_bgp_add_route_mode_nvegroup(
if (ecom)
ecommunity_free(&ecom);
+ if (iattr)
+ bgp_attr_unintern(&iattr);
}
static void vnc_import_bgp_del_route_mode_plain(struct bgp *bgp,
diff --git a/doc/developer/cli.rst b/doc/developer/cli.rst
index 2a08531bd7..61b9cf6acb 100644
--- a/doc/developer/cli.rst
+++ b/doc/developer/cli.rst
@@ -177,29 +177,29 @@ parser, but this is merely a dumb copy job.
Here is a brief summary of the various token types along with examples.
-+-----------------+-------------------------+-------------------------------------------------------+
-| Token type | Syntax | Description |
-+=================+=========================+=======================================================+
-| ``WORD`` | ``show ip bgp`` | Matches itself. In the example every token is a WORD. |
-+-----------------+-------------------------+-------------------------------------------------------+
-| ``IPV4`` | ``A.B.C.D`` | Matches an IPv4 address. |
-+-----------------+-------------------------+-------------------------------------------------------+
-| ``IPV6`` | ``X:X::X:X`` | Matches an IPv6 address. |
-+-----------------+-------------------------+-------------------------------------------------------+
-| ``IPV4_PREFIX`` | ``A.B.C.D/M`` | Matches an IPv4 prefix in CIDR notation. |
-+-----------------+-------------------------+-------------------------------------------------------+
-| ``IPV6_PREFIX`` | ``X:X::X:X/M`` | Matches an IPv6 prefix in CIDR notation. |
-+-----------------+-------------------------+-------------------------------------------------------+
-| ``MAC`` | ``X:X:X:X:X:X`` | Matches a 48-bit mac address. |
-+-----------------+-------------------------+-------------------------------------------------------+
-| ``MAC_PREFIX`` | ``X:X:X:X:X:X/M`` | Matches a 48-bit mac address with a mask. |
-+-----------------+-------------------------+-------------------------------------------------------+
-| ``VARIABLE`` | ``FOOBAR`` | Matches anything. |
-+-----------------+-------------------------+-------------------------------------------------------+
-| ``RANGE`` | ``(X-Y)`` | Matches numbers in the range X..Y inclusive. |
-+-----------------+-------------------------+-------------------------------------------------------+
-| ``ASNUM`` | ``<A.B|(1-4294967295>`` | Matches an AS in plain or dot format. |
-+-----------------+-------------------------+-------------------------------------------------------+
++-----------------+--------------------------+-------------------------------------------------------+
+| Token type | Syntax | Description |
++=================+==========================+=======================================================+
+| ``WORD`` | ``show ip bgp`` | Matches itself. In the example every token is a WORD. |
++-----------------+--------------------------+-------------------------------------------------------+
+| ``IPV4`` | ``A.B.C.D`` | Matches an IPv4 address. |
++-----------------+--------------------------+-------------------------------------------------------+
+| ``IPV6`` | ``X:X::X:X`` | Matches an IPv6 address. |
++-----------------+--------------------------+-------------------------------------------------------+
+| ``IPV4_PREFIX`` | ``A.B.C.D/M`` | Matches an IPv4 prefix in CIDR notation. |
++-----------------+--------------------------+-------------------------------------------------------+
+| ``IPV6_PREFIX`` | ``X:X::X:X/M`` | Matches an IPv6 prefix in CIDR notation. |
++-----------------+--------------------------+-------------------------------------------------------+
+| ``MAC`` | ``X:X:X:X:X:X`` | Matches a 48-bit mac address. |
++-----------------+--------------------------+-------------------------------------------------------+
+| ``MAC_PREFIX`` | ``X:X:X:X:X:X/M`` | Matches a 48-bit mac address with a mask. |
++-----------------+--------------------------+-------------------------------------------------------+
+| ``VARIABLE`` | ``FOOBAR`` | Matches anything. |
++-----------------+--------------------------+-------------------------------------------------------+
+| ``RANGE`` | ``(X-Y)`` | Matches numbers in the range X..Y inclusive. |
++-----------------+--------------------------+-------------------------------------------------------+
+| ``ASNUM`` | ``<A.B|(1-4294967295)>`` | Matches an AS in plain or dot format. |
++-----------------+--------------------------+-------------------------------------------------------+
When presented with user input, the parser will search over all defined
commands in the current context to find a match. It is aware of the various
diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst
index 320824ec1d..f11fff5dee 100644
--- a/doc/developer/workflow.rst
+++ b/doc/developer/workflow.rst
@@ -95,7 +95,7 @@ March/July/November. Walking backwards from this date:
are considered lowest priority (regardless of when they were opened.)
- 4 weeks earlier, the stable branch separates from master (named
- ``dev/MAJOR.MINOR`` at this point) and tagged as ```base_X.Y``.
+ ``dev/MAJOR.MINOR`` at this point) and tagged as ``base_X.Y``.
Master is unfrozen and new features may again proceed.
Part of unfreezing master is editing the ``AC_INIT`` statement in
@@ -365,7 +365,6 @@ There is a built-in commit linter. Basic rules:
`Check <https://github.com/FRRouting/frr/tree/master/.github/commitlint.config.js>`_ all
the supported subsystems.
-- Commit messages must start with a capital letter
- Commit messages must not end with a period ``.``
Why was my pull request closed?
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 1798f1ad2a..946f0699f2 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -2290,7 +2290,7 @@ Numbered Community Lists
^^^^^^^^^^^^^^^^^^^^^^^^
When number is used for BGP community list name, the number has
-special meanings. Community list number in the range from 1 and 99 is
+special meanings. Community list number in the range from 1 to 99 is
standard community list. Community list number in the range from 100
to 500 is expanded community list. These community lists are called
as numbered community lists. On the other hand normal community lists
diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst
index d68fa67259..055841d230 100644
--- a/doc/user/isisd.rst
+++ b/doc/user/isisd.rst
@@ -79,6 +79,12 @@ writing, *isisd* does not support multiple ISIS processes.
- wide
Use new style of TLVs to carry wider metric. FRR uses this as a default value
+.. clicmd:: advertise-high-metrics
+
+ Advertise high metric value on all interfaces to gracefully shift traffic off the router. Reference: :rfc:`3277`
+
+ For narrow metrics, the high metric value is 63; for wide metrics, 16777215; for transition metrics, 62.
+
.. clicmd:: set-overload-bit
Set overload bit to avoid any transit traffic.
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
index dd5f921bef..8644da2f08 100644
--- a/isisd/isis_circuit.c
+++ b/isisd/isis_circuit.c
@@ -1499,6 +1499,10 @@ ferr_r isis_circuit_metric_set(struct isis_circuit *circuit, int level,
return ferr_cfg_invalid("metric %d too large for narrow metric",
metric);
+ /* Don't modify metric if advertise high metrics is configured */
+ if (circuit->area && circuit->area->advertise_high_metrics)
+ return ferr_ok();
+
/* inform ldp-sync of metric change
* if ldp-sync is running need to save metric
* and restore new values after ldp-sync completion.
diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c
index 5c7f610881..4a598aa8c9 100644
--- a/isisd/isis_cli.c
+++ b/isisd/isis_cli.c
@@ -440,6 +440,29 @@ void cli_show_isis_overload_on_startup(struct vty *vty,
}
/*
+ * XPath: /frr-isisd:isis/instance/advertise-high-metrics
+ */
+DEFPY_YANG(advertise_high_metrics, advertise_high_metrics_cmd,
+ "[no] advertise-high-metrics",
+ NO_STR "Advertise high metric value on all interfaces\n")
+{
+ nb_cli_enqueue_change(vty, "./advertise-high-metrics", NB_OP_MODIFY,
+ no ? "false" : "true");
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void cli_show_advertise_high_metrics(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ if (yang_dnode_get_bool(dnode, NULL))
+ vty_out(vty, " advertise-high-metrics\n");
+ else if (show_defaults)
+ vty_out(vty, " no advertise-high-metrics\n");
+}
+
+/*
* XPath: /frr-isisd:isis/instance/attach-send
*/
DEFPY_YANG(attached_bit_send, attached_bit_send_cmd, "[no] attached-bit send",
@@ -3160,6 +3183,8 @@ void isis_cli_init(void)
install_element(ISIS_NODE, &metric_style_cmd);
install_element(ISIS_NODE, &no_metric_style_cmd);
+ install_element(ISIS_NODE, &advertise_high_metrics_cmd);
+
install_element(ISIS_NODE, &area_passwd_cmd);
install_element(ISIS_NODE, &domain_passwd_cmd);
install_element(ISIS_NODE, &no_area_passwd_cmd);
diff --git a/isisd/isis_nb.c b/isisd/isis_nb.c
index 5caa61a4d1..7dc3a0eb3d 100644
--- a/isisd/isis_nb.c
+++ b/isisd/isis_nb.c
@@ -82,6 +82,13 @@ const struct frr_yang_module_info frr_isisd_info = {
}
},
{
+ .xpath = "/frr-isisd:isis/instance/advertise-high-metrics",
+ .cbs = {
+ .cli_show = cli_show_advertise_high_metrics,
+ .modify = isis_instance_advertise_high_metrics_modify,
+ }
+ },
+ {
.xpath = "/frr-isisd:isis/instance/metric-style",
.cbs = {
.cli_show = cli_show_isis_metric_style,
diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h
index c90f6dca37..480b2ce041 100644
--- a/isisd/isis_nb.h
+++ b/isisd/isis_nb.h
@@ -26,6 +26,7 @@ int isis_instance_attached_receive_modify(struct nb_cb_modify_args *args);
int isis_instance_attached_modify(struct nb_cb_modify_args *args);
int isis_instance_overload_enabled_modify(struct nb_cb_modify_args *args);
int isis_instance_overload_on_startup_modify(struct nb_cb_modify_args *args);
+int isis_instance_advertise_high_metrics_modify(struct nb_cb_modify_args *args);
int isis_instance_metric_style_modify(struct nb_cb_modify_args *args);
int isis_instance_purge_originator_modify(struct nb_cb_modify_args *args);
int isis_instance_lsp_mtu_modify(struct nb_cb_modify_args *args);
@@ -464,6 +465,9 @@ void cli_show_isis_overload(struct vty *vty, const struct lyd_node *dnode,
void cli_show_isis_overload_on_startup(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults);
+void cli_show_advertise_high_metrics(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults);
void cli_show_isis_metric_style(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
void cli_show_isis_area_pwd(struct vty *vty, const struct lyd_node *dnode,
diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c
index ea021a4ff5..2b3355bc9f 100644
--- a/isisd/isis_nb_config.c
+++ b/isisd/isis_nb_config.c
@@ -361,6 +361,24 @@ int isis_instance_overload_on_startup_modify(struct nb_cb_modify_args *args)
}
/*
+ * XPath: /frr-isisd:isis/instance/advertise-high-metrics
+ */
+int isis_instance_advertise_high_metrics_modify(struct nb_cb_modify_args *args)
+{
+ struct isis_area *area;
+ bool advertise_high_metrics;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ advertise_high_metrics = yang_dnode_get_bool(args->dnode, NULL);
+ area = nb_running_get_entry(args->dnode, NULL, true);
+ isis_area_advertise_high_metrics_set(area, advertise_high_metrics);
+
+ return NB_OK;
+}
+
+/*
* XPath: /frr-isisd:isis/instance/metric-style
*/
int isis_instance_metric_style_modify(struct nb_cb_modify_args *args)
diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c
index 4f8ea4a5e7..af69fac1cd 100644
--- a/isisd/isis_pfpacket.c
+++ b/isisd/isis_pfpacket.c
@@ -35,14 +35,25 @@
/* tcpdump -i eth0 'isis' -dd */
static const struct sock_filter isisfilter[] = {
/* NB: we're in SOCK_DGRAM, so src/dst mac + length are stripped
- * off!
- * (OTOH it's a bit more lower-layer agnostic and might work
- * over GRE?) */
- /* { 0x28, 0, 0, 0x0000000c - 14 }, */
- /* { 0x25, 5, 0, 0x000005dc }, */
- {0x28, 0, 0, 0x0000000e - 14}, {0x15, 0, 3, 0x0000fefe},
- {0x30, 0, 0, 0x00000011 - 14}, {0x15, 0, 1, 0x00000083},
- {0x6, 0, 0, 0x00040000}, {0x6, 0, 0, 0x00000000},
+ * off! */
+ /* The following BPF filter accepts IS-IS over LLC and IS-IS over
+ * ethertype 0x00fe.
+ * BPF assembly:
+ * l0: ldh [0]
+ * l1: jeq #0xfefe, l2, l4
+ * l2: ldb [3]
+ * l3: jmp l7
+ * l4: ldh proto
+ * l5: jeq #0x00fe, l6, l9
+ * l6: ldb [0]
+ * l7: jeq #0x83, l8, l9
+ * l8: ret #0x40000
+ * l9: ret #0 */
+ {0x28, 0, 0, 0000000000}, {0x15, 0, 2, 0x0000fefe},
+ {0x30, 0, 0, 0x00000003}, {0x05, 0, 0, 0x00000003},
+ {0x28, 0, 0, 0xfffff000}, {0x15, 0, 3, 0x000000fe},
+ {0x30, 0, 0, 0000000000}, {0x15, 0, 1, 0x00000083},
+ {0x06, 0, 0, 0x00040000}, {0x06, 0, 0, 0000000000},
};
static const struct sock_fprog bpf = {
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 852d7b88e8..586785b05f 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -2503,6 +2503,9 @@ static void common_isis_summary_vty(struct vty *vty, struct isis *isis)
vty_out(vty, " RX counters per PDU type:\n");
pdu_counter_print(vty, " ", area->pdu_rx_counters);
+ vty_out(vty, " Advertise high metrics: %s\n",
+ area->advertise_high_metrics ? "Enabled" : "Disabled");
+
for (level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) {
if ((area->is_type & level) == 0)
continue;
@@ -3247,6 +3250,58 @@ void config_end_lsp_generate(struct isis_area *area)
}
}
+void isis_area_advertise_high_metrics_set(struct isis_area *area,
+ bool advertise_high_metrics)
+{
+ struct listnode *node;
+ struct isis_circuit *circuit;
+ int max_metric;
+ char xpath[XPATH_MAXLEN];
+ struct lyd_node *dnode;
+ int configured_metric_l1;
+ int configured_metric_l2;
+
+ if (area->advertise_high_metrics == advertise_high_metrics)
+ return;
+
+ if (advertise_high_metrics) {
+ if (area->oldmetric && area->newmetric)
+ max_metric = ISIS_NARROW_METRIC_INFINITY;
+ else if (area->newmetric)
+ max_metric = MAX_WIDE_LINK_METRIC;
+ else
+ max_metric = MAX_NARROW_LINK_METRIC;
+
+ for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
+ isis_circuit_metric_set(circuit, IS_LEVEL_1,
+ max_metric);
+ isis_circuit_metric_set(circuit, IS_LEVEL_2,
+ max_metric);
+ }
+
+ area->advertise_high_metrics = true;
+ } else {
+ area->advertise_high_metrics = false;
+ for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
+ /* Get configured metric */
+ snprintf(xpath, XPATH_MAXLEN,
+ "/frr-interface:lib/interface[name='%s']",
+ circuit->interface->name);
+ dnode = yang_dnode_get(running_config->dnode, xpath);
+
+ configured_metric_l1 = yang_dnode_get_uint32(
+ dnode, "./frr-isisd:isis/metric/level-1");
+ configured_metric_l2 = yang_dnode_get_uint32(
+ dnode, "./frr-isisd:isis/metric/level-2");
+
+ isis_circuit_metric_set(circuit, IS_LEVEL_1,
+ configured_metric_l1);
+ isis_circuit_metric_set(circuit, IS_LEVEL_2,
+ configured_metric_l2);
+ }
+ }
+}
+
/*
* Returns the path of the file (non-volatile memory) that contains restart
* information.
diff --git a/isisd/isisd.h b/isisd/isisd.h
index 0f1161e574..37a36fd37a 100644
--- a/isisd/isisd.h
+++ b/isisd/isisd.h
@@ -175,6 +175,8 @@ struct isis_area {
uint32_t overload_on_startup_time;
/* advertise prefixes of passive interfaces only? */
bool advertise_passive_only;
+ /* Are we advertising high metrics? */
+ bool advertise_high_metrics;
/* L1/L2 router identifier for inter-area traffic */
char attached_bit_send;
char attached_bit_rcv_ignore;
@@ -289,6 +291,8 @@ void isis_area_switchover_routes(struct isis_area *area, int family,
void isis_area_overload_bit_set(struct isis_area *area, bool overload_bit);
void isis_area_overload_on_startup_set(struct isis_area *area,
uint32_t startup_time);
+void isis_area_advertise_high_metrics_set(struct isis_area *area,
+ bool advertise_high_metrics);
void isis_area_attached_bit_send_set(struct isis_area *area, bool attached_bit);
void isis_area_attached_bit_receive_set(struct isis_area *area,
bool attached_bit);
diff --git a/lib/log.c b/lib/log.c
index b1a06bfb26..f7ab86fd9d 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -506,6 +506,26 @@ const char *zserv_command_string(unsigned int command)
return command_types[command].string;
}
+#define DESC_ENTRY(T) [(T)] = {(T), (#T), '\0'}
+static const struct zebra_desc_table gr_client_cap_types[] = {
+ DESC_ENTRY(ZEBRA_CLIENT_GR_CAPABILITIES),
+ DESC_ENTRY(ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE),
+ DESC_ENTRY(ZEBRA_CLIENT_ROUTE_UPDATE_PENDING),
+ DESC_ENTRY(ZEBRA_CLIENT_GR_DISABLE),
+ DESC_ENTRY(ZEBRA_CLIENT_RIB_STALE_TIME),
+};
+#undef DESC_ENTRY
+
+const char *zserv_gr_client_cap_string(uint32_t zcc)
+{
+ if (zcc >= array_size(gr_client_cap_types)) {
+ flog_err(EC_LIB_DEVELOPMENT, "unknown zserv command type: %u",
+ zcc);
+ return unknown.string;
+ }
+ return gr_client_cap_types[zcc].string;
+}
+
int proto_name2num(const char *s)
{
unsigned i;
diff --git a/lib/log.h b/lib/log.h
index b8452ac215..8a95b7a005 100644
--- a/lib/log.h
+++ b/lib/log.h
@@ -113,6 +113,7 @@ extern int proto_name2num(const char *s);
extern int proto_redistnum(int afi, const char *s);
extern const char *zserv_command_string(unsigned int command);
+extern const char *zserv_gr_client_cap_string(unsigned int zcc);
#define OSPF_LOG(level, cond, fmt, ...) \
do { \
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index 0575f5abe1..5b2b204dd8 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -515,11 +515,21 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
summary->path.origin.id =
ADV_ROUTER_IN_PREFIX(&route->prefix);
} else {
+ struct ospf6_lsa *old;
+
summary->path.origin.type =
htons(OSPF6_LSTYPE_INTER_PREFIX);
- summary->path.origin.id = ospf6_new_ls_id(
- summary->path.origin.type,
- summary->path.origin.adv_router, area->lsdb);
+
+ /* Try to reuse LS-ID from previous running instance. */
+ old = ospf6_find_inter_prefix_lsa(area->ospf6, area,
+ &route->prefix);
+ if (old)
+ summary->path.origin.id = old->header->id;
+ else
+ summary->path.origin.id = ospf6_new_ls_id(
+ summary->path.origin.type,
+ summary->path.origin.adv_router,
+ area->lsdb);
}
summary = ospf6_route_add(summary, summary_table);
} else {
@@ -1136,11 +1146,9 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
}
if (CHECK_FLAG(prefix_lsa->prefix.prefix_options,
- OSPF6_PREFIX_OPTION_NU)
- || CHECK_FLAG(prefix_lsa->prefix.prefix_options,
- OSPF6_PREFIX_OPTION_LA)) {
+ OSPF6_PREFIX_OPTION_NU)) {
if (is_debug)
- zlog_debug("Prefix has NU/LA bit set, ignore");
+ zlog_debug("Prefix has the NU bit set, ignore");
if (old)
ospf6_route_remove(old, table);
return;
@@ -1153,7 +1161,8 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
if (!OSPF6_OPT_ISSET(router_lsa->options, OSPF6_OPT_R)
|| !OSPF6_OPT_ISSET(router_lsa->options, OSPF6_OPT_V6)) {
if (is_debug)
- zlog_debug("Prefix has NU/LA bit set, ignore");
+ zlog_debug(
+ "Router-LSA has the V6-bit or R-bit unset, ignore");
if (old)
ospf6_route_remove(old, table);
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 05275c52ea..b2cdbc9b57 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -1380,8 +1380,8 @@ ospf6_external_aggr_match(struct ospf6 *ospf6, struct prefix *p)
void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
struct prefix *prefix,
unsigned int nexthop_num,
- struct in6_addr *nexthop, route_tag_t tag,
- struct ospf6 *ospf6)
+ const struct in6_addr *nexthop,
+ route_tag_t tag, struct ospf6 *ospf6)
{
route_map_result_t ret;
struct ospf6_route troute;
@@ -1469,9 +1469,13 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
info->type = type;
- if (nexthop_num && nexthop)
+ if (nexthop_num && nexthop) {
ospf6_route_add_nexthop(match, ifindex, nexthop);
- else
+ if (!IN6_IS_ADDR_UNSPECIFIED(nexthop)
+ && !IN6_IS_ADDR_LINKLOCAL(nexthop))
+ memcpy(&info->forwarding, nexthop,
+ sizeof(struct in6_addr));
+ } else
ospf6_route_add_nexthop(match, ifindex, NULL);
match->path.origin.id = htonl(info->id);
@@ -1515,9 +1519,13 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
}
info->type = type;
- if (nexthop_num && nexthop)
+ if (nexthop_num && nexthop) {
ospf6_route_add_nexthop(route, ifindex, nexthop);
- else
+ if (!IN6_IS_ADDR_UNSPECIFIED(nexthop)
+ && !IN6_IS_ADDR_LINKLOCAL(nexthop))
+ memcpy(&info->forwarding, nexthop,
+ sizeof(struct in6_addr));
+ } else
ospf6_route_add_nexthop(route, ifindex, NULL);
route = ospf6_route_add(route, ospf6->external_table);
diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h
index 15982ca64c..d63e467278 100644
--- a/ospf6d/ospf6_asbr.h
+++ b/ospf6d/ospf6_asbr.h
@@ -114,7 +114,7 @@ extern int ospf6_asbr_is_asbr(struct ospf6 *o);
extern void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
struct prefix *prefix,
unsigned int nexthop_num,
- struct in6_addr *nexthop,
+ const struct in6_addr *nexthop,
route_tag_t tag, struct ospf6 *ospf6);
extern void ospf6_asbr_redistribute_remove(int type, ifindex_t ifindex,
struct prefix *prefix,
diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c
index 2d2069566c..db1520ff20 100644
--- a/ospf6d/ospf6_flood.c
+++ b/ospf6d/ospf6_flood.c
@@ -1105,9 +1105,12 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from,
&new->refresh);
}
+ /* GR: check for network topology change. */
struct ospf6 *ospf6 = from->ospf6_if->area->ospf6;
struct ospf6_area *area = from->ospf6_if->area;
- if (ospf6->gr_info.restart_in_progress)
+ if (ospf6->gr_info.restart_in_progress &&
+ (new->header->type == ntohs(OSPF6_LSTYPE_ROUTER) ||
+ new->header->type == ntohs(OSPF6_LSTYPE_NETWORK)))
ospf6_gr_check_lsdb_consistency(ospf6, area);
return;
diff --git a/ospf6d/ospf6_gr.c b/ospf6d/ospf6_gr.c
index c182e48f2e..847531361e 100644
--- a/ospf6d/ospf6_gr.c
+++ b/ospf6d/ospf6_gr.c
@@ -127,6 +127,7 @@ static void ospf6_gr_restart_exit(struct ospf6 *ospf6, const char *reason)
{
struct ospf6_area *area;
struct listnode *onode, *anode;
+ struct ospf6_route *route;
if (IS_DEBUG_OSPF6_GR)
zlog_debug("GR: exiting graceful restart: %s", reason);
@@ -148,8 +149,16 @@ static void ospf6_gr_restart_exit(struct ospf6 *ospf6, const char *reason)
*/
OSPF6_ROUTER_LSA_EXECUTE(area);
+ /*
+ * Force reorigination of intra-area-prefix-LSAs to handle
+ * areas without any full adjacency.
+ */
+ OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(area);
+
for (ALL_LIST_ELEMENTS_RO(area->if_list, anode, oi)) {
- OSPF6_LINK_LSA_EXECUTE(oi);
+ /* Reoriginate Link-LSA. */
+ if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
+ OSPF6_LINK_LSA_EXECUTE(oi);
/*
* 2) The router should reoriginate network-LSAs on all
@@ -161,6 +170,16 @@ static void ospf6_gr_restart_exit(struct ospf6 *ospf6, const char *reason)
}
/*
+ * While all self-originated NSSA and AS-external LSAs were already
+ * learned from the helping neighbors, we need to reoriginate them in
+ * order to ensure they will be refreshed periodically.
+ */
+ for (route = ospf6_route_head(ospf6->external_table); route;
+ route = ospf6_route_next(route))
+ ospf6_handle_external_lsa_origination(ospf6, route,
+ &route->prefix);
+
+ /*
* 3) The router reruns its OSPF routing calculations, this time
* installing the results into the system forwarding table, and
* originating summary-LSAs, Type-7 LSAs and AS-external-LSAs as
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index 7a22fdf064..7afb47c752 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -592,6 +592,7 @@ static struct ospf6_neighbor *better_drouter(struct ospf6_neighbor *a,
uint8_t dr_election(struct ospf6_interface *oi)
{
+ struct ospf6 *ospf6 = oi->area->ospf6;
struct listnode *node, *nnode;
struct ospf6_neighbor *on, *drouter, *bdrouter, myself;
struct ospf6_neighbor *best_drouter, *best_bdrouter;
@@ -602,13 +603,12 @@ uint8_t dr_election(struct ospf6_interface *oi)
/* pseudo neighbor myself, including noting current DR/BDR (1) */
memset(&myself, 0, sizeof(myself));
- inet_ntop(AF_INET, &oi->area->ospf6->router_id, myself.name,
- sizeof(myself.name));
+ inet_ntop(AF_INET, &ospf6->router_id, myself.name, sizeof(myself.name));
myself.state = OSPF6_NEIGHBOR_TWOWAY;
myself.drouter = oi->drouter;
myself.bdrouter = oi->bdrouter;
myself.priority = oi->priority;
- myself.router_id = oi->area->ospf6->router_id;
+ myself.router_id = ospf6->router_id;
/* Electing BDR (2) */
for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
@@ -657,8 +657,10 @@ uint8_t dr_election(struct ospf6_interface *oi)
/* If DR or BDR change, invoke AdjOK? for each neighbor (7) */
/* RFC 2328 section 12.4. Originating LSAs (3) will be handled
accordingly after AdjOK */
- if (oi->drouter != (drouter ? drouter->router_id : htonl(0))
- || oi->bdrouter != (bdrouter ? bdrouter->router_id : htonl(0))) {
+
+ if (oi->drouter != (drouter ? drouter->router_id : htonl(0)) ||
+ oi->bdrouter != (bdrouter ? bdrouter->router_id : htonl(0)) ||
+ ospf6->gr_info.restart_in_progress) {
if (IS_OSPF6_DEBUG_INTERFACE)
zlog_debug("DR Election on %s: DR: %s BDR: %s",
oi->interface->name,
diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c
index 0221102b59..586183731c 100644
--- a/ospf6d/ospf6_lsdb.c
+++ b/ospf6d/ospf6_lsdb.c
@@ -13,8 +13,10 @@
#include "vty.h"
#include "ospf6_proto.h"
+#include "ospf6_area.h"
#include "ospf6_lsa.h"
#include "ospf6_lsdb.h"
+#include "ospf6_abr.h"
#include "ospf6_asbr.h"
#include "ospf6_route.h"
#include "ospf6d.h"
@@ -216,6 +218,31 @@ struct ospf6_lsa *ospf6_find_external_lsa(struct ospf6 *ospf6, struct prefix *p)
return lsa;
}
+struct ospf6_lsa *ospf6_find_inter_prefix_lsa(struct ospf6 *ospf6,
+ struct ospf6_area *area,
+ struct prefix *p)
+{
+ struct ospf6_lsa *lsa;
+ uint16_t type = htons(OSPF6_LSTYPE_INTER_PREFIX);
+
+ for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id, lsa)) {
+ struct ospf6_inter_prefix_lsa *prefix_lsa;
+ struct prefix prefix;
+
+ prefix_lsa =
+ (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
+ lsa->header);
+ prefix.family = AF_INET6;
+ prefix.prefixlen = prefix_lsa->prefix.prefix_length;
+ ospf6_prefix_in6_addr(&prefix.u.prefix6, prefix_lsa,
+ &prefix_lsa->prefix);
+ if (prefix_same(p, &prefix))
+ return lsa;
+ }
+
+ return NULL;
+}
+
struct ospf6_lsa *ospf6_lsdb_lookup_next(uint16_t type, uint32_t id,
uint32_t adv_router,
struct ospf6_lsdb *lsdb)
diff --git a/ospf6d/ospf6_lsdb.h b/ospf6d/ospf6_lsdb.h
index 7e20b05447..a2444f1c14 100644
--- a/ospf6d/ospf6_lsdb.h
+++ b/ospf6d/ospf6_lsdb.h
@@ -29,6 +29,9 @@ extern struct ospf6_lsa *ospf6_lsdb_lookup(uint16_t type, uint32_t id,
extern struct ospf6_lsa *ospf6_lsdb_lookup_next(uint16_t type, uint32_t id,
uint32_t adv_router,
struct ospf6_lsdb *lsdb);
+extern struct ospf6_lsa *ospf6_find_inter_prefix_lsa(struct ospf6 *ospf6,
+ struct ospf6_area *area,
+ struct prefix *p);
extern void ospf6_lsdb_add(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb);
extern void ospf6_lsdb_remove(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb);
diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c
index 72dfa240af..443032933d 100644
--- a/ospf6d/ospf6_route.c
+++ b/ospf6d/ospf6_route.c
@@ -267,7 +267,8 @@ int ospf6_num_nexthops(struct list *nh_list)
return (listcount(nh_list));
}
-void ospf6_add_nexthop(struct list *nh_list, int ifindex, struct in6_addr *addr)
+void ospf6_add_nexthop(struct list *nh_list, int ifindex,
+ const struct in6_addr *addr)
{
struct ospf6_nexthop *nh;
struct ospf6_nexthop nh_match;
diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h
index 2d4fcc930e..c2125951ec 100644
--- a/ospf6d/ospf6_route.h
+++ b/ospf6d/ospf6_route.h
@@ -312,7 +312,7 @@ extern int ospf6_num_nexthops(struct list *nh_list);
extern void ospf6_copy_nexthops(struct list *dst, struct list *src);
extern void ospf6_merge_nexthops(struct list *dst, struct list *src);
extern void ospf6_add_nexthop(struct list *nh_list, int ifindex,
- struct in6_addr *addr);
+ const struct in6_addr *addr);
extern void ospf6_add_route_nexthop_blackhole(struct ospf6_route *route);
extern int ospf6_num_nexthops(struct list *nh_list);
extern bool ospf6_route_cmp_nexthops(struct ospf6_route *a,
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index 6fe0a24926..0ccbb4d65d 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -252,7 +252,7 @@ static int ospf6_zebra_read_route(ZAPI_CALLBACK_ARGS)
{
struct zapi_route api;
unsigned long ifindex;
- struct in6_addr *nexthop;
+ const struct in6_addr *nexthop = &in6addr_any;
struct ospf6 *ospf6;
struct prefix_ipv6 p;
@@ -272,7 +272,9 @@ static int ospf6_zebra_read_route(ZAPI_CALLBACK_ARGS)
return 0;
ifindex = api.nexthops[0].ifindex;
- nexthop = &api.nexthops[0].gate.ipv6;
+ if (api.nexthops[0].type == NEXTHOP_TYPE_IPV6
+ || api.nexthops[0].type == NEXTHOP_TYPE_IPV6_IFINDEX)
+ nexthop = &api.nexthops[0].gate.ipv6;
if (IS_OSPF6_DEBUG_ZEBRA(RECV))
zlog_debug(
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 5268c9896b..2937c4ec0c 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -2102,6 +2102,14 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph,
if (ospf_flood(oi->ospf, nbr, current, lsa)
< 0) /* Trap NSSA later. */
DISCARD_LSA(lsa, 5);
+
+ /* GR: check for network topology change. */
+ if (ospf->gr_info.restart_in_progress &&
+ ((lsa->data->type == OSPF_ROUTER_LSA ||
+ lsa->data->type == OSPF_NETWORK_LSA)))
+ ospf_gr_check_lsdb_consistency(oi->ospf,
+ oi->area);
+
continue;
}
@@ -2214,9 +2222,6 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph,
assert(listcount(lsas) == 0);
list_delete(&lsas);
-
- if (ospf->gr_info.restart_in_progress)
- ospf_gr_check_lsdb_consistency(oi->ospf, oi->area);
}
/* OSPF Link State Acknowledgment message read -- RFC2328 Section 13.7. */
diff --git a/pimd/pim_util.c b/pimd/pim_util.c
index 948b615f71..657e84ae50 100644
--- a/pimd/pim_util.c
+++ b/pimd/pim_util.c
@@ -159,7 +159,7 @@ int pim_get_all_mcast_group(struct prefix *prefix)
bool pim_addr_is_multicast(pim_addr addr)
{
#if PIM_IPV == 4
- if (IN_MULTICAST(addr.s_addr))
+ if (IN_MULTICAST(ntohl(addr.s_addr)))
return true;
#else
if (IN6_IS_ADDR_MULTICAST(&addr))
diff --git a/tests/topotests/bgp_ipv6_ll_peering/__init__.py b/tests/topotests/bgp_ipv6_ll_peering/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_ipv6_ll_peering/__init__.py
diff --git a/tests/topotests/bgp_ipv6_ll_peering/r1/bgpd.conf b/tests/topotests/bgp_ipv6_ll_peering/r1/bgpd.conf
new file mode 100644
index 0000000000..724cbf84ab
--- /dev/null
+++ b/tests/topotests/bgp_ipv6_ll_peering/r1/bgpd.conf
@@ -0,0 +1,6 @@
+router bgp 65001
+ bgp router-id 10.0.0.1
+ no bgp ebgp-requires-policy
+ neighbor fe80:1::2 remote-as external
+ neighbor fe80:1::2 timers 3 10
+ neighbor fe80:1::2 interface r1-eth0
diff --git a/tests/topotests/bgp_ipv6_ll_peering/r1/zebra.conf b/tests/topotests/bgp_ipv6_ll_peering/r1/zebra.conf
new file mode 100644
index 0000000000..4e93d4f4e5
--- /dev/null
+++ b/tests/topotests/bgp_ipv6_ll_peering/r1/zebra.conf
@@ -0,0 +1,4 @@
+!
+interface r1-eth0
+ ipv6 address fe80:1::1/64
+!
diff --git a/tests/topotests/bgp_ipv6_ll_peering/r2/bgpd.conf b/tests/topotests/bgp_ipv6_ll_peering/r2/bgpd.conf
new file mode 100644
index 0000000000..44f79dfc33
--- /dev/null
+++ b/tests/topotests/bgp_ipv6_ll_peering/r2/bgpd.conf
@@ -0,0 +1,6 @@
+router bgp 65002
+ bgp router-id 10.0.0.2
+ no bgp ebgp-requires-policy
+ neighbor fe80:1::1 remote-as external
+ neighbor fe80:1::1 timers 3 10
+ neighbor fe80:1::1 interface r2-eth0
diff --git a/tests/topotests/bgp_ipv6_ll_peering/r2/zebra.conf b/tests/topotests/bgp_ipv6_ll_peering/r2/zebra.conf
new file mode 100644
index 0000000000..1e703cda36
--- /dev/null
+++ b/tests/topotests/bgp_ipv6_ll_peering/r2/zebra.conf
@@ -0,0 +1,4 @@
+!
+interface r2-eth0
+ ipv6 address fe80:1::2/64
+!
diff --git a/tests/topotests/bgp_ipv6_ll_peering/test_bgp_ipv6_ll_peering.py b/tests/topotests/bgp_ipv6_ll_peering/test_bgp_ipv6_ll_peering.py
new file mode 100644
index 0000000000..ea974b5302
--- /dev/null
+++ b/tests/topotests/bgp_ipv6_ll_peering/test_bgp_ipv6_ll_peering.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# Copyright (c) 2023 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+"""
+Check if IPv6 Link-Local BGP peering works fine.
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 3):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_ipv6_link_local_peering():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+
+ def _bgp_converge():
+ output = json.loads(r1.vtysh_cmd("show bgp summary json"))
+ expected = {
+ "ipv4Unicast": {
+ "peers": {
+ "fe80:1::2": {
+ "state": "Established",
+ }
+ }
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see BGP convergence on R2"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/conftest.py b/tests/topotests/conftest.py
index 2a57f6c26e..df5d066023 100755
--- a/tests/topotests/conftest.py
+++ b/tests/topotests/conftest.py
@@ -396,12 +396,7 @@ def pytest_runtest_setup(item):
def pytest_runtest_makereport(item, call):
"Log all assert messages to default logger with error level"
- # Nothing happened
- if call.when == "call":
- pause = topotest_extra_config["pause"]
- else:
- pause = False
-
+ pause = bool(item.config.getoption("--pause"))
title = "unset"
if call.excinfo is None:
diff --git a/tests/topotests/isis_advertise_high_metrics/__init__.py b/tests/topotests/isis_advertise_high_metrics/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/isis_advertise_high_metrics/__init__.py
diff --git a/tests/topotests/isis_advertise_high_metrics/r1/isisd.conf b/tests/topotests/isis_advertise_high_metrics/r1/isisd.conf
new file mode 100644
index 0000000000..747c64ef4f
--- /dev/null
+++ b/tests/topotests/isis_advertise_high_metrics/r1/isisd.conf
@@ -0,0 +1,19 @@
+hostname r1
+! debug isis adj-packets
+! debug isis events
+! debug isis update-packets
+interface eth-r2
+ ip router isis 1
+ isis circuit-type level-2-only
+ isis network point-to-point
+!
+interface eth-r3
+ ip router isis 1
+ isis circuit-type level-2-only
+ isis metric 20
+ isis network point-to-point
+!
+router isis 1
+ is-type level-2-only
+ net 10.0000.0000.0000.0000.0000.0000.0000.0000.0000.00
+! \ No newline at end of file
diff --git a/tests/topotests/isis_advertise_high_metrics/r1/zebra.conf b/tests/topotests/isis_advertise_high_metrics/r1/zebra.conf
new file mode 100644
index 0000000000..b14ce0d88d
--- /dev/null
+++ b/tests/topotests/isis_advertise_high_metrics/r1/zebra.conf
@@ -0,0 +1,5 @@
+interface eth-r2
+ ip address 192.168.1.0/31
+
+interface eth-r3
+ ip address 192.168.1.2/31 \ No newline at end of file
diff --git a/tests/topotests/isis_advertise_high_metrics/r2/isisd.conf b/tests/topotests/isis_advertise_high_metrics/r2/isisd.conf
new file mode 100644
index 0000000000..cee62ad57a
--- /dev/null
+++ b/tests/topotests/isis_advertise_high_metrics/r2/isisd.conf
@@ -0,0 +1,18 @@
+hostname r2
+! debug isis adj-packets
+! debug isis events
+! debug isis update-packets
+interface eth-r1
+ ip router isis 1
+ isis circuit-type level-2-only
+ isis network point-to-point
+!
+interface eth-r4
+ ip router isis 1
+ isis circuit-type level-2-only
+ isis network point-to-point
+!
+router isis 1
+ is-type level-2-only
+ net 10.0000.0000.0000.0000.0000.0000.0000.0000.0001.00
+! \ No newline at end of file
diff --git a/tests/topotests/isis_advertise_high_metrics/r2/zebra.conf b/tests/topotests/isis_advertise_high_metrics/r2/zebra.conf
new file mode 100644
index 0000000000..01de593415
--- /dev/null
+++ b/tests/topotests/isis_advertise_high_metrics/r2/zebra.conf
@@ -0,0 +1,5 @@
+interface eth-r1
+ ip address 192.168.1.1/31
+
+interface eth-r4
+ ip address 192.168.1.7/31 \ No newline at end of file
diff --git a/tests/topotests/isis_advertise_high_metrics/r3/isisd.conf b/tests/topotests/isis_advertise_high_metrics/r3/isisd.conf
new file mode 100644
index 0000000000..6d795f093c
--- /dev/null
+++ b/tests/topotests/isis_advertise_high_metrics/r3/isisd.conf
@@ -0,0 +1,20 @@
+hostname r3
+! debug isis adj-packets
+! debug isis events
+! debug isis update-packets
+interface eth-r1
+ ip router isis 1
+ isis circuit-type level-2-only
+ isis metric 20
+ isis network point-to-point
+!
+interface eth-r4
+ ip router isis 1
+ isis circuit-type level-2-only
+ isis metric 20
+ isis network point-to-point
+!
+router isis 1
+ is-type level-2-only
+ net 10.0000.0000.0000.0000.0000.0000.0000.0000.0002.00
+! \ No newline at end of file
diff --git a/tests/topotests/isis_advertise_high_metrics/r3/zebra.conf b/tests/topotests/isis_advertise_high_metrics/r3/zebra.conf
new file mode 100644
index 0000000000..668431ca4f
--- /dev/null
+++ b/tests/topotests/isis_advertise_high_metrics/r3/zebra.conf
@@ -0,0 +1,5 @@
+interface eth-r1
+ ip address 192.168.1.3/31
+
+interface eth-r4
+ ip address 192.168.1.4/31 \ No newline at end of file
diff --git a/tests/topotests/isis_advertise_high_metrics/r4/isisd.conf b/tests/topotests/isis_advertise_high_metrics/r4/isisd.conf
new file mode 100644
index 0000000000..b281014b9e
--- /dev/null
+++ b/tests/topotests/isis_advertise_high_metrics/r4/isisd.conf
@@ -0,0 +1,19 @@
+hostname r4
+! debug isis adj-packets
+! debug isis events
+! debug isis update-packets
+interface eth-r2
+ ip router isis 1
+ isis circuit-type level-2-only
+ isis network point-to-point
+!
+interface eth-r3
+ ip router isis 1
+ isis circuit-type level-2-only
+ isis metric 20
+ isis network point-to-point
+!
+router isis 1
+ is-type level-2-only
+ net 10.0000.0000.0000.0000.0000.0000.0000.0000.0003.00
+! \ No newline at end of file
diff --git a/tests/topotests/isis_advertise_high_metrics/r4/zebra.conf b/tests/topotests/isis_advertise_high_metrics/r4/zebra.conf
new file mode 100644
index 0000000000..6819dbb89e
--- /dev/null
+++ b/tests/topotests/isis_advertise_high_metrics/r4/zebra.conf
@@ -0,0 +1,5 @@
+interface eth-r2
+ ip address 192.168.1.6/31
+
+interface eth-r3
+ ip address 192.168.1.5/31
diff --git a/tests/topotests/isis_advertise_high_metrics/test_isis_advertise_high_metrics.py b/tests/topotests/isis_advertise_high_metrics/test_isis_advertise_high_metrics.py
new file mode 100644
index 0000000000..5eef879e3f
--- /dev/null
+++ b/tests/topotests/isis_advertise_high_metrics/test_isis_advertise_high_metrics.py
@@ -0,0 +1,485 @@
+#!/usr/bin/env python
+
+#
+# test_isis_advertise_high_metrics.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2020 by Volta Networks
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+r"""
+test_isis_advertise_high_metrics.py: Advertise High Metrics FRR ISIS Test
+"""
+
+import os
+import re
+import sys
+import pytest
+import json
+from time import sleep
+from functools import partial
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.common_config import (
+ retry,
+ stop_router,
+ start_router,
+)
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+pytestmark = [pytest.mark.isisd]
+
+
+def build_topo(tgen):
+ "Build function"
+
+ # Add ISIS routers:
+ # r2
+ # / \
+ # r1 r4
+ # \ /
+ # r3
+
+ #
+ # Define FRR Routers
+ #
+ for router in ["r1", "r2", "r3", "r4"]:
+ tgen.add_router(router)
+ #
+ # Define connections
+ #
+ switch = tgen.add_switch("s0")
+ switch.add_link(tgen.gears["r1"], nodeif="eth-r2")
+ switch.add_link(tgen.gears["r2"], nodeif="eth-r1")
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"], nodeif="eth-r3")
+ switch.add_link(tgen.gears["r3"], nodeif="eth-r1")
+
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r2"], nodeif="eth-r4")
+ switch.add_link(tgen.gears["r4"], nodeif="eth-r2")
+
+ switch = tgen.add_switch("s3")
+ switch.add_link(tgen.gears["r3"], nodeif="eth-r4")
+ switch.add_link(tgen.gears["r4"], nodeif="eth-r3")
+
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ # For all registered routers, load the zebra configuration file
+ for rname, router in tgen.routers().items():
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
+ )
+
+ # After loading the configurations, this function loads configured daemons.
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+
+ # This function tears down the whole topology.
+ tgen.stop_topology()
+
+
+@retry(retry_timeout=60)
+def _check_interface_metrics(router, expected_metrics):
+ "Verfiy metrics on router's isis interfaces"
+
+ tgen = get_topogen()
+ router = tgen.gears[router]
+ logger.info(f"check_interface_metrics {router}")
+ isis_interface_output = router.vtysh_cmd(
+ "show isis interface detail json"
+ )
+
+ intf_json = json.loads(isis_interface_output)
+ for i in range(len(expected_metrics)):
+ metric = intf_json["areas"][0]["circuits"][i]["interface"]["levels"][0]["metric"]
+ if (metric != expected_metrics[i]):
+ intf_name = intf_json["areas"][0]["circuits"][i]["interface"]["name"]
+ return "{} with expected metric {} on {} got {}".format(
+ router.name, expected_metrics[i], intf_name, metric
+ )
+ return True
+
+
+def check_interface_metrics(router, expected_metrics):
+ "Verfiy metrics on router's isis interfaces"
+
+ assertmsg = _check_interface_metrics(
+ router, expected_metrics
+ )
+ assert assertmsg is True, assertmsg
+
+
+@retry(retry_timeout=60)
+def _check_lsp_metrics(router, lsp, expected_metrics):
+ "Verfiy metrics on router's lsp"
+ tgen = get_topogen()
+ router = tgen.gears[router]
+ logger.info(f"check_lsp_metrics {router}")
+ isis_lsp_output = router.vtysh_cmd(
+ "show isis database detail {}".format(lsp)
+ )
+
+ metrics_list = [int(i) for i in re.findall(r"Metric: (\d+)", isis_lsp_output)]
+ if len(metrics_list) == 0:
+ return False
+ for metric in metrics_list:
+ if metric not in expected_metrics:
+ return "{} with expected metrics {} got {}".format(
+ router.name, expected_metrics, metrics_list
+ )
+
+ return True
+
+
+def check_lsp_metrics(router, lsp, expected_metrics):
+ "Verfiy metrics on router's lsp"
+
+ assertmsg = _check_lsp_metrics(
+ router, lsp, expected_metrics
+ )
+ assert assertmsg is True, assertmsg
+
+
+@retry(retry_timeout=60)
+def _check_ip_route(router, destination, expected_interface):
+ "Verfiy IS-IS route"
+
+ tgen = get_topogen()
+ router = tgen.gears[router]
+ logger.info(f"check_ip_route {router}")
+ route_output = router.vtysh_cmd(
+ "show ip route {} json".format(destination)
+ )
+ route_json = json.loads(route_output)
+
+ interface = route_json[destination][0]["nexthops"][0]["interfaceName"]
+
+ if (interface != expected_interface):
+ return "{} with expected route to {} got {} expected {}".format(
+ router.name, destination, interface, expected_interface
+ )
+
+ return True
+
+
+def check_ip_route(router, destination, expected_interface):
+ "Verfiy IS-IS route"
+
+ assertmsg = _check_ip_route(
+ router, destination, expected_interface
+ )
+ assert assertmsg is True, assertmsg
+
+
+def test_isis_daemon_up():
+ "Check isis daemon up before starting test"
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for router in ["r1", "r2", "r3", "r4"]:
+ r = tgen.gears[router]
+ daemons = r.vtysh_cmd(
+ "show daemons"
+ )
+ assert "isisd" in daemons
+
+ # Verify initial metric values.
+ check_lsp_metrics("r1", "r1.00-00", [10, 20])
+ check_lsp_metrics("r2", "r2.00-00", [10, 10])
+ check_lsp_metrics("r3", "r3.00-00", [20, 20])
+ check_lsp_metrics("r4", "r4.00-00", [10, 20])
+
+
+def test_isis_advertise_high_metrics():
+ "Check that advertise high metrics behaves as expected"
+
+ tgen = get_topogen()
+ net = get_topogen().net
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Testing advertise high metrics basic behavior")
+
+ # Confirm low metrics values on each isis interface on r1
+ r1 = tgen.gears["r1"]
+ check_interface_metrics("r1", [10, 20])
+
+ # Confirm low metrics values within isis database on r1
+ check_lsp_metrics("r1", "r1.00-00", [10, 20])
+
+ # Configure advertise high metrics
+ r1.vtysh_cmd(
+ f"""
+ configure
+ router isis 1
+ advertise-high-metrics
+ """
+ )
+
+ # Confirm high wide metrics values on each isis interface on r1
+ check_interface_metrics("r1", [16777215])
+
+ # Confirm high wide metrics values within isis database on r1
+ check_lsp_metrics("r1", "r1.00-00", [16777215])
+
+ # Remove advertise high metrics
+ r1.vtysh_cmd(
+ f"""
+ configure
+ router isis 1
+ no advertise-high-metrics
+ """
+ )
+
+ # Confirm low metrics values on each isis interface on r1
+ check_interface_metrics("r1", [10, 20])
+
+ # Confirm low metrics values within isis database on r1
+ check_lsp_metrics("r1", "r1.00-00", [10, 20])
+
+
+def test_isis_advertise_high_metrics_narrow():
+ "Check that advertise high metrics behaves as expected with narrow metrics"
+
+ tgen = get_topogen()
+ net = get_topogen().net
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Testing advertise high metrics with narrow metric style")
+
+ r1 = tgen.gears["r1"]
+
+ # Configure narrow metric-style
+ r1.vtysh_cmd(
+ f"""
+ configure
+ router isis 1
+ metric-style narrow
+ """
+ )
+
+ # Confirm low metrics values on each isis interface on r1
+ check_interface_metrics("r1", [10, 20])
+
+ # Confirm low metrics values within isis database on r1
+ check_lsp_metrics("r1", "r1.00-00", [10, 20])
+
+ # Configure advertise high metrics
+ r1.vtysh_cmd(
+ f"""
+ configure
+ router isis 1
+ advertise-high-metrics
+ """
+ )
+
+ # Confirm high narrow metrics values on each isis interface on r1
+ check_interface_metrics("r1", [63])
+
+ # Confirm high narrow metrics values within isis database on r1
+ check_lsp_metrics("r1", "r1.00-00", [63])
+
+ # Remove advertise high metrics
+ r1.vtysh_cmd(
+ f"""
+ configure
+ router isis 1
+ no advertise-high-metrics
+ """
+ )
+
+ # Confirm low metrics values on each isis interface on r1
+ check_interface_metrics("r1", [10, 20])
+
+ # Confirm low metrics values within isis database on r1
+ check_lsp_metrics("r1", "r1.00-00", [10, 20])
+
+ # Remove narrow metric-style
+ r1.vtysh_cmd(
+ f"""
+ configure
+ router isis 1
+ no metric-style narrow
+ """
+ )
+
+
+def test_isis_advertise_high_metrics_transition():
+ "Check that advertise high metrics behaves as expected with transition metrics"
+ tgen = get_topogen()
+ net = get_topogen().net
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Testing advertise high metrics with transition metric style")
+
+ r1 = tgen.gears["r1"]
+
+ # Configure transition metric-style
+ r1.vtysh_cmd(
+ f"""
+ configure
+ router isis 1
+ metric-style transition
+ """
+ )
+
+ # Confirm low metrics values on each isis interface on r1
+ check_interface_metrics("r1", [10, 20])
+
+ # Confirm low metrics values within isis database on r1
+ check_lsp_metrics("r1", "r1.00-00", [10, 20])
+
+ # Configure advertise high metrics
+ r1.vtysh_cmd(
+ f"""
+ configure
+ router isis 1
+ advertise-high-metrics
+ """
+ )
+
+ # Confirm high transition metrics values on each isis interface on r1
+ check_interface_metrics("r1", [62])
+
+ # Confirm high transition metrics values within isis database on r1
+ check_lsp_metrics("r1", "r1.00-00", [62])
+
+ # Remove advertise high metrics
+ r1.vtysh_cmd(
+ f"""
+ configure
+ router isis 1
+ no advertise-high-metrics
+ """
+ )
+
+ # Confirm low metrics values on each isis interface on r1
+ check_interface_metrics("r1", [10, 20])
+
+ # Confirm low metrics values within isis database on r1
+ check_lsp_metrics("r1", "r1.00-00", [10, 20])
+
+ # Remove narrow metric-style
+ r1.vtysh_cmd(
+ f"""
+ configure
+ router isis 1
+ no metric-style transition
+ """
+ )
+
+
+def test_isis_advertise_high_metrics_route():
+ """
+ Topology:
+
+ r2
+ / \
+ r1 r4
+ \ /
+ r3
+
+ Devices are configured with preferred route between r1 and r4:
+ r1 -> r2 -> r4
+ Configure "advertise-high-metrics" on r2 and check that preferred route is:
+ r1 -> r3 -> r4.
+ Shut r3 and check that preferred route is:
+ r1 -> r2 -> r4.
+ """
+ tgen = get_topogen()
+ net = get_topogen().net
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Testing advertise high metrics route behavior")
+
+ r1 = tgen.gears["r1"]
+ r2 = tgen.gears["r2"]
+
+ # Verify the preferred path from r1 to r4 (192.168.1.6) is currently via 192.168.1.1, eth-r2
+ check_ip_route("r1", "192.168.1.6/31", "eth-r2")
+
+ # Configure advertise high metrics on r2
+ r2.vtysh_cmd(
+ f"""
+ configure
+ router isis 1
+ advertise-high-metrics
+ """
+ )
+
+ # Verify the preferred path from r1 to r4 (192.168.1.6) is now via 192.168.1.3, eth-r3
+ check_ip_route("r1", "192.168.1.6/31", "eth-r3")
+
+ # Shutdown r3
+ logger.info("Stop router r3")
+ stop_router(tgen, "r3")
+
+ # Verify the preferred path from r1 to r4 (192.168.1.6) is now via 192.168.1.1, eth-r2
+ check_ip_route("r1", "192.168.1.6/31", "eth-r2")
+
+ # Start r3
+ logger.info("Start router r3")
+ start_router(tgen, "r3")
+
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip("Memory leak test/report is disabled")
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang
index ff3ba5d12b..0c2cf232fb 100644
--- a/yang/frr-isisd.yang
+++ b/yang/frr-isisd.yang
@@ -1169,6 +1169,13 @@ module frr-isisd {
"Define the style of TLVs metric supported.";
}
+ leaf advertise-high-metrics {
+ type boolean;
+ default "false";
+ description
+ "Advertise high metric value on all interfaces.";
+ }
+
leaf purge-originator {
type boolean;
default "false";
diff --git a/zebra/zebra_gr.c b/zebra/zebra_gr.c
index 3bd5b51fbc..3724ea0901 100644
--- a/zebra/zebra_gr.c
+++ b/zebra/zebra_gr.c
@@ -111,14 +111,17 @@ static struct client_gr_info *zebra_gr_client_info_create(struct zserv *client)
static void zebra_gr_client_info_delte(struct zserv *client,
struct client_gr_info *info)
{
+ struct vrf *vrf = vrf_lookup_by_id(info->vrf_id);
+
TAILQ_REMOVE(&(client->gr_info_queue), info, gr_info);
THREAD_OFF(info->t_stale_removal);
XFREE(MTYPE_ZEBRA_GR, info->current_prefix);
- LOG_GR("%s: Instance info is being deleted for client %s", __func__,
- zebra_route_string(client->proto));
+ LOG_GR("%s: Instance info is being deleted for client %s vrf %s(%u)",
+ __func__, zebra_route_string(client->proto), VRF_LOGNAME(vrf),
+ info->vrf_id);
/* Delete all the stale routes. */
info->do_delete = true;
@@ -154,6 +157,8 @@ int32_t zebra_gr_client_disconnect(struct zserv *client)
TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) {
if (ZEBRA_CLIENT_GR_ENABLED(info->capabilities)
&& (info->t_stale_removal == NULL)) {
+ struct vrf *vrf = vrf_lookup_by_id(info->vrf_id);
+
thread_add_timer(
zrouter.master,
zebra_gr_route_stale_delete_timer_expiry, info,
@@ -162,8 +167,9 @@ int32_t zebra_gr_client_disconnect(struct zserv *client)
info->current_afi = AFI_IP;
info->stale_client_ptr = client;
info->stale_client = true;
- LOG_GR("%s: Client %s Stale timer update to %d",
+ LOG_GR("%s: Client %s vrf %s(%u) Stale timer update to %d",
__func__, zebra_route_string(client->proto),
+ VRF_LOGNAME(vrf), info->vrf_id,
info->stale_removal_time);
}
}
@@ -180,6 +186,7 @@ static void zebra_gr_delete_stale_client(struct client_gr_info *info)
{
struct client_gr_info *bgp_info;
struct zserv *s_client = NULL;
+ struct vrf *vrf = vrf_lookup_by_id(info->vrf_id);
s_client = info->stale_client_ptr;
@@ -204,8 +211,9 @@ static void zebra_gr_delete_stale_client(struct client_gr_info *info)
return;
}
- LOG_GR("%s: Client %s is being deleted", __func__,
- zebra_route_string(s_client->proto));
+ LOG_GR("%s: Client %s vrf %s(%u) is being deleted", __func__,
+ zebra_route_string(s_client->proto), VRF_LOGNAME(vrf),
+ info->vrf_id);
TAILQ_INIT(&(s_client->gr_info_queue));
listnode_delete(zrouter.stale_client_list, s_client);
@@ -324,10 +332,13 @@ static void zebra_client_update_info(struct zserv *client, struct zapi_cap *api)
/* Update other parameters */
if (!info->gr_enable) {
+ struct vrf *vrf = vrf_lookup_by_id(api->vrf_id);
+
client->gr_instance_count++;
- LOG_GR("%s: Cient %s GR enabled count %d", __func__,
- zebra_route_string(client->proto),
+ LOG_GR("%s: Cient %s vrf %s(%u) GR enabled count %d",
+ __func__, zebra_route_string(client->proto),
+ VRF_LOGNAME(vrf), api->vrf_id,
client->gr_instance_count);
info->capabilities = api->cap;
@@ -342,9 +353,11 @@ static void zebra_client_update_info(struct zserv *client, struct zapi_cap *api)
/* Update the stale removal timer */
if (info && info->t_stale_removal == NULL) {
+ struct vrf *vrf = vrf_lookup_by_id(info->vrf_id);
- LOG_GR("%s: Stale time: %d is now update to: %d",
- __func__, info->stale_removal_time,
+ LOG_GR("%s: vrf %s(%u) Stale time: %d is now update to: %d",
+ __func__, VRF_LOGNAME(vrf), info->vrf_id,
+ info->stale_removal_time,
api->stale_removal_time);
info->stale_removal_time = api->stale_removal_time;
@@ -352,19 +365,35 @@ static void zebra_client_update_info(struct zserv *client, struct zapi_cap *api)
break;
case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
- LOG_GR(
- "%s: Client %s route update complete for AFI %d, SAFI %d",
- __func__, zebra_route_string(client->proto), api->afi,
- api->safi);
- if (info)
+ if (!info) {
+ LOG_GR("%s: Client %s route update complete for AFI %d, SAFI %d",
+ __func__, zebra_route_string(client->proto),
+ api->afi, api->safi);
+ } else {
+ struct vrf *vrf = vrf_lookup_by_id(info->vrf_id);
+
+ LOG_GR("%s: Client %s vrf %s(%u) route update complete for AFI %d, SAFI %d",
+ __func__, zebra_route_string(client->proto),
+ VRF_LOGNAME(vrf), info->vrf_id, api->afi,
+ api->safi);
info->route_sync[api->afi][api->safi] = true;
+ }
break;
case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
- LOG_GR("%s: Client %s route update pending for AFI %d, SAFI %d",
- __func__, zebra_route_string(client->proto), api->afi,
- api->safi);
- if (info)
+ if (!info) {
+ LOG_GR("%s: Client %s route update pending for AFI %d, SAFI %d",
+ __func__, zebra_route_string(client->proto),
+ api->afi, api->safi);
+ } else {
+ struct vrf *vrf = vrf_lookup_by_id(info->vrf_id);
+
+ LOG_GR("%s: Client %s vrf %s(%u) route update pending for AFI %d, SAFI %d",
+ __func__, zebra_route_string(client->proto),
+ VRF_LOGNAME(vrf), info->vrf_id, api->afi,
+ api->safi);
+
info->af_enabled[api->afi][api->safi] = true;
+ }
break;
}
}
@@ -434,12 +463,11 @@ void zread_client_capabilities(ZAPI_HANDLER_ARGS)
*/
static void zebra_gr_route_stale_delete_timer_expiry(struct thread *thread)
{
- struct client_gr_info *info;
+ struct client_gr_info *info = THREAD_ARG(thread);
int32_t cnt = 0;
struct zserv *client;
+ struct vrf *vrf = vrf_lookup_by_id(info->vrf_id);
- info = THREAD_ARG(thread);
- info->t_stale_removal = NULL;
client = (struct zserv *)info->stale_client_ptr;
/* Set the flag to indicate all stale route deletion */
@@ -450,8 +478,9 @@ static void zebra_gr_route_stale_delete_timer_expiry(struct thread *thread)
/* Restart the timer */
if (cnt > 0) {
- LOG_GR("%s: Client %s processed %d routes. Start timer again",
- __func__, zebra_route_string(client->proto), cnt);
+ LOG_GR("%s: Client %s vrf %s(%u) processed %d routes. Start timer again",
+ __func__, zebra_route_string(client->proto),
+ VRF_LOGNAME(vrf), info->vrf_id, cnt);
thread_add_timer(zrouter.master,
zebra_gr_route_stale_delete_timer_expiry, info,
@@ -459,8 +488,9 @@ static void zebra_gr_route_stale_delete_timer_expiry(struct thread *thread)
&info->t_stale_removal);
} else {
/* No routes to delete for the VRF */
- LOG_GR("%s: Client %s all stale routes processed", __func__,
- zebra_route_string(client->proto));
+ LOG_GR("%s: Client %s vrf %s(%u) all stale routes processed",
+ __func__, zebra_route_string(client->proto),
+ VRF_LOGNAME(vrf), info->vrf_id);
XFREE(MTYPE_ZEBRA_GR, info->current_prefix);
info->current_afi = 0;
@@ -513,7 +543,8 @@ static int32_t zebra_gr_delete_stale_route(struct client_gr_info *info,
s_client = info->stale_client_ptr;
if (s_client == NULL) {
- LOG_GR("%s: Stale client not present", __func__);
+ LOG_GR("%s: Stale client %s(%u) not present", __func__,
+ zvrf->vrf->name, zvrf->vrf->vrf_id);
return -1;
}
@@ -521,8 +552,8 @@ static int32_t zebra_gr_delete_stale_route(struct client_gr_info *info,
instance = s_client->instance;
curr_afi = info->current_afi;
- LOG_GR("%s: Client %s stale routes are being deleted", __func__,
- zebra_route_string(proto));
+ LOG_GR("%s: Client %s %s(%u) stale routes are being deleted", __func__,
+ zebra_route_string(proto), zvrf->vrf->name, zvrf->vrf->vrf_id);
/* Process routes for all AFI */
for (afi = curr_afi; afi < AFI_MAX; afi++) {
@@ -602,13 +633,13 @@ static int32_t zebra_gr_delete_stale_routes(struct client_gr_info *info)
/* Get the current VRF */
vrf = vrf_lookup_by_id(info->vrf_id);
if (vrf == NULL) {
- LOG_GR("%s: Invalid VRF %d", __func__, info->vrf_id);
+ LOG_GR("%s: Invalid VRF specified %u", __func__, info->vrf_id);
return -1;
}
zvrf = vrf->info;
if (zvrf == NULL) {
- LOG_GR("%s: Invalid VRF entry %d", __func__, info->vrf_id);
+ LOG_GR("%s: Invalid VRF entry %u", __func__, info->vrf_id);
return -1;
}
@@ -639,9 +670,12 @@ static void zebra_gr_process_client_stale_routes(struct zserv *client,
FOREACH_AFI_SAFI_NSF (afi, safi) {
if (info->af_enabled[afi][safi]) {
if (!info->route_sync[afi][safi]) {
- LOG_GR("%s: Client %s route update not completed for AFI %d, SAFI %d",
+ struct vrf *vrf = vrf_lookup_by_id(vrf_id);
+
+ LOG_GR("%s: Client %s vrf: %s(%u) route update not completed for AFI %d, SAFI %d",
__func__,
- zebra_route_string(client->proto), afi,
+ zebra_route_string(client->proto),
+ VRF_LOGNAME(vrf), info->vrf_id, afi,
safi);
return;
}
@@ -653,9 +687,11 @@ static void zebra_gr_process_client_stale_routes(struct zserv *client,
* Cancel the stale timer and process the routes
*/
if (info->t_stale_removal) {
- LOG_GR("%s: Client %s canceled stale delete timer vrf %d",
+ struct vrf *vrf = vrf_lookup_by_id(vrf_id);
+
+ LOG_GR("%s: Client %s canceled stale delete timer vrf %s(%d)",
__func__, zebra_route_string(client->proto),
- info->vrf_id);
+ VRF_LOGNAME(vrf), info->vrf_id);
THREAD_OFF(info->t_stale_removal);
thread_execute(zrouter.master,
zebra_gr_route_stale_delete_timer_expiry, info,
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index d25505839c..4c2d546126 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -3730,14 +3730,20 @@ void zebra_mpls_print_lsp(struct vty *vty, struct zebra_vrf *zvrf,
/* Lookup table. */
lsp_table = zvrf->lsp_table;
- if (!lsp_table)
+ if (!lsp_table) {
+ if (use_json)
+ vty_out(vty, "{}\n");
return;
+ }
/* If entry is not present, exit. */
tmp_ile.in_label = label;
lsp = hash_lookup(lsp_table, &tmp_ile);
- if (!lsp)
+ if (!lsp) {
+ if (use_json)
+ vty_out(vty, "{}\n");
return;
+ }
if (use_json) {
json = lsp_json(lsp);