summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfdd/bfd.c53
-rw-r--r--bfdd/bfd_packet.c2
-rw-r--r--bfdd/bfdd_nb_config.c101
-rw-r--r--bgpd/bgp_advertise.c2
-rw-r--r--bgpd/bgp_attr.c34
-rw-r--r--bgpd/bgp_attr.h43
-rw-r--r--bgpd/bgp_community_alias.c7
-rw-r--r--bgpd/bgp_conditional_adv.c10
-rw-r--r--bgpd/bgp_dump.c28
-rw-r--r--bgpd/bgp_evpn.c13
-rw-r--r--bgpd/bgp_evpn.h2
-rw-r--r--bgpd/bgp_label.c9
-rw-r--r--bgpd/bgp_memory.c1
-rw-r--r--bgpd/bgp_memory.h1
-rw-r--r--bgpd/bgp_mplsvpn.c9
-rw-r--r--bgpd/bgp_route.c10
-rw-r--r--bgpd/bgp_route.h1
-rw-r--r--bgpd/bgp_rpki.c77
-rw-r--r--bgpd/bgp_updgrp.c11
-rw-r--r--bgpd/bgp_updgrp.h4
-rw-r--r--bgpd/bgp_updgrp_adv.c11
-rw-r--r--bgpd/bgp_updgrp_packet.c44
-rw-r--r--doc/user/bfd.rst2
-rw-r--r--doc/user/ospfd.rst8
-rw-r--r--doc/user/pim.rst24
-rw-r--r--lib/stream.c12
-rw-r--r--lib/stream.h7
-rw-r--r--ospf6d/ospf6_asbr.c7
-rw-r--r--ospf6d/ospf6_asbr.h3
-rw-r--r--ospf6d/ospf6_top.c4
-rw-r--r--ospf6d/ospf6_top.h2
-rw-r--r--ospfd/ospf_asbr.c4
-rw-r--r--ospfd/ospf_asbr.h2
-rw-r--r--ospfd/ospf_interface.c2
-rw-r--r--ospfd/ospf_vty.c20
-rw-r--r--ospfd/ospfd.h2
-rw-r--r--tests/topotests/bgp_dont_capability_negotiate/__init__.py (renamed from tests/topotests/bgp_dont_capability_negogiate/__init__.py)0
-rw-r--r--tests/topotests/bgp_dont_capability_negotiate/r1/bgpd.conf (renamed from tests/topotests/bgp_dont_capability_negogiate/r1/bgpd.conf)0
-rw-r--r--tests/topotests/bgp_dont_capability_negotiate/r1/zebra.conf (renamed from tests/topotests/bgp_dont_capability_negogiate/r1/zebra.conf)0
-rw-r--r--tests/topotests/bgp_dont_capability_negotiate/r2/bgpd.conf (renamed from tests/topotests/bgp_dont_capability_negogiate/r2/bgpd.conf)0
-rw-r--r--tests/topotests/bgp_dont_capability_negotiate/r2/zebra.conf (renamed from tests/topotests/bgp_dont_capability_negogiate/r2/zebra.conf)0
-rw-r--r--tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py (renamed from tests/topotests/bgp_dont_capability_negogiate/test_bgp_dont_capability_negotiate.py)0
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r1/ospf6d.conf52
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r1/zebra.conf5
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r2/ospf6d.conf14
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r2/zebra.conf5
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r3/ospf6d.conf14
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r3/zebra.conf5
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r4/ospf6d.conf14
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r4/zebra.conf5
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r5/ospf6d.conf39
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r5/zebra.conf5
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r6/ospf6d.conf9
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r6/zebra.conf5
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r7/ospf6d.conf11
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r7/zebra.conf5
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r8/ospf6d.conf9
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r8/zebra.conf5
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r9/ospf6d.conf11
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r9/zebra.conf5
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/test_ospf6_ecmp_inter_area.py207
-rw-r--r--yang/frr-bfdd.yang23
-rw-r--r--zebra/rib.h2
-rw-r--r--zebra/zebra_rib.c53
-rw-r--r--zebra/zebra_vrf.c34
65 files changed, 771 insertions, 338 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index c9a327490c..fbe0436b50 100644
--- a/bfdd/bfd.c
+++ b/bfdd/bfd.c
@@ -51,8 +51,6 @@ static void bs_admin_down_handler(struct bfd_session *bs, int nstate);
static void bs_down_handler(struct bfd_session *bs, int nstate);
static void bs_init_handler(struct bfd_session *bs, int nstate);
static void bs_up_handler(struct bfd_session *bs, int nstate);
-static void bs_neighbour_admin_down_handler(struct bfd_session *bfd,
- uint8_t diag);
/**
* Remove BFD profile from all BFD sessions so we don't leave dangling
@@ -997,9 +995,18 @@ static void bs_down_handler(struct bfd_session *bs, int nstate)
*/
bs->ses_state = PTM_BFD_INIT;
- /* Answer peer with INIT immediately in passive mode. */
+ /*
+ * RFC 5880, Section 6.1.
+ * A system taking the Passive role MUST NOT begin
+ * sending BFD packets for a particular session until
+ * it has received a BFD packet for that session, and thus
+ * has learned the remote system's discriminator value.
+ *
+ * Now we can start transmission timer in passive mode.
+ */
if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_PASSIVE))
- ptm_bfd_snd(bs, 0);
+ ptm_bfd_xmt_TO(bs, 0);
+
break;
case PTM_BFD_INIT:
@@ -1026,7 +1033,7 @@ static void bs_init_handler(struct bfd_session *bs, int nstate)
* Remote peer doesn't want to talk, so lets make the
* connection down.
*/
- bs->ses_state = PTM_BFD_DOWN;
+ ptm_bfd_sess_dn(bs, BD_NEIGHBOR_DOWN);
break;
case PTM_BFD_DOWN:
@@ -1047,46 +1054,10 @@ static void bs_init_handler(struct bfd_session *bs, int nstate)
}
}
-static void bs_neighbour_admin_down_handler(struct bfd_session *bfd,
- uint8_t diag)
-{
- int old_state = bfd->ses_state;
-
- bfd->local_diag = diag;
- bfd->discrs.remote_discr = 0;
- bfd->ses_state = PTM_BFD_DOWN;
- bfd->polling = 0;
- bfd->demand_mode = 0;
- monotime(&bfd->downtime);
-
- /* Slow down the control packets, the connection is down. */
- bs_set_slow_timers(bfd);
-
- /* only signal clients when going from up->down state */
- if (old_state == PTM_BFD_UP)
- control_notify(bfd, PTM_BFD_ADM_DOWN);
-
- /* Stop echo packet transmission if they are active */
- if (CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE))
- ptm_bfd_echo_stop(bfd);
-
- if (old_state != bfd->ses_state) {
- bfd->stats.session_down++;
- if (bglobal.debug_peer_event)
- zlog_debug("state-change: [%s] %s -> %s reason:%s",
- bs_to_string(bfd), state_list[old_state].str,
- state_list[bfd->ses_state].str,
- get_diag_str(bfd->local_diag));
- }
-}
-
static void bs_up_handler(struct bfd_session *bs, int nstate)
{
switch (nstate) {
case PTM_BFD_ADM_DOWN:
- bs_neighbour_admin_down_handler(bs, BD_ADMIN_DOWN);
- break;
-
case PTM_BFD_DOWN:
/* Peer lost or asked to shutdown connection. */
ptm_bfd_sess_dn(bs, BD_NEIGHBOR_DOWN);
diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c
index 839f06329a..8eda78ebdb 100644
--- a/bfdd/bfd_packet.c
+++ b/bfdd/bfd_packet.c
@@ -692,7 +692,7 @@ int bfd_recv_cb(struct thread *t)
/* RFC 5880, Section 6.5: handle POLL/FINAL negotiation sequence. */
if (bfd->polling && BFD_GETFBIT(cp->flags)) {
- /* Disable pooling. */
+ /* Disable polling. */
bfd->polling = 0;
/* Handle poll finalization. */
diff --git a/bfdd/bfdd_nb_config.c b/bfdd/bfdd_nb_config.c
index 859e9475d0..c1a2ad7bb4 100644
--- a/bfdd/bfdd_nb_config.c
+++ b/bfdd/bfdd_nb_config.c
@@ -333,13 +333,9 @@ int bfdd_bfd_profile_desired_transmission_interval_modify(
struct nb_cb_modify_args *args)
{
struct bfd_profile *bp;
- uint32_t min_tx;
switch (args->event) {
case NB_EV_VALIDATE:
- min_tx = yang_dnode_get_uint32(args->dnode, NULL);
- if (min_tx < 10000 || min_tx > 60000000)
- return NB_ERR_VALIDATION;
break;
case NB_EV_PREPARE:
@@ -347,12 +343,8 @@ int bfdd_bfd_profile_desired_transmission_interval_modify(
break;
case NB_EV_APPLY:
- min_tx = yang_dnode_get_uint32(args->dnode, NULL);
bp = nb_running_get_entry(args->dnode, NULL, true);
- if (bp->min_tx == min_tx)
- return NB_OK;
-
- bp->min_tx = min_tx;
+ bp->min_tx = yang_dnode_get_uint32(args->dnode, NULL);
bfd_profile_update(bp);
break;
@@ -371,13 +363,9 @@ int bfdd_bfd_profile_required_receive_interval_modify(
struct nb_cb_modify_args *args)
{
struct bfd_profile *bp;
- uint32_t min_rx;
switch (args->event) {
case NB_EV_VALIDATE:
- min_rx = yang_dnode_get_uint32(args->dnode, NULL);
- if (min_rx < 10000 || min_rx > 60000000)
- return NB_ERR_VALIDATION;
break;
case NB_EV_PREPARE:
@@ -385,12 +373,8 @@ int bfdd_bfd_profile_required_receive_interval_modify(
break;
case NB_EV_APPLY:
- min_rx = yang_dnode_get_uint32(args->dnode, NULL);
bp = nb_running_get_entry(args->dnode, NULL, true);
- if (bp->min_rx == min_rx)
- return NB_OK;
-
- bp->min_rx = min_rx;
+ bp->min_rx = yang_dnode_get_uint32(args->dnode, NULL);
bfd_profile_update(bp);
break;
@@ -408,17 +392,12 @@ int bfdd_bfd_profile_required_receive_interval_modify(
int bfdd_bfd_profile_administrative_down_modify(struct nb_cb_modify_args *args)
{
struct bfd_profile *bp;
- bool shutdown;
if (args->event != NB_EV_APPLY)
return NB_OK;
- shutdown = yang_dnode_get_bool(args->dnode, NULL);
bp = nb_running_get_entry(args->dnode, NULL, true);
- if (bp->admin_shutdown == shutdown)
- return NB_OK;
-
- bp->admin_shutdown = shutdown;
+ bp->admin_shutdown = yang_dnode_get_bool(args->dnode, NULL);
bfd_profile_update(bp);
return NB_OK;
@@ -430,17 +409,12 @@ int bfdd_bfd_profile_administrative_down_modify(struct nb_cb_modify_args *args)
int bfdd_bfd_profile_passive_mode_modify(struct nb_cb_modify_args *args)
{
struct bfd_profile *bp;
- bool passive;
if (args->event != NB_EV_APPLY)
return NB_OK;
- passive = yang_dnode_get_bool(args->dnode, NULL);
bp = nb_running_get_entry(args->dnode, NULL, true);
- if (bp->passive == passive)
- return NB_OK;
-
- bp->passive = passive;
+ bp->passive = yang_dnode_get_bool(args->dnode, NULL);
bfd_profile_update(bp);
return NB_OK;
@@ -452,17 +426,12 @@ int bfdd_bfd_profile_passive_mode_modify(struct nb_cb_modify_args *args)
int bfdd_bfd_profile_minimum_ttl_modify(struct nb_cb_modify_args *args)
{
struct bfd_profile *bp;
- uint8_t minimum_ttl;
if (args->event != NB_EV_APPLY)
return NB_OK;
- minimum_ttl = yang_dnode_get_uint8(args->dnode, NULL);
bp = nb_running_get_entry(args->dnode, NULL, true);
- if (bp->minimum_ttl == minimum_ttl)
- return NB_OK;
-
- bp->minimum_ttl = minimum_ttl;
+ bp->minimum_ttl = yang_dnode_get_uint8(args->dnode, NULL);
bfd_profile_update(bp);
return NB_OK;
@@ -511,13 +480,9 @@ int bfdd_bfd_profile_desired_echo_transmission_interval_modify(
struct nb_cb_modify_args *args)
{
struct bfd_profile *bp;
- uint32_t min_tx;
switch (args->event) {
case NB_EV_VALIDATE:
- min_tx = yang_dnode_get_uint32(args->dnode, NULL);
- if (min_tx < 10000 || min_tx > 60000000)
- return NB_ERR_VALIDATION;
break;
case NB_EV_PREPARE:
@@ -525,12 +490,8 @@ int bfdd_bfd_profile_desired_echo_transmission_interval_modify(
break;
case NB_EV_APPLY:
- min_tx = yang_dnode_get_uint32(args->dnode, NULL);
bp = nb_running_get_entry(args->dnode, NULL, true);
- if (bp->min_echo_tx == min_tx)
- return NB_OK;
-
- bp->min_echo_tx = min_tx;
+ bp->min_echo_tx = yang_dnode_get_uint32(args->dnode, NULL);
bfd_profile_update(bp);
break;
@@ -549,15 +510,9 @@ int bfdd_bfd_profile_required_echo_receive_interval_modify(
struct nb_cb_modify_args *args)
{
struct bfd_profile *bp;
- uint32_t min_rx;
switch (args->event) {
case NB_EV_VALIDATE:
- min_rx = yang_dnode_get_uint32(args->dnode, NULL);
- if (min_rx == 0)
- return NB_OK;
- if (min_rx < 10000 || min_rx > 60000000)
- return NB_ERR_VALIDATION;
break;
case NB_EV_PREPARE:
@@ -565,12 +520,8 @@ int bfdd_bfd_profile_required_echo_receive_interval_modify(
break;
case NB_EV_APPLY:
- min_rx = yang_dnode_get_uint32(args->dnode, NULL);
bp = nb_running_get_entry(args->dnode, NULL, true);
- if (bp->min_echo_rx == min_rx)
- return NB_OK;
-
- bp->min_echo_rx = min_rx;
+ bp->min_echo_rx = yang_dnode_get_uint32(args->dnode, NULL);
bfd_profile_update(bp);
break;
@@ -677,13 +628,10 @@ int bfdd_bfd_sessions_single_hop_detection_multiplier_modify(
int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify(
struct nb_cb_modify_args *args)
{
- uint32_t tx_interval = yang_dnode_get_uint32(args->dnode, NULL);
struct bfd_session *bs;
switch (args->event) {
case NB_EV_VALIDATE:
- if (tx_interval < 10000 || tx_interval > 60000000)
- return NB_ERR_VALIDATION;
break;
case NB_EV_PREPARE:
@@ -692,10 +640,8 @@ int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify(
case NB_EV_APPLY:
bs = nb_running_get_entry(args->dnode, NULL, true);
- if (tx_interval == bs->timers.desired_min_tx)
- return NB_OK;
-
- bs->peer_profile.min_tx = tx_interval;
+ bs->peer_profile.min_tx =
+ yang_dnode_get_uint32(args->dnode, NULL);
bfd_session_apply(bs);
break;
@@ -713,13 +659,10 @@ int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify(
int bfdd_bfd_sessions_single_hop_required_receive_interval_modify(
struct nb_cb_modify_args *args)
{
- uint32_t rx_interval = yang_dnode_get_uint32(args->dnode, NULL);
struct bfd_session *bs;
switch (args->event) {
case NB_EV_VALIDATE:
- if (rx_interval < 10000 || rx_interval > 60000000)
- return NB_ERR_VALIDATION;
break;
case NB_EV_PREPARE:
@@ -728,10 +671,8 @@ int bfdd_bfd_sessions_single_hop_required_receive_interval_modify(
case NB_EV_APPLY:
bs = nb_running_get_entry(args->dnode, NULL, true);
- if (rx_interval == bs->timers.required_min_rx)
- return NB_OK;
-
- bs->peer_profile.min_rx = rx_interval;
+ bs->peer_profile.min_rx =
+ yang_dnode_get_uint32(args->dnode, NULL);
bfd_session_apply(bs);
break;
@@ -836,13 +777,10 @@ int bfdd_bfd_sessions_single_hop_echo_mode_modify(
int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify(
struct nb_cb_modify_args *args)
{
- uint32_t echo_interval = yang_dnode_get_uint32(args->dnode, NULL);
struct bfd_session *bs;
switch (args->event) {
case NB_EV_VALIDATE:
- if (echo_interval < 10000 || echo_interval > 60000000)
- return NB_ERR_VALIDATION;
break;
case NB_EV_PREPARE:
@@ -851,10 +789,8 @@ int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify(
case NB_EV_APPLY:
bs = nb_running_get_entry(args->dnode, NULL, true);
- if (echo_interval == bs->timers.desired_min_echo_tx)
- return NB_OK;
-
- bs->peer_profile.min_echo_tx = echo_interval;
+ bs->peer_profile.min_echo_tx =
+ yang_dnode_get_uint32(args->dnode, NULL);
bfd_session_apply(bs);
break;
@@ -873,15 +809,10 @@ int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify(
int bfdd_bfd_sessions_single_hop_required_echo_receive_interval_modify(
struct nb_cb_modify_args *args)
{
- uint32_t echo_interval = yang_dnode_get_uint32(args->dnode, NULL);
struct bfd_session *bs;
switch (args->event) {
case NB_EV_VALIDATE:
- if (echo_interval == 0)
- return NB_OK;
- if (echo_interval < 10000 || echo_interval > 60000000)
- return NB_ERR_VALIDATION;
break;
case NB_EV_PREPARE:
@@ -890,10 +821,8 @@ int bfdd_bfd_sessions_single_hop_required_echo_receive_interval_modify(
case NB_EV_APPLY:
bs = nb_running_get_entry(args->dnode, NULL, true);
- if (echo_interval == bs->timers.required_min_echo_rx)
- return NB_OK;
-
- bs->peer_profile.min_echo_rx = echo_interval;
+ bs->peer_profile.min_echo_rx =
+ yang_dnode_get_uint32(args->dnode, NULL);
bfd_session_apply(bs);
break;
diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c
index 9da97d110f..34776bd6db 100644
--- a/bgpd/bgp_advertise.c
+++ b/bgpd/bgp_advertise.c
@@ -151,7 +151,7 @@ bool bgp_adj_out_lookup(struct peer *peer, struct bgp_dest *dest,
struct peer_af *paf;
afi_t afi;
safi_t safi;
- int addpath_capable;
+ bool addpath_capable;
RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
SUBGRP_FOREACH_PEER (adj->subgroup, paf)
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index f2d9762581..5e773ca1f1 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -95,6 +95,16 @@ static const struct message attr_flag_str[] = {
static struct hash *cluster_hash;
+struct attr_extra *bgp_attr_extra_alloc(void)
+{
+ return XCALLOC(MTYPE_ATTR_EXTRA, sizeof(struct attr_extra));
+}
+
+void bgp_attr_extra_free(struct attr *attr)
+{
+ XFREE(MTYPE_ATTR_EXTRA, attr->extra);
+}
+
static void *cluster_hash_alloc(void *p)
{
const struct cluster_list *val = (const struct cluster_list *)p;
@@ -777,6 +787,7 @@ static void attrhash_init(void)
*/
static void attr_vfree(void *attr)
{
+ bgp_attr_extra_free(attr);
XFREE(MTYPE_ATTR, attr);
}
@@ -1183,6 +1194,7 @@ void bgp_attr_unintern(struct attr **pattr)
if (attr->refcnt == 0) {
ret = hash_release(attrhash, attr);
assert(ret != NULL);
+ bgp_attr_extra_free(attr);
XFREE(MTYPE_ATTR, attr);
*pattr = NULL;
}
@@ -3727,11 +3739,11 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
const struct prefix *p,
const struct prefix_rd *prd, mpls_label_t *label,
- uint32_t num_labels, int addpath_encode,
+ uint32_t num_labels, bool addpath_capable,
uint32_t addpath_tx_id, struct attr *attr)
{
if (safi == SAFI_MPLS_VPN) {
- if (addpath_encode)
+ if (addpath_capable)
stream_putl(s, addpath_tx_id);
/* Label, RD, Prefix write. */
stream_putc(s, p->prefixlen + 88);
@@ -3741,17 +3753,17 @@ void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
} else if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
/* EVPN prefix - contents depend on type */
bgp_evpn_encode_prefix(s, p, prd, label, num_labels, attr,
- addpath_encode, addpath_tx_id);
+ addpath_capable, addpath_tx_id);
} else if (safi == SAFI_LABELED_UNICAST) {
/* Prefix write with label. */
- stream_put_labeled_prefix(s, p, label, addpath_encode,
+ stream_put_labeled_prefix(s, p, label, addpath_capable,
addpath_tx_id);
} else if (safi == SAFI_FLOWSPEC) {
stream_putc(s, p->u.prefix_flowspec.prefixlen);
stream_put(s, (const void *)p->u.prefix_flowspec.ptr,
p->u.prefix_flowspec.prefixlen);
} else
- stream_put_prefix_addpath(s, p, addpath_encode, addpath_tx_id);
+ stream_put_prefix_addpath(s, p, addpath_capable, addpath_tx_id);
}
size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi,
@@ -3895,7 +3907,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
struct prefix *p, afi_t afi, safi_t safi,
struct peer *from, struct prefix_rd *prd,
mpls_label_t *label, uint32_t num_labels,
- int addpath_encode, uint32_t addpath_tx_id)
+ bool addpath_capable, uint32_t addpath_tx_id)
{
size_t cp;
size_t aspath_sizep;
@@ -3919,7 +3931,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi,
vecarr, attr);
bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label,
- num_labels, addpath_encode,
+ num_labels, addpath_capable,
addpath_tx_id, attr);
bgp_packet_mpattr_end(s, mpattrlen_pos);
}
@@ -4418,7 +4430,7 @@ void bgp_packet_mpunreach_prefix(struct stream *s, const struct prefix *p,
afi_t afi, safi_t safi,
const struct prefix_rd *prd,
mpls_label_t *label, uint32_t num_labels,
- int addpath_encode, uint32_t addpath_tx_id,
+ bool addpath_capable, uint32_t addpath_tx_id,
struct attr *attr)
{
uint8_t wlabel[3] = {0x80, 0x00, 0x00};
@@ -4429,7 +4441,7 @@ void bgp_packet_mpunreach_prefix(struct stream *s, const struct prefix *p,
}
bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label, num_labels,
- addpath_encode, addpath_tx_id, attr);
+ addpath_capable, addpath_tx_id, attr);
}
void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt)
@@ -4472,7 +4484,7 @@ void bgp_dump_routes_attr(struct stream *s, struct attr *attr,
unsigned long len;
size_t aspath_lenp;
struct aspath *aspath;
- int addpath_encode = 0;
+ bool addpath_capable = false;
uint32_t addpath_tx_id = 0;
/* Remember current pointer. */
@@ -4601,7 +4613,7 @@ void bgp_dump_routes_attr(struct stream *s, struct attr *attr,
stream_putc(s, 0);
/* Prefix */
- stream_put_prefix_addpath(s, prefix, addpath_encode,
+ stream_put_prefix_addpath(s, prefix, addpath_capable,
addpath_tx_id);
/* Set MP attribute length. */
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 3573c2ae03..6e9a4e7c3b 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -159,6 +159,11 @@ struct bgp_attr_srv6_l3vpn {
uint8_t transposition_offset;
};
+struct attr_extra {
+ /* Extended Communities attribute. */
+ struct ecommunity *ipv6_ecommunity;
+};
+
/* BGP core attribute structure. */
struct attr {
/* AS Path structure */
@@ -199,8 +204,8 @@ struct attr {
/* Extended Communities attribute. */
struct ecommunity *ecommunity;
- /* Extended Communities attribute. */
- struct ecommunity *ipv6_ecommunity;
+ /* Extra attributes, non IPv4/IPv6 AFI related */
+ struct attr_extra *extra;
/* Large Communities attribute. */
struct lcommunity *lcommunity;
@@ -400,12 +405,14 @@ extern struct attr *bgp_attr_aggregate_intern(
struct community *community, struct ecommunity *ecommunity,
struct lcommunity *lcommunity, struct bgp_aggregate *aggregate,
uint8_t atomic_aggregate, const struct prefix *p);
-extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *,
- struct stream *, struct attr *,
+extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
+ struct stream *s, struct attr *attr,
struct bpacket_attr_vec_arr *vecarr,
- struct prefix *, afi_t, safi_t,
- struct peer *, struct prefix_rd *,
- mpls_label_t *, uint32_t, int, uint32_t);
+ struct prefix *p, afi_t afi, safi_t safi,
+ struct peer *from, struct prefix_rd *prd,
+ mpls_label_t *label, uint32_t num_labels,
+ bool addpath_capable,
+ uint32_t addpath_tx_id);
extern void bgp_dump_routes_attr(struct stream *s, struct attr *attr,
const struct prefix *p);
extern bool attrhash_cmp(const void *arg1, const void *arg2);
@@ -456,8 +463,8 @@ extern void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
const struct prefix *p,
const struct prefix_rd *prd,
mpls_label_t *label, uint32_t num_labels,
- int addpath_encode, uint32_t addpath_tx_id,
- struct attr *);
+ bool addpath_capable,
+ uint32_t addpath_tx_id, struct attr *);
extern size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi,
const struct prefix *p);
extern void bgp_packet_mpattr_end(struct stream *s, size_t sizep);
@@ -467,11 +474,13 @@ extern size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi,
extern void bgp_packet_mpunreach_prefix(
struct stream *s, const struct prefix *p, afi_t afi, safi_t safi,
const struct prefix_rd *prd, mpls_label_t *label, uint32_t num_labels,
- int addpath_encode, uint32_t addpath_tx_id, struct attr *attr);
+ bool addpath_capable, uint32_t addpath_tx_id, struct attr *attr);
extern void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt);
extern bgp_attr_parse_ret_t bgp_attr_nexthop_valid(struct peer *peer,
struct attr *attr);
+extern struct attr_extra *bgp_attr_extra_alloc(void);
+extern void bgp_attr_extra_free(struct attr *attr);
static inline int bgp_rmap_nhop_changed(uint32_t out_rmap_flags,
uint32_t in_rmap_flags)
@@ -508,13 +517,23 @@ static inline void bgp_attr_set_pmsi_tnl_type(struct attr *attr,
static inline struct ecommunity *
bgp_attr_get_ipv6_ecommunity(const struct attr *attr)
{
- return attr->ipv6_ecommunity;
+ if (attr->extra)
+ return attr->extra->ipv6_ecommunity;
+
+ return NULL;
}
static inline void bgp_attr_set_ipv6_ecommunity(struct attr *attr,
struct ecommunity *ipv6_ecomm)
{
- attr->ipv6_ecommunity = ipv6_ecomm;
+ if (!attr->extra) {
+ if (!ipv6_ecomm)
+ return;
+
+ attr->extra = bgp_attr_extra_alloc();
+ }
+
+ attr->extra->ipv6_ecommunity = ipv6_ecomm;
}
static inline struct transit *bgp_attr_get_transit(const struct attr *attr)
diff --git a/bgpd/bgp_community_alias.c b/bgpd/bgp_community_alias.c
index 793f3ac9ac..2c86efb5a0 100644
--- a/bgpd/bgp_community_alias.c
+++ b/bgpd/bgp_community_alias.c
@@ -40,9 +40,7 @@ static bool bgp_ca_community_hash_cmp(const void *p1, const void *p2)
const struct community_alias *ca1 = p1;
const struct community_alias *ca2 = p2;
- return (strncmp(ca1->community, ca2->community,
- sizeof(struct community_alias))
- == 0);
+ return (strcmp(ca1->community, ca2->community) == 0);
}
static unsigned int bgp_ca_alias_hash_key(const void *p)
@@ -57,8 +55,7 @@ static bool bgp_ca_alias_hash_cmp(const void *p1, const void *p2)
const struct community_alias *ca1 = p1;
const struct community_alias *ca2 = p2;
- return (strncmp(ca1->alias, ca2->alias, sizeof(struct community_alias))
- == 0);
+ return (strcmp(ca1->alias, ca2->alias) == 0);
}
static void *bgp_community_alias_alloc(void *p)
diff --git a/bgpd/bgp_conditional_adv.c b/bgpd/bgp_conditional_adv.c
index 8e2f6ff501..c0dd3d6f81 100644
--- a/bgpd/bgp_conditional_adv.c
+++ b/bgpd/bgp_conditional_adv.c
@@ -75,7 +75,7 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi,
struct route_map *rmap,
enum update_type update_type)
{
- int addpath_capable;
+ bool addpath_capable;
struct bgp_dest *dest;
struct bgp_path_info *pi;
struct bgp_path_info path;
@@ -124,12 +124,8 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi,
if (ret != RMAP_PERMITMATCH)
continue;
- if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
- || (addpath_capable
- && bgp_addpath_tx_path(
- peer->addpath_type[afi][safi],
- pi))) {
-
+ if (bgp_check_selected(pi, peer, addpath_capable, afi,
+ safi)) {
/* Skip route-map checks in
* subgroup_announce_check while executing from
* the conditional advertise scanner process.
diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c
index 2f0b87aa3a..9ddfe7bb5f 100644
--- a/bgpd/bgp_dump.c
+++ b/bgpd/bgp_dump.c
@@ -298,14 +298,6 @@ static void bgp_dump_routes_index_table(struct bgp *bgp)
fflush(bgp_dump_routes.fp);
}
-static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
-{
-
- return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
- && CHECK_FLAG(peer->af_cap[afi][safi],
- PEER_CAP_ADDPATH_AF_TX_RCV));
-}
-
static struct bgp_path_info *
bgp_dump_route_node_record(int afi, struct bgp_dest *dest,
struct bgp_path_info *path, unsigned int seq)
@@ -313,16 +305,16 @@ bgp_dump_route_node_record(int afi, struct bgp_dest *dest,
struct stream *obuf;
size_t sizep;
size_t endp;
- int addpath_encoded;
+ bool addpath_capable;
const struct prefix *p = bgp_dest_get_prefix(dest);
obuf = bgp_dump_obuf;
stream_reset(obuf);
- addpath_encoded = bgp_addpath_encode_rx(path->peer, afi, SAFI_UNICAST);
+ addpath_capable = bgp_addpath_encode_rx(path->peer, afi, SAFI_UNICAST);
/* MRT header */
- if (afi == AFI_IP && addpath_encoded)
+ if (afi == AFI_IP && addpath_capable)
bgp_dump_header(obuf, MSG_TABLE_DUMP_V2,
TABLE_DUMP_V2_RIB_IPV4_UNICAST_ADDPATH,
BGP_DUMP_ROUTES);
@@ -330,7 +322,7 @@ bgp_dump_route_node_record(int afi, struct bgp_dest *dest,
bgp_dump_header(obuf, MSG_TABLE_DUMP_V2,
TABLE_DUMP_V2_RIB_IPV4_UNICAST,
BGP_DUMP_ROUTES);
- else if (afi == AFI_IP6 && addpath_encoded)
+ else if (afi == AFI_IP6 && addpath_capable)
bgp_dump_header(obuf, MSG_TABLE_DUMP_V2,
TABLE_DUMP_V2_RIB_IPV6_UNICAST_ADDPATH,
BGP_DUMP_ROUTES);
@@ -378,7 +370,7 @@ bgp_dump_route_node_record(int afi, struct bgp_dest *dest,
stream_putl(obuf, time(NULL) - (bgp_clock() - path->uptime));
/*Path Identifier*/
- if (addpath_encoded) {
+ if (addpath_capable) {
stream_putl(obuf, path->addpath_rx_id);
}
@@ -549,15 +541,15 @@ static void bgp_dump_packet_func(struct bgp_dump *bgp_dump, struct peer *peer,
struct stream *packet)
{
struct stream *obuf;
- int addpath_encoded = 0;
+ bool addpath_capable = false;
/* If dump file pointer is disabled return immediately. */
if (bgp_dump->fp == NULL)
return;
if (peer->su.sa.sa_family == AF_INET) {
- addpath_encoded =
+ addpath_capable =
bgp_addpath_encode_rx(peer, AFI_IP, SAFI_UNICAST);
} else if (peer->su.sa.sa_family == AF_INET6) {
- addpath_encoded =
+ addpath_capable =
bgp_addpath_encode_rx(peer, AFI_IP6, SAFI_UNICAST);
}
@@ -566,13 +558,13 @@ static void bgp_dump_packet_func(struct bgp_dump *bgp_dump, struct peer *peer,
stream_reset(obuf);
/* Dump header and common part. */
- if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV) && addpath_encoded) {
+ if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV) && addpath_capable) {
bgp_dump_header(obuf, MSG_PROTOCOL_BGP4MP,
BGP4MP_MESSAGE_AS4_ADDPATH, bgp_dump->type);
} else if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)) {
bgp_dump_header(obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE_AS4,
bgp_dump->type);
- } else if (addpath_encoded) {
+ } else if (addpath_capable) {
bgp_dump_header(obuf, MSG_PROTOCOL_BGP4MP,
BGP4MP_MESSAGE_ADDPATH, bgp_dump->type);
} else {
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 8572ebabc7..de246b07ee 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -4903,12 +4903,12 @@ void bgp_evpn_route2json(const struct prefix_evpn *p, json_object *json)
void bgp_evpn_encode_prefix(struct stream *s, const struct prefix *p,
const struct prefix_rd *prd, mpls_label_t *label,
uint32_t num_labels, struct attr *attr,
- int addpath_encode, uint32_t addpath_tx_id)
+ bool addpath_capable, uint32_t addpath_tx_id)
{
struct prefix_evpn *evp = (struct prefix_evpn *)p;
int len, ipa_len = 0;
- if (addpath_encode)
+ if (addpath_capable)
stream_putl(s, addpath_tx_id);
/* Route type */
@@ -4990,7 +4990,7 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
afi_t afi;
safi_t safi;
uint32_t addpath_id;
- int addpath_encoded;
+ bool addpath_capable;
int psize = 0;
uint8_t rtype;
struct prefix p;
@@ -5002,17 +5002,14 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
safi = packet->safi;
addpath_id = 0;
- addpath_encoded =
- (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
- && CHECK_FLAG(peer->af_cap[afi][safi],
- PEER_CAP_ADDPATH_AF_TX_RCV));
+ addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
for (; pnt < lim; pnt += psize) {
/* Clear prefix structure. */
memset(&p, 0, sizeof(struct prefix));
/* Deal with path-id if AddPath is supported. */
- if (addpath_encoded) {
+ if (addpath_capable) {
/* When packet overflow occurs return immediately. */
if (pnt + BGP_ADDPATH_ID_LEN > lim)
return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h
index eec746e3be..67659ea198 100644
--- a/bgpd/bgp_evpn.h
+++ b/bgpd/bgp_evpn.h
@@ -183,7 +183,7 @@ extern void bgp_evpn_route2json(const struct prefix_evpn *p, json_object *json);
extern void bgp_evpn_encode_prefix(struct stream *s, const struct prefix *p,
const struct prefix_rd *prd,
mpls_label_t *label, uint32_t num_labels,
- struct attr *attr, int addpath_encode,
+ struct attr *attr, bool addpath_capable,
uint32_t addpath_tx_id);
extern int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
struct bgp_nlri *packet, int withdraw);
diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c
index c101cf917b..4a20f2c090 100644
--- a/bgpd/bgp_label.c
+++ b/bgpd/bgp_label.c
@@ -335,7 +335,7 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
int prefixlen;
afi_t afi;
safi_t safi;
- int addpath_encoded;
+ bool addpath_capable;
uint32_t addpath_id;
mpls_label_t label = MPLS_INVALID_LABEL;
uint8_t llen;
@@ -346,16 +346,13 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
safi = packet->safi;
addpath_id = 0;
- addpath_encoded =
- (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
- && CHECK_FLAG(peer->af_cap[afi][safi],
- PEER_CAP_ADDPATH_AF_TX_RCV));
+ addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
for (; pnt < lim; pnt += psize) {
/* Clear prefix structure. */
memset(&p, 0, sizeof(struct prefix));
- if (addpath_encoded) {
+ if (addpath_capable) {
/* When packet overflow occurs return immediately. */
if (pnt + BGP_ADDPATH_ID_LEN > lim)
diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c
index ffb1ec162b..7fbadab694 100644
--- a/bgpd/bgp_memory.c
+++ b/bgpd/bgp_memory.c
@@ -43,6 +43,7 @@ DEFINE_MTYPE(BGPD, BGP_UPDGRP, "BGP update group");
DEFINE_MTYPE(BGPD, BGP_UPD_SUBGRP, "BGP update subgroup");
DEFINE_MTYPE(BGPD, BGP_PACKET, "BGP packet");
DEFINE_MTYPE(BGPD, ATTR, "BGP attribute");
+DEFINE_MTYPE(BGPD, ATTR_EXTRA, "BGP extra attribute");
DEFINE_MTYPE(BGPD, AS_PATH, "BGP aspath");
DEFINE_MTYPE(BGPD, AS_SEG, "BGP aspath seg");
DEFINE_MTYPE(BGPD, AS_SEG_DATA, "BGP aspath segment data");
diff --git a/bgpd/bgp_memory.h b/bgpd/bgp_memory.h
index 63e7b40ef7..ffab8a1bcc 100644
--- a/bgpd/bgp_memory.h
+++ b/bgpd/bgp_memory.h
@@ -39,6 +39,7 @@ DECLARE_MTYPE(BGP_UPDGRP);
DECLARE_MTYPE(BGP_UPD_SUBGRP);
DECLARE_MTYPE(BGP_PACKET);
DECLARE_MTYPE(ATTR);
+DECLARE_MTYPE(ATTR_EXTRA);
DECLARE_MTYPE(AS_PATH);
DECLARE_MTYPE(AS_SEG);
DECLARE_MTYPE(AS_SEG_DATA);
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index e24c1ab764..ce95b355ad 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -112,7 +112,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr,
mpls_label_t label = {0};
afi_t afi;
safi_t safi;
- int addpath_encoded;
+ bool addpath_capable;
uint32_t addpath_id;
int ret = 0;
@@ -126,17 +126,14 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr,
safi = packet->safi;
addpath_id = 0;
- addpath_encoded =
- (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
- && CHECK_FLAG(peer->af_cap[afi][safi],
- PEER_CAP_ADDPATH_AF_TX_RCV));
+ addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
#define VPN_PREFIXLEN_MIN_BYTES (3 + 8) /* label + RD */
while (STREAM_READABLE(data) > 0) {
/* Clear prefix structure. */
memset(&p, 0, sizeof(struct prefix));
- if (addpath_encoded) {
+ if (addpath_capable) {
STREAM_GET(&addpath_id, data, BGP_ADDPATH_ID_LEN);
addpath_id = ntohl(addpath_id);
}
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index b795fbbafa..fa83a457bf 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -5599,7 +5599,7 @@ void bgp_reset(void)
prefix_list_reset();
}
-static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
+bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
{
return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
&& CHECK_FLAG(peer->af_cap[afi][safi],
@@ -5618,7 +5618,7 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
int ret;
afi_t afi;
safi_t safi;
- int addpath_encoded;
+ bool addpath_capable;
uint32_t addpath_id;
pnt = packet->nlri;
@@ -5626,7 +5626,7 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
afi = packet->afi;
safi = packet->safi;
addpath_id = 0;
- addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
+ addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
/* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
syntactic validity. If the field is syntactically incorrect,
@@ -5635,7 +5635,7 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
/* Clear prefix structure. */
memset(&p, 0, sizeof(struct prefix));
- if (addpath_encoded) {
+ if (addpath_capable) {
/* When packet overflow occurs return immediately. */
if (pnt + BGP_ADDPATH_ID_LEN >= lim)
@@ -9841,7 +9841,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
int first = 0;
struct listnode *node, *nnode;
struct peer *peer;
- int addpath_capable;
+ bool addpath_capable;
int has_adj;
unsigned int first_as;
bool nexthop_self =
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 741690a028..317995594a 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -838,4 +838,5 @@ extern void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
extern void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr);
const char *
bgp_path_selection_reason2str(enum bgp_path_selection_reason reason);
+extern bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi);
#endif /* _QUAGGA_BGP_ROUTE_H */
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index 6a89a7195c..e5027359e7 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -63,6 +63,8 @@
#include "bgpd/bgp_rpki_clippy.c"
#endif
+static struct thread *t_rpki;
+
DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_CACHE, "BGP RPKI Cache server");
DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_CACHE_GROUP, "BGP RPKI Cache server group");
@@ -361,14 +363,13 @@ static int bgpd_sync_callback(struct thread *thread)
struct listnode *node;
struct prefix *prefix;
struct pfx_record rec;
+ int retval;
+ int socket = THREAD_FD(thread);
- thread_add_read(bm->master, bgpd_sync_callback, NULL,
- rpki_sync_socket_bgpd, NULL);
+ thread_add_read(bm->master, bgpd_sync_callback, NULL, socket, &t_rpki);
if (atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst)) {
- while (read(rpki_sync_socket_bgpd, &rec,
- sizeof(struct pfx_record))
- != -1)
+ while (read(socket, &rec, sizeof(rec) != -1))
;
atomic_store_explicit(&rtr_update_overflow, 0,
@@ -377,12 +378,20 @@ static int bgpd_sync_callback(struct thread *thread)
return 0;
}
- int retval =
- read(rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record));
- if (retval != sizeof(struct pfx_record)) {
- RPKI_DEBUG("Could not read from rpki_sync_socket_bgpd");
+ retval = read(socket, &rec, sizeof(rec));
+ if (retval != sizeof(rec)) {
+ RPKI_DEBUG("Could not read from socket");
return retval;
}
+
+ /* RTR-Server crashed/terminated, let's handle and switch
+ * to the second available RTR-Server according to preference.
+ */
+ if (rec.socket && rec.socket->state == RTR_ERROR_FATAL) {
+ reset(true);
+ return 0;
+ }
+
prefix = pfx_record_to_prefix(&rec);
afi_t afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6;
@@ -441,29 +450,53 @@ static void revalidate_all_routes(void)
{
struct bgp *bgp;
struct listnode *node;
+ afi_t afi;
+ safi_t safi;
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
struct peer *peer;
struct listnode *peer_listnode;
for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) {
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (!peer->afc_nego[afi][safi])
+ continue;
- for (size_t i = 0; i < 2; i++) {
- safi_t safi;
- afi_t afi = (i == 0) ? AFI_IP : AFI_IP6;
-
- for (safi = SAFI_UNICAST; safi < SAFI_MAX;
- safi++) {
- if (!peer->bgp->rib[afi][safi])
- continue;
+ if (!peer->bgp->rib[afi][safi])
+ continue;
- bgp_soft_reconfig_in(peer, afi, safi);
- }
+ bgp_soft_reconfig_in(peer, afi, safi);
}
}
}
}
+static void rpki_connection_status_cb(const struct rtr_mgr_group *group
+ __attribute__((unused)),
+ enum rtr_mgr_status status,
+ const struct rtr_socket *socket
+ __attribute__((unused)),
+ void *data __attribute__((unused)))
+{
+ struct pfx_record rec = {0};
+ int retval;
+
+ if (rtr_is_stopping ||
+ atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst))
+ return;
+
+ if (status == RTR_MGR_ERROR)
+ rec.socket = socket;
+
+ retval = write(rpki_sync_socket_rtr, &rec, sizeof(rec));
+ if (retval == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
+ atomic_store_explicit(&rtr_update_overflow, 1,
+ memory_order_seq_cst);
+
+ else if (retval != sizeof(rec))
+ RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
+}
+
static void rpki_update_cb_sync_rtr(struct pfx_table *p __attribute__((unused)),
const struct pfx_record rec,
const bool added __attribute__((unused)))
@@ -505,9 +538,8 @@ static void rpki_init_sync_socket(void)
goto err;
}
-
thread_add_read(bm->master, bgpd_sync_callback, NULL,
- rpki_sync_socket_bgpd, NULL);
+ rpki_sync_socket_bgpd, &t_rpki);
return;
@@ -575,7 +607,8 @@ static int start(void)
RPKI_DEBUG("Polling period: %d", polling_period);
ret = rtr_mgr_init(&rtr_config, groups, groups_len, polling_period,
expire_interval, retry_interval,
- rpki_update_cb_sync_rtr, NULL, NULL, NULL);
+ rpki_update_cb_sync_rtr, NULL,
+ rpki_connection_status_cb, NULL);
if (ret == RTR_ERROR) {
RPKI_DEBUG("Init rtr_mgr failed.");
return ERROR;
diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c
index a65be3d128..bfcb4810d1 100644
--- a/bgpd/bgp_updgrp.c
+++ b/bgpd/bgp_updgrp.c
@@ -49,6 +49,7 @@
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_errors.h"
#include "bgpd/bgp_fsm.h"
+#include "bgpd/bgp_addpath.h"
#include "bgpd/bgp_advertise.h"
#include "bgpd/bgp_packet.h"
#include "bgpd/bgp_updgrp.h"
@@ -1925,9 +1926,17 @@ int update_group_clear_update_dbg(struct update_group *updgrp, void *arg)
}
/* Return true if we should addpath encode NLRI to this peer */
-int bgp_addpath_encode_tx(struct peer *peer, afi_t afi, safi_t safi)
+bool bgp_addpath_encode_tx(struct peer *peer, afi_t afi, safi_t safi)
{
return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV)
&& CHECK_FLAG(peer->af_cap[afi][safi],
PEER_CAP_ADDPATH_AF_RX_RCV));
}
+
+bool bgp_check_selected(struct bgp_path_info *bpi, struct peer *peer,
+ bool addpath_capable, afi_t afi, safi_t safi)
+{
+ return (CHECK_FLAG(bpi->flags, BGP_PATH_SELECTED) ||
+ (addpath_capable &&
+ bgp_addpath_tx_path(peer->addpath_type[afi][safi], bpi)));
+}
diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h
index 0da6dfd19d..5a9bebf8fe 100644
--- a/bgpd/bgp_updgrp.h
+++ b/bgpd/bgp_updgrp.h
@@ -461,7 +461,9 @@ extern int update_group_clear_update_dbg(struct update_group *updgrp,
void *arg);
extern void update_bgp_group_free(struct bgp *bgp);
-extern int bgp_addpath_encode_tx(struct peer *peer, afi_t afi, safi_t safi);
+extern bool bgp_addpath_encode_tx(struct peer *peer, afi_t afi, safi_t safi);
+extern bool bgp_check_selected(struct bgp_path_info *bpi, struct peer *peer,
+ bool addpath_capable, afi_t afi, safi_t safi);
/*
* Inline functions
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index 9faf318716..2110dcb8bc 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -145,7 +145,7 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)
safi_t safi;
struct peer *peer;
struct bgp_adj_out *adj, *adj_next;
- int addpath_capable;
+ bool addpath_capable;
afi = UPDGRP_AFI(updgrp);
safi = UPDGRP_SAFI(updgrp);
@@ -655,7 +655,7 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
struct peer *peer;
afi_t afi;
safi_t safi;
- int addpath_capable;
+ bool addpath_capable;
struct bgp *bgp;
bool advertise;
@@ -687,11 +687,8 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
for (ri = bgp_dest_get_bgp_path_info(dest); ri; ri = ri->next)
- if (CHECK_FLAG(ri->flags, BGP_PATH_SELECTED)
- || (addpath_capable
- && bgp_addpath_tx_path(
- peer->addpath_type[afi][safi],
- ri))) {
+ if (bgp_check_selected(ri, peer, addpath_capable, afi,
+ safi)) {
if (subgroup_announce_check(dest, ri, subgrp,
dest_p, &attr,
false)) {
diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c
index 341c7dd78b..cf24e1d689 100644
--- a/bgpd/bgp_updgrp_packet.c
+++ b/bgpd/bgp_updgrp_packet.c
@@ -672,7 +672,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
char send_attr_str[BUFSIZ];
int send_attr_printed = 0;
int num_pfx = 0;
- int addpath_encode = 0;
+ bool addpath_capable = false;
int addpath_overhead = 0;
uint32_t addpath_tx_id = 0;
struct prefix_rd *prd = NULL;
@@ -695,8 +695,8 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
bpacket_attr_vec_arr_reset(&vecarr);
- addpath_encode = bgp_addpath_encode_tx(peer, afi, safi);
- addpath_overhead = addpath_encode ? BGP_ADDPATH_ID_LEN : 0;
+ addpath_capable = bgp_addpath_encode_tx(peer, afi, safi);
+ addpath_overhead = addpath_capable ? BGP_ADDPATH_ID_LEN : 0;
adv = bgp_adv_fifo_first(&subgrp->sync->update);
while (adv) {
@@ -788,7 +788,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
if ((afi == AFI_IP && safi == SAFI_UNICAST)
&& !peer_cap_enhe(peer, afi, safi))
- stream_put_prefix_addpath(s, dest_p, addpath_encode,
+ stream_put_prefix_addpath(s, dest_p, addpath_capable,
addpath_tx_id);
else {
/* Encode the prefix in MP_REACH_NLRI attribute */
@@ -813,7 +813,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
bgp_packet_mpattr_prefix(snlri, afi, safi, dest_p, prd,
label_pnt, num_labels,
- addpath_encode, addpath_tx_id,
+ addpath_capable, addpath_tx_id,
adv->baa->attr);
}
@@ -846,7 +846,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
bgp_debug_rdpfxpath2str(afi, safi, prd, dest_p,
label_pnt, num_labels,
- addpath_encode, addpath_tx_id,
+ addpath_capable, addpath_tx_id,
&adv->baa->attr->evpn_overlay,
pfx_buf, sizeof(pfx_buf));
zlog_debug("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s",
@@ -924,7 +924,7 @@ struct bpacket *subgroup_withdraw_packet(struct update_subgroup *subgrp)
int space_remaining = 0;
int space_needed = 0;
int num_pfx = 0;
- int addpath_encode = 0;
+ bool addpath_capable = false;
int addpath_overhead = 0;
uint32_t addpath_tx_id = 0;
const struct prefix_rd *prd = NULL;
@@ -941,8 +941,8 @@ struct bpacket *subgroup_withdraw_packet(struct update_subgroup *subgrp)
safi = SUBGRP_SAFI(subgrp);
s = subgrp->work;
stream_reset(s);
- addpath_encode = bgp_addpath_encode_tx(peer, afi, safi);
- addpath_overhead = addpath_encode ? BGP_ADDPATH_ID_LEN : 0;
+ addpath_capable = bgp_addpath_encode_tx(peer, afi, safi);
+ addpath_overhead = addpath_capable ? BGP_ADDPATH_ID_LEN : 0;
while ((adv = bgp_adv_fifo_first(&subgrp->sync->withdraw)) != NULL) {
const struct prefix *dest_p;
@@ -970,7 +970,7 @@ struct bpacket *subgroup_withdraw_packet(struct update_subgroup *subgrp)
if (afi == AFI_IP && safi == SAFI_UNICAST
&& !peer_cap_enhe(peer, afi, safi))
- stream_put_prefix_addpath(s, dest_p, addpath_encode,
+ stream_put_prefix_addpath(s, dest_p, addpath_capable,
addpath_tx_id);
else {
if (dest->pdest)
@@ -1005,7 +1005,7 @@ struct bpacket *subgroup_withdraw_packet(struct update_subgroup *subgrp)
}
bgp_packet_mpunreach_prefix(s, dest_p, afi, safi, prd,
- NULL, 0, addpath_encode,
+ NULL, 0, addpath_capable,
addpath_tx_id, NULL);
}
@@ -1015,7 +1015,7 @@ struct bpacket *subgroup_withdraw_packet(struct update_subgroup *subgrp)
char pfx_buf[BGP_PRD_PATH_STRLEN];
bgp_debug_rdpfxpath2str(afi, safi, prd, dest_p, NULL, 0,
- addpath_encode, addpath_tx_id,
+ addpath_capable, addpath_tx_id,
NULL, pfx_buf, sizeof(pfx_buf));
zlog_debug("u%" PRIu64 ":s%" PRIu64" send UPDATE %s -- unreachable",
subgrp->update_group->id, subgrp->id,
@@ -1068,7 +1068,7 @@ void subgroup_default_update_packet(struct update_subgroup *subgrp,
afi_t afi;
safi_t safi;
struct bpacket_attr_vec_arr vecarr;
- int addpath_encode = 0;
+ bool addpath_capable = false;
if (DISABLE_BGP_ANNOUNCE)
return;
@@ -1080,7 +1080,7 @@ void subgroup_default_update_packet(struct update_subgroup *subgrp,
afi = SUBGRP_AFI(subgrp);
safi = SUBGRP_SAFI(subgrp);
bpacket_attr_vec_arr_reset(&vecarr);
- addpath_encode = bgp_addpath_encode_tx(peer, afi, safi);
+ addpath_capable = bgp_addpath_encode_tx(peer, afi, safi);
memset(&p, 0, sizeof(p));
p.family = afi2family(afi);
@@ -1100,7 +1100,7 @@ void subgroup_default_update_packet(struct update_subgroup *subgrp,
bgp_dump_attr(attr, attrstr, sizeof(attrstr));
- if (addpath_encode)
+ if (addpath_capable)
snprintf(tx_id_buf, sizeof(tx_id_buf),
" with addpath ID %u",
BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
@@ -1125,7 +1125,7 @@ void subgroup_default_update_packet(struct update_subgroup *subgrp,
stream_putw(s, 0);
total_attr_len = bgp_packet_attribute(
NULL, peer, s, attr, &vecarr, &p, afi, safi, from, NULL, NULL,
- 0, addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
+ 0, addpath_capable, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
/* Set Total Path Attribute Length. */
stream_putw_at(s, pos, total_attr_len);
@@ -1134,7 +1134,7 @@ void subgroup_default_update_packet(struct update_subgroup *subgrp,
if (p.family == AF_INET && safi == SAFI_UNICAST
&& !peer_cap_enhe(peer, afi, safi))
stream_put_prefix_addpath(
- s, &p, addpath_encode,
+ s, &p, addpath_capable,
BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
/* Set size. */
@@ -1158,7 +1158,7 @@ void subgroup_default_withdraw_packet(struct update_subgroup *subgrp)
size_t mplen_pos = 0;
afi_t afi;
safi_t safi;
- int addpath_encode = 0;
+ bool addpath_capable = false;
if (DISABLE_BGP_ANNOUNCE)
return;
@@ -1166,7 +1166,7 @@ void subgroup_default_withdraw_packet(struct update_subgroup *subgrp)
peer = SUBGRP_PEER(subgrp);
afi = SUBGRP_AFI(subgrp);
safi = SUBGRP_SAFI(subgrp);
- addpath_encode = bgp_addpath_encode_tx(peer, afi, safi);
+ addpath_capable = bgp_addpath_encode_tx(peer, afi, safi);
memset(&p, 0, sizeof(p));
p.family = afi2family(afi);
@@ -1180,7 +1180,7 @@ void subgroup_default_withdraw_packet(struct update_subgroup *subgrp)
* ============================ 29 */
char tx_id_buf[30];
- if (addpath_encode)
+ if (addpath_capable)
snprintf(tx_id_buf, sizeof(tx_id_buf),
" with addpath ID %u",
BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
@@ -1204,7 +1204,7 @@ void subgroup_default_withdraw_packet(struct update_subgroup *subgrp)
if (p.family == AF_INET && safi == SAFI_UNICAST
&& !peer_cap_enhe(peer, afi, safi)) {
stream_put_prefix_addpath(
- s, &p, addpath_encode,
+ s, &p, addpath_capable,
BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
unfeasible_len = stream_get_endp(s) - cp - 2;
@@ -1220,7 +1220,7 @@ void subgroup_default_withdraw_packet(struct update_subgroup *subgrp)
mp_start = stream_get_endp(s);
mplen_pos = bgp_packet_mpunreach_start(s, afi, safi);
bgp_packet_mpunreach_prefix(
- s, &p, afi, safi, NULL, NULL, 0, addpath_encode,
+ s, &p, afi, safi, NULL, NULL, 0, addpath_capable,
BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE, NULL);
/* Set the mp_unreach attr's length */
diff --git a/doc/user/bfd.rst b/doc/user/bfd.rst
index 4e5674e736..14aacc0f6b 100644
--- a/doc/user/bfd.rst
+++ b/doc/user/bfd.rst
@@ -237,7 +237,7 @@ BFD Peer Specific Commands
Notes:
- Profile configurations can be overriden on a peer basis by specifying
- new parameters in peer configuration node.
+ non-default parameters in peer configuration node.
- Non existing profiles can be configured and they will only be applied
once they start to exist.
- If the profile gets updated the new configuration will be applied to all
diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst
index 91e823e7a7..ed4d02d89b 100644
--- a/doc/user/ospfd.rst
+++ b/doc/user/ospfd.rst
@@ -337,14 +337,18 @@ Areas
announced into backbone area if area 0.0.0.10 contains at least one intra-area
network (i.e. described with router or network LSA) from this range.
-.. clicmd:: area A.B.C.D range IPV4_PREFIX not-advertise
+.. clicmd:: area A.B.C.D range A.B.C.D/M not-advertise
+
+.. clicmd:: area (0-4294967295) range A.B.C.D/M not-advertise
Instead of summarizing intra area paths filter them - i.e. intra area paths from this
range are not advertised into other areas.
This command makes sense in ABR only.
-.. clicmd:: area A.B.C.D range IPV4_PREFIX substitute IPV4_PREFIX
+.. clicmd:: area A.B.C.D range A.B.C.D/M substitute A.B.C.D/M
+
+.. clicmd:: area (0-4294967295) range A.B.C.D/M substitute A.B.C.D/M
Substitute summarized prefix with another prefix.
diff --git a/doc/user/pim.rst b/doc/user/pim.rst
index 899a6b0078..1b418a4349 100644
--- a/doc/user/pim.rst
+++ b/doc/user/pim.rst
@@ -65,6 +65,18 @@ Certain signals have special meanings to *pimd*.
prefix of group ranges covered. This command is vrf aware, to configure for
a vrf, enter the vrf submode.
+.. clicmd:: ip pim rp keep-alive-timer (1-65535)
+
+ Modify the time out value for a S,G flow from 1-65535 seconds at RP.
+ The normal keepalive period for the KAT(S,G) defaults to 210 seconds.
+ However, at the RP, the keepalive period must be at least the
+ Register_Suppression_Time, or the RP may time out the (S,G) state
+ before the next Null-Register arrives. Thus, the KAT(S,G) is set to
+ max(Keepalive_Period, RP_Keepalive_Period) when a Register-Stop is sent.
+ If choosing a value below 31 seconds be aware that some hardware platforms
+ cannot see data flowing in better than 30 second chunks. This command is
+ vrf aware, to configure for a vrf, enter the vrf submode.
+
.. clicmd:: ip pim register-accept-list PLIST
When pim receives a register packet the source of the packet will be compared
@@ -72,10 +84,14 @@ Certain signals have special meanings to *pimd*.
processing continues. If a deny is returned for the source address of the
register packet a register stop message is sent to the source.
-.. clicmd:: ip pim spt-switchover infinity-and-beyond
+.. clicmd:: ip pim spt-switchover infinity-and-beyond [prefix-list PLIST]
- On the last hop router if it is desired to not switch over to the SPT tree.
- Configure this command. This command is vrf aware, to configure for a vrf,
+ On the last hop router if it is desired to not switch over to the SPT tree
+ configure this command. Optional parameter prefix-list can be use to control
+ which groups to switch or not switch. If a group is PERMIT as per the
+ PLIST, then the SPT switchover does not happen for it and if it is DENY,
+ then the SPT switchover happens.
+ This command is vrf aware, to configure for a vrf,
enter the vrf submode.
.. clicmd:: ip pim ecmp
@@ -103,7 +119,7 @@ Certain signals have special meanings to *pimd*.
.. clicmd:: ip pim keep-alive-timer (1-65535)
- Modify the time out value for a S,G flow from 1-60000 seconds. If choosing
+ Modify the time out value for a S,G flow from 1-65535 seconds. If choosing
a value below 31 seconds be aware that some hardware platforms cannot see data
flowing in better than 30 second chunks. This command is vrf aware, to
configure for a vrf, enter the vrf submode.
diff --git a/lib/stream.c b/lib/stream.c
index 1557500c60..c15baa0a2c 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -990,7 +990,7 @@ int stream_put_in6_addr_at(struct stream *s, size_t putp,
/* Put prefix by nlri type format. */
int stream_put_prefix_addpath(struct stream *s, const struct prefix *p,
- int addpath_encode, uint32_t addpath_tx_id)
+ bool addpath_capable, uint32_t addpath_tx_id)
{
size_t psize;
size_t psize_with_addpath;
@@ -999,7 +999,7 @@ int stream_put_prefix_addpath(struct stream *s, const struct prefix *p,
psize = PSIZE(p->prefixlen);
- if (addpath_encode)
+ if (addpath_capable)
psize_with_addpath = psize + 4;
else
psize_with_addpath = psize;
@@ -1009,7 +1009,7 @@ int stream_put_prefix_addpath(struct stream *s, const struct prefix *p,
return 0;
}
- if (addpath_encode) {
+ if (addpath_capable) {
s->data[s->endp++] = (uint8_t)(addpath_tx_id >> 24);
s->data[s->endp++] = (uint8_t)(addpath_tx_id >> 16);
s->data[s->endp++] = (uint8_t)(addpath_tx_id >> 8);
@@ -1030,7 +1030,7 @@ int stream_put_prefix(struct stream *s, const struct prefix *p)
/* Put NLRI with label */
int stream_put_labeled_prefix(struct stream *s, const struct prefix *p,
- mpls_label_t *label, int addpath_encode,
+ mpls_label_t *label, bool addpath_capable,
uint32_t addpath_tx_id)
{
size_t psize;
@@ -1040,14 +1040,14 @@ int stream_put_labeled_prefix(struct stream *s, const struct prefix *p,
STREAM_VERIFY_SANE(s);
psize = PSIZE(p->prefixlen);
- psize_with_addpath = psize + (addpath_encode ? 4 : 0);
+ psize_with_addpath = psize + (addpath_capable ? 4 : 0);
if (STREAM_WRITEABLE(s) < (psize_with_addpath + 3)) {
STREAM_BOUND_WARN(s, "put");
return 0;
}
- if (addpath_encode) {
+ if (addpath_capable) {
s->data[s->endp++] = (uint8_t)(addpath_tx_id >> 24);
s->data[s->endp++] = (uint8_t)(addpath_tx_id >> 16);
s->data[s->endp++] = (uint8_t)(addpath_tx_id >> 8);
diff --git a/lib/stream.h b/lib/stream.h
index dedbf37984..35733e7438 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -197,13 +197,12 @@ extern int stream_put_in_addr_at(struct stream *s, size_t putp,
const struct in_addr *addr);
extern int stream_put_in6_addr_at(struct stream *s, size_t putp,
const struct in6_addr *addr);
-extern int stream_put_prefix_addpath(struct stream *s,
- const struct prefix *p,
- int addpath_encode,
+extern int stream_put_prefix_addpath(struct stream *s, const struct prefix *p,
+ bool addpath_capable,
uint32_t addpath_tx_id);
extern int stream_put_prefix(struct stream *s, const struct prefix *p);
extern int stream_put_labeled_prefix(struct stream *, const struct prefix *,
- mpls_label_t *, int addpath_encode,
+ mpls_label_t *, bool addpath_capable,
uint32_t addpath_tx_id);
extern void stream_get(void *, struct stream *, size_t);
extern bool stream_get2(void *data, struct stream *s, size_t size);
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 5e7ba81a33..203ae14f2d 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -3383,8 +3383,8 @@ ospf6_start_asbr_summary_delay_timer(struct ospf6 *ospf6,
}
if (IS_OSPF6_DEBUG_AGGR)
- zlog_debug("%s: Start Aggregator delay timer %d(in seconds).",
- __func__, ospf6->aggr_delay_interval);
+ zlog_debug("%s: Start Aggregator delay timer %u(in seconds).",
+ __func__, ospf6->aggr_delay_interval);
ospf6->aggr_action = operation;
thread_add_timer(master,
@@ -3421,8 +3421,7 @@ int ospf6_asbr_external_rt_advertise(struct ospf6 *ospf6,
return OSPF6_SUCCESS;
}
-int ospf6_external_aggr_delay_timer_set(struct ospf6 *ospf6,
- unsigned int interval)
+int ospf6_external_aggr_delay_timer_set(struct ospf6 *ospf6, uint16_t interval)
{
ospf6->aggr_delay_interval = interval;
diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h
index 0aa1374a46..0487bb14c3 100644
--- a/ospf6d/ospf6_asbr.h
+++ b/ospf6d/ospf6_asbr.h
@@ -163,8 +163,7 @@ extern void ospf6_asbr_status_update(struct ospf6 *ospf6, int status);
int ospf6_asbr_external_rt_advertise(struct ospf6 *ospf6,
struct prefix *p);
-int ospf6_external_aggr_delay_timer_set(struct ospf6 *ospf6,
- unsigned int interval);
+int ospf6_external_aggr_delay_timer_set(struct ospf6 *ospf6, uint16_t interval);
int ospf6_asbr_external_rt_no_advertise(struct ospf6 *ospf6,
struct prefix *p);
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index b9e3e5b97c..57a55a6ef4 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -2010,8 +2010,8 @@ ospf6_show_summary_address(struct vty *vty, struct ospf6 *ospf6,
if (!uj) {
ospf6_show_vrf_name(vty, ospf6, json_vrf);
- vty_out(vty, "aggregation delay interval :%d(in seconds)\n\n",
- ospf6->aggr_delay_interval);
+ vty_out(vty, "aggregation delay interval :%u(in seconds)\n\n",
+ ospf6->aggr_delay_interval);
vty_out(vty, "%s\n", header);
} else {
json_vrf = json_object_new_object();
diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h
index d49b28e89d..b9f7235b46 100644
--- a/ospf6d/ospf6_top.h
+++ b/ospf6d/ospf6_top.h
@@ -230,7 +230,7 @@ struct ospf6 {
#define OSPF6_EXTL_AGGR_DEFAULT_DELAY 5
/* For ASBR summary delay timer */
- int aggr_delay_interval;
+ uint16_t aggr_delay_interval;
/* Table of configured Aggregate addresses */
struct route_table *rt_aggr_tbl;
diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c
index 000c62e305..8cb85b4626 100644
--- a/ospfd/ospf_asbr.c
+++ b/ospfd/ospf_asbr.c
@@ -1108,7 +1108,7 @@ static void ospf_external_aggr_timer(struct ospf *ospf,
}
if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
- zlog_debug("%s: Start Aggregator delay timer %d(in seconds).",
+ zlog_debug("%s: Start Aggregator delay timer %u(in seconds).",
__func__, ospf->aggr_delay_interval);
ospf->aggr_action = operation;
@@ -1232,7 +1232,7 @@ int ospf_asbr_external_rt_advertise(struct ospf *ospf, struct prefix_ipv4 *p)
return OSPF_SUCCESS;
}
-int ospf_external_aggregator_timer_set(struct ospf *ospf, unsigned int interval)
+int ospf_external_aggregator_timer_set(struct ospf *ospf, uint16_t interval)
{
ospf->aggr_delay_interval = interval;
return OSPF_SUCCESS;
diff --git a/ospfd/ospf_asbr.h b/ospfd/ospf_asbr.h
index 160883144f..f7dbca7587 100644
--- a/ospfd/ospf_asbr.h
+++ b/ospfd/ospf_asbr.h
@@ -148,7 +148,7 @@ ospf_originate_summary_lsa(struct ospf *ospf,
struct ospf_external_aggr_rt *aggr,
struct external_info *ei);
extern int ospf_external_aggregator_timer_set(struct ospf *ospf,
- unsigned int interval);
+ uint16_t interval);
extern void ospf_external_aggrigator_free(struct ospf_external_aggr_rt *aggr);
extern struct ospf_external_aggr_rt *
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 299e753ccf..2626cccc37 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -845,6 +845,8 @@ int ospf_if_down(struct ospf_interface *oi)
/* Shutdown packet reception and sending */
ospf_if_stream_unset(oi);
+ if (!ospf->new_table)
+ return 1;
for (rn = route_top(ospf->new_table); rn; rn = route_next(rn)) {
or = rn->info;
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index ce91b32afa..c82c8cb42e 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -9993,7 +9993,7 @@ DEFUN (ospf_external_route_aggregation,
ospf_external_route_aggregation_cmd,
"summary-address A.B.C.D/M [tag (1-4294967295)]",
"External summary address\n"
- "Summary address prefix (a.b.c.d/m) \n"
+ "Summary address prefix\n"
"Router tag \n"
"Router tag value\n")
{
@@ -10034,7 +10034,7 @@ DEFUN (no_ospf_external_route_aggregation,
"no summary-address A.B.C.D/M [tag (1-4294967295)]",
NO_STR
"External summary address\n"
- "Summary address prefix (a.b.c.d/m)\n"
+ "Summary address prefix\n"
"Router tag\n"
"Router tag value\n")
{
@@ -10324,7 +10324,7 @@ DEFUN (ospf_external_route_aggregation_no_adrvertise,
ospf_external_route_aggregation_no_adrvertise_cmd,
"summary-address A.B.C.D/M no-advertise",
"External summary address\n"
- "Summary address prefix (a.b.c.d/m) \n"
+ "Summary address prefix\n"
"Don't advertise summary route \n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
@@ -10360,7 +10360,7 @@ DEFUN (no_ospf_external_route_aggregation_no_adrvertise,
"no summary-address A.B.C.D/M no-advertise",
NO_STR
"External summary address\n"
- "Summary address prefix (a.b.c.d/m)\n"
+ "Summary address prefix\n"
"Advertise summary route to the AS \n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
@@ -10399,7 +10399,7 @@ DEFUN (ospf_route_aggregation_timer,
"Timer interval(in seconds)\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
- unsigned int interval = 0;
+ uint16_t interval = 0;
interval = strtoul(argv[2]->arg, NULL, 10);
@@ -11429,7 +11429,7 @@ static int ospf_show_summary_address(struct vty *vty, struct ospf *ospf,
ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf);
if (!uj)
- vty_out(vty, "aggregation delay interval :%d(in seconds)\n\n",
+ vty_out(vty, "aggregation delay interval :%u(in seconds)\n\n",
ospf->aggr_delay_interval);
else
json_object_int_add(json_vrf, "aggregation delay interval",
@@ -12191,15 +12191,19 @@ static int config_write_ospf_external_aggregator(struct vty *vty,
{
struct route_node *rn;
+ if (ospf->aggr_delay_interval != OSPF_EXTL_AGGR_DEFAULT_DELAY)
+ vty_out(vty, " aggregation timer %u\n",
+ ospf->aggr_delay_interval);
+
/* print 'summary-address A.B.C.D/M' */
for (rn = route_top(ospf->rt_aggr_tbl); rn; rn = route_next(rn))
if (rn->info) {
struct ospf_external_aggr_rt *aggr = rn->info;
- vty_out(vty, " summary-address %pI4/%d ",
+ vty_out(vty, " summary-address %pI4/%d",
&aggr->p.prefix, aggr->p.prefixlen);
if (aggr->tag)
- vty_out(vty, " tag %u ", aggr->tag);
+ vty_out(vty, " tag %u", aggr->tag);
if (CHECK_FLAG(aggr->flags,
OSPF_EXTERNAL_AGGRT_NO_ADVERTISE))
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index 3369429eba..4f1b1493a6 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -377,7 +377,7 @@ struct ospf {
struct thread *t_external_aggr;
/* delay interval in seconds */
- unsigned int aggr_delay_interval;
+ uint16_t aggr_delay_interval;
/* Table of configured Aggregate addresses */
struct route_table *rt_aggr_tbl;
diff --git a/tests/topotests/bgp_dont_capability_negogiate/__init__.py b/tests/topotests/bgp_dont_capability_negotiate/__init__.py
index e69de29bb2..e69de29bb2 100644
--- a/tests/topotests/bgp_dont_capability_negogiate/__init__.py
+++ b/tests/topotests/bgp_dont_capability_negotiate/__init__.py
diff --git a/tests/topotests/bgp_dont_capability_negogiate/r1/bgpd.conf b/tests/topotests/bgp_dont_capability_negotiate/r1/bgpd.conf
index b429efe076..b429efe076 100644
--- a/tests/topotests/bgp_dont_capability_negogiate/r1/bgpd.conf
+++ b/tests/topotests/bgp_dont_capability_negotiate/r1/bgpd.conf
diff --git a/tests/topotests/bgp_dont_capability_negogiate/r1/zebra.conf b/tests/topotests/bgp_dont_capability_negotiate/r1/zebra.conf
index b29940f46a..b29940f46a 100644
--- a/tests/topotests/bgp_dont_capability_negogiate/r1/zebra.conf
+++ b/tests/topotests/bgp_dont_capability_negotiate/r1/zebra.conf
diff --git a/tests/topotests/bgp_dont_capability_negogiate/r2/bgpd.conf b/tests/topotests/bgp_dont_capability_negotiate/r2/bgpd.conf
index 4af2cd6a80..4af2cd6a80 100644
--- a/tests/topotests/bgp_dont_capability_negogiate/r2/bgpd.conf
+++ b/tests/topotests/bgp_dont_capability_negotiate/r2/bgpd.conf
diff --git a/tests/topotests/bgp_dont_capability_negogiate/r2/zebra.conf b/tests/topotests/bgp_dont_capability_negotiate/r2/zebra.conf
index dc15cf756a..dc15cf756a 100644
--- a/tests/topotests/bgp_dont_capability_negogiate/r2/zebra.conf
+++ b/tests/topotests/bgp_dont_capability_negotiate/r2/zebra.conf
diff --git a/tests/topotests/bgp_dont_capability_negogiate/test_bgp_dont_capability_negotiate.py b/tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py
index 272fdd334a..272fdd334a 100644
--- a/tests/topotests/bgp_dont_capability_negogiate/test_bgp_dont_capability_negotiate.py
+++ b/tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r1/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r1/ospf6d.conf
new file mode 100644
index 0000000000..6c7cb96240
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/r1/ospf6d.conf
@@ -0,0 +1,52 @@
+debug ospf6 lsa all
+debug ospf6 message all
+debug ospf6 route all
+debug ospf6 spf time
+debug ospf6 spf database
+debug ospf6 zebra send
+debug ospf6 zebra recv
+
+debug ospf6 lsa router
+debug ospf6 lsa router originate
+debug ospf6 lsa router examine
+debug ospf6 lsa router flooding
+debug ospf6 lsa as-external
+debug ospf6 lsa as-external originate
+debug ospf6 lsa as-external examine
+debug ospf6 lsa as-external flooding
+debug ospf6 lsa intra-prefix
+debug ospf6 lsa intra-prefix originate
+debug ospf6 lsa intra-prefix examine
+debug ospf6 lsa intra-prefix flooding
+debug ospf6 border-routers
+debug ospf6 zebra
+debug ospf6 interface
+debug ospf6 neighbor
+debug ospf6 flooding
+debug ospf6 gr helper
+debug ospf6 spf process
+debug ospf6 route intra-area
+debug ospf6 route inter-area
+debug ospf6 abr
+debug ospf6 asbr
+debug ospf6 nssa
+!
+interface r1-eth0
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r1-eth1
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r1-eth2
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+router ospf6
+ ospf6 router-id 10.254.254.1
+ redistribute connected
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r1/zebra.conf b/tests/topotests/ospf6_ecmp_inter_area/r1/zebra.conf
new file mode 100644
index 0000000000..236ed0bf2e
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/r1/zebra.conf
@@ -0,0 +1,5 @@
+ipv6 forwarding
+!
+interface lo
+ ipv6 address 2001:db8:1::1/64
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r2/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r2/ospf6d.conf
new file mode 100644
index 0000000000..49215f6b66
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/r2/ospf6d.conf
@@ -0,0 +1,14 @@
+interface r2-eth0
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r2-eth1
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+router ospf6
+ ospf6 router-id 10.254.254.2
+ redistribute connected
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r2/zebra.conf b/tests/topotests/ospf6_ecmp_inter_area/r2/zebra.conf
new file mode 100644
index 0000000000..1b79b09a9e
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/r2/zebra.conf
@@ -0,0 +1,5 @@
+ipv6 forwarding
+!
+interface lo
+ ipv6 address 2001:db8:2::1/64
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r3/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r3/ospf6d.conf
new file mode 100644
index 0000000000..8b918bf78a
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/r3/ospf6d.conf
@@ -0,0 +1,14 @@
+interface r3-eth0
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r3-eth1
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+router ospf6
+ ospf6 router-id 10.254.254.3
+ redistribute connected
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r3/zebra.conf b/tests/topotests/ospf6_ecmp_inter_area/r3/zebra.conf
new file mode 100644
index 0000000000..efb3c35c5a
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/r3/zebra.conf
@@ -0,0 +1,5 @@
+ipv6 forwarding
+!
+interface lo
+ ipv6 address 2001:db8:3::1/64
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r4/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r4/ospf6d.conf
new file mode 100644
index 0000000000..3cc8645cf4
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/r4/ospf6d.conf
@@ -0,0 +1,14 @@
+interface r4-eth0
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r4-eth1
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+router ospf6
+ ospf6 router-id 10.254.254.4
+ redistribute connected
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r4/zebra.conf b/tests/topotests/ospf6_ecmp_inter_area/r4/zebra.conf
new file mode 100644
index 0000000000..3479af48d0
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/r4/zebra.conf
@@ -0,0 +1,5 @@
+ipv6 forwarding
+!
+interface lo
+ ipv6 address 2001:db8:4::1/64
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r5/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r5/ospf6d.conf
new file mode 100644
index 0000000000..2a6c9abd2e
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/r5/ospf6d.conf
@@ -0,0 +1,39 @@
+interface r5-eth0
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r5-eth1
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r5-eth2
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r5-eth3
+ ipv6 ospf6 area 1
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r5-eth4
+ ipv6 ospf6 area 1
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r5-eth5
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r5-eth6
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+router ospf6
+ ospf6 router-id 10.254.254.5
+ redistribute connected
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r5/zebra.conf b/tests/topotests/ospf6_ecmp_inter_area/r5/zebra.conf
new file mode 100644
index 0000000000..851cc9db69
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/r5/zebra.conf
@@ -0,0 +1,5 @@
+ipv6 forwarding
+!
+interface lo
+ ipv6 address 2001:db8:5::1/64
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r6/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r6/ospf6d.conf
new file mode 100644
index 0000000000..a1f48b51a5
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/r6/ospf6d.conf
@@ -0,0 +1,9 @@
+interface r6-eth0
+ ipv6 ospf6 area 1
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+router ospf6
+ ospf6 router-id 10.254.254.6
+ redistribute connected
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r6/zebra.conf b/tests/topotests/ospf6_ecmp_inter_area/r6/zebra.conf
new file mode 100644
index 0000000000..b98da4b541
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/r6/zebra.conf
@@ -0,0 +1,5 @@
+ipv6 forwarding
+!
+interface lo
+ ipv6 address 2001:db8:6::1/64
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r7/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r7/ospf6d.conf
new file mode 100644
index 0000000000..0e49b0df6c
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/r7/ospf6d.conf
@@ -0,0 +1,11 @@
+interface lo
+ ipv6 ospf6 area 1
+!
+interface r7-eth0
+ ipv6 ospf6 area 1
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+router ospf6
+ ospf6 router-id 10.254.254.7
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r7/zebra.conf b/tests/topotests/ospf6_ecmp_inter_area/r7/zebra.conf
new file mode 100644
index 0000000000..a410be8f73
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/r7/zebra.conf
@@ -0,0 +1,5 @@
+ipv6 forwarding
+!
+interface lo
+ ipv6 address 2001:db8:7::1/64
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r8/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r8/ospf6d.conf
new file mode 100644
index 0000000000..fb5483ce99
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/r8/ospf6d.conf
@@ -0,0 +1,9 @@
+interface r8-eth0
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+router ospf6
+ ospf6 router-id 10.254.254.8
+ redistribute connected
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r8/zebra.conf b/tests/topotests/ospf6_ecmp_inter_area/r8/zebra.conf
new file mode 100644
index 0000000000..8e343d8f45
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/r8/zebra.conf
@@ -0,0 +1,5 @@
+ipv6 forwarding
+!
+interface lo
+ ipv6 address 2001:db8:8::1/64
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r9/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r9/ospf6d.conf
new file mode 100644
index 0000000000..57fa8e32ee
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/r9/ospf6d.conf
@@ -0,0 +1,11 @@
+interface lo
+ ipv6 ospf6 area 0
+!
+interface r9-eth0
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+router ospf6
+ ospf6 router-id 10.254.254.9
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r9/zebra.conf b/tests/topotests/ospf6_ecmp_inter_area/r9/zebra.conf
new file mode 100644
index 0000000000..e267496a98
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/r9/zebra.conf
@@ -0,0 +1,5 @@
+ipv6 forwarding
+!
+interface lo
+ ipv6 address 2001:db8:9::1/64
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/test_ospf6_ecmp_inter_area.py b/tests/topotests/ospf6_ecmp_inter_area/test_ospf6_ecmp_inter_area.py
new file mode 100644
index 0000000000..886b52c59c
--- /dev/null
+++ b/tests/topotests/ospf6_ecmp_inter_area/test_ospf6_ecmp_inter_area.py
@@ -0,0 +1,207 @@
+#!/usr/bin/env python
+
+# test_ospf6_ecmp_inter_area.py
+#
+# Copyright (c) 2021, 2022 by Martin Buck
+# Copyright (c) 2016 by
+# Network Device Education Foundation, Inc. ("NetDEF")
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_ospf6_ecmp_inter_area.py: Test OSPFv3 ECMP inter-area nexthop update
+
+Check proper removal of ECMP nexthops after a path used by one nexthop
+disappears. We remove a path by bringing down a link required by that
+path which is not adjacent to the router being checked. This is important
+because when bringing down adjacent links, the kernel might remove the
+nexthops itself without ospf6d having to do anything.
+
+Useful as a regression test for #9720.
+
+Topology:
+ .
+ Area 0 . Area 1
+ .
+ -- R2 -- . ---- R6
+ / \ ./
+R1 -- R3 -- R5 ---- R7 Area 1
+ \ / \\ ..............
+ -- R4 -- \--- R8 Area 0
+ \
+ -- R9
+
+We check routes on R1, primarily those towards R6/7/8/9. Those to R6/7 are
+inter-area routes with R5 being ABR, those to R8/9 are intra-area routes
+and are used for reference. R6/R8 announce external routes, R7/R9 announce
+internal routes.
+
+With all links up, we expect 3 ECMP paths and 3 nexthops on R1 towards each
+of R6/7/8/9. Then we bring down the R2-R5 link, causing only 2 remaining
+paths and 2 nexthops on R1. The test is successful if the number of nexthops
+for the routes on R1 is as expected.
+"""
+
+import os
+import sys
+from functools import partial
+import pytest
+
+# 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.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+pytestmark = [pytest.mark.ospf6d]
+
+
+def build_topo(tgen):
+ "Build function"
+
+ # Create 9 routers
+ for routern in range(1, 10):
+ tgen.add_router("r{}".format(routern))
+
+ tgen.gears["r1"].add_link(tgen.gears["r2"])
+ tgen.gears["r1"].add_link(tgen.gears["r3"])
+ tgen.gears["r1"].add_link(tgen.gears["r4"])
+ tgen.gears["r2"].add_link(tgen.gears["r5"])
+ tgen.gears["r3"].add_link(tgen.gears["r5"])
+ tgen.gears["r4"].add_link(tgen.gears["r5"])
+ tgen.gears["r5"].add_link(tgen.gears["r6"])
+ tgen.gears["r5"].add_link(tgen.gears["r7"])
+ tgen.gears["r5"].add_link(tgen.gears["r8"])
+ tgen.gears["r5"].add_link(tgen.gears["r9"])
+
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+ for rname, router in router_list.items():
+ daemon_file = "{}/{}/zebra.conf".format(CWD, rname)
+ if os.path.isfile(daemon_file):
+ router.load_config(TopoRouter.RD_ZEBRA, daemon_file)
+
+ daemon_file = "{}/{}/ospf6d.conf".format(CWD, rname)
+ if os.path.isfile(daemon_file):
+ router.load_config(TopoRouter.RD_OSPF6, daemon_file)
+
+ # Initialize all routers.
+ tgen.start_router()
+
+
+def test_wait_protocol_convergence():
+ "Wait for OSPFv3 to converge"
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("waiting for protocols to converge")
+
+ def expect_neighbor_full(router, neighbor):
+ "Wait until OSPFv3 neighborship is full"
+ logger.info("waiting for OSPFv3 router '{}' neighborship with '{}'".format(router, neighbor))
+ test_func = partial(
+ topotest.router_json_cmp,
+ tgen.gears[router],
+ "show ipv6 ospf6 neighbor json",
+ {"neighbors": [{"neighborId": neighbor, "state": "Full"}]},
+ )
+ _, result = topotest.run_and_expect(test_func, None,
+ count=130, wait=1)
+ assertmsg = '"{}" convergence failure'.format(router)
+ assert result is None, assertmsg
+
+ expect_neighbor_full("r1", "10.254.254.2")
+ expect_neighbor_full("r1", "10.254.254.3")
+ expect_neighbor_full("r1", "10.254.254.4")
+ expect_neighbor_full("r2", "10.254.254.1")
+ expect_neighbor_full("r2", "10.254.254.5")
+ expect_neighbor_full("r3", "10.254.254.1")
+ expect_neighbor_full("r3", "10.254.254.5")
+ expect_neighbor_full("r4", "10.254.254.1")
+ expect_neighbor_full("r4", "10.254.254.5")
+ expect_neighbor_full("r5", "10.254.254.2")
+ expect_neighbor_full("r5", "10.254.254.3")
+ expect_neighbor_full("r5", "10.254.254.4")
+ expect_neighbor_full("r5", "10.254.254.6")
+ expect_neighbor_full("r5", "10.254.254.7")
+ expect_neighbor_full("r5", "10.254.254.8")
+ expect_neighbor_full("r5", "10.254.254.9")
+ expect_neighbor_full("r6", "10.254.254.5")
+ expect_neighbor_full("r7", "10.254.254.5")
+ expect_neighbor_full("r8", "10.254.254.5")
+ expect_neighbor_full("r9", "10.254.254.5")
+
+def test_ecmp_inter_area():
+ "Test whether OSPFv3 ECMP nexthops are properly updated for inter-area routes after link down"
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def num_nexthops(router):
+ routes = tgen.gears[router].vtysh_cmd("show ipv6 ospf6 route json", isjson=True)
+ route_prefixes_infos = sorted(routes.get("routes", {}).items())
+ return [len(ri.get("nextHops", [])) for rp, ri in route_prefixes_infos]
+
+ def expect_num_nexthops(router, expected_num_nexthops, count):
+ "Wait until number of nexthops for routes matches expectation"
+ logger.info("waiting for OSPFv3 router '{}' nexthops {}".format(router, expected_num_nexthops))
+ test_func = partial(num_nexthops, router)
+ _, result = topotest.run_and_expect(test_func, expected_num_nexthops,
+ count=count, wait=3)
+ assert result == expected_num_nexthops, \
+ "'{}' wrong number of route nexthops".format(router)
+
+ # Check nexthops pre link-down
+ expect_num_nexthops("r1", [1, 1, 1, 3, 3, 3, 3, 3], 4)
+
+ logger.info("triggering R2-R4 link down")
+ tgen.gears["r2"].run("ip link set r2-eth1 down")
+
+ #tgen.mininet_cli()
+ # Check nexthops post link-down
+ expect_num_nexthops("r1", [1, 1, 1, 2, 2, 2, 2, 2], 8)
+
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+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-bfdd.yang b/yang/frr-bfdd.yang
index d2746e3503..08b6073479 100644
--- a/yang/frr-bfdd.yang
+++ b/yang/frr-bfdd.yang
@@ -67,14 +67,14 @@ module frr-bfdd {
typedef multiplier {
description "Detection multiplier";
type uint8 {
- range 2..255;
+ range "2..255";
}
}
typedef discriminator {
description "BFD session identification";
type uint32 {
- range 1..4294967295;
+ range "1..4294967295";
}
}
@@ -170,14 +170,18 @@ module frr-bfdd {
}
leaf desired-transmission-interval {
- type uint32;
+ type uint32 {
+ range "10000..60000000";
+ }
units microseconds;
default 300000;
description "Minimum desired control packet transmission interval";
}
leaf required-receive-interval {
- type uint32;
+ type uint32 {
+ range "10000..60000000";
+ }
units microseconds;
default 300000;
description "Minimum required control packet receive interval";
@@ -207,14 +211,18 @@ module frr-bfdd {
}
leaf desired-echo-transmission-interval {
- type uint32;
+ type uint32 {
+ range "10000..60000000";
+ }
units microseconds;
default 50000;
description "Minimum desired echo packet transmission interval";
}
leaf required-echo-receive-interval {
- type uint32;
+ type uint32 {
+ range "0 | 10000..60000000";
+ }
units microseconds;
default 50000;
description "Minimum required echo packet receive interval";
@@ -226,8 +234,9 @@ module frr-bfdd {
leaf minimum-ttl {
type uint8 {
- range 1..254;
+ range "1..254";
}
+ default "254";
description
"Minimum expected TTL on received packets.";
}
diff --git a/zebra/rib.h b/zebra/rib.h
index d873eb22d1..c1aeb7f07e 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -481,6 +481,8 @@ int zebra_rib_queue_evpn_rem_vtep_del(vrf_id_t vrf_id, vni_t vni,
struct in_addr vtep_ip);
extern void meta_queue_free(struct meta_queue *mq);
+extern void rib_meta_queue_free_vrf(struct meta_queue *mq,
+ struct zebra_vrf *zvrf);
extern int zebra_rib_labeled_unicast(struct route_entry *re);
extern struct route_table *rib_table_ipv6;
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index d00413a222..fbd3c6eb77 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -2944,6 +2944,59 @@ void meta_queue_free(struct meta_queue *mq)
XFREE(MTYPE_WORK_QUEUE, mq);
}
+void rib_meta_queue_free_vrf(struct meta_queue *mq, struct zebra_vrf *zvrf)
+{
+ vrf_id_t vrf_id = zvrf->vrf->vrf_id;
+ unsigned int i;
+
+ for (i = 0; i < MQ_SIZE; i++) {
+ struct listnode *lnode, *nnode;
+ void *data;
+ bool del;
+
+ for (ALL_LIST_ELEMENTS(mq->subq[i], lnode, nnode, data)) {
+ del = false;
+
+ if (i == META_QUEUE_EVPN) {
+ struct wq_evpn_wrapper *w = data;
+
+ if (w->vrf_id == vrf_id) {
+ XFREE(MTYPE_WQ_WRAPPER, w);
+ del = true;
+ }
+ } else if (i ==
+ route_info[ZEBRA_ROUTE_NHG].meta_q_map) {
+ struct wq_nhg_wrapper *w = data;
+
+ if (w->type == WQ_NHG_WRAPPER_TYPE_CTX &&
+ w->u.ctx->vrf_id == vrf_id) {
+ nhg_ctx_free(&w->u.ctx);
+ XFREE(MTYPE_WQ_WRAPPER, w);
+ del = true;
+ } else if (w->type == WQ_NHG_WRAPPER_TYPE_NHG &&
+ w->u.nhe->vrf_id == vrf_id) {
+ zebra_nhg_free(w->u.nhe);
+ XFREE(MTYPE_WQ_WRAPPER, w);
+ del = true;
+ }
+ } else {
+ struct route_node *rnode = data;
+ rib_dest_t *dest = rib_dest_from_rnode(rnode);
+
+ if (dest && rib_dest_vrf(dest) == zvrf) {
+ route_unlock_node(rnode);
+ del = true;
+ }
+ }
+
+ if (del) {
+ list_delete_node(mq->subq[i], lnode);
+ mq->size--;
+ }
+ }
+ }
+}
+
/* initialise zebra rib work queue */
static void rib_queue_init(void)
{
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index 842dc3f576..f88a65d952 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -177,7 +177,6 @@ static int zebra_vrf_disable(struct vrf *vrf)
struct interface *ifp;
afi_t afi;
safi_t safi;
- unsigned i;
assert(zvrf);
if (IS_ZEBRA_DEBUG_EVENT)
@@ -222,21 +221,7 @@ static int zebra_vrf_disable(struct vrf *vrf)
if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
/* clean-up work queues */
- for (i = 0; i < MQ_SIZE; i++) {
- struct listnode *lnode, *nnode;
- struct route_node *rnode;
- rib_dest_t *dest;
-
- for (ALL_LIST_ELEMENTS(zrouter.mq->subq[i], lnode, nnode,
- rnode)) {
- dest = rib_dest_from_rnode(rnode);
- if (dest && rib_dest_vrf(dest) == zvrf) {
- route_unlock_node(rnode);
- list_delete_node(zrouter.mq->subq[i], lnode);
- zrouter.mq->size--;
- }
- }
- }
+ rib_meta_queue_free_vrf(zrouter.mq, zvrf);
/* Cleanup (free) routing tables and NHT tables. */
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
@@ -262,7 +247,6 @@ static int zebra_vrf_delete(struct vrf *vrf)
{
struct zebra_vrf *zvrf = vrf->info;
struct other_route_table *otable;
- unsigned i;
assert(zvrf);
if (IS_ZEBRA_DEBUG_EVENT)
@@ -272,21 +256,7 @@ static int zebra_vrf_delete(struct vrf *vrf)
table_manager_disable(zvrf);
/* clean-up work queues */
- for (i = 0; i < MQ_SIZE; i++) {
- struct listnode *lnode, *nnode;
- struct route_node *rnode;
- rib_dest_t *dest;
-
- for (ALL_LIST_ELEMENTS(zrouter.mq->subq[i], lnode, nnode,
- rnode)) {
- dest = rib_dest_from_rnode(rnode);
- if (dest && rib_dest_vrf(dest) == zvrf) {
- route_unlock_node(rnode);
- list_delete_node(zrouter.mq->subq[i], lnode);
- zrouter.mq->size--;
- }
- }
- }
+ rib_meta_queue_free_vrf(zrouter.mq, zvrf);
/* Free Vxlan and MPLS. */
zebra_vxlan_close_tables(zvrf);