diff options
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); |
