summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
authorDaniel Baumann <daniel@debian.org>2024-11-17 07:10:47 +0100
committerDaniel Baumann <daniel@debian.org>2024-11-17 07:10:47 +0100
commitd785318c6f0fc8ee4b0e92eed928d0fcd5debc0c (patch)
tree9656d5d79eba42e52e7e6e208f8f8ab39b63c756 /bgpd
parentAdding upstream version 10.1.1. (diff)
downloadfrr-d785318c6f0fc8ee4b0e92eed928d0fcd5debc0c.tar.xz
frr-d785318c6f0fc8ee4b0e92eed928d0fcd5debc0c.zip
Adding upstream version 10.2.upstream/10.2
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_addpath.c6
-rw-r--r--bgpd/bgp_addpath.h6
-rw-r--r--bgpd/bgp_attr.c376
-rw-r--r--bgpd/bgp_attr.h59
-rw-r--r--bgpd/bgp_attr_evpn.c36
-rw-r--r--bgpd/bgp_attr_evpn.h9
-rw-r--r--bgpd/bgp_bmp.c40
-rw-r--r--bgpd/bgp_btoa.c2
-rw-r--r--bgpd/bgp_clist.c6
-rw-r--r--bgpd/bgp_clist.h4
-rw-r--r--bgpd/bgp_community.c7
-rw-r--r--bgpd/bgp_damp.c3
-rw-r--r--bgpd/bgp_debug.c4
-rw-r--r--bgpd/bgp_ecommunity.c63
-rw-r--r--bgpd/bgp_ecommunity.h4
-rw-r--r--bgpd/bgp_evpn.c362
-rw-r--r--bgpd/bgp_evpn.h4
-rw-r--r--bgpd/bgp_evpn_mh.c199
-rw-r--r--bgpd/bgp_evpn_mh.h2
-rw-r--r--bgpd/bgp_evpn_private.h2
-rw-r--r--bgpd/bgp_evpn_vty.c39
-rw-r--r--bgpd/bgp_flowspec.c2
-rw-r--r--bgpd/bgp_flowspec_util.c44
-rw-r--r--bgpd/bgp_fsm.c439
-rw-r--r--bgpd/bgp_fsm.h5
-rw-r--r--bgpd/bgp_label.c4
-rw-r--r--bgpd/bgp_mac.c7
-rw-r--r--bgpd/bgp_main.c36
-rw-r--r--bgpd/bgp_memory.c2
-rw-r--r--bgpd/bgp_memory.h2
-rw-r--r--bgpd/bgp_mpath.c438
-rw-r--r--bgpd/bgp_mpath.h29
-rw-r--r--bgpd/bgp_mplsvpn.c401
-rw-r--r--bgpd/bgp_mplsvpn.h2
-rw-r--r--bgpd/bgp_mplsvpn_snmp.c5
-rw-r--r--bgpd/bgp_network.c9
-rw-r--r--bgpd/bgp_network.h1
-rw-r--r--bgpd/bgp_nexthop.c2
-rw-r--r--bgpd/bgp_nexthop.h3
-rw-r--r--bgpd/bgp_nht.c84
-rw-r--r--bgpd/bgp_open.c103
-rw-r--r--bgpd/bgp_packet.c74
-rw-r--r--bgpd/bgp_pbr.c200
-rw-r--r--bgpd/bgp_route.c528
-rw-r--r--bgpd/bgp_route.h32
-rw-r--r--bgpd/bgp_routemap.c134
-rw-r--r--bgpd/bgp_rpki.c77
-rw-r--r--bgpd/bgp_script.h5
-rw-r--r--bgpd/bgp_snmp.c22
-rw-r--r--bgpd/bgp_snmp_bgp4v2.c4
-rw-r--r--bgpd/bgp_updgrp.c18
-rw-r--r--bgpd/bgp_updgrp_packet.c18
-rw-r--r--bgpd/bgp_vty.c826
-rw-r--r--bgpd/bgp_vty.h52
-rw-r--r--bgpd/bgp_zebra.c523
-rw-r--r--bgpd/bgp_zebra.h7
-rw-r--r--bgpd/bgpd.c508
-rw-r--r--bgpd/bgpd.h147
-rw-r--r--bgpd/rfapi/vnc_export_bgp.c46
59 files changed, 3551 insertions, 2521 deletions
diff --git a/bgpd/bgp_addpath.c b/bgpd/bgp_addpath.c
index f391c138..aada6e55 100644
--- a/bgpd/bgp_addpath.c
+++ b/bgpd/bgp_addpath.c
@@ -361,8 +361,7 @@ void bgp_addpath_type_changed(struct bgp *bgp)
}
}
-int bgp_addpath_capability_action(enum bgp_addpath_strat addpath_type,
- uint8_t paths)
+int bgp_addpath_capability_action(enum bgp_addpath_strat addpath_type, uint16_t paths)
{
int action = CAPABILITY_ACTION_UNSET;
@@ -392,8 +391,7 @@ int bgp_addpath_capability_action(enum bgp_addpath_strat addpath_type,
* change take effect.
*/
void bgp_addpath_set_peer_type(struct peer *peer, afi_t afi, safi_t safi,
- enum bgp_addpath_strat addpath_type,
- uint8_t paths)
+ enum bgp_addpath_strat addpath_type, uint16_t paths)
{
struct bgp *bgp = peer->bgp;
enum bgp_addpath_strat old_type;
diff --git a/bgpd/bgp_addpath.h b/bgpd/bgp_addpath.h
index c267ebe4..f1ff98ea 100644
--- a/bgpd/bgp_addpath.h
+++ b/bgpd/bgp_addpath.h
@@ -62,13 +62,11 @@ bool bgp_addpath_tx_path(enum bgp_addpath_strat strat,
* Change the type of addpath used for a peer.
*/
void bgp_addpath_set_peer_type(struct peer *peer, afi_t afi, safi_t safi,
- enum bgp_addpath_strat addpath_type,
- uint8_t paths);
+ enum bgp_addpath_strat addpath_type, uint16_t paths);
void bgp_addpath_update_ids(struct bgp *bgp, struct bgp_dest *dest, afi_t afi,
safi_t safi);
void bgp_addpath_type_changed(struct bgp *bgp);
-extern int bgp_addpath_capability_action(enum bgp_addpath_strat addpath_type,
- uint8_t paths);
+extern int bgp_addpath_capability_action(enum bgp_addpath_strat addpath_type, uint16_t paths);
#endif
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index e4ee589a..1a2fa831 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -198,6 +198,7 @@ static struct hash *vnc_hash = NULL;
#endif
static struct hash *srv6_l3vpn_hash;
static struct hash *srv6_vpn_hash;
+static struct hash *evpn_overlay_hash;
struct bgp_attr_encap_subtlv *encap_tlv_dup(struct bgp_attr_encap_subtlv *orig)
{
@@ -479,22 +480,11 @@ static bool bgp_attr_aigp_get_tlv_metric(uint8_t *pnt, int length,
return false;
}
-static uint64_t bgp_aigp_metric_total(struct bgp_path_info *bpi)
-{
- uint64_t aigp = bgp_attr_get_aigp_metric(bpi->attr);
-
- if (bpi->nexthop)
- return aigp + bpi->nexthop->metric;
- else
- return aigp;
-}
-
-static void stream_put_bgp_aigp_tlv_metric(struct stream *s,
- struct bgp_path_info *bpi)
+static void stream_put_bgp_aigp_tlv_metric(struct stream *s, uint64_t aigp)
{
stream_putc(s, BGP_AIGP_TLV_METRIC);
stream_putw(s, BGP_AIGP_TLV_METRIC_LEN);
- stream_putq(s, bgp_aigp_metric_total(bpi));
+ stream_putq(s, aigp);
}
static bool bgp_attr_aigp_valid(uint8_t *pnt, int length)
@@ -549,6 +539,81 @@ static bool bgp_attr_aigp_valid(uint8_t *pnt, int length)
return true;
}
+static void *evpn_overlay_hash_alloc(void *p)
+{
+ return p;
+}
+
+void evpn_overlay_free(struct bgp_route_evpn *bre)
+{
+ XFREE(MTYPE_BGP_EVPN_OVERLAY, bre);
+}
+
+static struct bgp_route_evpn *evpn_overlay_intern(struct bgp_route_evpn *bre)
+{
+ struct bgp_route_evpn *find;
+
+ find = hash_get(evpn_overlay_hash, bre, evpn_overlay_hash_alloc);
+ if (find != bre)
+ evpn_overlay_free(bre);
+ find->refcnt++;
+ return find;
+}
+
+static void evpn_overlay_unintern(struct bgp_route_evpn **brep)
+{
+ struct bgp_route_evpn *bre = *brep;
+
+ if (!*brep)
+ return;
+
+ if (bre->refcnt)
+ bre->refcnt--;
+
+ if (bre->refcnt == 0) {
+ hash_release(evpn_overlay_hash, bre);
+ evpn_overlay_free(bre);
+ *brep = NULL;
+ }
+}
+
+static uint32_t evpn_overlay_hash_key_make(const void *p)
+{
+ const struct bgp_route_evpn *bre = p;
+ uint32_t key = 0;
+
+ if (IS_IPADDR_V4(&bre->gw_ip))
+ key = jhash_1word(bre->gw_ip.ipaddr_v4.s_addr, 0);
+ else
+ key = jhash2(bre->gw_ip.ipaddr_v6.s6_addr32,
+ array_size(bre->gw_ip.ipaddr_v6.s6_addr32), 0);
+
+ key = jhash_1word(bre->type, key);
+ key = jhash(bre->eth_s_id.val, sizeof(bre->eth_s_id.val), key);
+ return key;
+}
+
+static bool evpn_overlay_hash_cmp(const void *p1, const void *p2)
+{
+ const struct bgp_route_evpn *bre1 = p1;
+ const struct bgp_route_evpn *bre2 = p2;
+
+ return bgp_route_evpn_same(bre1, bre2);
+}
+
+static void evpn_overlay_init(void)
+{
+ evpn_overlay_hash = hash_create(evpn_overlay_hash_key_make,
+ evpn_overlay_hash_cmp,
+ "BGP EVPN Overlay");
+}
+
+static void evpn_overlay_finish(void)
+{
+ hash_clean_and_free(&evpn_overlay_hash,
+ (void (*)(void *))evpn_overlay_free);
+}
+
static void *srv6_l3vpn_hash_alloc(void *p)
{
return p;
@@ -788,6 +853,8 @@ unsigned int attrhash_key_make(const void *p)
MIX(encap_hash_key_make(attr->encap_subtlvs));
if (attr->srv6_l3vpn)
MIX(srv6_l3vpn_hash_key_make(attr->srv6_l3vpn));
+ if (bgp_attr_get_evpn_overlay(attr))
+ MIX(evpn_overlay_hash_key_make(bgp_attr_get_evpn_overlay(attr)));
if (attr->srv6_vpn)
MIX(srv6_vpn_hash_key_make(attr->srv6_vpn));
#ifdef ENABLE_BGP_VNC
@@ -814,19 +881,16 @@ bool attrhash_cmp(const void *p1, const void *p2)
const struct attr *attr1 = p1;
const struct attr *attr2 = p2;
- if (attr1->flag == attr2->flag && attr1->origin == attr2->origin
- && attr1->nexthop.s_addr == attr2->nexthop.s_addr
- && attr1->aspath == attr2->aspath
- && bgp_attr_get_community(attr1)
- == bgp_attr_get_community(attr2)
- && attr1->med == attr2->med
- && attr1->local_pref == attr2->local_pref
- && attr1->rmap_change_flags == attr2->rmap_change_flags) {
+ if (attr1->flag == attr2->flag && attr1->origin == attr2->origin &&
+ attr1->nexthop.s_addr == attr2->nexthop.s_addr &&
+ attr1->aspath == attr2->aspath &&
+ bgp_attr_get_community(attr1) == bgp_attr_get_community(attr2) &&
+ attr1->med == attr2->med && attr1->local_pref == attr2->local_pref &&
+ attr1->rmap_change_flags == attr2->rmap_change_flags) {
if (attr1->aggregator_as == attr2->aggregator_as &&
attr1->aggregator_addr.s_addr ==
attr2->aggregator_addr.s_addr &&
- attr1->weight == attr2->weight &&
- attr1->tag == attr2->tag &&
+ attr1->weight == attr2->weight && attr1->tag == attr2->tag &&
attr1->label_index == attr2->label_index &&
attr1->mp_nexthop_len == attr2->mp_nexthop_len &&
bgp_attr_get_ecommunity(attr1) ==
@@ -835,10 +899,8 @@ bool attrhash_cmp(const void *p1, const void *p2)
bgp_attr_get_ipv6_ecommunity(attr2) &&
bgp_attr_get_lcommunity(attr1) ==
bgp_attr_get_lcommunity(attr2) &&
- bgp_attr_get_cluster(attr1) ==
- bgp_attr_get_cluster(attr2) &&
- bgp_attr_get_transit(attr1) ==
- bgp_attr_get_transit(attr2) &&
+ bgp_attr_get_cluster(attr1) == bgp_attr_get_cluster(attr2) &&
+ bgp_attr_get_transit(attr1) == bgp_attr_get_transit(attr2) &&
bgp_attr_get_aigp_metric(attr1) ==
bgp_attr_get_aigp_metric(attr2) &&
attr1->rmap_table_id == attr2->rmap_table_id &&
@@ -870,8 +932,7 @@ bool attrhash_cmp(const void *p1, const void *p2)
srv6_vpn_same(attr1->srv6_vpn, attr2->srv6_vpn) &&
attr1->srte_color == attr2->srte_color &&
attr1->nh_type == attr2->nh_type &&
- attr1->bh_type == attr2->bh_type &&
- attr1->otc == attr2->otc)
+ attr1->bh_type == attr2->bh_type && attr1->otc == attr2->otc)
return true;
}
@@ -961,6 +1022,7 @@ struct attr *bgp_attr_intern(struct attr *attr)
struct ecommunity *ipv6_ecomm = NULL;
struct lcommunity *lcomm = NULL;
struct community *comm = NULL;
+ struct bgp_route_evpn *bre = NULL;
/* Intern referenced structure. */
if (attr->aspath) {
@@ -1027,6 +1089,16 @@ struct attr *bgp_attr_intern(struct attr *attr)
else
attr->encap_subtlvs->refcnt++;
}
+
+ bre = bgp_attr_get_evpn_overlay(attr);
+ if (bre) {
+ if (!bre->refcnt)
+ bgp_attr_set_evpn_overlay(attr,
+ evpn_overlay_intern(bre));
+ else
+ bre->refcnt++;
+ }
+
if (attr->srv6_l3vpn) {
if (!attr->srv6_l3vpn->refcnt)
attr->srv6_l3vpn = srv6_l3vpn_intern(attr->srv6_l3vpn);
@@ -1072,14 +1144,14 @@ struct attr *bgp_attr_default_set(struct attr *attr, struct bgp *bgp,
memset(attr, 0, sizeof(struct attr));
attr->origin = origin;
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN));
attr->aspath = aspath_empty(bgp->asnotation);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH));
attr->weight = BGP_ATTR_DEFAULT_WEIGHT;
attr->tag = 0;
attr->label_index = BGP_INVALID_LABEL_INDEX;
attr->label = MPLS_INVALID_LABEL;
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP));
attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
attr->local_pref = bgp->default_local_pref;
@@ -1101,18 +1173,18 @@ struct attr *bgp_attr_aggregate_intern(
/* Origin attribute. */
attr.origin = origin;
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
+ SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN));
/* MED */
attr.med = 0;
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
+ SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
/* AS path attribute. */
if (aspath)
attr.aspath = aspath_intern(aspath);
else
attr.aspath = aspath_empty(bgp->asnotation);
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
+ SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH));
if (community) {
uint32_t gshut = COMMUNITY_GSHUT;
@@ -1142,8 +1214,8 @@ struct attr *bgp_attr_aggregate_intern(
attr.weight = BGP_ATTR_DEFAULT_WEIGHT;
attr.mp_nexthop_len = IPV6_MAX_BYTELEN;
if (!aggregate->as_set || atomic_aggregate)
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
+ SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE));
+ SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR));
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
attr.aggregator_as = bgp->confed_id;
else
@@ -1161,7 +1233,7 @@ struct attr *bgp_attr_aggregate_intern(
*/
if (p->family == AF_INET) {
/* Next hop attribute. */
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
+ SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP));
attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
}
@@ -1216,6 +1288,7 @@ void bgp_attr_unintern_sub(struct attr *attr)
struct lcommunity *lcomm = NULL;
struct community *comm = NULL;
struct transit *transit;
+ struct bgp_route_evpn *bre;
/* aspath refcount shoud be decrement. */
aspath_unintern(&attr->aspath);
@@ -1257,6 +1330,10 @@ void bgp_attr_unintern_sub(struct attr *attr)
srv6_l3vpn_unintern(&attr->srv6_l3vpn);
srv6_vpn_unintern(&attr->srv6_vpn);
+
+ bre = bgp_attr_get_evpn_overlay(attr);
+ evpn_overlay_unintern(&bre);
+ bgp_attr_set_evpn_overlay(attr, NULL);
}
/* Free bgp attribute and aspath. */
@@ -1289,6 +1366,7 @@ void bgp_attr_flush(struct attr *attr)
struct cluster_list *cluster;
struct lcommunity *lcomm;
struct community *comm;
+ struct bgp_route_evpn *bre;
if (attr->aspath && !attr->aspath->refcnt) {
aspath_free(attr->aspath);
@@ -1347,6 +1425,11 @@ void bgp_attr_flush(struct attr *attr)
bgp_attr_set_vnc_subtlvs(attr, NULL);
}
#endif
+ bre = bgp_attr_get_evpn_overlay(attr);
+ if (bre && !bre->refcnt) {
+ evpn_overlay_free(bre);
+ bgp_attr_set_evpn_overlay(attr, NULL);
+ }
}
/* Implement draft-scudder-idr-optional-transitive behaviour and
@@ -1467,8 +1550,8 @@ bgp_attr_flags_diagnose(struct bgp_attr_parser_args *args,
uint8_t real_flags = args->flags;
const uint8_t attr_code = args->type;
- desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
- real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
+ UNSET_FLAG(desired_flags, BGP_ATTR_FLAG_EXTLEN);
+ UNSET_FLAG(real_flags, BGP_ATTR_FLAG_EXTLEN);
for (i = 0; i <= 2; i++) /* O,T,P, but not E */
if (CHECK_FLAG(desired_flags, attr_flag_str[i].key)
!= CHECK_FLAG(real_flags, attr_flag_str[i].key)) {
@@ -1582,7 +1665,7 @@ static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args *args)
&& CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS))
SET_FLAG(mask, BGP_ATTR_FLAG_PARTIAL);
- if ((flags & ~mask) == attr_flags_values[attr_code])
+ if (CHECK_FLAG(flags, ~mask) == attr_flags_values[attr_code])
return false;
bgp_attr_flags_diagnose(args, attr_flags_values[attr_code]);
@@ -1624,7 +1707,7 @@ bgp_attr_origin(struct bgp_attr_parser_args *args)
}
/* Set oring attribute flag. */
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN));
return 0;
}
@@ -1674,7 +1757,7 @@ static int bgp_attr_aspath(struct bgp_attr_parser_args *args)
}
/* Set aspath attribute flag. */
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH));
return BGP_ATTR_PARSE_PROCEED;
}
@@ -1778,7 +1861,7 @@ static int bgp_attr_as4_path(struct bgp_attr_parser_args *args,
}
/* Set aspath attribute flag. */
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH));
return BGP_ATTR_PARSE_PROCEED;
}
@@ -1828,7 +1911,7 @@ bgp_attr_nexthop(struct bgp_attr_parser_args *args)
}
attr->nexthop.s_addr = stream_get_ipv4(peer->curr);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP));
return BGP_ATTR_PARSE_PROCEED;
}
@@ -1851,7 +1934,7 @@ static enum bgp_attr_parse_ret bgp_attr_med(struct bgp_attr_parser_args *args)
attr->med = stream_getl(peer->curr);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
return BGP_ATTR_PARSE_PROCEED;
}
@@ -1889,7 +1972,7 @@ bgp_attr_local_pref(struct bgp_attr_parser_args *args)
STREAM_GETL(peer->curr, attr->local_pref);
/* Set the local-pref flag. */
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF));
return BGP_ATTR_PARSE_PROCEED;
@@ -1918,7 +2001,7 @@ static int bgp_attr_atomic(struct bgp_attr_parser_args *args)
goto atomic_ignore;
/* Set atomic aggregate flag. */
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE));
return BGP_ATTR_PARSE_PROCEED;
@@ -1976,7 +2059,7 @@ static int bgp_attr_aggregator(struct bgp_attr_parser_args *args)
zlog_debug("%s: attributes: %s", __func__, attr_str);
}
} else {
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR));
}
return BGP_ATTR_PARSE_PROCEED;
@@ -2027,7 +2110,7 @@ bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args,
zlog_debug("%s: attributes: %s", __func__, attr_str);
}
} else {
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR));
}
return BGP_ATTR_PARSE_PROCEED;
@@ -2066,12 +2149,13 @@ bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr,
* should not send them
*/
if (BGP_DEBUG(as4, AS4)) {
- if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
+ if (CHECK_FLAG(attr->flag,
+ (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH))))
zlog_debug("[AS4] %s %s AS4_PATH", peer->host,
"AS4 capable peer, yet it sent");
- if (attr->flag
- & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
+ if (CHECK_FLAG(attr->flag,
+ (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR))))
zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
peer->host,
"AS4 capable peer, yet it sent");
@@ -2083,8 +2167,9 @@ bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr,
/* We have a asn16 peer. First, look for AS4_AGGREGATOR
* because that may override AS4_PATH
*/
- if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR))) {
- if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
+ if (CHECK_FLAG(attr->flag, (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))) {
+ if (CHECK_FLAG(attr->flag,
+ (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)))) {
/* received both.
* if the as_number in aggregator is not AS_TRANS,
* then AS4_AGGREGATOR and AS4_PATH shall be ignored
@@ -2124,13 +2209,14 @@ bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr,
attr->aggregator_as = as4_aggregator;
/* sweep it under the carpet and simulate a "good"
* AGGREGATOR */
- attr->flag |= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR));
+ SET_FLAG(attr->flag,
+ (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)));
}
}
/* need to reconcile NEW_AS_PATH and AS_PATH */
- if (!ignore_as4_path
- && (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))) {
+ if (!ignore_as4_path &&
+ (CHECK_FLAG(attr->flag, (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH))))) {
newpath = aspath_reconcile_as4(attr->aspath, as4_path);
if (!newpath)
return BGP_ATTR_PARSE_ERROR;
@@ -2215,7 +2301,7 @@ bgp_attr_originator_id(struct bgp_attr_parser_args *args)
attr->originator_id.s_addr = stream_get_ipv4(peer->curr);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID));
return BGP_ATTR_PARSE_PROCEED;
@@ -2473,7 +2559,7 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
stream_forward_getp(s, nlri_len);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI));
return BGP_ATTR_PARSE_PROCEED;
#undef LEN_LEFT
@@ -2525,7 +2611,7 @@ int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
stream_forward_getp(s, withdraw_len);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI));
return BGP_ATTR_PARSE_PROCEED;
}
@@ -2575,7 +2661,6 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
const bgp_size_t length = args->length;
- uint8_t sticky = 0;
bool proxy = false;
struct ecommunity *ecomm;
@@ -2586,10 +2671,9 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
args->total);
}
- ecomm = ecommunity_parse(
- stream_pnt(peer->curr), length,
- CHECK_FLAG(peer->flags,
- PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
+ ecomm = ecommunity_parse(stream_pnt(peer->curr), length,
+ CHECK_FLAG(peer->flags,
+ PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
bgp_attr_set_ecommunity(attr, ecomm);
/* XXX: fix ecommunity_parse to use stream API */
stream_forward_getp(peer->curr, length);
@@ -2605,23 +2689,22 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
attr->df_pref = bgp_attr_df_pref_from_ec(attr, &attr->df_alg);
/* Extract MAC mobility sequence number, if any. */
- attr->mm_seqnum = bgp_attr_mac_mobility_seqnum(attr, &sticky);
- attr->sticky = sticky;
+ attr->mm_seqnum = bgp_attr_mac_mobility_seqnum(attr);
/* Check if this is a Gateway MAC-IP advertisement */
- attr->default_gw = bgp_attr_default_gw(attr);
+ bgp_attr_default_gw(attr);
/* Handle scenario where router flag ecommunity is not
* set but default gw ext community is present.
* Use default gateway, set and propogate R-bit.
*/
- if (attr->default_gw)
- attr->router_flag = 1;
+ if (CHECK_FLAG(attr->evpn_flags, ATTR_EVPN_FLAG_DEFAULT_GW))
+ SET_FLAG(attr->evpn_flags, ATTR_EVPN_FLAG_ROUTER);
/* Check EVPN Neighbor advertisement flags, R-bit */
- bgp_attr_evpn_na_flag(attr, &attr->router_flag, &proxy);
+ bgp_attr_evpn_na_flag(attr, &proxy);
if (proxy)
- attr->es_flags |= ATTR_ES_PROXY_ADVERT;
+ SET_FLAG(attr->es_flags, ATTR_ES_PROXY_ADVERT);
/* Extract the Rmac, if any */
if (bgp_attr_rmac(attr, &attr->rmac)) {
@@ -2692,6 +2775,9 @@ static int bgp_attr_encap(struct bgp_attr_parser_args *args)
uint8_t type = args->type;
uint8_t flag = args->flags;
+ if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
+ goto encap_ignore;
+
if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
|| !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) {
zlog_err("Tunnel Encap attribute flag isn't optional and transitive %d",
@@ -2810,7 +2896,14 @@ static int bgp_attr_encap(struct bgp_attr_parser_args *args)
args->total);
}
- return 0;
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ENCAP));
+
+ return BGP_ATTR_PARSE_PROCEED;
+
+encap_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ return bgp_attr_ignore(peer, type);
}
@@ -3202,6 +3295,9 @@ enum bgp_attr_parse_ret bgp_attr_prefix_sid(struct bgp_attr_parser_args *args)
size_t headersz = sizeof(type) + sizeof(length);
size_t psid_parsed_length = 0;
+ if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
+ goto prefix_sid_ignore;
+
while (STREAM_READABLE(peer->curr) > 0
&& psid_parsed_length < args->length) {
@@ -3249,6 +3345,11 @@ enum bgp_attr_parse_ret bgp_attr_prefix_sid(struct bgp_attr_parser_args *args)
SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID));
return BGP_ATTR_PARSE_PROCEED;
+
+prefix_sid_ignore:
+ stream_forward_getp(peer->curr, args->length);
+
+ return bgp_attr_ignore(peer, args->type);
}
/* PMSI tunnel attribute (RFC 6514)
@@ -3263,6 +3364,9 @@ bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
uint8_t tnl_type;
int attr_parse_len = 2 + BGP_LABEL_BYTES;
+ if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
+ goto pmsi_tunnel_ignore;
+
/* Verify that the receiver is expecting "ingress replication" as we
* can only support that.
*/
@@ -3291,7 +3395,7 @@ bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
}
}
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL));
bgp_attr_set_pmsi_tnl_type(attr, tnl_type);
stream_get(&attr->label, peer->curr, BGP_LABEL_BYTES);
@@ -3299,6 +3403,11 @@ bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
stream_forward_getp(peer->curr, length - attr_parse_len);
return BGP_ATTR_PARSE_PROCEED;
+
+pmsi_tunnel_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ return bgp_attr_ignore(peer, args->type);
}
/* AIGP attribute (rfc7311) */
@@ -3369,7 +3478,7 @@ static enum bgp_attr_parse_ret bgp_attr_otc(struct bgp_attr_parser_args *args)
args->total);
}
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_OTC));
return BGP_ATTR_PARSE_PROCEED;
@@ -3566,18 +3675,17 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
* unused. They MUST be zero when sent and MUST be ignored when
* received.
*/
- flag = 0xF0 & stream_getc(BGP_INPUT(peer));
+ flag = CHECK_FLAG(0xF0, stream_getc(BGP_INPUT(peer)));
type = stream_getc(BGP_INPUT(peer));
/* Check whether Extended-Length applies and is in bounds */
if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN)
&& ((endp - startp) < (BGP_ATTR_MIN_LEN + 1))) {
- flog_warn(
- EC_BGP_EXT_ATTRIBUTE_TOO_SMALL,
- "%s: Extended length set, but just %lu bytes of attr header",
- peer->host,
- (unsigned long)(endp
- - stream_pnt(BGP_INPUT(peer))));
+ flog_warn(EC_BGP_EXT_ATTRIBUTE_TOO_SMALL,
+ "%s: Extended length set, but just %lu bytes of attr header",
+ peer->host,
+ (unsigned long)(endp -
+ stream_pnt(BGP_INPUT(peer))));
if (peer->sort != BGP_PEER_EBGP) {
bgp_notify_send(peer->connection,
@@ -3924,7 +4032,7 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
* Finally do the checks on the aspath we did not do yet
* because we waited for a potentially synthesized aspath.
*/
- if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) {
+ if (CHECK_FLAG(attr->flag, (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))) {
ret = bgp_attr_aspath_check(peer, attr);
if (ret != BGP_ATTR_PARSE_PROCEED)
goto done;
@@ -4102,8 +4210,8 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
case SAFI_MULTICAST:
case SAFI_LABELED_UNICAST:
case SAFI_EVPN: {
- if (attr->mp_nexthop_len
- == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
+ if (attr->mp_nexthop_len ==
+ BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
stream_putc(s,
BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL);
stream_put(s, &attr->mp_nexthop_global,
@@ -4324,12 +4432,12 @@ static void bgp_packet_mpattr_tea(struct bgp *bgp, struct peer *peer,
BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN);
stream_putc(s, attrtype);
- stream_putw(s, attrlenfield & 0xffff);
+ stream_putw(s, CHECK_FLAG(attrlenfield, 0xffff));
} else {
/* 1-octet length field */
stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL);
stream_putc(s, attrtype);
- stream_putc(s, attrlenfield & 0xff);
+ stream_putc(s, CHECK_FLAG(attrlenfield, 0xff));
}
if (attrtype == BGP_ATTR_ENCAP) {
@@ -4440,14 +4548,11 @@ static void bgp_packet_ecommunity_attribute(struct stream *s, struct peer *peer,
}
/* Make attribute packet. */
-bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
- struct stream *s, struct attr *attr,
- struct bpacket_attr_vec_arr *vecarr,
- struct prefix *p, afi_t afi, safi_t safi,
- struct peer *from, struct prefix_rd *prd,
- mpls_label_t *label, uint8_t num_labels,
- bool addpath_capable, uint32_t addpath_tx_id,
- struct bgp_path_info *bpi)
+bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, struct stream *s,
+ struct attr *attr, struct bpacket_attr_vec_arr *vecarr,
+ struct prefix *p, afi_t afi, safi_t safi, struct peer *from,
+ struct prefix_rd *prd, mpls_label_t *label, uint8_t num_labels,
+ bool addpath_capable, uint32_t addpath_tx_id)
{
size_t cp;
size_t aspath_sizep;
@@ -4476,6 +4581,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
bgp_packet_mpattr_end(s, mpattrlen_pos);
}
+ (void)peer_sort(peer);
+
/* Origin attribute. */
stream_putc(s, BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_ORIGIN);
@@ -4569,15 +4676,15 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
&& !peer_cap_enhe(peer, afi, safi)) {
afi_t nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->mp_nexthop_len);
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))) {
stream_putc(s, BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_NEXT_HOP);
bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s,
attr);
stream_putc(s, 4);
stream_put_ipv4(s, attr->nexthop.s_addr);
- } else if (peer_cap_enhe(from, afi, safi)
- || (nh_afi == AFI_IP6)) {
+ } else if (peer_cap_enhe(from, afi, safi) ||
+ (nh_afi == AFI_IP6)) {
/*
* Likely this is the case when an IPv4 prefix was
* received with Extended Next-hop capability in this
@@ -4599,8 +4706,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
}
/* MED attribute. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)
- || bgp->maxmed_active) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) ||
+ bgp->maxmed_active) {
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
stream_putc(s, BGP_ATTR_MULTI_EXIT_DISC);
stream_putc(s, 4);
@@ -4618,14 +4725,14 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
}
/* Atomic aggregate. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))) {
stream_putc(s, BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_ATOMIC_AGGREGATE);
stream_putc(s, 0);
}
/* Aggregator. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
/* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_AGGREGATOR);
@@ -4656,8 +4763,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
}
/* Community attribute. */
- if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
- && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) {
+ if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) &&
+ CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) {
struct community *comm = NULL;
comm = bgp_attr_get_community(attr);
@@ -4681,8 +4788,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
* Large Community attribute.
*/
if (CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_SEND_LARGE_COMMUNITY)
- && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) {
+ PEER_FLAG_SEND_LARGE_COMMUNITY) &&
+ CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) {
if (lcom_length(bgp_attr_get_lcommunity(attr)) > 255) {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
@@ -4712,7 +4819,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
stream_putc(s, BGP_ATTR_ORIGINATOR_ID);
stream_putc(s, 4);
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
+ if (CHECK_FLAG(attr->flag,
+ ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))
stream_put_in_addr(s, &attr->originator_id);
else
stream_put_in_addr(s, &from->remote_id);
@@ -4725,7 +4833,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
stream_putc(s, cluster->length + 4);
/* If this peer configuration's parent BGP has
* cluster_id. */
- if (bgp->config & BGP_CONFIG_CLUSTER_ID)
+ if (CHECK_FLAG(bgp->config, BGP_CONFIG_CLUSTER_ID))
stream_put_in_addr(s, &bgp->cluster_id);
else
stream_put_in_addr(s, &bgp->router_id);
@@ -4734,7 +4842,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
stream_putc(s, 4);
/* If this peer configuration's parent BGP has
* cluster_id. */
- if (bgp->config & BGP_CONFIG_CLUSTER_ID)
+ if (CHECK_FLAG(bgp->config, BGP_CONFIG_CLUSTER_ID))
stream_put_in_addr(s, &bgp->cluster_id);
else
stream_put_in_addr(s, &bgp->router_id);
@@ -4902,7 +5010,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
}
/* PMSI Tunnel */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL))) {
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_PMSI_TUNNEL);
stream_putc(s, 9); // Length
@@ -4915,7 +5023,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
}
/* OTC */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_OTC))) {
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_OTC);
stream_putc(s, 4);
@@ -4923,10 +5031,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
}
/* AIGP */
- if (bpi && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP) &&
- (CHECK_FLAG(peer->flags, PEER_FLAG_AIGP) ||
- peer->sub_sort == BGP_PEER_EBGP_OAD ||
- peer->sort != BGP_PEER_EBGP)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) && AIGP_TRANSMIT_ALLOWED(peer)) {
/* At the moment only AIGP Metric TLV exists for AIGP
* attribute. If more comes in, do not forget to update
* attr_len variable to include new ones.
@@ -4936,7 +5041,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
stream_putc(s, BGP_ATTR_AIGP);
stream_putc(s, attr_len);
- stream_put_bgp_aigp_tlv_metric(s, bpi);
+ stream_put_bgp_aigp_tlv_metric(s, attr->aigp_metric);
}
/* Unknown transit attribute. */
@@ -5006,6 +5111,7 @@ void bgp_attr_init(void)
transit_init();
encap_init();
srv6_init();
+ evpn_overlay_init();
}
void bgp_attr_finish(void)
@@ -5019,6 +5125,7 @@ void bgp_attr_finish(void)
transit_finish();
encap_finish();
srv6_finish();
+ evpn_overlay_finish();
}
/* Make attribute packet. */
@@ -5064,7 +5171,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
}
/* MED attribute. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))) {
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
stream_putc(s, BGP_ATTR_MULTI_EXIT_DISC);
stream_putc(s, 4);
@@ -5072,7 +5179,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
}
/* Local preference. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
stream_putc(s, BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_LOCAL_PREF);
stream_putc(s, 4);
@@ -5080,14 +5187,14 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
}
/* Atomic aggregate. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))) {
stream_putc(s, BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_ATOMIC_AGGREGATE);
stream_putc(s, 0);
}
/* Aggregator. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_AGGREGATOR);
stream_putc(s, 8);
@@ -5096,7 +5203,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
}
/* Community attribute. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) {
struct community *comm = NULL;
comm = bgp_attr_get_community(attr);
@@ -5107,9 +5214,8 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
stream_putc(s, BGP_ATTR_COMMUNITIES);
stream_putw(s, comm->size * 4);
} else {
- stream_putc(s,
- BGP_ATTR_FLAG_OPTIONAL
- | BGP_ATTR_FLAG_TRANS);
+ stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
+ BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_COMMUNITIES);
stream_putc(s, comm->size * 4);
}
@@ -5117,7 +5223,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
}
/* Large Community attribute. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) {
if (lcom_length(bgp_attr_get_lcommunity(attr)) > 255) {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
@@ -5126,9 +5232,8 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
stream_putw(s,
lcom_length(bgp_attr_get_lcommunity(attr)));
} else {
- stream_putc(s,
- BGP_ATTR_FLAG_OPTIONAL
- | BGP_ATTR_FLAG_TRANS);
+ stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
+ BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
stream_putc(s,
lcom_length(bgp_attr_get_lcommunity(attr)));
@@ -5172,11 +5277,10 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
}
/* Prefix SID */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID))) {
if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
- stream_putc(s,
- BGP_ATTR_FLAG_OPTIONAL
- | BGP_ATTR_FLAG_TRANS);
+ stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
+ BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_PREFIX_SID);
stream_putc(s, 10);
stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX);
@@ -5188,7 +5292,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
}
/* OTC */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_OTC))) {
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_OTC);
stream_putc(s, 4);
@@ -5196,7 +5300,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
}
/* AIGP */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP))) {
/* At the moment only AIGP Metric TLV exists for AIGP
* attribute. If more comes in, do not forget to update
* attr_len variable to include new ones.
@@ -5206,7 +5310,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_AIGP);
stream_putc(s, attr_len);
- stream_put_bgp_aigp_tlv_metric(s, bpi);
+ stream_put_bgp_aigp_tlv_metric(s, attr->aigp_metric);
}
/* Return total size of attribute. */
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index f353e769..5633c2f8 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -197,9 +197,6 @@ struct attr {
#define ATTR_ES_L3_NHG_ACTIVE (1 << 6)
#define ATTR_ES_L3_NHG (ATTR_ES_L3_NHG_USE | ATTR_ES_L3_NHG_ACTIVE)
- /* NA router flag (R-bit) support in EVPN */
- uint8_t router_flag;
-
/* Distance as applied by Route map */
uint8_t distance;
@@ -212,7 +209,7 @@ struct attr {
/* has the route-map changed any attribute?
Used on the peer outbound side. */
- uint32_t rmap_change_flags;
+ uint16_t rmap_change_flags;
/* Multi-Protocol Nexthop, AFI IPv6 */
struct in6_addr mp_nexthop_global;
@@ -256,11 +253,12 @@ struct attr {
/* MP Nexthop length */
uint8_t mp_nexthop_len;
- /* Static MAC for EVPN */
- uint8_t sticky;
-
- /* Flag for default gateway extended community in EVPN */
- uint8_t default_gw;
+ /* EVPN flags */
+ uint8_t evpn_flags;
+#define ATTR_EVPN_FLAG_STICKY (1 << 0)
+#define ATTR_EVPN_FLAG_DEFAULT_GW (1 << 1)
+/* NA router flag (R-bit) support in EVPN */
+#define ATTR_EVPN_FLAG_ROUTER (1 << 2)
/* route tag */
route_tag_t tag;
@@ -280,7 +278,7 @@ struct attr {
struct bgp_attr_encap_subtlv *vnc_subtlvs; /* VNC-specific */
#endif
/* EVPN */
- struct bgp_route_evpn evpn_overlay;
+ struct bgp_route_evpn *evpn_overlay;
/* EVPN MAC Mobility sequence number, if any. */
uint32_t mm_seqnum;
@@ -295,7 +293,7 @@ struct attr {
/* EVPN local router-mac */
struct ethaddr rmac;
- uint16_t encap_tunneltype;
+ uint8_t encap_tunneltype;
/* rmap set table */
uint32_t rmap_table_id;
@@ -355,7 +353,7 @@ struct transit {
__builtin_choose_expr((X) >= 1 && (X) <= 64, 1ULL << ((X)-1), (void)0)
#define BGP_CLUSTER_LIST_LENGTH(attr) \
- (((attr)->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) \
+ (CHECK_FLAG((attr)->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) \
? bgp_attr_get_cluster((attr))->length \
: 0)
@@ -389,12 +387,12 @@ 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 *peer, struct stream *s, struct attr *attr,
- struct bpacket_attr_vec_arr *vecarr, struct prefix *p, afi_t afi,
- safi_t safi, struct peer *from, struct prefix_rd *prd,
- mpls_label_t *label, uint8_t num_labels, bool addpath_capable,
- uint32_t addpath_tx_id, struct bgp_path_info *bpi);
+extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, struct stream *s,
+ struct attr *attr, struct bpacket_attr_vec_arr *vecarr,
+ struct prefix *p, afi_t afi, safi_t safi, struct peer *from,
+ struct prefix_rd *prd, mpls_label_t *label,
+ uint8_t num_labels, bool addpath_capable,
+ uint32_t addpath_tx_id);
extern void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
const struct prefix *p);
extern bool attrhash_cmp(const void *arg1, const void *arg2);
@@ -587,6 +585,10 @@ static inline void bgp_attr_set_transit(struct attr *attr,
attr->transit = transit;
}
+#define AIGP_TRANSMIT_ALLOWED(peer) \
+ (CHECK_FLAG((peer)->flags, PEER_FLAG_AIGP) || ((peer)->sub_sort == BGP_PEER_EBGP_OAD) || \
+ ((peer)->sort != BGP_PEER_EBGP))
+
static inline uint64_t bgp_attr_get_aigp_metric(const struct attr *attr)
{
return attr->aigp_metric;
@@ -595,9 +597,17 @@ static inline uint64_t bgp_attr_get_aigp_metric(const struct attr *attr)
static inline void bgp_attr_set_aigp_metric(struct attr *attr, uint64_t aigp)
{
attr->aigp_metric = aigp;
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP));
+}
- if (aigp)
- SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP));
+static inline uint64_t bgp_aigp_metric_total(struct bgp_path_info *bpi)
+{
+ uint64_t aigp = bgp_attr_get_aigp_metric(bpi->attr);
+
+ if (bpi->nexthop)
+ return aigp + bpi->nexthop->metric;
+ else
+ return aigp;
}
static inline struct cluster_list *bgp_attr_get_cluster(const struct attr *attr)
@@ -616,16 +626,16 @@ static inline void bgp_attr_set_cluster(struct attr *attr,
UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST));
}
-static inline const struct bgp_route_evpn *
+static inline struct bgp_route_evpn *
bgp_attr_get_evpn_overlay(const struct attr *attr)
{
- return &attr->evpn_overlay;
+ return attr->evpn_overlay;
}
static inline void bgp_attr_set_evpn_overlay(struct attr *attr,
- struct bgp_route_evpn *eo)
+ struct bgp_route_evpn *bre)
{
- memcpy(&attr->evpn_overlay, eo, sizeof(struct bgp_route_evpn));
+ attr->evpn_overlay = bre;
}
static inline struct bgp_attr_encap_subtlv *
@@ -648,5 +658,6 @@ bgp_attr_set_vnc_subtlvs(struct attr *attr,
}
extern bool route_matches_soo(struct bgp_path_info *pi, struct ecommunity *soo);
+extern void evpn_overlay_free(struct bgp_route_evpn *bre);
#endif /* _QUAGGA_BGP_ATTR_H */
diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c
index bbc4ba95..a3ffe61e 100644
--- a/bgpd/bgp_attr_evpn.c
+++ b/bgpd/bgp_attr_evpn.c
@@ -24,6 +24,13 @@
bool bgp_route_evpn_same(const struct bgp_route_evpn *e1,
const struct bgp_route_evpn *e2)
{
+ if (!e1 && e2)
+ return false;
+ if (!e2 && e1)
+ return false;
+ if (!e1 && !e2)
+ return true;
+
return (e1->type == e2->type &&
!memcmp(&(e1->eth_s_id), &(e2->eth_s_id), sizeof(esi_t)) &&
!ipaddr_cmp(&(e1->gw_ip), &(e2->gw_ip)));
@@ -115,14 +122,14 @@ bool bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac)
/*
* return true if attr contains default gw extended community
*/
-uint8_t bgp_attr_default_gw(struct attr *attr)
+void bgp_attr_default_gw(struct attr *attr)
{
struct ecommunity *ecom;
uint32_t i;
ecom = bgp_attr_get_ecommunity(attr);
if (!ecom || !ecom->size)
- return 0;
+ return;
/* If there is a default gw extendd community return true otherwise
* return 0 */
@@ -136,10 +143,9 @@ uint8_t bgp_attr_default_gw(struct attr *attr)
if ((type == ECOMMUNITY_ENCODE_OPAQUE
&& sub_type == ECOMMUNITY_EVPN_SUBTYPE_DEF_GW))
- return 1;
+ SET_FLAG(attr->evpn_flags, ATTR_EVPN_FLAG_DEFAULT_GW);
}
-
- return 0;
+ UNSET_FLAG(attr->evpn_flags, ATTR_EVPN_FLAG_DEFAULT_GW);
}
/*
@@ -183,7 +189,7 @@ uint16_t bgp_attr_df_pref_from_ec(struct attr *attr, uint8_t *alg)
* Fetch and return the sequence number from MAC Mobility extended
* community, if present, else 0.
*/
-uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky)
+uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr)
{
struct ecommunity *ecom;
uint32_t i;
@@ -212,10 +218,11 @@ uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky)
continue;
flags = *pnt++;
- if (flags & ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY)
- *sticky = 1;
+ if (CHECK_FLAG(flags,
+ ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY))
+ SET_FLAG(attr->evpn_flags, ATTR_EVPN_FLAG_STICKY);
else
- *sticky = 0;
+ UNSET_FLAG(attr->evpn_flags, ATTR_EVPN_FLAG_STICKY);
pnt++;
pnt = ptr_get_be32(pnt, &seq_num);
@@ -229,8 +236,7 @@ uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky)
/*
* return true if attr contains router flag extended community
*/
-void bgp_attr_evpn_na_flag(struct attr *attr,
- uint8_t *router_flag, bool *proxy)
+void bgp_attr_evpn_na_flag(struct attr *attr, bool *proxy)
{
struct ecommunity *ecom;
uint32_t i;
@@ -253,10 +259,12 @@ void bgp_attr_evpn_na_flag(struct attr *attr,
sub_type == ECOMMUNITY_EVPN_SUBTYPE_ND) {
val = *pnt++;
- if (val & ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG)
- *router_flag = 1;
+ if (CHECK_FLAG(val,
+ ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG))
+ SET_FLAG(attr->evpn_flags,
+ ATTR_EVPN_FLAG_ROUTER);
- if (val & ECOMMUNITY_EVPN_SUBTYPE_PROXY_FLAG)
+ if (CHECK_FLAG(val, ECOMMUNITY_EVPN_SUBTYPE_PROXY_FLAG))
*proxy = true;
break;
diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h
index f8d3978b..cc0e3e44 100644
--- a/bgpd/bgp_attr_evpn.h
+++ b/bgpd/bgp_attr_evpn.h
@@ -23,6 +23,7 @@ enum overlay_index_type {
* MAC overlay index is stored in the RMAC attribute.
*/
struct bgp_route_evpn {
+ unsigned long refcnt;
enum overlay_index_type type;
esi_t eth_s_id;
struct ipaddr gw_ip;
@@ -36,12 +37,10 @@ extern void bgp_add_routermac_ecom(struct attr *attr,
extern int bgp_build_evpn_prefix(int type, uint32_t eth_tag,
struct prefix *dst);
extern bool bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac);
-extern uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr,
- uint8_t *sticky);
-extern uint8_t bgp_attr_default_gw(struct attr *attr);
+extern uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr);
+extern void bgp_attr_default_gw(struct attr *attr);
-extern void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag,
- bool *proxy);
+extern void bgp_attr_evpn_na_flag(struct attr *attr, bool *proxy);
extern uint16_t bgp_attr_df_pref_from_ec(struct attr *attr, uint8_t *alg);
diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c
index 675e4765..7b67d4b8 100644
--- a/bgpd/bgp_bmp.c
+++ b/bgpd/bgp_bmp.c
@@ -934,9 +934,8 @@ static struct stream *bmp_update(const struct prefix *p, struct prefix_rd *prd,
stream_putw(s, 0);
/* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
- total_attr_len =
- bgp_packet_attribute(NULL, peer, s, attr, &vecarr, NULL, afi,
- safi, peer, NULL, NULL, 0, 0, 0, NULL);
+ total_attr_len = bgp_packet_attribute(NULL, peer, s, attr, &vecarr, NULL, afi, safi, peer,
+ NULL, NULL, 0, 0, 0);
/* space check? */
@@ -1047,7 +1046,7 @@ static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags,
static bool bmp_wrsync(struct bmp *bmp, struct pullwr *pullwr)
{
- uint8_t bpi_num_labels;
+ uint8_t bpi_num_labels, adjin_num_labels;
afi_t afi;
safi_t safi;
@@ -1241,11 +1240,12 @@ afibreak:
bpi_num_labels ? bpi->extra->labels->label : NULL,
bpi_num_labels);
- if (adjin)
- /* TODO: set label here when adjin supports labels */
- bmp_monitor(bmp, adjin->peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE,
- bn_p, prd, adjin->attr, afi, safi, adjin->uptime,
- NULL, 0);
+ if (adjin) {
+ adjin_num_labels = adjin->labels ? adjin->labels->num_labels : 0;
+ bmp_monitor(bmp, adjin->peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE, bn_p, prd,
+ adjin->attr, afi, safi, adjin->uptime,
+ adjin_num_labels ? &adjin->labels->label[0] : NULL, adjin_num_labels);
+ }
if (bn)
bgp_dest_unlock_node(bn);
@@ -1382,7 +1382,7 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
struct peer *peer;
struct bgp_dest *bn = NULL;
bool written = false;
- uint8_t bpi_num_labels;
+ uint8_t bpi_num_labels, adjin_num_labels;
bqe = bmp_pull(bmp);
if (!bqe)
@@ -1453,10 +1453,11 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
if (adjin->peer == peer)
break;
}
- /* TODO: set label here when adjin supports labels */
- bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE,
- &bqe->p, prd, adjin ? adjin->attr : NULL, afi, safi,
- adjin ? adjin->uptime : monotime(NULL), NULL, 0);
+ adjin_num_labels = adjin && adjin->labels ? adjin->labels->num_labels : 0;
+ bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE, &bqe->p, prd,
+ adjin ? adjin->attr : NULL, afi, safi,
+ adjin ? adjin->uptime : monotime(NULL),
+ adjin_num_labels ? &adjin->labels->label[0] : NULL, adjin_num_labels);
written = true;
}
@@ -2543,9 +2544,9 @@ DEFPY(bmp_monitor_cfg, bmp_monitor_cmd,
prev = bt->afimon[afi][safi];
if (no)
- bt->afimon[afi][safi] &= ~flag;
+ UNSET_FLAG(bt->afimon[afi][safi], flag);
else
- bt->afimon[afi][safi] |= flag;
+ SET_FLAG(bt->afimon[afi][safi], flag);
if (prev == bt->afimon[afi][safi])
return CMD_SUCCESS;
@@ -2743,7 +2744,7 @@ DEFPY(show_bmp,
}
out = ttable_dump(tt, "\n");
vty_out(vty, "%s", out);
- XFREE(MTYPE_TMP, out);
+ XFREE(MTYPE_TMP_TTABLE, out);
ttable_del(tt);
vty_out(vty, "\n %zu connected clients:\n",
@@ -2770,7 +2771,7 @@ DEFPY(show_bmp,
}
out = ttable_dump(tt, "\n");
vty_out(vty, "%s", out);
- XFREE(MTYPE_TMP, out);
+ XFREE(MTYPE_TMP_TTABLE, out);
ttable_del(tt);
vty_out(vty, "\n");
}
@@ -2828,8 +2829,7 @@ static int bmp_config_write(struct bgp *bgp, struct vty *vty)
afi2str_lower(afi), safi2str(safi));
}
frr_each (bmp_listeners, &bt->listeners, bl)
- vty_out(vty, " \n bmp listener %pSU port %d\n",
- &bl->addr, bl->port);
+ vty_out(vty, " bmp listener %pSU port %d\n", &bl->addr, bl->port);
frr_each (bmp_actives, &bt->actives, ba) {
vty_out(vty, " bmp connect %s port %u min-retry %u max-retry %u",
diff --git a/bgpd/bgp_btoa.c b/bgpd/bgp_btoa.c
index 1d5034ef..32823cc3 100644
--- a/bgpd/bgp_btoa.c
+++ b/bgpd/bgp_btoa.c
@@ -69,7 +69,7 @@ static void attr_parse(struct stream *s, uint16_t len)
flag = stream_getc(s);
type = stream_getc(s);
- if (flag & BGP_ATTR_FLAG_EXTLEN)
+ if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN))
length = stream_getw(s);
else
length = stream_getc(s);
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c
index 153cbd6e..61ba5274 100644
--- a/bgpd/bgp_clist.c
+++ b/bgpd/bgp_clist.c
@@ -182,7 +182,7 @@ community_list_insert(struct community_list_handler *ch, const char *name,
}
/* In case of name is all digit character */
- if (i == strlen(name)) {
+ if (i == strlen(name) && number <= COMMUNITY_LIST_NUMBER_MAX) {
new->sort = COMMUNITY_LIST_NUMBER;
/* Set access_list to number list. */
@@ -496,8 +496,8 @@ static char *community_str_get(struct community *com, int i)
break;
default:
str = XSTRDUP(MTYPE_COMMUNITY_STR, "65536:65535");
- as = (comval >> 16) & 0xFFFF;
- val = comval & 0xFFFF;
+ as = CHECK_FLAG((comval >> 16), 0xFFFF);
+ val = CHECK_FLAG(comval, 0xFFFF);
snprintf(str, strlen(str), "%u:%d", as, val);
break;
}
diff --git a/bgpd/bgp_clist.h b/bgpd/bgp_clist.h
index 29bd880c..7f35a6d5 100644
--- a/bgpd/bgp_clist.h
+++ b/bgpd/bgp_clist.h
@@ -20,6 +20,10 @@
/* Number and string based community-list name. */
#define COMMUNITY_LIST_STRING 0
#define COMMUNITY_LIST_NUMBER 1
+/* The numbered community-list (including large/ext communities)
+ * have a range between 1-500.
+ */
+#define COMMUNITY_LIST_NUMBER_MAX 500
#define COMMUNITY_SEQ_NUMBER_AUTO -1
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c
index 8e4c4305..602c1437 100644
--- a/bgpd/bgp_community.c
+++ b/bgpd/bgp_community.c
@@ -416,13 +416,12 @@ static void set_community_string(struct community *com, bool make_json,
}
break;
default:
- as = (comval >> 16) & 0xFFFF;
- val = comval & 0xFFFF;
+ as = CHECK_FLAG((comval >> 16), 0xFFFF);
+ val = CHECK_FLAG(comval, 0xFFFF);
char buf[32];
snprintf(buf, sizeof(buf), "%u:%d", as, val);
const char *com2alias =
- translate_alias ? bgp_community2alias(buf)
- : buf;
+ translate_alias ? bgp_community2alias(buf) : buf;
strlcat(str, com2alias, len);
if (make_json) {
diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c
index 339bfae5..93f5a199 100644
--- a/bgpd/bgp_damp.c
+++ b/bgpd/bgp_damp.c
@@ -779,7 +779,8 @@ int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi,
bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
bgp = bgp_get_default();
- if (bgp == NULL) {
+
+ if (bgp == NULL || IS_BGP_INSTANCE_HIDDEN(bgp)) {
vty_out(vty, "No BGP process is configured\n");
return CMD_WARNING;
}
diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c
index 6228432b..97c3e574 100644
--- a/bgpd/bgp_debug.c
+++ b/bgpd/bgp_debug.c
@@ -2558,7 +2558,7 @@ static int bgp_debug_per_prefix(const struct prefix *p,
struct bgp_debug_filter *filter;
struct listnode *node, *nnode;
- if (term_bgp_debug_type & BGP_DEBUG_TYPE) {
+ if (CHECK_FLAG(term_bgp_debug_type, BGP_DEBUG_TYPE)) {
/* We are debugging all prefixes so return true */
if (!per_prefix_list || list_isempty(per_prefix_list))
return 1;
@@ -2591,7 +2591,7 @@ static bool bgp_debug_per_peer(char *host, const struct prefix *p,
struct bgp_debug_filter *filter;
struct listnode *node, *nnode;
- if (term_bgp_debug_type & BGP_DEBUG_TYPE) {
+ if (CHECK_FLAG(term_bgp_debug_type, BGP_DEBUG_TYPE)) {
/* We are debugging all peers so return true */
if (!per_peer_list || list_isempty(per_peer_list))
return true;
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index 1beb0307..547dcdf7 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -515,7 +515,7 @@ static int ecommunity_encode_internal(uint8_t type, uint8_t sub_type,
/* Fill in the values. */
eval->val[0] = type;
if (!trans)
- eval->val[0] |= ECOMMUNITY_FLAG_NON_TRANSITIVE;
+ SET_FLAG(eval->val[0], ECOMMUNITY_FLAG_NON_TRANSITIVE);
eval->val[1] = sub_type;
if (type == ECOMMUNITY_ENCODE_AS) {
encode_route_target_as(as, val, eval, trans);
@@ -1293,11 +1293,12 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
== ECOMMUNITY_EVPN_SUBTYPE_ESI_LABEL) {
uint8_t flags = *++pnt;
- snprintf(encbuf,
- sizeof(encbuf), "ESI-label-Rt:%s",
- (flags &
- ECOMMUNITY_EVPN_SUBTYPE_ESI_SA_FLAG) ?
- "SA":"AA");
+ snprintf(encbuf, sizeof(encbuf),
+ "ESI-label-Rt:%s",
+ CHECK_FLAG(flags,
+ ECOMMUNITY_EVPN_SUBTYPE_ESI_SA_FLAG)
+ ? "SA"
+ : "AA");
} else if (*pnt
== ECOMMUNITY_EVPN_SUBTYPE_DF_ELECTION) {
uint8_t alg;
@@ -1337,38 +1338,37 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
char buf[ECOMMUNITY_STRLEN];
memset(buf, 0, sizeof(buf));
- ecommunity_rt_soo_str_internal(buf, sizeof(buf),
- (const uint8_t *)pnt,
- type &
- ~ECOMMUNITY_ENCODE_TRANS_EXP,
- ECOMMUNITY_ROUTE_TARGET,
- format,
- ecom->unit_size);
+ ecommunity_rt_soo_str_internal(
+ buf, sizeof(buf), (const uint8_t *)pnt,
+ CHECK_FLAG(type,
+ ~ECOMMUNITY_ENCODE_TRANS_EXP),
+ ECOMMUNITY_ROUTE_TARGET, format,
+ ecom->unit_size);
snprintf(encbuf, sizeof(encbuf), "%s", buf);
} else if (sub_type ==
ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6) {
char buf[64];
memset(buf, 0, sizeof(buf));
- ecommunity_rt_soo_str_internal(buf, sizeof(buf),
- (const uint8_t *)pnt,
- type &
- ~ECOMMUNITY_ENCODE_TRANS_EXP,
- ECOMMUNITY_ROUTE_TARGET,
- ECOMMUNITY_FORMAT_DISPLAY,
- ecom->unit_size);
+ ecommunity_rt_soo_str_internal(
+ buf, sizeof(buf), (const uint8_t *)pnt,
+ CHECK_FLAG(type,
+ ~ECOMMUNITY_ENCODE_TRANS_EXP),
+ ECOMMUNITY_ROUTE_TARGET,
+ ECOMMUNITY_FORMAT_DISPLAY,
+ ecom->unit_size);
snprintf(encbuf, sizeof(encbuf),
"FS:redirect VRF %s", buf);
} else if (sub_type == ECOMMUNITY_REDIRECT_VRF) {
char buf[16];
memset(buf, 0, sizeof(buf));
- ecommunity_rt_soo_str(buf, sizeof(buf),
- (const uint8_t *)pnt,
- type &
- ~ECOMMUNITY_ENCODE_TRANS_EXP,
- ECOMMUNITY_ROUTE_TARGET,
- ECOMMUNITY_FORMAT_DISPLAY);
+ ecommunity_rt_soo_str(
+ buf, sizeof(buf), (const uint8_t *)pnt,
+ CHECK_FLAG(type,
+ ~ECOMMUNITY_ENCODE_TRANS_EXP),
+ ECOMMUNITY_ROUTE_TARGET,
+ ECOMMUNITY_FORMAT_DISPLAY);
snprintf(encbuf, sizeof(encbuf),
"FS:redirect VRF %s", buf);
snprintf(encbuf, sizeof(encbuf),
@@ -1640,12 +1640,13 @@ int ecommunity_fill_pbr_action(struct ecommunity_val *ecom_eval,
} else if (ecom_eval->val[1] == ECOMMUNITY_TRAFFIC_ACTION) {
api->action = ACTION_TRAFFIC_ACTION;
/* else distribute code is set by default */
- if (ecom_eval->val[5] & (1 << FLOWSPEC_TRAFFIC_ACTION_TERMINAL))
- api->u.za.filter |= TRAFFIC_ACTION_TERMINATE;
+ if (CHECK_FLAG(ecom_eval->val[5],
+ (1 << FLOWSPEC_TRAFFIC_ACTION_TERMINAL)))
+ SET_FLAG(api->u.za.filter, TRAFFIC_ACTION_TERMINATE);
else
- api->u.za.filter |= TRAFFIC_ACTION_DISTRIBUTE;
+ SET_FLAG(api->u.za.filter, TRAFFIC_ACTION_DISTRIBUTE);
if (ecom_eval->val[5] == 1 << FLOWSPEC_TRAFFIC_ACTION_SAMPLE)
- api->u.za.filter |= TRAFFIC_ACTION_SAMPLE;
+ SET_FLAG(api->u.za.filter, TRAFFIC_ACTION_SAMPLE);
} else if (ecom_eval->val[1] == ECOMMUNITY_TRAFFIC_MARKING) {
api->action = ACTION_MARKING;
@@ -1940,7 +1941,7 @@ struct ecommunity *ecommunity_replace_linkbw(as_t as, struct ecommunity *ecom,
return new;
type = *eval;
- if (type & ECOMMUNITY_FLAG_NON_TRANSITIVE)
+ if (CHECK_FLAG(type, ECOMMUNITY_FLAG_NON_TRANSITIVE))
return new;
/* Transitive link-bandwidth exists, replace with the passed
diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h
index 929e4e60..67c16aeb 100644
--- a/bgpd/bgp_ecommunity.h
+++ b/bgpd/bgp_ecommunity.h
@@ -155,12 +155,12 @@ struct ecommunity_ip6 {
/* Extended community value is eight octet. */
struct ecommunity_val {
- char val[ECOMMUNITY_SIZE];
+ uint8_t val[ECOMMUNITY_SIZE];
};
/* IPv6 Extended community value is eight octet. */
struct ecommunity_val_ipv6 {
- char val[IPV6_ECOMMUNITY_SIZE];
+ uint8_t val[IPV6_ECOMMUNITY_SIZE];
};
#define ecom_length_size(X, Y) ((X)->size * (Y))
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 7af6ff7c..0a8ce615 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -117,7 +117,7 @@ int vni_list_cmp(void *p1, void *p2)
static unsigned int vrf_import_rt_hash_key_make(const void *p)
{
const struct vrf_irt_node *irt = p;
- const char *pnt = irt->rt.val;
+ const uint8_t *pnt = irt->rt.val;
return jhash(pnt, 8, 0x5abc1234);
}
@@ -229,7 +229,7 @@ static int is_vrf_present_in_irt_vrfs(struct list *vrfs, struct bgp *bgp_vrf)
static unsigned int import_rt_hash_key_make(const void *p)
{
const struct irt_node *irt = p;
- const char *pnt = irt->rt.val;
+ const uint8_t *pnt = irt->rt.val;
return jhash(pnt, 8, 0xdeadbeef);
}
@@ -621,7 +621,7 @@ static void form_auto_rt(struct bgp *bgp, vni_t vni, struct list *rtl,
struct listnode *node;
if (bgp->advertise_autort_rfc8365)
- vni |= EVPN_AUTORT_VXLAN;
+ SET_FLAG(vni, EVPN_AUTORT_VXLAN);
encode_route_target_as((bgp->as & 0xFFFF), vni, &eval, true);
ecomadd = ecommunity_new();
@@ -1159,9 +1159,8 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
}
/* Add MAC mobility (sticky) if needed. */
- if (attr->sticky) {
+ if (CHECK_FLAG(attr->evpn_flags, ATTR_EVPN_FLAG_STICKY)) {
seqnum = 0;
- memset(&ecom_sticky, 0, sizeof(ecom_sticky));
encode_mac_mobility_extcomm(1, seqnum, &eval_sticky);
ecom_sticky.size = 1;
ecom_sticky.unit_size = ECOMMUNITY_SIZE;
@@ -1179,8 +1178,7 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
}
/* Add default gateway, if needed. */
- if (attr->default_gw) {
- memset(&ecom_default_gw, 0, sizeof(ecom_default_gw));
+ if (CHECK_FLAG(attr->evpn_flags, ATTR_EVPN_FLAG_DEFAULT_GW)) {
encode_default_gw_extcomm(&eval_default_gw);
ecom_default_gw.size = 1;
ecom_default_gw.unit_size = ECOMMUNITY_SIZE;
@@ -1191,9 +1189,11 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
}
proxy = !!(attr->es_flags & ATTR_ES_PROXY_ADVERT);
- if (attr->router_flag || proxy) {
- memset(&ecom_na, 0, sizeof(ecom_na));
- encode_na_flag_extcomm(&eval_na, attr->router_flag, proxy);
+ if (CHECK_FLAG(attr->evpn_flags, ATTR_EVPN_FLAG_ROUTER) || proxy) {
+ encode_na_flag_extcomm(&eval_na,
+ CHECK_FLAG(attr->evpn_flags,
+ ATTR_EVPN_FLAG_ROUTER),
+ proxy);
ecom_na.size = 1;
ecom_na.unit_size = ECOMMUNITY_SIZE;
ecom_na.val = (uint8_t *)eval_na.val;
@@ -1278,12 +1278,15 @@ enum zclient_send_status evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn
flags = 0;
if (pi->sub_type == BGP_ROUTE_IMPORTED) {
- if (pi->attr->sticky)
+ if (CHECK_FLAG(pi->attr->evpn_flags,
+ ATTR_EVPN_FLAG_STICKY))
SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
- if (pi->attr->default_gw)
+ if (CHECK_FLAG(pi->attr->evpn_flags,
+ ATTR_EVPN_FLAG_DEFAULT_GW))
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
if (is_evpn_prefix_ipaddr_v6(p) &&
- pi->attr->router_flag)
+ CHECK_FLAG(pi->attr->evpn_flags,
+ ATTR_EVPN_FLAG_ROUTER))
SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
seq = mac_mobility_seqnum(pi->attr);
@@ -1311,12 +1314,11 @@ enum zclient_send_status evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn
* flag set install the local entry as a router entry
*/
if (is_evpn_prefix_ipaddr_v6(p) &&
- (pi->attr->es_flags &
- ATTR_ES_PEER_ROUTER))
+ CHECK_FLAG(pi->attr->es_flags, ATTR_ES_PEER_ROUTER))
SET_FLAG(flags,
ZEBRA_MACIP_TYPE_ROUTER_FLAG);
- if (!(pi->attr->es_flags & ATTR_ES_PEER_ACTIVE))
+ if (!CHECK_FLAG(pi->attr->es_flags, ATTR_ES_PEER_ACTIVE))
SET_FLAG(flags,
ZEBRA_MACIP_TYPE_PROXY_ADVERT);
}
@@ -1608,12 +1610,16 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_evpn,
struct bgp_labels bgp_labels = {};
struct bgp_path_info *local_pi = NULL;
struct bgp_path_info *tmp_pi = NULL;
+ struct aspath *new_aspath;
+ struct attr static_attr = { 0 };
*route_changed = 0;
/* See if this is an update of an existing route, or a new add. */
local_pi = bgp_evpn_route_get_local_path(bgp_evpn, dest);
+ static_attr = *attr;
+
/*
* create a new route entry if one doesn't exist.
* Otherwise see if route attr has changed
@@ -1623,8 +1629,19 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_evpn,
/* route has changed as this is the first entry */
*route_changed = 1;
+ /*
+ * if the asn values are different, copy the as of
+ * source vrf to the target entry
+ */
+ if (bgp_vrf->as != bgp_evpn->as) {
+ new_aspath = aspath_dup(static_attr.aspath);
+ new_aspath = aspath_add_seq(new_aspath, bgp_vrf->as);
+ static_attr.aspath = new_aspath;
+ }
+
/* Add (or update) attribute to hash. */
- attr_new = bgp_attr_intern(attr);
+ attr_new = bgp_attr_intern(&static_attr);
+ bgp_attr_flush(&static_attr);
/* create the route info from attribute */
pi = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0,
@@ -1738,20 +1755,30 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp,
BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP)) {
if (src_attr &&
!IN6_IS_ADDR_UNSPECIFIED(&src_attr->mp_nexthop_global)) {
- attr.evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP;
- SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
- memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
+ struct bgp_route_evpn *bre =
+ XCALLOC(MTYPE_BGP_EVPN_OVERLAY,
+ sizeof(struct bgp_route_evpn));
+
+ bre->type = OVERLAY_INDEX_GATEWAY_IP;
+ SET_IPADDR_V6(&bre->gw_ip);
+ memcpy(&bre->gw_ip.ipaddr_v6,
&src_attr->mp_nexthop_global,
sizeof(struct in6_addr));
+ bgp_attr_set_evpn_overlay(&attr, bre);
}
} else if (src_afi == AFI_IP &&
CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP)) {
if (src_attr && src_attr->nexthop.s_addr != 0) {
- attr.evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP;
- SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
- memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
- &src_attr->nexthop, sizeof(struct in_addr));
+ struct bgp_route_evpn *bre =
+ XCALLOC(MTYPE_BGP_EVPN_OVERLAY,
+ sizeof(struct bgp_route_evpn));
+
+ bre->type = OVERLAY_INDEX_GATEWAY_IP;
+ SET_IPADDR_V4(&bre->gw_ip);
+ memcpy(&bre->gw_ip.ipaddr_v4, &src_attr->nexthop,
+ sizeof(struct in_addr));
+ bgp_attr_set_evpn_overlay(&attr, bre);
}
}
@@ -1840,7 +1867,8 @@ static void bgp_evpn_get_sync_info(struct bgp *bgp, esi_t *esi,
*active_on_peer = true;
}
- if (second_best_path->attr->router_flag)
+ if (CHECK_FLAG(second_best_path->attr->evpn_flags,
+ ATTR_EVPN_FLAG_ROUTER))
*peer_router = true;
/* we use both proxy and non-proxy imports to
@@ -1883,42 +1911,44 @@ static void update_evpn_route_entry_sync_info(struct bgp *bgp,
mac);
attr->mm_sync_seqnum = max_sync_seq;
if (active_on_peer)
- attr->es_flags |= ATTR_ES_PEER_ACTIVE;
+ SET_FLAG(attr->es_flags, ATTR_ES_PEER_ACTIVE);
else
- attr->es_flags &= ~ATTR_ES_PEER_ACTIVE;
+ UNSET_FLAG(attr->es_flags, ATTR_ES_PEER_ACTIVE);
if (proxy_from_peer)
- attr->es_flags |= ATTR_ES_PEER_PROXY;
+ SET_FLAG(attr->es_flags, ATTR_ES_PEER_PROXY);
else
- attr->es_flags &= ~ATTR_ES_PEER_PROXY;
+ UNSET_FLAG(attr->es_flags, ATTR_ES_PEER_PROXY);
if (peer_router)
- attr->es_flags |= ATTR_ES_PEER_ROUTER;
+ SET_FLAG(attr->es_flags, ATTR_ES_PEER_ROUTER);
else
- attr->es_flags &= ~ATTR_ES_PEER_ROUTER;
+ UNSET_FLAG(attr->es_flags, ATTR_ES_PEER_ROUTER);
if (BGP_DEBUG(evpn_mh, EVPN_MH_RT)) {
char esi_buf[ESI_STR_LEN];
- zlog_debug(
- "setup sync info for %pFX es %s max_seq %d %s%s%s",
- evp,
- esi_to_str(esi, esi_buf,
- sizeof(esi_buf)),
- max_sync_seq,
- (attr->es_flags & ATTR_ES_PEER_ACTIVE)
- ? "peer-active "
- : "",
- (attr->es_flags & ATTR_ES_PEER_PROXY)
- ? "peer-proxy "
- : "",
- (attr->es_flags & ATTR_ES_PEER_ROUTER)
- ? "peer-router "
- : "");
+ zlog_debug("setup sync info for %pFX es %s max_seq %d %s%s%s",
+ evp,
+ esi_to_str(esi, esi_buf,
+ sizeof(esi_buf)),
+ max_sync_seq,
+ CHECK_FLAG(attr->es_flags,
+ ATTR_ES_PEER_ACTIVE)
+ ? "peer-active "
+ : "",
+ CHECK_FLAG(attr->es_flags,
+ ATTR_ES_PEER_PROXY)
+ ? "peer-proxy "
+ : "",
+ CHECK_FLAG(attr->es_flags,
+ ATTR_ES_PEER_ROUTER)
+ ? "peer-router "
+ : "");
}
}
} else {
attr->mm_sync_seqnum = 0;
- attr->es_flags &= ~ATTR_ES_PEER_ACTIVE;
- attr->es_flags &= ~ATTR_ES_PEER_PROXY;
+ UNSET_FLAG(attr->es_flags, ATTR_ES_PEER_ACTIVE);
+ UNSET_FLAG(attr->es_flags, ATTR_ES_PEER_PROXY);
}
}
@@ -1940,7 +1970,6 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
struct attr local_attr;
struct bgp_labels bgp_labels = {};
int route_change = 1;
- uint8_t sticky = 0;
const struct prefix_evpn *evp;
*pi = NULL;
@@ -1972,9 +2001,7 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
local_attr = *attr;
/* Extract MAC mobility sequence number, if any. */
- local_attr.mm_seqnum =
- bgp_attr_mac_mobility_seqnum(&local_attr, &sticky);
- local_attr.sticky = sticky;
+ local_attr.mm_seqnum = bgp_attr_mac_mobility_seqnum(&local_attr);
/* Add (or update) attribute to hash. */
attr_new = bgp_attr_intern(&local_attr);
@@ -2069,9 +2096,8 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
BGP_PATH_ATTR_CHANGED);
/* Extract MAC mobility sequence number, if any. */
- local_attr.mm_seqnum = bgp_attr_mac_mobility_seqnum(
- &local_attr, &sticky);
- local_attr.sticky = sticky;
+ local_attr.mm_seqnum =
+ bgp_attr_mac_mobility_seqnum(&local_attr);
attr_new = bgp_attr_intern(&local_attr);
@@ -2114,22 +2140,18 @@ static void evpn_zebra_reinstall_best_route(struct bgp *bgp,
}
}
- if (curr_select && curr_select->type == ZEBRA_ROUTE_BGP
- && (curr_select->sub_type == BGP_ROUTE_IMPORTED ||
- bgp_evpn_attr_is_sync(curr_select->attr)))
- if (curr_select && curr_select->type == ZEBRA_ROUTE_BGP &&
- (curr_select->sub_type == BGP_ROUTE_IMPORTED ||
- bgp_evpn_attr_is_sync(curr_select->attr))) {
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS))
- evpn_zebra_install(bgp, vpn,
- (const struct prefix_evpn *)
- bgp_dest_get_prefix(
- dest),
- curr_select);
- else
- bgp_zebra_route_install(dest, curr_select, bgp,
- true, vpn, false);
- }
+ if (curr_select && curr_select->type == ZEBRA_ROUTE_BGP &&
+ (curr_select->sub_type == BGP_ROUTE_IMPORTED ||
+ bgp_evpn_attr_is_sync(curr_select->attr))) {
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS))
+ evpn_zebra_install(bgp, vpn,
+ (const struct prefix_evpn *)
+ bgp_dest_get_prefix(dest),
+ curr_select);
+ else
+ bgp_zebra_route_install(dest, curr_select, bgp, true,
+ vpn, false);
+ }
}
/*
@@ -2204,21 +2226,23 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
attr.nexthop = vpn->originator_ip;
attr.mp_nexthop_global_in = vpn->originator_ip;
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
- attr.sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY) ? 1 : 0;
- attr.default_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW) ? 1 : 0;
- attr.router_flag = CHECK_FLAG(flags,
- ZEBRA_MACIP_TYPE_ROUTER_FLAG) ? 1 : 0;
+ if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY))
+ SET_FLAG(attr.evpn_flags, ATTR_EVPN_FLAG_STICKY);
+ if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW))
+ SET_FLAG(attr.evpn_flags, ATTR_EVPN_FLAG_DEFAULT_GW);
+ if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG))
+ SET_FLAG(attr.evpn_flags, ATTR_EVPN_FLAG_ROUTER);
if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT))
- attr.es_flags |= ATTR_ES_PROXY_ADVERT;
+ SET_FLAG(attr.es_flags, ATTR_ES_PROXY_ADVERT);
if (esi && bgp_evpn_is_esi_valid(esi)) {
memcpy(&attr.esi, esi, sizeof(esi_t));
- attr.es_flags |= ATTR_ES_IS_LOCAL;
+ SET_FLAG(attr.es_flags, ATTR_ES_IS_LOCAL);
}
/* PMSI is only needed for type-3 routes */
if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) {
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
+ SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL));
bgp_attr_set_pmsi_tnl_type(&attr, PMSI_TNLTYPE_INGR_REPL);
}
@@ -2250,8 +2274,12 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
* IPv4 or IPv6 global addresses and we're advertising L3VNI with
* these routes.
*/
- add_l3_ecomm = bgp_evpn_route_add_l3_ecomm_ok(
- vpn, p, (attr.es_flags & ATTR_ES_IS_LOCAL) ? &attr.esi : NULL);
+ add_l3_ecomm =
+ bgp_evpn_route_add_l3_ecomm_ok(vpn, p,
+ CHECK_FLAG(attr.es_flags,
+ ATTR_ES_IS_LOCAL)
+ ? &attr.esi
+ : NULL);
if (bgp->evpn_info)
macvrf_soo = bgp->evpn_info->soo;
@@ -2509,13 +2537,12 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
attr.nexthop = vpn->originator_ip;
attr.mp_nexthop_global_in = vpn->originator_ip;
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
- attr.sticky = (local_pi->attr->sticky) ? 1 : 0;
- attr.router_flag = (local_pi->attr->router_flag) ? 1 : 0;
+ attr.evpn_flags = local_pi->attr->evpn_flags;
attr.es_flags = local_pi->attr->es_flags;
- if (local_pi->attr->default_gw) {
- attr.default_gw = 1;
+ if (CHECK_FLAG(local_pi->attr->evpn_flags, ATTR_EVPN_FLAG_DEFAULT_GW)) {
+ SET_FLAG(attr.evpn_flags, ATTR_EVPN_FLAG_DEFAULT_GW);
if (is_evpn_prefix_ipaddr_v6(&evp))
- attr.router_flag = 1;
+ SET_FLAG(attr.evpn_flags, ATTR_EVPN_FLAG_ROUTER);
}
memcpy(&attr.esi, &local_pi->attr->esi, sizeof(esi_t));
bgp_evpn_get_rmac_nexthop(vpn, &evp, &attr,
@@ -2524,9 +2551,12 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
/* Add L3 VNI RTs and RMAC for non IPv6 link-local if
* using L3 VNI for type-2 routes also.
*/
- add_l3_ecomm = bgp_evpn_route_add_l3_ecomm_ok(
- vpn, &evp,
- (attr.es_flags & ATTR_ES_IS_LOCAL) ? &attr.esi : NULL);
+ add_l3_ecomm =
+ bgp_evpn_route_add_l3_ecomm_ok(vpn, &evp,
+ CHECK_FLAG(attr.es_flags,
+ ATTR_ES_IS_LOCAL)
+ ? &attr.esi
+ : NULL);
if (bgp->evpn_info)
macvrf_soo = bgp->evpn_info->soo;
@@ -3030,6 +3060,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
bool use_l3nhg = false;
bool is_l3nhg_active = false;
char buf1[INET6_ADDRSTRLEN];
+ struct bgp_route_evpn *bre;
memset(pp, 0, sizeof(struct prefix));
ip_prefix_from_evpn_prefix(evp, pp);
@@ -3063,45 +3094,43 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
* make sure to set the flag for next hop attribute.
*/
attr = *parent_pi->attr;
- if (attr.evpn_overlay.type != OVERLAY_INDEX_GATEWAY_IP) {
- if (afi == AFI_IP6)
- evpn_convert_nexthop_to_ipv6(&attr);
- else {
- attr.nexthop = attr.mp_nexthop_global_in;
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
- }
- } else {
-
+ bre = bgp_attr_get_evpn_overlay(&attr);
+ if (bre && bre->type == OVERLAY_INDEX_GATEWAY_IP) {
/*
* If gateway IP overlay index is specified in the NLRI of
* EVPN RT-5, this gateway IP should be used as the nexthop
* for the prefix in the VRF
*/
if (bgp_debug_zebra(NULL)) {
- zlog_debug(
- "Install gateway IP %s as nexthop for prefix %pFX in vrf %s",
- inet_ntop(pp->family, &attr.evpn_overlay.gw_ip,
- buf1, sizeof(buf1)), pp,
- vrf_id_to_name(bgp_vrf->vrf_id));
+ zlog_debug("Install gateway IP %s as nexthop for prefix %pFX in vrf %s",
+ inet_ntop(pp->family, &bre->gw_ip, buf1,
+ sizeof(buf1)),
+ pp, vrf_id_to_name(bgp_vrf->vrf_id));
}
if (afi == AFI_IP6) {
- memcpy(&attr.mp_nexthop_global,
- &attr.evpn_overlay.gw_ip.ipaddr_v6,
+ memcpy(&attr.mp_nexthop_global, &bre->gw_ip.ipaddr_v6,
sizeof(struct in6_addr));
attr.mp_nexthop_len = IPV6_MAX_BYTELEN;
} else {
- attr.nexthop = attr.evpn_overlay.gw_ip.ipaddr_v4;
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
+ attr.nexthop = bre->gw_ip.ipaddr_v4;
+ SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP));
+ }
+ } else {
+ if (afi == AFI_IP6)
+ evpn_convert_nexthop_to_ipv6(&attr);
+ else {
+ attr.nexthop = attr.mp_nexthop_global_in;
+ SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP));
}
}
bgp_evpn_es_vrf_use_nhg(bgp_vrf, &parent_pi->attr->esi, &use_l3nhg,
&is_l3nhg_active, NULL);
if (use_l3nhg)
- attr.es_flags |= ATTR_ES_L3_NHG_USE;
+ SET_FLAG(attr.es_flags, ATTR_ES_L3_NHG_USE);
if (is_l3nhg_active)
- attr.es_flags |= ATTR_ES_L3_NHG_ACTIVE;
+ SET_FLAG(attr.es_flags, ATTR_ES_L3_NHG_ACTIVE);
/* Check if route entry is already present. */
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
@@ -3143,22 +3172,20 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
}
/* Gateway IP nexthop should be resolved */
- if (attr.evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
+ if (bre && bre->type == OVERLAY_INDEX_GATEWAY_IP) {
if (bgp_find_or_add_nexthop(bgp_vrf, bgp_vrf, afi, safi, pi,
NULL, 0, NULL))
bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
else {
if (BGP_DEBUG(nht, NHT)) {
- inet_ntop(pp->family,
- &attr.evpn_overlay.gw_ip,
- buf1, sizeof(buf1));
+ inet_ntop(pp->family, &bre->gw_ip, buf1,
+ sizeof(buf1));
zlog_debug("%s: gateway IP NH unresolved",
buf1);
}
bgp_path_info_unset_flag(dest, pi, BGP_PATH_VALID);
}
} else {
-
/* as it is an importation, change nexthop */
bgp_path_info_set_flag(dest, pi, BGP_PATH_ANNC_NH_SELF);
}
@@ -3267,8 +3294,7 @@ static int install_evpn_route_entry_in_vni_common(
if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
zlog_debug("VNI %d path %pFX chg to %s es",
vpn->vni, &pi->net->rn->p,
- new_local_es ? "local"
- : "non-local");
+ new_local_es ? "local" : "non-local");
bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
}
@@ -3451,9 +3477,8 @@ uninstall_evpn_route_entry_in_vni_mac(struct bgp *bgp, struct bgpevpn *vpn,
* Uninstall route entry from the VRF routing table and send message
* to zebra, if appropriate.
*/
-static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
- const struct prefix_evpn *evp,
- struct bgp_path_info *parent_pi)
+int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, const struct prefix_evpn *evp,
+ struct bgp_path_info *parent_pi)
{
struct bgp_dest *dest;
struct bgp_path_info *pi;
@@ -3631,7 +3656,7 @@ static int is_route_matching_for_vrf(struct bgp *bgp_vrf,
assert(attr);
/* Route should have valid RT to be even considered. */
- if (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)))
+ if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)))
return 0;
ecom = bgp_attr_get_ecommunity(attr);
@@ -3698,7 +3723,7 @@ static int is_route_matching_for_vni(struct bgp *bgp, struct bgpevpn *vpn,
assert(attr);
/* Route should have valid RT to be even considered. */
- if (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)))
+ if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)))
return 0;
ecom = bgp_attr_get_ecommunity(attr);
@@ -3820,10 +3845,8 @@ static int bgp_evpn_route_rmac_self_check(struct bgp *bgp_vrf,
}
/* don't import hosts that are locally attached */
-static inline bool
-bgp_evpn_skip_vrf_import_of_local_es(struct bgp *bgp_vrf,
- const struct prefix_evpn *evp,
- struct bgp_path_info *pi, int install)
+bool bgp_evpn_skip_vrf_import_of_local_es(struct bgp *bgp_vrf, const struct prefix_evpn *evp,
+ struct bgp_path_info *pi, int install)
{
esi_t *esi;
@@ -4200,7 +4223,7 @@ static int bgp_evpn_install_uninstall_table(struct bgp *bgp, afi_t afi,
return 0;
/* If we don't have Route Target, nothing much to do. */
- if (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)))
+ if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)))
return 0;
/* EAD prefix in the global table doesn't include the VTEP-IP so
@@ -4689,7 +4712,6 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
{
struct prefix_rd prd;
struct prefix_evpn p = {};
- struct bgp_route_evpn evpn = {};
uint8_t ipaddr_len;
uint8_t macaddr_len;
/* holds the VNI(s) as in packet */
@@ -4731,9 +4753,9 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
STREAM_GET(&attr->esi, pkt, sizeof(esi_t));
if (bgp_evpn_is_esi_local_and_non_bypass(&attr->esi))
- attr->es_flags |= ATTR_ES_IS_LOCAL;
+ SET_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
else
- attr->es_flags &= ~ATTR_ES_IS_LOCAL;
+ UNSET_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
} else {
STREAM_FORWARD_GETP(pkt, sizeof(esi_t));
}
@@ -4791,11 +4813,11 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
if (attr)
bgp_update(peer, (struct prefix *)&p, addpath_id, attr, afi,
safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd,
- &label[0], num_labels, 0, &evpn);
+ &label[0], num_labels, 0, NULL);
else
bgp_withdraw(peer, (struct prefix *)&p, addpath_id, afi, safi,
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, &label[0],
- num_labels, &evpn);
+ num_labels);
goto done;
fail:
@@ -4835,8 +4857,7 @@ static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi,
* Note: We just simply ignore the values as it is not clear if
* doing anything else is better.
*/
- if (attr &&
- (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL))) {
+ if (attr && CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL))) {
enum pta_type pmsi_tnl_type = bgp_attr_get_pmsi_tnl_type(attr);
if (pmsi_tnl_type != PMSI_TNLTYPE_INGR_REPL
@@ -4885,8 +4906,7 @@ static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi,
0, 0, NULL);
else
bgp_withdraw(peer, (struct prefix *)&p, addpath_id, afi, safi,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0,
- NULL);
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0);
return 0;
}
@@ -4899,7 +4919,8 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
{
struct prefix_rd prd;
struct prefix_evpn p;
- struct bgp_route_evpn evpn;
+ struct bgp_route_evpn *evpn = XCALLOC(MTYPE_BGP_EVPN_OVERLAY,
+ sizeof(struct bgp_route_evpn));
uint8_t ippfx_len;
uint32_t eth_tag;
mpls_label_t label; /* holds the VNI as in the packet */
@@ -4914,6 +4935,7 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
flog_err(EC_BGP_EVPN_ROUTE_INVALID,
"%u:%s - Rx EVPN Type-5 NLRI with invalid length %d",
peer->bgp->vrf_id, peer->host, psize);
+ evpn_overlay_free(evpn);
return -1;
}
@@ -4929,12 +4951,9 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
p.prefixlen = EVPN_ROUTE_PREFIXLEN;
p.prefix.route_type = BGP_EVPN_IP_PREFIX_ROUTE;
- /* Additional information outside of prefix - ESI and GW IP */
- memset(&evpn, 0, sizeof(evpn));
-
/* Fetch ESI overlay index */
if (attr)
- memcpy(&evpn.eth_s_id, pfx, sizeof(esi_t));
+ memcpy(&evpn->eth_s_id, pfx, sizeof(esi_t));
pfx += ESI_BYTES;
/* Fetch Ethernet Tag. */
@@ -4949,6 +4968,7 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
EC_BGP_EVPN_ROUTE_INVALID,
"%u:%s - Rx EVPN Type-5 NLRI with invalid IP Prefix length %d",
peer->bgp->vrf_id, peer->host, ippfx_len);
+ evpn_overlay_free(evpn);
return -1;
}
p.prefix.prefix_addr.ip_prefix_length = ippfx_len;
@@ -4961,16 +4981,16 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
SET_IPADDR_V4(&p.prefix.prefix_addr.ip);
memcpy(&p.prefix.prefix_addr.ip.ipaddr_v4, pfx, 4);
pfx += 4;
- SET_IPADDR_V4(&evpn.gw_ip);
- memcpy(&evpn.gw_ip.ipaddr_v4, pfx, 4);
+ SET_IPADDR_V4(&evpn->gw_ip);
+ memcpy(&evpn->gw_ip.ipaddr_v4, pfx, 4);
pfx += 4;
} else {
SET_IPADDR_V6(&p.prefix.prefix_addr.ip);
memcpy(&p.prefix.prefix_addr.ip.ipaddr_v6, pfx,
IPV6_MAX_BYTELEN);
pfx += IPV6_MAX_BYTELEN;
- SET_IPADDR_V6(&evpn.gw_ip);
- memcpy(&evpn.gw_ip.ipaddr_v6, pfx, IPV6_MAX_BYTELEN);
+ SET_IPADDR_V6(&evpn->gw_ip);
+ memcpy(&evpn->gw_ip.ipaddr_v6, pfx, IPV6_MAX_BYTELEN);
pfx += IPV6_MAX_BYTELEN;
}
@@ -4988,20 +5008,20 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
* An update containing a non-zero gateway IP and a non-zero ESI
* at the same time is should be treated as withdraw
*/
- if (bgp_evpn_is_esi_valid(&evpn.eth_s_id) &&
- !ipaddr_is_zero(&evpn.gw_ip)) {
+ if (bgp_evpn_is_esi_valid(&evpn->eth_s_id) &&
+ !ipaddr_is_zero(&evpn->gw_ip)) {
flog_err(EC_BGP_EVPN_ROUTE_INVALID,
"%s - Rx EVPN Type-5 ESI and gateway-IP both non-zero.",
peer->host);
is_valid_update = false;
- } else if (bgp_evpn_is_esi_valid(&evpn.eth_s_id))
- evpn.type = OVERLAY_INDEX_ESI;
- else if (!ipaddr_is_zero(&evpn.gw_ip))
- evpn.type = OVERLAY_INDEX_GATEWAY_IP;
+ } else if (bgp_evpn_is_esi_valid(&evpn->eth_s_id))
+ evpn->type = OVERLAY_INDEX_ESI;
+ else if (!ipaddr_is_zero(&evpn->gw_ip))
+ evpn->type = OVERLAY_INDEX_GATEWAY_IP;
if (attr) {
if (is_zero_mac(&attr->rmac) &&
- !bgp_evpn_is_esi_valid(&evpn.eth_s_id) &&
- ipaddr_is_zero(&evpn.gw_ip) && label == 0) {
+ !bgp_evpn_is_esi_valid(&evpn->eth_s_id) &&
+ ipaddr_is_zero(&evpn->gw_ip) && label == 0) {
flog_err(EC_BGP_EVPN_ROUTE_INVALID,
"%s - Rx EVPN Type-5 ESI, gateway-IP, RMAC and label all zero",
peer->host);
@@ -5016,7 +5036,7 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
if (attr && is_valid_update)
bgp_update(peer, (struct prefix *)&p, addpath_id, attr, afi,
safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd,
- &label, 1, 0, &evpn);
+ &label, 1, 0, evpn);
else {
if (!is_valid_update) {
char attr_str[BUFSIZ] = {0};
@@ -5028,8 +5048,8 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
attr_str);
}
bgp_withdraw(peer, (struct prefix *)&p, addpath_id, afi, safi,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, &label, 1,
- &evpn);
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, &label, 1);
+ evpn_overlay_free(evpn);
}
return 0;
@@ -5043,12 +5063,16 @@ static void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p,
int len;
char temp[16];
const struct evpn_addr *p_evpn_p;
+ struct bgp_route_evpn *bre = NULL;
memset(&temp, 0, sizeof(temp));
if (p->family != AF_EVPN)
return;
p_evpn_p = &(p->u.prefix_evpn);
+ if (attr)
+ bre = bgp_attr_get_evpn_overlay(attr);
+
/* len denites the total len of IP and GW-IP in the route
IP and GW-IP have to be both ipv4 or ipv6
*/
@@ -5059,7 +5083,7 @@ static void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p,
/* Prefix contains RD, ESI, EthTag, IP length, IP, GWIP and VNI */
stream_putc(s, 8 + 10 + 4 + 1 + len + 3);
stream_put(s, prd->val, 8);
- if (attr && attr->evpn_overlay.type == OVERLAY_INDEX_ESI)
+ if (attr && bre && bre->type == OVERLAY_INDEX_ESI)
stream_put(s, &attr->esi, sizeof(esi_t));
else
stream_put(s, 0, sizeof(esi_t));
@@ -5069,15 +5093,11 @@ static void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p,
stream_put_ipv4(s, p_evpn_p->prefix_addr.ip.ipaddr_v4.s_addr);
else
stream_put(s, &p_evpn_p->prefix_addr.ip.ipaddr_v6, 16);
- if (attr && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
- const struct bgp_route_evpn *evpn_overlay =
- bgp_attr_get_evpn_overlay(attr);
-
+ if (attr && bre && bre->type == OVERLAY_INDEX_GATEWAY_IP) {
if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
- stream_put_ipv4(s,
- evpn_overlay->gw_ip.ipaddr_v4.s_addr);
+ stream_put_ipv4(s, bre->gw_ip.ipaddr_v4.s_addr);
else
- stream_put(s, &(evpn_overlay->gw_ip.ipaddr_v6), 16);
+ stream_put(s, &(bre->gw_ip.ipaddr_v6), 16);
} else {
if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
stream_put_ipv4(s, 0);
@@ -5439,7 +5459,7 @@ void evpn_rt_delete_auto(struct bgp *bgp, vni_t vni, struct list *rtl,
struct ecommunity_val eval;
if (bgp->advertise_autort_rfc8365)
- vni |= EVPN_AUTORT_VXLAN;
+ SET_FLAG(vni, EVPN_AUTORT_VXLAN);
encode_route_target_as((bgp->as & 0xFFFF), vni, &eval, true);
@@ -7717,18 +7737,18 @@ static void bgp_evpn_remote_ip_process_nexthops(struct bgpevpn *vpn,
* MAC/IP route or SVI or tenant vrf being added to EVI.
* Set nexthop as valid only if it is already L3 reachable
*/
- if (resolve && bnc->flags & BGP_NEXTHOP_EVPN_INCOMPLETE) {
- bnc->flags &= ~BGP_NEXTHOP_EVPN_INCOMPLETE;
- bnc->flags |= BGP_NEXTHOP_VALID;
- bnc->change_flags |= BGP_NEXTHOP_MACIP_CHANGED;
+ if (resolve && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_EVPN_INCOMPLETE)) {
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_EVPN_INCOMPLETE);
+ SET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
+ SET_FLAG(bnc->change_flags, BGP_NEXTHOP_MACIP_CHANGED);
evaluate_paths(bnc);
}
/* MAC/IP route or SVI or tenant vrf being deleted from EVI */
- if (!resolve && bnc->flags & BGP_NEXTHOP_VALID) {
- bnc->flags &= ~BGP_NEXTHOP_VALID;
- bnc->flags |= BGP_NEXTHOP_EVPN_INCOMPLETE;
- bnc->change_flags |= BGP_NEXTHOP_MACIP_CHANGED;
+ if (!resolve && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
+ SET_FLAG(bnc->flags, BGP_NEXTHOP_EVPN_INCOMPLETE);
+ SET_FLAG(bnc->change_flags, BGP_NEXTHOP_MACIP_CHANGED);
evaluate_paths(bnc);
}
}
diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h
index dc82bcfb..10eff1dc 100644
--- a/bgpd/bgp_evpn.h
+++ b/bgpd/bgp_evpn.h
@@ -195,4 +195,8 @@ extern enum zclient_send_status
evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn,
const struct prefix_evpn *p, struct bgp_path_info *pi,
bool is_sync);
+bool bgp_evpn_skip_vrf_import_of_local_es(struct bgp *bgp_vrf, const struct prefix_evpn *evp,
+ struct bgp_path_info *pi, int install);
+int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, const struct prefix_evpn *evp,
+ struct bgp_path_info *parent_pi);
#endif /* _QUAGGA_BGP_EVPN_H */
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index d723a2b1..ad362524 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -770,8 +770,7 @@ int bgp_evpn_type4_route_process(struct peer *peer, afi_t afi, safi_t safi,
0, 0, NULL);
} else {
bgp_withdraw(peer, (struct prefix *)&p, addpath_id, afi, safi,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0,
- NULL);
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0);
}
return 0;
}
@@ -1239,8 +1238,7 @@ int bgp_evpn_type1_route_process(struct peer *peer, afi_t afi, safi_t safi,
0, 0, NULL);
} else {
bgp_withdraw(peer, (struct prefix *)&p, addpath_id, afi, safi,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0,
- NULL);
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0);
}
return 0;
}
@@ -1406,8 +1404,8 @@ bgp_zebra_send_remote_es_vtep(struct bgp *bgp, struct bgp_evpn_es_vtep *es_vtep,
return ZCLIENT_SEND_SUCCESS;
}
- if (es_vtep->flags & BGP_EVPNES_VTEP_ESR)
- flags |= ZAPI_ES_VTEP_FLAG_ESR_RXED;
+ if (CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ESR))
+ SET_FLAG(flags, ZAPI_ES_VTEP_FLAG_ESR_RXED);
s = zclient->obuf;
stream_reset(s);
@@ -1966,9 +1964,9 @@ static struct bgp_evpn_es *bgp_evpn_es_new(struct bgp *bgp, const esi_t *esi)
*/
static void bgp_evpn_es_free(struct bgp_evpn_es *es, const char *caller)
{
- if ((es->flags & (BGP_EVPNES_LOCAL | BGP_EVPNES_REMOTE))
- || listcount(es->macip_evi_path_list)
- || listcount(es->macip_global_path_list))
+ if (CHECK_FLAG(es->flags, (BGP_EVPNES_LOCAL | BGP_EVPNES_REMOTE)) ||
+ listcount(es->macip_evi_path_list) ||
+ listcount(es->macip_global_path_list))
return;
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
@@ -1993,8 +1991,8 @@ static void bgp_evpn_es_free(struct bgp_evpn_es *es, const char *caller)
static inline bool bgp_evpn_is_es_local_and_non_bypass(struct bgp_evpn_es *es)
{
- return (es->flags & BGP_EVPNES_LOCAL)
- && !(es->flags & BGP_EVPNES_BYPASS);
+ return CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL) &&
+ !CHECK_FLAG(es->flags, BGP_EVPNES_BYPASS);
}
/* init local info associated with the ES */
@@ -2076,8 +2074,8 @@ bool bgp_evpn_es_add_l3_ecomm_ok(esi_t *esi)
es = bgp_evpn_es_find(esi);
- return (!es || !(es->flags & BGP_EVPNES_LOCAL)
- || bgp_evpn_local_es_is_active(es));
+ return (!es || !CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL) ||
+ bgp_evpn_local_es_is_active(es));
}
static bool bgp_evpn_is_valid_local_path(struct bgp_path_info *pi)
@@ -2177,9 +2175,9 @@ static void bgp_evpn_mac_update_on_es_local_chg(struct bgp_evpn_es *es,
attr_tmp = *pi->attr;
if (is_local)
- attr_tmp.es_flags |= ATTR_ES_IS_LOCAL;
+ SET_FLAG(attr_tmp.es_flags, ATTR_ES_IS_LOCAL);
else
- attr_tmp.es_flags &= ~ATTR_ES_IS_LOCAL;
+ UNSET_FLAG(attr_tmp.es_flags, ATTR_ES_IS_LOCAL);
attr_new = bgp_attr_intern(&attr_tmp);
bgp_attr_unintern(&pi->attr);
pi->attr = attr_new;
@@ -2473,9 +2471,9 @@ static char *bgp_evpn_es_vteps_str(char *vtep_str, struct bgp_evpn_es *es,
for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
vtep_flag_str[0] = '\0';
- if (es_vtep->flags & BGP_EVPNES_VTEP_ESR)
+ if (CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ESR))
strlcat(vtep_flag_str, "E", sizeof(vtep_flag_str));
- if (es_vtep->flags & BGP_EVPNES_VTEP_ACTIVE)
+ if (CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE))
strlcat(vtep_flag_str, "A", sizeof(vtep_flag_str));
if (!strlen(vtep_flag_str))
@@ -2507,15 +2505,15 @@ static void bgp_evpn_es_json_vtep_fill(json_object *json_vteps,
json_object_string_addf(json_vtep_entry, "vtep_ip", "%pI4",
&es_vtep->vtep_ip);
- if (es_vtep->flags & (BGP_EVPNES_VTEP_ESR |
- BGP_EVPNES_VTEP_ACTIVE)) {
+ if (CHECK_FLAG(es_vtep->flags,
+ (BGP_EVPNES_VTEP_ESR | BGP_EVPNES_VTEP_ACTIVE))) {
json_flags = json_object_new_array();
- if (es_vtep->flags & BGP_EVPNES_VTEP_ESR)
+ if (CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ESR))
json_array_string_add(json_flags, "esr");
- if (es_vtep->flags & BGP_EVPNES_VTEP_ACTIVE)
+ if (CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE))
json_array_string_add(json_flags, "active");
json_object_object_add(json_vtep_entry, "flags", json_flags);
- if (es_vtep->flags & BGP_EVPNES_VTEP_ESR) {
+ if (CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ESR)) {
json_object_int_add(json_vtep_entry, "dfPreference",
es_vtep->df_pref);
json_object_string_add(
@@ -2539,9 +2537,9 @@ static void bgp_evpn_es_vteps_show_detail(struct vty *vty,
for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
vtep_flag_str[0] = '\0';
- if (es_vtep->flags & BGP_EVPNES_VTEP_ESR)
+ if (CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ESR))
strlcat(vtep_flag_str, "E", sizeof(vtep_flag_str));
- if (es_vtep->flags & BGP_EVPNES_VTEP_ACTIVE)
+ if (CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE))
strlcat(vtep_flag_str, "A", sizeof(vtep_flag_str));
if (!strlen(vtep_flag_str))
@@ -2550,7 +2548,7 @@ static void bgp_evpn_es_vteps_show_detail(struct vty *vty,
vty_out(vty, " %pI4 flags: %s", &es_vtep->vtep_ip,
vtep_flag_str);
- if (es_vtep->flags & BGP_EVPNES_VTEP_ESR)
+ if (CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ESR))
vty_out(vty, " df_alg: %s df_pref: %u\n",
evpn_es_df_alg2str(es_vtep->df_alg, alg_buf,
sizeof(alg_buf)),
@@ -2575,11 +2573,12 @@ static void bgp_evpn_es_show_entry(struct vty *vty,
json_object_string_addf(json, "rd", "%pRDP",
&es->es_base_frag->prd);
- if (es->flags & (BGP_EVPNES_LOCAL | BGP_EVPNES_REMOTE)) {
+ if (CHECK_FLAG(es->flags,
+ (BGP_EVPNES_LOCAL | BGP_EVPNES_REMOTE))) {
json_types = json_object_new_array();
- if (es->flags & BGP_EVPNES_LOCAL)
+ if (CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL))
json_array_string_add(json_types, "local");
- if (es->flags & BGP_EVPNES_REMOTE)
+ if (CHECK_FLAG(es->flags, BGP_EVPNES_REMOTE))
json_array_string_add(json_types, "remote");
json_object_object_add(json, "type", json_types);
}
@@ -2599,11 +2598,11 @@ static void bgp_evpn_es_show_entry(struct vty *vty,
char vtep_str[ES_VTEP_LIST_STR_SZ + BGP_EVPN_VTEPS_FLAG_STR_SZ];
type_str[0] = '\0';
- if (es->flags & BGP_EVPNES_BYPASS)
+ if (CHECK_FLAG(es->flags, BGP_EVPNES_BYPASS))
strlcat(type_str, "B", sizeof(type_str));
- if (es->flags & BGP_EVPNES_LOCAL)
+ if (CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL))
strlcat(type_str, "L", sizeof(type_str));
- if (es->flags & BGP_EVPNES_REMOTE)
+ if (CHECK_FLAG(es->flags, BGP_EVPNES_REMOTE))
strlcat(type_str, "R", sizeof(type_str));
if (es->inconsistencies)
strlcat(type_str, "I", sizeof(type_str));
@@ -2630,16 +2629,16 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty,
/* Add the "brief" info first */
bgp_evpn_es_show_entry(vty, es, json);
- if (es->flags
- & (BGP_EVPNES_OPER_UP | BGP_EVPNES_ADV_EVI
- | BGP_EVPNES_BYPASS)) {
+ if (CHECK_FLAG(es->flags,
+ (BGP_EVPNES_OPER_UP | BGP_EVPNES_ADV_EVI |
+ BGP_EVPNES_BYPASS))) {
json_flags = json_object_new_array();
- if (es->flags & BGP_EVPNES_OPER_UP)
+ if (CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP))
json_array_string_add(json_flags, "up");
- if (es->flags & BGP_EVPNES_ADV_EVI)
+ if (CHECK_FLAG(es->flags, BGP_EVPNES_ADV_EVI))
json_array_string_add(json_flags,
"advertiseEVI");
- if (es->flags & BGP_EVPNES_BYPASS)
+ if (CHECK_FLAG(es->flags, BGP_EVPNES_BYPASS))
json_array_string_add(json_flags, "bypass");
json_object_object_add(json, "flags", json_flags);
}
@@ -2655,7 +2654,7 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty,
listcount(es->macip_global_path_list));
json_object_int_add(json, "inconsistentVniVtepCount",
es->incons_evi_vtep_cnt);
- if (es->flags & BGP_EVPNES_LOCAL)
+ if (CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL))
json_object_int_add(json, "localEsDfPreference",
es->df_pref);
if (listcount(es->es_vtep_list)) {
@@ -2673,7 +2672,8 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty,
}
if (es->inconsistencies) {
json_incons = json_object_new_array();
- if (es->inconsistencies & BGP_EVPNES_INCONS_VTEP_LIST)
+ if (CHECK_FLAG(es->inconsistencies,
+ BGP_EVPNES_INCONS_VTEP_LIST))
json_array_string_add(json_incons,
"vni-vtep-mismatch");
json_object_object_add(json, "inconsistencies",
@@ -2684,9 +2684,9 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty,
char type_str[4];
type_str[0] = '\0';
- if (es->flags & BGP_EVPNES_LOCAL)
+ if (CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL))
strlcat(type_str, "L", sizeof(type_str));
- if (es->flags & BGP_EVPNES_REMOTE)
+ if (CHECK_FLAG(es->flags, BGP_EVPNES_REMOTE))
strlcat(type_str, "R", sizeof(type_str));
vty_out(vty, "ESI: %s\n", es->esi_str);
@@ -2694,10 +2694,10 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty,
vty_out(vty, " RD: %pRDP\n",
es->es_base_frag ? &es->es_base_frag->prd : NULL);
vty_out(vty, " Originator-IP: %pI4\n", &es->originator_ip);
- if (es->flags & BGP_EVPNES_LOCAL)
+ if (CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL))
vty_out(vty, " Local ES DF preference: %u\n",
es->df_pref);
- if (es->flags & BGP_EVPNES_BYPASS)
+ if (CHECK_FLAG(es->flags, BGP_EVPNES_BYPASS))
vty_out(vty, " LACP bypass: on\n");
vty_out(vty, " VNI Count: %d\n", listcount(es->es_evi_list));
vty_out(vty, " Remote VNI Count: %d\n",
@@ -2711,7 +2711,8 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty,
es->incons_evi_vtep_cnt);
if (es->inconsistencies) {
incons_str[0] = '\0';
- if (es->inconsistencies & BGP_EVPNES_INCONS_VTEP_LIST)
+ if (CHECK_FLAG(es->inconsistencies,
+ BGP_EVPNES_INCONS_VTEP_LIST))
strlcat(incons_str, "vni-vtep-mismatch",
sizeof(incons_str));
} else {
@@ -2935,7 +2936,7 @@ static void bgp_evpn_l3nhg_zebra_del(struct bgp_evpn_es_vrf *es_vrf)
static void bgp_evpn_l3nhg_deactivate(struct bgp_evpn_es_vrf *es_vrf)
{
- if (!(es_vrf->flags & BGP_EVPNES_VRF_NHG_ACTIVE))
+ if (!CHECK_FLAG(es_vrf->flags, BGP_EVPNES_VRF_NHG_ACTIVE))
return;
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
@@ -2943,7 +2944,7 @@ static void bgp_evpn_l3nhg_deactivate(struct bgp_evpn_es_vrf *es_vrf)
es_vrf->es->esi_str, es_vrf->bgp_vrf->vrf_id,
es_vrf->nhg_id);
bgp_evpn_l3nhg_zebra_del(es_vrf);
- es_vrf->flags &= ~BGP_EVPNES_VRF_NHG_ACTIVE;
+ UNSET_FLAG(es_vrf->flags, BGP_EVPNES_VRF_NHG_ACTIVE);
/* MAC-IPs can now be installed via the L3NHG */
bgp_evpn_es_path_update_on_es_vrf_chg(es_vrf, "l3nhg-deactivate");
}
@@ -2955,7 +2956,7 @@ static void bgp_evpn_l3nhg_activate(struct bgp_evpn_es_vrf *es_vrf, bool update)
return;
}
- if (es_vrf->flags & BGP_EVPNES_VRF_NHG_ACTIVE) {
+ if (CHECK_FLAG(es_vrf->flags, BGP_EVPNES_VRF_NHG_ACTIVE)) {
if (!update)
return;
} else {
@@ -2963,7 +2964,7 @@ static void bgp_evpn_l3nhg_activate(struct bgp_evpn_es_vrf *es_vrf, bool update)
zlog_debug("es %s vrf %u nhg %u activate",
es_vrf->es->esi_str, es_vrf->bgp_vrf->vrf_id,
es_vrf->nhg_id);
- es_vrf->flags |= BGP_EVPNES_VRF_NHG_ACTIVE;
+ SET_FLAG(es_vrf->flags, BGP_EVPNES_VRF_NHG_ACTIVE);
/* MAC-IPs can now be installed via the L3NHG */
bgp_evpn_es_path_update_on_es_vrf_chg(es_vrf, "l3nhg_activate");
}
@@ -3184,7 +3185,7 @@ void bgp_evpn_es_vrf_use_nhg(struct bgp *bgp_vrf, esi_t *esi, bool *use_l3nhg,
return;
*use_l3nhg = true;
- if (es_vrf->flags & BGP_EVPNES_VRF_NHG_ACTIVE)
+ if (CHECK_FLAG(es_vrf->flags, BGP_EVPNES_VRF_NHG_ACTIVE))
*is_l3nhg_active = true;
if (es_vrf_p)
*es_vrf_p = es_vrf;
@@ -3276,9 +3277,9 @@ static void bgp_evpn_es_vrf_show_entry(struct vty *vty,
json_object_string_add(json, "esi", es->esi_str);
json_object_string_add(json, "vrf", bgp_vrf->name_pretty);
- if (es_vrf->flags & (BGP_EVPNES_VRF_NHG_ACTIVE)) {
+ if (CHECK_FLAG(es_vrf->flags, (BGP_EVPNES_VRF_NHG_ACTIVE))) {
json_types = json_object_new_array();
- if (es_vrf->flags & BGP_EVPNES_VRF_NHG_ACTIVE)
+ if (CHECK_FLAG(es_vrf->flags, BGP_EVPNES_VRF_NHG_ACTIVE))
json_array_string_add(json_types, "active");
json_object_object_add(json, "flags", json_types);
}
@@ -3290,7 +3291,7 @@ static void bgp_evpn_es_vrf_show_entry(struct vty *vty,
char flags_str[4];
flags_str[0] = '\0';
- if (es_vrf->flags & BGP_EVPNES_VRF_NHG_ACTIVE)
+ if (CHECK_FLAG(es_vrf->flags, BGP_EVPNES_VRF_NHG_ACTIVE))
strlcat(flags_str, "A", sizeof(flags_str));
vty_out(vty, "%-30s %-15s %-5s %-8u %-8u %u\n", es->esi_str,
@@ -3400,7 +3401,7 @@ static void bgp_evpn_es_evi_vtep_free(struct bgp_evpn_es_evi_vtep *evi_vtep)
{
struct bgp_evpn_es_evi *es_evi = evi_vtep->es_evi;
- if (evi_vtep->flags & (BGP_EVPN_EVI_VTEP_EAD))
+ if (CHECK_FLAG(evi_vtep->flags, (BGP_EVPN_EVI_VTEP_EAD)))
/* as long as there is some reference we can't free it */
return;
@@ -3445,7 +3446,8 @@ bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp,
/* EAD-per-ES is sufficent to activate the PE */
ead_activity_flags = BGP_EVPN_EVI_VTEP_EAD_PER_ES;
- if ((evi_vtep->flags & ead_activity_flags) == ead_activity_flags)
+ if (CHECK_FLAG(evi_vtep->flags, ead_activity_flags) ==
+ ead_activity_flags)
SET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE);
else
UNSET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE);
@@ -3602,7 +3604,8 @@ bgp_evpn_es_evi_free(struct bgp_evpn_es_evi *es_evi)
/* cannot free the element as long as there is a local or remote
* reference
*/
- if (es_evi->flags & (BGP_EVPNES_EVI_LOCAL | BGP_EVPNES_EVI_REMOTE))
+ if (CHECK_FLAG(es_evi->flags,
+ (BGP_EVPNES_EVI_LOCAL | BGP_EVPNES_EVI_REMOTE)))
return es_evi;
bgp_evpn_es_frag_evi_del(es_evi, false);
bgp_evpn_es_vrf_deref(es_evi);
@@ -3804,6 +3807,7 @@ int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni)
bgp_evpn_ead_evi_route_update(bgp, es, vpn, &p);
}
+ bgp_evpn_local_es_evi_unistall_local_routes_in_vrfs(es, es_evi);
/* update EAD-ES */
if (bgp_evpn_local_es_is_active(es))
bgp_evpn_ead_es_route_update(bgp, es);
@@ -3924,8 +3928,8 @@ static void bgp_evpn_remote_es_evi_flush(struct bgp_evpn_es_evi *es_evi)
/* delete all VTEPs */
for (ALL_LIST_ELEMENTS(es_evi->es_evi_vtep_list, node, nnode,
evi_vtep)) {
- evi_vtep->flags &= ~(BGP_EVPN_EVI_VTEP_EAD_PER_ES
- | BGP_EVPN_EVI_VTEP_EAD_PER_EVI);
+ UNSET_FLAG(evi_vtep->flags, (BGP_EVPN_EVI_VTEP_EAD_PER_ES |
+ BGP_EVPN_EVI_VTEP_EAD_PER_EVI));
bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep);
bgp_evpn_es_evi_vtep_free(evi_vtep);
}
@@ -3973,9 +3977,9 @@ static char *bgp_evpn_es_evi_vteps_str(char *vtep_str,
vtep_str[0] = '\0';
for (ALL_LIST_ELEMENTS_RO(es_evi->es_evi_vtep_list, node, evi_vtep)) {
vtep_flag_str[0] = '\0';
- if (evi_vtep->flags & BGP_EVPN_EVI_VTEP_EAD_PER_ES)
+ if (CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_ES))
strlcat(vtep_flag_str, "E", sizeof(vtep_flag_str));
- if (evi_vtep->flags & BGP_EVPN_EVI_VTEP_EAD_PER_EVI)
+ if (CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_EVI))
strlcat(vtep_flag_str, "V", sizeof(vtep_flag_str));
if (!strnlen(vtep_flag_str, sizeof(vtep_flag_str)))
@@ -4006,12 +4010,12 @@ static void bgp_evpn_es_evi_json_vtep_fill(json_object *json_vteps,
json_object_string_addf(json_vtep_entry, "vtep_ip", "%pI4",
&evi_vtep->vtep_ip);
- if (evi_vtep->flags & (BGP_EVPN_EVI_VTEP_EAD_PER_ES |
- BGP_EVPN_EVI_VTEP_EAD_PER_EVI)) {
+ if (CHECK_FLAG(evi_vtep->flags, (BGP_EVPN_EVI_VTEP_EAD_PER_ES |
+ BGP_EVPN_EVI_VTEP_EAD_PER_EVI))) {
json_flags = json_object_new_array();
- if (evi_vtep->flags & BGP_EVPN_EVI_VTEP_EAD_PER_ES)
+ if (CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_ES))
json_array_string_add(json_flags, "ead-per-es");
- if (evi_vtep->flags & BGP_EVPN_EVI_VTEP_EAD_PER_EVI)
+ if (CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_EVI))
json_array_string_add(json_flags, "ead-per-evi");
json_object_object_add(json_vtep_entry,
"flags", json_flags);
@@ -4035,12 +4039,12 @@ static void bgp_evpn_es_evi_show_entry(struct vty *vty,
if (es_evi->vpn)
json_object_int_add(json, "vni", es_evi->vpn->vni);
- if (es_evi->flags & (BGP_EVPNES_EVI_LOCAL |
- BGP_EVPNES_EVI_REMOTE)) {
+ if (CHECK_FLAG(es_evi->flags, (BGP_EVPNES_EVI_LOCAL |
+ BGP_EVPNES_EVI_REMOTE))) {
json_types = json_object_new_array();
- if (es_evi->flags & BGP_EVPNES_EVI_LOCAL)
+ if (CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL))
json_array_string_add(json_types, "local");
- if (es_evi->flags & BGP_EVPNES_EVI_REMOTE)
+ if (CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_REMOTE))
json_array_string_add(json_types, "remote");
json_object_object_add(json, "type", json_types);
}
@@ -4059,11 +4063,11 @@ static void bgp_evpn_es_evi_show_entry(struct vty *vty,
char vtep_str[ES_VTEP_LIST_STR_SZ + BGP_EVPN_VTEPS_FLAG_STR_SZ];
type_str[0] = '\0';
- if (es_evi->flags & BGP_EVPNES_EVI_LOCAL)
+ if (CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL))
strlcat(type_str, "L", sizeof(type_str));
- if (es_evi->flags & BGP_EVPNES_EVI_REMOTE)
+ if (CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_REMOTE))
strlcat(type_str, "R", sizeof(type_str));
- if (es_evi->flags & BGP_EVPNES_EVI_INCONS_VTEP_LIST)
+ if (CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_INCONS_VTEP_LIST))
strlcat(type_str, "I", sizeof(type_str));
bgp_evpn_es_evi_vteps_str(vtep_str, es_evi, sizeof(vtep_str));
@@ -4090,7 +4094,7 @@ static void bgp_evpn_es_evi_show_entry_detail(struct vty *vty,
json_object_string_addf(json, "esFragmentRd",
BGP_RD_AS_FORMAT(mode),
&es_evi->es_frag->prd);
- if (es_evi->flags & BGP_EVPNES_EVI_INCONS_VTEP_LIST) {
+ if (CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_INCONS_VTEP_LIST)) {
json_flags = json_object_new_array();
json_array_string_add(json_flags, "es-vtep-mismatch");
json_object_object_add(json, "flags", json_flags);
@@ -4100,9 +4104,9 @@ static void bgp_evpn_es_evi_show_entry_detail(struct vty *vty,
char type_str[4];
type_str[0] = '\0';
- if (es_evi->flags & BGP_EVPNES_EVI_LOCAL)
+ if (CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL))
strlcat(type_str, "L", sizeof(type_str));
- if (es_evi->flags & BGP_EVPNES_EVI_REMOTE)
+ if (CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_REMOTE))
strlcat(type_str, "R", sizeof(type_str));
bgp_evpn_es_evi_vteps_str(vtep_str, es_evi, sizeof(vtep_str));
@@ -4119,8 +4123,10 @@ static void bgp_evpn_es_evi_show_entry_detail(struct vty *vty,
vty_out(vty, "\n");
}
vty_out(vty, " Inconsistencies: %s\n",
- (es_evi->flags & BGP_EVPNES_EVI_INCONS_VTEP_LIST) ?
- "es-vtep-mismatch":"-");
+ CHECK_FLAG(es_evi->flags,
+ BGP_EVPNES_EVI_INCONS_VTEP_LIST)
+ ? "es-vtep-mismatch"
+ : "-");
vty_out(vty, " VTEPs: %s\n", vtep_str);
vty_out(vty, "\n");
}
@@ -4514,12 +4520,12 @@ static void bgp_evpn_nh_zebra_update_send(struct bgp_evpn_nh *nh, bool add)
static void bgp_evpn_nh_zebra_update(struct bgp_evpn_nh *nh, bool add)
{
if (add && !is_zero_mac(&nh->rmac)) {
- nh->flags |= BGP_EVPN_NH_READY_FOR_ZEBRA;
+ SET_FLAG(nh->flags, BGP_EVPN_NH_READY_FOR_ZEBRA);
bgp_evpn_nh_zebra_update_send(nh, true);
} else {
- if (!(nh->flags & BGP_EVPN_NH_READY_FOR_ZEBRA))
+ if (!CHECK_FLAG(nh->flags, BGP_EVPN_NH_READY_FOR_ZEBRA))
return;
- nh->flags &= ~BGP_EVPN_NH_READY_FOR_ZEBRA;
+ UNSET_FLAG(nh->flags, BGP_EVPN_NH_READY_FOR_ZEBRA);
bgp_evpn_nh_zebra_update_send(nh, false);
}
}
@@ -4811,7 +4817,7 @@ static void bgp_evpn_path_nh_link(struct bgp *bgp_vrf, struct bgp_path_info *pi)
/* if NHG is not being used for this path we don't need to manage the
* nexthops in bgp (they are managed by zebra instead)
*/
- if (!(pi->attr->es_flags & ATTR_ES_L3_NHG_USE)) {
+ if (!CHECK_FLAG(pi->attr->es_flags, ATTR_ES_L3_NHG_USE)) {
if (nh_info)
bgp_evpn_path_nh_unlink(nh_info);
return;
@@ -5053,3 +5059,38 @@ void bgp_evpn_switch_ead_evi_rx(void)
}
}
}
+
+void bgp_evpn_local_es_evi_unistall_local_routes_in_vrfs(struct bgp_evpn_es *es,
+ struct bgp_evpn_es_evi *es_evi)
+{
+ struct listnode *node;
+ struct bgp_path_es_info *es_info;
+ struct bgp_path_info *pi;
+ const struct prefix_evpn *evp;
+ struct bgp_evpn_es_vrf *es_vrf = es_evi->es_vrf;
+
+ if (!es_vrf)
+ return;
+
+ for (ALL_LIST_ELEMENTS_RO(es->macip_global_path_list, node, es_info)) {
+ pi = es_info->pi;
+
+ if (!bgp_evpn_is_macip_path(pi))
+ continue;
+
+ evp = (const struct prefix_evpn *)bgp_dest_get_prefix(pi->net);
+
+ if (!(CHECK_FLAG(pi->flags, BGP_PATH_VALID) && pi->type == ZEBRA_ROUTE_BGP &&
+ pi->sub_type == BGP_ROUTE_NORMAL))
+ continue;
+
+ if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
+ zlog_debug("route %pFX is matched on local esi %s, uninstall from %s route table",
+ evp, es->esi_str, es_vrf->bgp_vrf->name_pretty);
+
+ if (!bgp_evpn_skip_vrf_import_of_local_es(es_vrf->bgp_vrf, evp, pi, 0))
+ continue;
+
+ uninstall_evpn_route_entry_in_vrf(es_vrf->bgp_vrf, evp, pi);
+ }
+}
diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h
index 5d393c37..149bf384 100644
--- a/bgpd/bgp_evpn_mh.h
+++ b/bgpd/bgp_evpn_mh.h
@@ -459,5 +459,7 @@ extern void bgp_evpn_path_nh_add(struct bgp *bgp_vrf, struct bgp_path_info *pi);
extern void bgp_evpn_path_nh_del(struct bgp *bgp_vrf, struct bgp_path_info *pi);
extern void bgp_evpn_mh_config_ead_export_rt(struct bgp *bgp,
struct ecommunity *ecom, bool del);
+extern void bgp_evpn_local_es_evi_unistall_local_routes_in_vrfs(struct bgp_evpn_es *es,
+ struct bgp_evpn_es_evi *es_evi);
#endif /* _FRR_BGP_EVPN_MH_H */
diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h
index 07bba9b4..b05df3d8 100644
--- a/bgpd/bgp_evpn_private.h
+++ b/bgpd/bgp_evpn_private.h
@@ -382,7 +382,7 @@ static inline void encode_mac_mobility_extcomm(int static_mac, uint32_t seq,
}
static inline void encode_na_flag_extcomm(struct ecommunity_val *eval,
- uint8_t na_flag, bool proxy)
+ bool na_flag, bool proxy)
{
memset(eval, 0, sizeof(*eval));
eval->val[0] = ECOMMUNITY_ENCODE_EVPN;
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index 846a82ba..958a9c64 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -2561,7 +2561,7 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
/* Prefix and num paths displayed once per prefix. */
route_vty_out_detail_header(vty, bgp, dest, bgp_dest_get_prefix(dest),
- NULL, afi, safi, json, false);
+ NULL, afi, safi, json, false, true);
/* Display each path for this prefix. */
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
@@ -2663,7 +2663,7 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
/* Prefix and num paths displayed once per prefix. */
route_vty_out_detail_header(vty, bgp, dest, (struct prefix *)&p, NULL,
- afi, safi, json, false);
+ afi, safi, json, false, true);
evp = (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
@@ -2798,7 +2798,7 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
/* Prefix and num paths displayed once per prefix. */
route_vty_out_detail_header(vty, bgp, dest, bgp_dest_get_prefix(dest),
- prd, afi, safi, json, false);
+ prd, afi, safi, json, false, false);
if (json)
json_paths = json_object_new_array();
@@ -2820,9 +2820,9 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
path_cnt++;
}
- if (json && path_cnt) {
+ if (json) {
if (path_cnt)
- json_object_object_addf(json, json_paths, "%pFX", &p);
+ json_object_object_add(json, "paths", json_paths);
json_object_int_add(json, "numPaths", path_cnt);
} else {
vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
@@ -2905,9 +2905,10 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
}
/* Prefix and num paths displayed once per prefix. */
- route_vty_out_detail_header(
- vty, bgp, dest, bgp_dest_get_prefix(dest), prd,
- afi, safi, json_prefix, false);
+ route_vty_out_detail_header(vty, bgp, dest,
+ bgp_dest_get_prefix(dest),
+ prd, afi, safi, json_prefix,
+ false, false);
prefix_cnt++;
}
@@ -3042,9 +3043,10 @@ static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp,
p->prefixlen);
} else
/* Prefix and num paths displayed once per prefix. */
- route_vty_out_detail_header(
- vty, bgp, dest, p, (struct prefix_rd *)rd_destp,
- AFI_L2VPN, SAFI_EVPN, json_prefix, false);
+ route_vty_out_detail_header(vty, bgp, dest, p,
+ (struct prefix_rd *)rd_destp,
+ AFI_L2VPN, SAFI_EVPN,
+ json_prefix, false, false);
/* For EVPN, the prefix is displayed for each path (to
* fit in with code that already exists).
@@ -3197,11 +3199,14 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
/* Prefix and num paths displayed once per prefix. */
if (detail)
- route_vty_out_detail_header(
- vty, bgp, dest,
- bgp_dest_get_prefix(dest),
- (struct prefix_rd *)rd_destp, AFI_L2VPN,
- SAFI_EVPN, json_prefix, false);
+ route_vty_out_detail_header(vty, bgp, dest,
+ bgp_dest_get_prefix(
+ dest),
+ (struct prefix_rd *)
+ rd_destp,
+ AFI_L2VPN, SAFI_EVPN,
+ json_prefix, false,
+ false);
/* For EVPN, the prefix is displayed for each path (to
* fit in
@@ -4840,7 +4845,7 @@ DEFUN(show_bgp_l2vpn_evpn_summary, show_bgp_l2vpn_evpn_summary_cmd,
char *vrf = NULL;
char *neighbor = NULL;
as_t as = 0; /* 0 means AS filter not set */
- int as_type = AS_UNSPECIFIED;
+ enum peer_asn_type as_type = AS_UNSPECIFIED;
uint16_t show_flags = 0;
if (argv_find(argv, argc, "vrf", &idx_vrf))
diff --git a/bgpd/bgp_flowspec.c b/bgpd/bgp_flowspec.c
index 6165bf89..bd04970f 100644
--- a/bgpd/bgp_flowspec.c
+++ b/bgpd/bgp_flowspec.c
@@ -195,7 +195,7 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
NULL, 0, 0, NULL);
} else {
bgp_withdraw(peer, &p, 0, afi, safi, ZEBRA_ROUTE_BGP,
- BGP_ROUTE_NORMAL, NULL, NULL, 0, NULL);
+ BGP_ROUTE_NORMAL, NULL, NULL, 0);
}
XFREE(MTYPE_TMP, temp);
diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c
index 66426ab3..31e14d41 100644
--- a/bgpd/bgp_flowspec_util.c
+++ b/bgpd/bgp_flowspec_util.c
@@ -305,14 +305,14 @@ int bgp_flowspec_op_decode(enum bgp_flowspec_util_nlri_t type,
break;
mval->value = value;
if (op[5] == 1)
- mval->compare_operator |=
- OPERATOR_COMPARE_LESS_THAN;
+ SET_FLAG(mval->compare_operator,
+ OPERATOR_COMPARE_LESS_THAN);
if (op[6] == 1)
- mval->compare_operator |=
- OPERATOR_COMPARE_GREATER_THAN;
+ SET_FLAG(mval->compare_operator,
+ OPERATOR_COMPARE_GREATER_THAN);
if (op[7] == 1)
- mval->compare_operator |=
- OPERATOR_COMPARE_EQUAL_TO;
+ SET_FLAG(mval->compare_operator,
+ OPERATOR_COMPARE_EQUAL_TO);
if (op[1] == 1)
mval->unary_operator = OPERATOR_UNARY_AND;
else
@@ -413,16 +413,16 @@ int bgp_flowspec_bitmask_decode(enum bgp_flowspec_util_nlri_t type,
mval->value = value;
if (op[6] == 1) {
/* different from */
- mval->compare_operator |=
- OPERATOR_COMPARE_LESS_THAN;
- mval->compare_operator |=
- OPERATOR_COMPARE_GREATER_THAN;
+ SET_FLAG(mval->compare_operator,
+ OPERATOR_COMPARE_LESS_THAN);
+ SET_FLAG(mval->compare_operator,
+ OPERATOR_COMPARE_GREATER_THAN);
} else
- mval->compare_operator |=
- OPERATOR_COMPARE_EQUAL_TO;
+ SET_FLAG(mval->compare_operator,
+ OPERATOR_COMPARE_EQUAL_TO);
if (op[7] == 1)
- mval->compare_operator |=
- OPERATOR_COMPARE_EXACT_MATCH;
+ SET_FLAG(mval->compare_operator,
+ OPERATOR_COMPARE_EXACT_MATCH);
if (op[1] == 1)
mval->unary_operator =
OPERATOR_UNARY_AND;
@@ -467,11 +467,11 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
case FLOWSPEC_SRC_PREFIX:
bitmask = 0;
if (type == FLOWSPEC_DEST_PREFIX) {
- bitmask |= PREFIX_DST_PRESENT;
+ SET_FLAG(bitmask, PREFIX_DST_PRESENT);
prefix = &bpem->dst_prefix;
prefix_offset = &bpem->dst_prefix_offset;
} else {
- bitmask |= PREFIX_SRC_PRESENT;
+ SET_FLAG(bitmask, PREFIX_SRC_PRESENT);
prefix = &bpem->src_prefix;
prefix_offset = &bpem->src_prefix_offset;
}
@@ -491,14 +491,16 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
*/
if (prefix->family == AF_INET
&& prefix->u.prefix4.s_addr == INADDR_ANY)
- bpem->match_bitmask_iprule |= bitmask;
+ SET_FLAG(bpem->match_bitmask_iprule,
+ bitmask);
else if (prefix->family == AF_INET6
&& !memcmp(&prefix->u.prefix6,
&in6addr_any,
sizeof(struct in6_addr)))
- bpem->match_bitmask_iprule |= bitmask;
+ SET_FLAG(bpem->match_bitmask_iprule,
+ bitmask);
else
- bpem->match_bitmask |= bitmask;
+ SET_FLAG(bpem->match_bitmask, bitmask);
}
offset += ret;
break;
@@ -640,8 +642,8 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
|| bpem->match_dst_port_num || bpem->match_protocol_num
|| bpem->match_bitmask || bpem->match_flowlabel_num)
bpem->type = BGP_PBR_IPSET;
- else if ((bpem->match_bitmask_iprule & PREFIX_SRC_PRESENT) ||
- (bpem->match_bitmask_iprule & PREFIX_DST_PRESENT))
+ else if (CHECK_FLAG(bpem->match_bitmask_iprule, PREFIX_SRC_PRESENT) ||
+ CHECK_FLAG(bpem->match_bitmask_iprule, PREFIX_DST_PRESENT))
/* the extracted policy rule may not need an
* iptables/ipset filtering. check this may not be
* a standard ip rule : permit any to any ( eg)
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index d41ef8ab..94fca23e 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -602,6 +602,7 @@ const char *const peer_down_str[] = {
"Socket Error",
"Admin. shutdown (RTT)",
"Suppress Fib Turned On or Off",
+ "Password config change",
};
static void bgp_graceful_restart_timer_off(struct peer_connection *connection,
@@ -687,6 +688,11 @@ static void bgp_set_llgr_stale(struct peer *peer, afi_t afi, safi_t safi)
COMMUNITY_NO_LLGR))
continue;
+ if (bgp_attr_get_community(pi->attr) &&
+ community_include(bgp_attr_get_community(pi->attr),
+ COMMUNITY_LLGR_STALE))
+ continue;
+
if (bgp_debug_neighbor_events(peer))
zlog_debug(
"%pBP Long-lived set stale community (LLGR_STALE) for: %pFX",
@@ -695,10 +701,8 @@ static void bgp_set_llgr_stale(struct peer *peer, afi_t afi, safi_t safi)
attr = *pi->attr;
bgp_attr_add_llgr_community(&attr);
pi->attr = bgp_attr_intern(&attr);
- bgp_recalculate_afi_safi_bestpaths(
- peer->bgp, afi, safi);
-
- break;
+ bgp_process(peer->bgp, rm, pi, afi,
+ safi);
}
}
} else {
@@ -715,6 +719,11 @@ static void bgp_set_llgr_stale(struct peer *peer, afi_t afi, safi_t safi)
COMMUNITY_NO_LLGR))
continue;
+ if (bgp_attr_get_community(pi->attr) &&
+ community_include(bgp_attr_get_community(pi->attr),
+ COMMUNITY_LLGR_STALE))
+ continue;
+
if (bgp_debug_neighbor_events(peer))
zlog_debug(
"%pBP Long-lived set stale community (LLGR_STALE) for: %pFX",
@@ -723,10 +732,7 @@ static void bgp_set_llgr_stale(struct peer *peer, afi_t afi, safi_t safi)
attr = *pi->attr;
bgp_attr_add_llgr_community(&attr);
pi->attr = bgp_attr_intern(&attr);
- bgp_recalculate_afi_safi_bestpaths(peer->bgp,
- afi, safi);
-
- break;
+ bgp_process(peer->bgp, dest, pi, afi, safi);
}
}
}
@@ -1482,7 +1488,7 @@ enum bgp_fsm_state_progress bgp_stop(struct peer_connection *connection)
EVENT_OFF(connection->t_connect);
EVENT_OFF(connection->t_holdtime);
EVENT_OFF(connection->t_routeadv);
- EVENT_OFF(peer->connection->t_delayopen);
+ EVENT_OFF(connection->t_delayopen);
/* Clear input and output buffer. */
frr_with_mutex (&connection->io_mtx) {
@@ -1801,18 +1807,14 @@ bgp_connect_fail(struct peer_connection *connection)
*/
static void bgp_connect_in_progress_update_connection(struct peer *peer)
{
- if (bgp_getsockname(peer) < 0) {
- if (!peer->su_remote &&
- !BGP_CONNECTION_SU_UNSPEC(peer->connection)) {
- /* if connect initiated, then dest port and dest addresses are well known */
- peer->su_remote = sockunion_dup(&peer->connection->su);
- if (sockunion_family(peer->su_remote) == AF_INET)
- peer->su_remote->sin.sin_port =
- htons(peer->port);
- else if (sockunion_family(peer->su_remote) == AF_INET6)
- peer->su_remote->sin6.sin6_port =
- htons(peer->port);
- }
+ bgp_updatesockname(peer);
+ if (!peer->su_remote && !BGP_CONNECTION_SU_UNSPEC(peer->connection)) {
+ /* if connect initiated, then dest port and dest addresses are well known */
+ peer->su_remote = sockunion_dup(&peer->connection->su);
+ if (sockunion_family(peer->su_remote) == AF_INET)
+ peer->su_remote->sin.sin_port = htons(peer->port);
+ else if (sockunion_family(peer->su_remote) == AF_INET6)
+ peer->su_remote->sin6.sin6_port = htons(peer->port);
}
}
@@ -2046,9 +2048,10 @@ static int bgp_start_deferral_timer(struct bgp *bgp, afi_t afi, safi_t safi,
}
gr_info->eor_required++;
/* Send message to RIB indicating route update pending */
- if (gr_info->af_enabled[afi][safi] == false) {
- gr_info->af_enabled[afi][safi] = true;
- /* Send message to RIB */
+ if (gr_info->af_enabled == false) {
+ gr_info->af_enabled = true;
+ gr_info->route_sync = false;
+ bgp->gr_route_sync_pending = true;
bgp_zebra_update(bgp, afi, safi,
ZEBRA_CLIENT_ROUTE_UPDATE_PENDING);
}
@@ -2082,7 +2085,7 @@ static int bgp_update_gr_info(struct peer *peer, afi_t afi, safi_t safi)
if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
&& BGP_PEER_RESTARTING_MODE(peer)) {
/* Check if the forwarding state is preserved */
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD)) {
+ if (bgp_gr_is_forwarding_preserved(bgp)) {
gr_info = &(bgp->gr_info[afi][safi]);
ret = bgp_start_deferral_timer(bgp, afi, safi, gr_info);
}
@@ -2199,8 +2202,7 @@ bgp_establish(struct peer_connection *connection)
} else {
if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer) &&
BGP_PEER_RESTARTING_MODE(peer) &&
- CHECK_FLAG(peer->bgp->flags,
- BGP_FLAG_GR_PRESERVE_FWD))
+ bgp_gr_is_forwarding_preserved(peer->bgp))
peer->bgp->gr_info[afi][safi]
.eor_required++;
}
@@ -2695,53 +2697,61 @@ int bgp_event_update(struct peer_connection *connection,
}
/* BGP GR Code */
-int bgp_gr_lookup_n_update_all_peer(struct bgp *bgp,
- enum global_mode global_new_state,
- enum global_mode global_old_state)
+static inline void
+bgp_peer_inherit_global_gr_mode(struct peer *peer,
+ enum global_mode global_gr_mode)
+{
+ switch (global_gr_mode) {
+ case GLOBAL_HELPER:
+ BGP_PEER_GR_HELPER_ENABLE(peer);
+ break;
+ case GLOBAL_GR:
+ BGP_PEER_GR_ENABLE(peer);
+ break;
+ case GLOBAL_DISABLE:
+ BGP_PEER_GR_DISABLE(peer);
+ break;
+ case GLOBAL_INVALID:
+ default:
+ zlog_err("Unexpected Global GR mode %d", global_gr_mode);
+ }
+}
+
+static void bgp_gr_update_mode_of_all_peers(struct bgp *bgp,
+ enum global_mode global_new_state)
{
struct peer *peer = {0};
struct listnode *node = {0};
struct listnode *nnode = {0};
enum peer_mode peer_old_state = PEER_INVALID;
- for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
-
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("%s [BGP_GR] Peer: (%s) :", __func__,
- peer->host);
+ /* TODO: Need to handle peer-groups. */
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
peer_old_state = bgp_peer_gr_mode_get(peer);
+ if (peer_old_state != PEER_GLOBAL_INHERIT)
+ continue;
- if (peer_old_state == PEER_GLOBAL_INHERIT) {
-
- /*
- *Reset only these peers and send a
- *new open message with the change capabilities.
- *Considering the mode to be "global_new_state" and
- *do all operation accordingly
- */
+ bgp_peer_inherit_global_gr_mode(peer, global_new_state);
+ bgp_peer_gr_flags_update(peer);
- switch (global_new_state) {
- case GLOBAL_HELPER:
- BGP_PEER_GR_HELPER_ENABLE(peer);
- break;
- case GLOBAL_GR:
- BGP_PEER_GR_ENABLE(peer);
- break;
- case GLOBAL_DISABLE:
- BGP_PEER_GR_DISABLE(peer);
- break;
- case GLOBAL_INVALID:
- zlog_debug("%s [BGP_GR] GLOBAL_INVALID",
- __func__);
- return BGP_ERR_GR_OPERATION_FAILED;
- }
- }
- }
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug("%pBP: Inherited Global GR mode, GR flags 0x%x peer flags 0x%" PRIx64
+ "...resetting session",
+ peer, peer->peer_gr_new_status_flag,
+ peer->flags);
- bgp->global_gr_present_state = global_new_state;
+ peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
- return BGP_GR_SUCCESS;
+ /* Reset session to match with behavior for other peer
+ * configs that require the session to be re-setup.
+ */
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
+ bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+ else
+ bgp_session_reset_safe(peer, &nnode);
+ }
}
int bgp_gr_update_all(struct bgp *bgp, enum global_gr_command global_gr_cmd)
@@ -2749,46 +2759,27 @@ int bgp_gr_update_all(struct bgp *bgp, enum global_gr_command global_gr_cmd)
enum global_mode global_new_state = GLOBAL_INVALID;
enum global_mode global_old_state = GLOBAL_INVALID;
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("%s [BGP_GR]START: global_gr_cmd :%s:", __func__,
- print_global_gr_cmd(global_gr_cmd));
-
global_old_state = bgp_global_gr_mode_get(bgp);
+ global_new_state = bgp->GLOBAL_GR_FSM[global_old_state][global_gr_cmd];
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("[BGP_GR] global_old_gr_state :%s:",
- print_global_gr_mode(global_old_state));
+ zlog_debug("%s: Handle GR command %s, current GR state %s, new GR state %s",
+ bgp->name_pretty, print_global_gr_cmd(global_gr_cmd),
+ print_global_gr_mode(global_old_state),
+ print_global_gr_mode(global_new_state));
- if (global_old_state != GLOBAL_INVALID) {
- global_new_state =
- bgp->GLOBAL_GR_FSM[global_old_state][global_gr_cmd];
-
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("[BGP_GR] global_new_gr_state :%s:",
- print_global_gr_mode(global_new_state));
- } else {
- zlog_err("%s [BGP_GR] global_old_state == GLOBAL_INVALID",
- __func__);
+ if (global_old_state == GLOBAL_INVALID)
return BGP_ERR_GR_OPERATION_FAILED;
- }
-
- if (global_new_state == GLOBAL_INVALID) {
- zlog_err("%s [BGP_GR] global_new_state == GLOBAL_INVALID",
- __func__);
+ if (global_new_state == GLOBAL_INVALID)
return BGP_ERR_GR_INVALID_CMD;
- }
- if (global_new_state == global_old_state) {
- /* Trace msg */
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "%s [BGP_GR] global_new_state == global_old_state :%s",
- __func__,
- print_global_gr_mode(global_new_state));
+ if (global_new_state == global_old_state)
return BGP_GR_NO_OPERATION;
- }
- return bgp_gr_lookup_n_update_all_peer(bgp, global_new_state,
- global_old_state);
+ /* Update global GR mode and process all peers in instance. */
+ bgp->global_gr_present_state = global_new_state;
+ bgp_gr_update_mode_of_all_peers(bgp, global_new_state);
+
+ return BGP_GR_SUCCESS;
}
const char *print_peer_gr_mode(enum peer_mode pr_mode)
@@ -2903,179 +2894,102 @@ int bgp_neighbor_graceful_restart(struct peer *peer,
{
enum peer_mode peer_new_state = PEER_INVALID;
enum peer_mode peer_old_state = PEER_INVALID;
- struct bgp_peer_gr peer_state;
+ struct bgp_peer_gr gr_fsm;
int result = BGP_GR_FAILURE;
- /*
- * fetch peer_old_state from peer structure also
- * fetch global_old_state from bgp structure,
- * peer had a back pointer to bgpo struct ;
- */
-
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("%s [BGP_GR] START:Peer: (%s) : peer_gr_cmd :%s:",
- __func__, peer->host,
- print_peer_gr_cmd(peer_gr_cmd));
-
peer_old_state = bgp_peer_gr_mode_get(peer);
+ gr_fsm = peer->PEER_GR_FSM[peer_old_state][peer_gr_cmd];
+ peer_new_state = gr_fsm.next_state;
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("%s [BGP_GR] peer_old_state: %d", __func__,
- peer_old_state);
+ zlog_debug("%pBP: Handle GR command %s, current GR state %s, new GR state %s",
+ peer, print_peer_gr_cmd(peer_gr_cmd),
+ print_peer_gr_mode(peer_old_state),
+ print_peer_gr_mode(peer_new_state));
if (peer_old_state == PEER_INVALID)
return BGP_ERR_GR_OPERATION_FAILED;
- peer_state = peer->PEER_GR_FSM[peer_old_state][peer_gr_cmd];
- peer_new_state = peer_state.next_state;
-
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("%s [BGP_GR] peer_new_state: %d", __func__,
- peer_new_state);
-
if (peer_new_state == PEER_INVALID)
return BGP_ERR_GR_INVALID_CMD;
- if (peer_new_state != peer_old_state) {
- result = peer_state.action_fun(peer, peer_old_state,
- peer_new_state);
- } else {
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] peer_old_state == peer_new_state !");
+ if (peer_new_state == peer_old_state)
return BGP_GR_NO_OPERATION;
- }
-
- if (result == BGP_GR_SUCCESS) {
- /* Update the mode i.e peer_new_state into the peer structure */
- peer->peer_gr_present_state = peer_new_state;
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] Successfully change the state of the peer to : %s : !",
- print_peer_gr_mode(peer_new_state));
-
- return BGP_GR_SUCCESS;
- }
+ result = gr_fsm.action_fun(peer, peer_old_state, peer_new_state);
return result;
}
-unsigned int bgp_peer_gr_action(struct peer *peer, enum peer_mode old_peer_state,
- enum peer_mode new_peer_state)
+static inline bool gr_mode_matches(enum peer_mode peer_gr_mode,
+ enum global_mode global_gr_mode)
{
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "%s [BGP_GR] Move peer from old_peer_state :%s: to new_peer_state :%s: !!!!",
- __func__, print_peer_gr_mode(old_peer_state),
- print_peer_gr_mode(new_peer_state));
+ if ((peer_gr_mode == PEER_HELPER && global_gr_mode == GLOBAL_HELPER) ||
+ (peer_gr_mode == PEER_GR && global_gr_mode == GLOBAL_GR) ||
+ (peer_gr_mode == PEER_DISABLE && global_gr_mode == GLOBAL_DISABLE))
+ return true;
+ return false;
+}
- enum global_mode bgp_gr_global_mode = GLOBAL_INVALID;
- unsigned int ret = BGP_GR_FAILURE;
+unsigned int bgp_peer_gr_action(struct peer *peer, enum peer_mode old_state,
+ enum peer_mode new_state)
+{
+ enum global_mode global_gr_mode;
+ bool session_reset = true;
- if (old_peer_state == new_peer_state) {
- /* Nothing to do over here as the present and old state is the
- * same */
+ if (old_state == new_state)
return BGP_GR_NO_OPERATION;
- }
- if ((old_peer_state == PEER_INVALID)
- || (new_peer_state == PEER_INVALID)) {
- /* something bad happend , print error message */
+ if ((old_state == PEER_INVALID) || (new_state == PEER_INVALID))
return BGP_ERR_GR_INVALID_CMD;
- }
- bgp_gr_global_mode = bgp_global_gr_mode_get(peer->bgp);
-
- if ((old_peer_state == PEER_GLOBAL_INHERIT)
- && (new_peer_state != PEER_GLOBAL_INHERIT)) {
-
- /* fetch the Mode running in the Global state machine
- *from the bgp structure into a variable called
- *bgp_gr_global_mode
- */
-
- /* Here we are checking if the
- *1. peer_new_state == global_mode == helper_mode
- *2. peer_new_state == global_mode == GR_mode
- *3. peer_new_state == global_mode == disabled_mode
- */
+ global_gr_mode = bgp_global_gr_mode_get(peer->bgp);
+ if ((old_state == PEER_GLOBAL_INHERIT) &&
+ (new_state != PEER_GLOBAL_INHERIT)) {
BGP_PEER_GR_GLOBAL_INHERIT_UNSET(peer);
- if ((int)new_peer_state == (int)bgp_gr_global_mode) {
- /* This is incremental updates i.e no tear down
- * of the existing session
- * as the peer is already working in the same mode.
+ if (gr_mode_matches(new_state, global_gr_mode))
+ /* Peer was inheriting the global state and
+ * its new state still is the same, so a
+ * session reset is not needed.
*/
- ret = BGP_GR_SUCCESS;
- } else {
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] Peer state changed from :%s ",
- print_peer_gr_mode(old_peer_state));
-
- bgp_peer_move_to_gr_mode(peer, new_peer_state);
-
- ret = BGP_GR_SUCCESS;
- }
- }
- /* In the case below peer is going into Global inherit mode i.e.
- * the peer would work as the mode configured at the global level
- */
- else if ((new_peer_state == PEER_GLOBAL_INHERIT)
- && (old_peer_state != PEER_GLOBAL_INHERIT)) {
- /* Here in this case it would be destructive
- * in all the cases except one case when,
- * Global GR is configured Disabled
- * and present_peer_state is not disable
- */
-
+ session_reset = false;
+ } else if ((new_state == PEER_GLOBAL_INHERIT) &&
+ (old_state != PEER_GLOBAL_INHERIT)) {
BGP_PEER_GR_GLOBAL_INHERIT_SET(peer);
- if ((int)old_peer_state == (int)bgp_gr_global_mode) {
- /* This is incremental updates
- *i.e no tear down of the existing session
- *as the peer is already working in the same mode.
- */
- ret = BGP_GR_SUCCESS;
- } else {
- /* Destructive always */
- /* Tear down the old session
- * and send the new capability
- * as per the bgp_gr_global_mode
+ if (gr_mode_matches(old_state, global_gr_mode))
+ /* Peer is inheriting the global state and
+ * its old state was also the same, so a
+ * session reset is not needed.
*/
+ session_reset = false;
+ }
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] Peer state changed from :%s",
- print_peer_gr_mode(old_peer_state));
+ /* Ensure we move to the new state and update flags */
+ bgp_peer_move_to_gr_mode(peer, new_state);
- bgp_peer_move_to_gr_mode(peer, bgp_gr_global_mode);
+ if (session_reset) {
+ peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
- ret = BGP_GR_SUCCESS;
- }
- } else {
- /*
- *This else case, it include all the cases except -->
- *(new_peer_state != Peer_Global) &&
- *( old_peer_state != Peer_Global )
+ /* Reset session to match with behavior for other peer
+ * configs that require the session to be re-setup.
*/
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("[BGP_GR] Peer state changed from :%s",
- print_peer_gr_mode(old_peer_state));
-
- bgp_peer_move_to_gr_mode(peer, new_peer_state);
-
- ret = BGP_GR_SUCCESS;
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
+ bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+ else
+ bgp_session_reset(peer);
}
- return ret;
+ return BGP_GR_SUCCESS;
}
-inline void bgp_peer_move_to_gr_mode(struct peer *peer, int new_state)
+void bgp_peer_move_to_gr_mode(struct peer *peer, enum peer_mode new_state)
{
- int bgp_global_gr_mode = bgp_global_gr_mode_get(peer->bgp);
+ enum global_mode global_gr_mode = bgp_global_gr_mode_get(peer->bgp);
+ enum peer_mode old_state = bgp_peer_gr_mode_get(peer);
switch (new_state) {
case PEER_HELPER:
@@ -3089,57 +3003,38 @@ inline void bgp_peer_move_to_gr_mode(struct peer *peer, int new_state)
break;
case PEER_GLOBAL_INHERIT:
BGP_PEER_GR_GLOBAL_INHERIT_SET(peer);
-
- if (bgp_global_gr_mode == GLOBAL_HELPER) {
- BGP_PEER_GR_HELPER_ENABLE(peer);
- } else if (bgp_global_gr_mode == GLOBAL_GR) {
- BGP_PEER_GR_ENABLE(peer);
- } else if (bgp_global_gr_mode == GLOBAL_DISABLE) {
- BGP_PEER_GR_DISABLE(peer);
- } else {
- zlog_err(
- "[BGP_GR] Default switch inherit mode ::: SOMETHING IS WRONG !!!");
- }
+ bgp_peer_inherit_global_gr_mode(peer, global_gr_mode);
break;
+ case PEER_INVALID:
default:
zlog_err(
"[BGP_GR] Default switch mode ::: SOMETHING IS WRONG !!!");
break;
}
+ bgp_peer_gr_flags_update(peer);
+ peer->peer_gr_present_state = new_state;
+
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("[BGP_GR] Peer state changed --to--> : %d : !",
- new_state);
+ zlog_debug("%pBP: Peer GR mode changed from %s to %s, GR flags 0x%x peer flags 0x%" PRIx64,
+ peer, print_peer_gr_mode(old_state),
+ print_peer_gr_mode(new_state),
+ peer->peer_gr_new_status_flag, peer->flags);
}
void bgp_peer_gr_flags_update(struct peer *peer)
{
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("%s [BGP_GR] called !", __func__);
if (CHECK_FLAG(peer->peer_gr_new_status_flag,
PEER_GRACEFUL_RESTART_NEW_STATE_HELPER))
SET_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART_HELPER);
else
UNSET_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART_HELPER);
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] Peer %s Flag PEER_FLAG_GRACEFUL_RESTART_HELPER : %s : !",
- peer->host,
- (CHECK_FLAG(peer->flags,
- PEER_FLAG_GRACEFUL_RESTART_HELPER)
- ? "Set"
- : "UnSet"));
+
if (CHECK_FLAG(peer->peer_gr_new_status_flag,
PEER_GRACEFUL_RESTART_NEW_STATE_RESTART))
SET_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART);
else
UNSET_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART);
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] Peer %s Flag PEER_FLAG_GRACEFUL_RESTART : %s : !",
- peer->host,
- (CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)
- ? "Set"
- : "UnSet"));
+
if (CHECK_FLAG(peer->peer_gr_new_status_flag,
PEER_GRACEFUL_RESTART_NEW_STATE_INHERIT))
SET_FLAG(peer->flags,
@@ -3147,28 +3042,28 @@ void bgp_peer_gr_flags_update(struct peer *peer)
else
UNSET_FLAG(peer->flags,
PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT);
+
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] Peer %s Flag PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT : %s : !",
- peer->host,
- (CHECK_FLAG(peer->flags,
- PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT)
- ? "Set"
- : "UnSet"));
-
- if (!CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)
- && !CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART_HELPER)) {
- zlog_debug("[BGP_GR] Peer %s UNSET PEER_STATUS_NSF_MODE!",
- peer->host);
+ zlog_debug("%pBP: Peer flags updated to 0x%" PRIx64
+ ", GR flags 0x%x, GR mode %s",
+ peer, peer->flags, peer->peer_gr_new_status_flag,
+ print_peer_gr_mode(bgp_peer_gr_mode_get(peer)));
+ /*
+ * If GR has been completely disabled for the peer and we were
+ * acting as the Helper for the peer (i.e., keeping stale routes
+ * and running the restart timer or stalepath timer), clear those
+ * states.
+ */
+ if (!CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART) &&
+ !CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART_HELPER)) {
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) {
-
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%pBP: GR disabled, stopping NSF and clearing stale routes",
+ peer);
peer_nsf_stop(peer);
- zlog_debug(
- "[BGP_GR] Peer %s UNSET PEER_STATUS_NSF_WAIT!",
- peer->host);
}
}
}
diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h
index bcdd4919..85c48896 100644
--- a/bgpd/bgp_fsm.h
+++ b/bgpd/bgp_fsm.h
@@ -151,7 +151,7 @@ int bgp_neighbor_graceful_restart(struct peer *peer,
enum peer_gr_command peer_gr_cmd);
unsigned int bgp_peer_gr_action(struct peer *peer, enum peer_mode old_peer_state,
enum peer_mode new_peer_state);
-void bgp_peer_move_to_gr_mode(struct peer *peer, int new_state);
+void bgp_peer_move_to_gr_mode(struct peer *peer, enum peer_mode new_state);
unsigned int bgp_peer_gr_helper_enable(struct peer *peer);
unsigned int bgp_peer_gr_enable(struct peer *peer);
unsigned int bgp_peer_gr_global_inherit(struct peer *peer);
@@ -160,9 +160,6 @@ enum peer_mode bgp_peer_gr_mode_get(struct peer *peer);
enum global_mode bgp_global_gr_mode_get(struct bgp *bgp);
enum peer_mode bgp_get_peer_gr_mode_from_flags(struct peer *peer);
unsigned int bgp_peer_gr_global_inherit_unset(struct peer *peer);
-int bgp_gr_lookup_n_update_all_peer(struct bgp *bgp,
- enum global_mode global_new_state,
- enum global_mode global_old_state);
void bgp_peer_gr_flags_update(struct peer *peer);
const char *print_peer_gr_mode(enum peer_mode pr_mode);
const char *print_peer_gr_cmd(enum peer_gr_command pr_gr_cmd);
diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c
index f03b820d..5db36217 100644
--- a/bgpd/bgp_label.c
+++ b/bgpd/bgp_label.c
@@ -38,7 +38,7 @@ static void *bgp_labels_hash_alloc(void *p)
struct bgp_labels *new;
uint8_t i;
- new = XMALLOC(MTYPE_BGP_LABELS, sizeof(struct bgp_labels));
+ new = XCALLOC(MTYPE_BGP_LABELS, sizeof(struct bgp_labels));
new->num_labels = labels->num_labels;
for (i = 0; i < labels->num_labels; i++)
@@ -576,7 +576,7 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
} else {
bgp_withdraw(peer, &p, addpath_id, packet->afi,
SAFI_UNICAST, ZEBRA_ROUTE_BGP,
- BGP_ROUTE_NORMAL, NULL, &label, 1, NULL);
+ BGP_ROUTE_NORMAL, NULL, &label, 1);
}
}
diff --git a/bgpd/bgp_mac.c b/bgpd/bgp_mac.c
index 28fb4527..86d6281e 100644
--- a/bgpd/bgp_mac.c
+++ b/bgpd/bgp_mac.c
@@ -143,7 +143,6 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
const struct prefix *p = bgp_dest_get_prefix(dest);
struct prefix_evpn *pevpn = (struct prefix_evpn *)dest;
struct prefix_rd prd;
- struct bgp_route_evpn *evpn;
if (pevpn->family == AF_EVPN
&& pevpn->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE
@@ -195,12 +194,10 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
continue;
}
- memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
- sizeof(evpn));
bgp_update(peer, p, pi->addpath_rx_id, pi->attr,
AFI_L2VPN, SAFI_EVPN, ZEBRA_ROUTE_BGP,
- BGP_ROUTE_NORMAL, &prd, label_pnt,
- num_labels, 1, evpn);
+ BGP_ROUTE_NORMAL, &prd, label_pnt, num_labels,
+ 1, bgp_attr_get_evpn_overlay(pi->attr));
}
}
}
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index 97658d34..535d2fc5 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -63,18 +63,16 @@ DEFINE_HOOK(bgp_hook_vrf_update, (struct vrf *vrf, bool enabled),
(vrf, enabled));
/* bgpd options, we use GNU getopt library. */
-static const struct option longopts[] = {
- { "bgp_port", required_argument, NULL, 'p' },
- { "listenon", required_argument, NULL, 'l' },
- { "no_kernel", no_argument, NULL, 'n' },
- { "skip_runas", no_argument, NULL, 'S' },
- { "ecmp", required_argument, NULL, 'e' },
- { "int_num", required_argument, NULL, 'I' },
- { "no_zebra", no_argument, NULL, 'Z' },
- { "socket_size", required_argument, NULL, 's' },
- { "v6-with-v4-nexthops", no_argument, NULL, 'v' },
- { 0 }
-};
+static const struct option longopts[] = { { "bgp_port", required_argument, NULL, 'p' },
+ { "listenon", required_argument, NULL, 'l' },
+ { "no_kernel", no_argument, NULL, 'n' },
+ { "skip_runas", no_argument, NULL, 'S' },
+ { "ecmp", required_argument, NULL, 'e' },
+ { "int_num", required_argument, NULL, 'I' },
+ { "no_zebra", no_argument, NULL, 'Z' },
+ { "socket_size", required_argument, NULL, 's' },
+ { "v6-with-v4-nexthops", no_argument, NULL, 'x' },
+ { 0 } };
/* signal definitions */
void sighup(void);
@@ -424,11 +422,12 @@ int main(int argc, char **argv)
int buffer_size = BGP_SOCKET_SNDBUF_SIZE;
char *address;
struct listnode *node;
+ bool v6_with_v4_nexthops = false;
addresses->cmp = (int (*)(void *, void *))strcmp;
frr_preinit(&bgpd_di, argc, argv);
- frr_opt_add("p:l:SnZe:I:s:" DEPRECATED_OPTIONS, longopts,
+ frr_opt_add("p:l:SnZe:I:s:x" DEPRECATED_OPTIONS, longopts,
" -p, --bgp_port Set BGP listen port number (0 means do not listen).\n"
" -l, --listenon Listen on specified address (implies -n)\n"
" -n, --no_kernel Do not install route to kernel.\n"
@@ -437,7 +436,7 @@ int main(int argc, char **argv)
" -e, --ecmp Specify ECMP to use.\n"
" -I, --int_num Set instance number (label-manager)\n"
" -s, --socket_size Set BGP peer socket send buffer size\n"
- " , --v6-with-v4-nexthop Allow BGP to form v6 neighbors using v4 nexthops\n");
+ " -x, --v6-with-v4-nexthop Allow BGP to form v6 neighbors using v4 nexthops\n");
/* Command line argument treatment. */
while (1) {
@@ -499,8 +498,8 @@ int main(int argc, char **argv)
case 's':
buffer_size = atoi(optarg);
break;
- case 'v':
- bm->v6_with_v4_nexthops = true;
+ case 'x':
+ v6_with_v4_nexthops = true;
break;
default:
frr_help_exit(1);
@@ -511,13 +510,18 @@ int main(int argc, char **argv)
/* BGP master init. */
bgp_master_init(frr_init(), buffer_size, addresses);
+ bm->startup_time = monotime(NULL);
bm->port = bgp_port;
+ bm->v6_with_v4_nexthops = v6_with_v4_nexthops;
if (bgp_port == 0)
bgp_option_set(BGP_OPT_NO_LISTEN);
if (no_fib_flag || no_zebra_flag)
bgp_option_set(BGP_OPT_NO_FIB);
if (no_zebra_flag)
bgp_option_set(BGP_OPT_NO_ZEBRA);
+ if (bgpd_di.graceful_restart)
+ SET_FLAG(bm->flags, BM_FLAG_GRACEFUL_RESTART);
+
bgp_error_init();
/* Initializations. */
libagentx_init();
diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c
index c1804fb7..c2599ade 100644
--- a/bgpd/bgp_memory.c
+++ b/bgpd/bgp_memory.c
@@ -135,3 +135,5 @@ DEFINE_MTYPE(BGPD, EVPN_REMOTE_IP, "BGP EVPN Remote IP hash entry");
DEFINE_MTYPE(BGPD, BGP_NOTIFICATION, "BGP Notification Message");
DEFINE_MTYPE(BGPD, BGP_SOFT_VERSION, "Software Version");
+
+DEFINE_MTYPE(BGPD, BGP_EVPN_OVERLAY, "BGP EVPN Overlay");
diff --git a/bgpd/bgp_memory.h b/bgpd/bgp_memory.h
index 4ae49a2c..1f76945d 100644
--- a/bgpd/bgp_memory.h
+++ b/bgpd/bgp_memory.h
@@ -134,4 +134,6 @@ DECLARE_MTYPE(BGP_NOTIFICATION);
DECLARE_MTYPE(BGP_SOFT_VERSION);
+DECLARE_MTYPE(BGP_EVPN_OVERLAY);
+
#endif /* _QUAGGA_BGP_MEMORY_H */
diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c
index e12d84b8..609afa42 100644
--- a/bgpd/bgp_mpath.c
+++ b/bgpd/bgp_mpath.c
@@ -2,8 +2,10 @@
/*
* BGP Multipath
* Copyright (C) 2010 Google Inc.
+ * 2024 Nvidia Corporation
+ * Donald Sharp
*
- * This file is part of Quagga
+ * This file is part of FRR
*/
#include <zebra.h>
@@ -191,78 +193,6 @@ int bgp_path_info_nexthop_cmp(struct bgp_path_info *bpi1,
}
/*
- * bgp_path_info_mpath_cmp
- *
- * This function determines our multipath list ordering. By ordering
- * the list we can deterministically select which paths are included
- * in the multipath set. The ordering also helps in detecting changes
- * in the multipath selection so we can detect whether to send an
- * update to zebra.
- *
- * The order of paths is determined first by received nexthop, and then
- * by peer address if the nexthops are the same.
- */
-static int bgp_path_info_mpath_cmp(void *val1, void *val2)
-{
- struct bgp_path_info *bpi1, *bpi2;
- int compare;
-
- bpi1 = val1;
- bpi2 = val2;
-
- compare = bgp_path_info_nexthop_cmp(bpi1, bpi2);
-
- if (!compare) {
- if (!bpi1->peer->su_remote && !bpi2->peer->su_remote)
- compare = 0;
- else if (!bpi1->peer->su_remote)
- compare = 1;
- else if (!bpi2->peer->su_remote)
- compare = -1;
- else
- compare = sockunion_cmp(bpi1->peer->su_remote,
- bpi2->peer->su_remote);
- }
-
- return compare;
-}
-
-/*
- * bgp_mp_list_init
- *
- * Initialize the mp_list, which holds the list of multipaths
- * selected by bgp_best_selection
- */
-void bgp_mp_list_init(struct list *mp_list)
-{
- assert(mp_list);
- memset(mp_list, 0, sizeof(struct list));
- mp_list->cmp = bgp_path_info_mpath_cmp;
-}
-
-/*
- * bgp_mp_list_clear
- *
- * Clears all entries out of the mp_list
- */
-void bgp_mp_list_clear(struct list *mp_list)
-{
- assert(mp_list);
- list_delete_all_node(mp_list);
-}
-
-/*
- * bgp_mp_list_add
- *
- * Adds a multipath entry to the mp_list
- */
-void bgp_mp_list_add(struct list *mp_list, struct bgp_path_info *mpinfo)
-{
- assert(mp_list && mpinfo);
- listnode_add_sort(mp_list, mpinfo);
-}
-
-/*
* bgp_path_info_mpath_new
*
* Allocate and zero memory for a new bgp_path_info_mpath element
@@ -274,6 +204,7 @@ static struct bgp_path_info_mpath *bgp_path_info_mpath_new(void)
new_mpath = XCALLOC(MTYPE_BGP_MPATH_INFO,
sizeof(struct bgp_path_info_mpath));
+ new_mpath->mp_count = 1;
return new_mpath;
}
@@ -287,6 +218,8 @@ void bgp_path_info_mpath_free(struct bgp_path_info_mpath **mpath)
if (mpath && *mpath) {
if ((*mpath)->mp_attr)
bgp_attr_unintern(&(*mpath)->mp_attr);
+ (*mpath)->mp_attr = NULL;
+
XFREE(MTYPE_BGP_MPATH_INFO, *mpath);
}
}
@@ -314,58 +247,22 @@ bgp_path_info_mpath_get(struct bgp_path_info *path)
}
/*
- * bgp_path_info_mpath_enqueue
- *
- * Enqueue a path onto the multipath list given the previous multipath
- * list entry
- */
-static void bgp_path_info_mpath_enqueue(struct bgp_path_info *prev_info,
- struct bgp_path_info *path)
-{
- struct bgp_path_info_mpath *prev, *mpath;
-
- prev = bgp_path_info_mpath_get(prev_info);
- mpath = bgp_path_info_mpath_get(path);
- if (!prev || !mpath)
- return;
-
- mpath->mp_next = prev->mp_next;
- mpath->mp_prev = prev;
- if (prev->mp_next)
- prev->mp_next->mp_prev = mpath;
- prev->mp_next = mpath;
-
- SET_FLAG(path->flags, BGP_PATH_MULTIPATH);
-}
-
-/*
- * bgp_path_info_mpath_dequeue
- *
- * Remove a path from the multipath list
- */
-void bgp_path_info_mpath_dequeue(struct bgp_path_info *path)
-{
- struct bgp_path_info_mpath *mpath = path->mpath;
- if (!mpath)
- return;
- if (mpath->mp_prev)
- mpath->mp_prev->mp_next = mpath->mp_next;
- if (mpath->mp_next)
- mpath->mp_next->mp_prev = mpath->mp_prev;
- mpath->mp_next = mpath->mp_prev = NULL;
- UNSET_FLAG(path->flags, BGP_PATH_MULTIPATH);
-}
-
-/*
* bgp_path_info_mpath_next
*
* Given a bgp_path_info, return the next multipath entry
*/
struct bgp_path_info *bgp_path_info_mpath_next(struct bgp_path_info *path)
{
- if (!path->mpath || !path->mpath->mp_next)
- return NULL;
- return path->mpath->mp_next->mp_info;
+ path = path->next;
+
+ while (path) {
+ if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
+ return path;
+
+ path = path->next;
+ }
+
+ return NULL;
}
/*
@@ -386,7 +283,8 @@ struct bgp_path_info *bgp_path_info_mpath_first(struct bgp_path_info *path)
uint32_t bgp_path_info_mpath_count(struct bgp_path_info *path)
{
if (!path->mpath)
- return 0;
+ return 1;
+
return path->mpath->mp_count;
}
@@ -411,6 +309,10 @@ static void bgp_path_info_mpath_count_set(struct bgp_path_info *path,
* bgp_path_info_mpath_lb_update
*
* Update cumulative info related to link-bandwidth
+ *
+ * This is only set on the first mpath of the list
+ * as such we should UNSET the flags when removing
+ * to ensure nothing accidently happens
*/
static void bgp_path_info_mpath_lb_update(struct bgp_path_info *path, bool set,
bool all_paths_lb, uint64_t cum_bw)
@@ -472,10 +374,10 @@ bool bgp_path_info_mpath_chkwtd(struct bgp *bgp, struct bgp_path_info *path)
*/
if (bgp->lb_handling != BGP_LINK_BW_SKIP_MISSING &&
bgp->lb_handling != BGP_LINK_BW_DEFWT_4_MISSING)
- return (path->mpath->mp_flags & BGP_MP_LB_ALL);
+ return CHECK_FLAG(path->mpath->mp_flags, BGP_MP_LB_ALL);
/* At least one path should have bandwidth. */
- return (path->mpath->mp_flags & BGP_MP_LB_PRESENT);
+ return CHECK_FLAG(path->mpath->mp_flags, BGP_MP_LB_PRESENT);
}
/*
@@ -511,58 +413,51 @@ static void bgp_path_info_mpath_attr_set(struct bgp_path_info *path,
/*
* bgp_path_info_mpath_update
*
- * Compare and sync up the multipath list with the mp_list generated by
- * bgp_best_selection
+ * Compare and sync up the multipath flags with what was choosen
+ * in best selection
*/
void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
- struct bgp_path_info *new_best,
- struct bgp_path_info *old_best,
- struct list *mp_list,
- struct bgp_maxpaths_cfg *mpath_cfg)
+ struct bgp_path_info *new_best, struct bgp_path_info *old_best,
+ uint32_t num_candidates, struct bgp_maxpaths_cfg *mpath_cfg)
{
uint16_t maxpaths, mpath_count, old_mpath_count;
uint64_t bwval;
uint64_t cum_bw, old_cum_bw;
- struct listnode *mp_node, *mp_next_node;
- struct bgp_path_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath;
- int mpath_changed, debug;
+ struct bgp_path_info *cur_iterator = NULL;
+ bool mpath_changed, debug;
bool all_paths_lb;
char path_buf[PATH_ADDPATH_STR_BUFFER];
+ bool old_mpath, new_mpath;
- mpath_changed = 0;
+ mpath_changed = false;
maxpaths = multipath_num;
mpath_count = 0;
- cur_mpath = NULL;
old_mpath_count = 0;
old_cum_bw = cum_bw = 0;
- prev_mpath = new_best;
- mp_node = listhead(mp_list);
debug = bgp_debug_bestpath(dest);
- if (new_best) {
- mpath_count++;
- if (new_best != old_best)
- bgp_path_info_mpath_dequeue(new_best);
- maxpaths = (new_best->peer->sort == BGP_PEER_IBGP)
- ? mpath_cfg->maxpaths_ibgp
- : mpath_cfg->maxpaths_ebgp;
- }
-
if (old_best) {
- cur_mpath = bgp_path_info_mpath_first(old_best);
old_mpath_count = bgp_path_info_mpath_count(old_best);
+ if (old_mpath_count == 1)
+ SET_FLAG(old_best->flags, BGP_PATH_MULTIPATH);
old_cum_bw = bgp_path_info_mpath_cumbw(old_best);
bgp_path_info_mpath_count_set(old_best, 0);
bgp_path_info_mpath_lb_update(old_best, false, false, 0);
- bgp_path_info_mpath_dequeue(old_best);
+ bgp_path_info_mpath_free(&old_best->mpath);
+ old_best->mpath = NULL;
+ }
+
+ if (new_best) {
+ maxpaths = (new_best->peer->sort == BGP_PEER_IBGP) ? mpath_cfg->maxpaths_ibgp
+ : mpath_cfg->maxpaths_ebgp;
+ cur_iterator = new_best;
}
if (debug)
- zlog_debug("%pBD(%s): starting mpath update, newbest %s num candidates %d old-mpath-count %d old-cum-bw %" PRIu64,
- dest, bgp->name_pretty,
- new_best ? new_best->peer->host : "NONE",
- mp_list ? listcount(mp_list) : 0, old_mpath_count,
- old_cum_bw);
+ zlog_debug("%pBD(%s): starting mpath update, newbest %s num candidates %d old-mpath-count %d old-cum-bw %" PRIu64
+ " maxpaths set %u",
+ dest, bgp->name_pretty, new_best ? new_best->peer->host : "NONE",
+ num_candidates, old_mpath_count, old_cum_bw, maxpaths);
/*
* We perform an ordered walk through both lists in parallel.
@@ -576,213 +471,106 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
* to skip over it
*/
all_paths_lb = true; /* We'll reset if any path doesn't have LB. */
- while (mp_node || cur_mpath) {
- struct bgp_path_info *tmp_info;
+ while (cur_iterator) {
+ old_mpath = CHECK_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH);
+ new_mpath = CHECK_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH_NEW);
+
+ UNSET_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH_NEW);
/*
- * We can bail out of this loop if all existing paths on the
- * multipath list have been visited (for cleanup purposes) and
- * the maxpath requirement is fulfulled
+ * If the current mpath count is equal to the number of
+ * maxpaths that can be used then we can bail, after
+ * we clean up the flags associated with the rest of the
+ * bestpaths
*/
- if (!cur_mpath && (mpath_count >= maxpaths))
- break;
+ if (mpath_count >= maxpaths) {
+ while (cur_iterator) {
+ UNSET_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH);
+ UNSET_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH_NEW);
- mp_next_node = mp_node ? listnextnode(mp_node) : NULL;
- next_mpath =
- cur_mpath ? bgp_path_info_mpath_next(cur_mpath) : NULL;
- tmp_info = mp_node ? listgetdata(mp_node) : NULL;
+ cur_iterator = cur_iterator->next;
+ }
- if (debug)
- zlog_debug("%pBD(%s): comparing candidate %s with existing mpath %s",
- dest, bgp->name_pretty,
- tmp_info ? tmp_info->peer->host : "NONE",
- cur_mpath ? cur_mpath->peer->host : "NONE");
+ if (debug)
+ zlog_debug("%pBD(%s): Mpath count %u is equal to maximum paths allowed, finished comparision for MPATHS",
+ dest, bgp->name_pretty, mpath_count);
+
+ break;
+ }
+ if (debug)
+ zlog_debug("%pBD(%s): Candidate %s old_mpath: %u new_mpath: %u, Nexthop %pI4 current mpath count: %u",
+ dest, bgp->name_pretty, cur_iterator->peer->host, old_mpath,
+ new_mpath, &cur_iterator->attr->nexthop, mpath_count);
/*
- * If equal, the path was a multipath and is still a multipath.
- * Insert onto new multipath list if maxpaths allows.
+ * There is nothing to do if the cur_iterator is neither a old path
+ * or a new path
*/
- if (mp_node && (listgetdata(mp_node) == cur_mpath)) {
- list_delete_node(mp_list, mp_node);
- bgp_path_info_mpath_dequeue(cur_mpath);
- if ((mpath_count < maxpaths)
- && prev_mpath
- && bgp_path_info_nexthop_cmp(prev_mpath,
- cur_mpath)) {
- bgp_path_info_mpath_enqueue(prev_mpath,
- cur_mpath);
- prev_mpath = cur_mpath;
- mpath_count++;
- if (ecommunity_linkbw_present(bgp_attr_get_ecommunity(
- cur_mpath->attr),
- &bwval) ||
- ecommunity_linkbw_present(
- bgp_attr_get_ipv6_ecommunity(
- cur_mpath->attr),
- &bwval))
- cum_bw += bwval;
- else
- all_paths_lb = false;
- if (debug) {
- bgp_path_info_path_with_addpath_rx_str(
- cur_mpath, path_buf,
- sizeof(path_buf));
- zlog_debug("%pBD: %s is still multipath, cur count %d",
- dest, path_buf, mpath_count);
- }
- } else {
- mpath_changed = 1;
- if (debug) {
- bgp_path_info_path_with_addpath_rx_str(
- cur_mpath, path_buf,
- sizeof(path_buf));
- zlog_debug("%pBD: remove mpath %s nexthop %pI4, cur count %d",
- dest, path_buf,
- &cur_mpath->attr->nexthop,
- mpath_count);
- }
- }
- mp_node = mp_next_node;
- cur_mpath = next_mpath;
+ if (!old_mpath && !new_mpath) {
+ UNSET_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH);
+ cur_iterator = cur_iterator->next;
continue;
}
- if (cur_mpath
- && (!mp_node
- || (bgp_path_info_mpath_cmp(cur_mpath,
- listgetdata(mp_node))
- < 0))) {
- /*
- * If here, we have an old multipath and either the
- * mp_list
- * is finished or the next mp_node points to a later
- * multipath, so we need to purge this path from the
- * multipath list
- */
- bgp_path_info_mpath_dequeue(cur_mpath);
- mpath_changed = 1;
+ if (new_mpath) {
+ mpath_count++;
+
+ if (cur_iterator != new_best)
+ SET_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH);
+
+ if (!old_mpath)
+ mpath_changed = true;
+
+ if (ecommunity_linkbw_present(bgp_attr_get_ecommunity(cur_iterator->attr),
+ &bwval) ||
+ ecommunity_linkbw_present(bgp_attr_get_ipv6_ecommunity(
+ cur_iterator->attr),
+ &bwval))
+ cum_bw += bwval;
+ else
+ all_paths_lb = false;
+
if (debug) {
- bgp_path_info_path_with_addpath_rx_str(
- cur_mpath, path_buf, sizeof(path_buf));
- zlog_debug("%pBD: remove mpath %s nexthop %pI4, cur count %d",
- dest, path_buf,
- &cur_mpath->attr->nexthop,
- mpath_count);
+ bgp_path_info_path_with_addpath_rx_str(cur_iterator, path_buf,
+ sizeof(path_buf));
+ zlog_debug("%pBD: add mpath %s nexthop %pI4, cur count %d cum_bw: %" PRIu64
+ " all_paths_lb: %u",
+ dest, path_buf, &cur_iterator->attr->nexthop,
+ mpath_count, cum_bw, all_paths_lb);
}
- cur_mpath = next_mpath;
} else {
/*
- * If here, we have a path on the mp_list that was not
- * previously
- * a multipath (due to non-equivalance or maxpaths
- * exceeded),
- * or the matching multipath is sorted later in the
- * multipath
- * list. Before we enqueue the path on the new multipath
- * list,
- * make sure its not on the old_best multipath list or
- * referenced
- * via next_mpath:
- * - If next_mpath points to this new path, update
- * next_mpath to
- * point to the multipath after this one
- * - Dequeue the path from the multipath list just to
- * make sure
+ * We know that old_mpath is true and new_mpath is false in this path
*/
- new_mpath = listgetdata(mp_node);
- list_delete_node(mp_list, mp_node);
- assert(new_mpath);
- assert(prev_mpath);
- if ((mpath_count < maxpaths) && (new_mpath != new_best)
- && bgp_path_info_nexthop_cmp(prev_mpath,
- new_mpath)) {
- bgp_path_info_mpath_dequeue(new_mpath);
-
- bgp_path_info_mpath_enqueue(prev_mpath,
- new_mpath);
- prev_mpath = new_mpath;
- mpath_changed = 1;
- mpath_count++;
- if (ecommunity_linkbw_present(bgp_attr_get_ecommunity(
- new_mpath->attr),
- &bwval) ||
- ecommunity_linkbw_present(
- bgp_attr_get_ipv6_ecommunity(
- new_mpath->attr),
- &bwval))
- cum_bw += bwval;
- else
- all_paths_lb = false;
- if (debug) {
- bgp_path_info_path_with_addpath_rx_str(
- new_mpath, path_buf,
- sizeof(path_buf));
- zlog_debug("%pBD: add mpath %s nexthop %pI4, cur count %d",
- dest, path_buf,
- &new_mpath->attr->nexthop,
- mpath_count);
- }
- }
- mp_node = mp_next_node;
+ mpath_changed = true;
+ UNSET_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH);
}
+
+ cur_iterator = cur_iterator->next;
}
if (new_best) {
- bgp_path_info_mpath_count_set(new_best, mpath_count - 1);
- if (mpath_count <= 1 ||
- (!ecommunity_linkbw_present(bgp_attr_get_ecommunity(
- new_best->attr),
- &bwval) &&
- !ecommunity_linkbw_present(bgp_attr_get_ipv6_ecommunity(
- new_best->attr),
- &bwval)))
- all_paths_lb = false;
- else
- cum_bw += bwval;
- bgp_path_info_mpath_lb_update(new_best, true,
- all_paths_lb, cum_bw);
-
+ if (mpath_count > 1 || new_best->mpath) {
+ bgp_path_info_mpath_count_set(new_best, mpath_count);
+ bgp_path_info_mpath_lb_update(new_best, true, all_paths_lb, cum_bw);
+ }
if (debug)
zlog_debug("%pBD(%s): New mpath count (incl newbest) %d mpath-change %s all_paths_lb %d cum_bw %" PRIu64,
dest, bgp->name_pretty, mpath_count,
mpath_changed ? "YES" : "NO", all_paths_lb,
cum_bw);
+ if (mpath_count == 1)
+ UNSET_FLAG(new_best->flags, BGP_PATH_MULTIPATH);
if (mpath_changed
|| (bgp_path_info_mpath_count(new_best) != old_mpath_count))
SET_FLAG(new_best->flags, BGP_PATH_MULTIPATH_CHG);
- if ((mpath_count - 1) != old_mpath_count ||
- old_cum_bw != cum_bw)
+ if ((mpath_count) != old_mpath_count || old_cum_bw != cum_bw)
SET_FLAG(new_best->flags, BGP_PATH_LINK_BW_CHG);
}
}
/*
- * bgp_mp_dmed_deselect
- *
- * Clean up multipath information for BGP_PATH_DMED_SELECTED path that
- * is not selected as best path
- */
-void bgp_mp_dmed_deselect(struct bgp_path_info *dmed_best)
-{
- struct bgp_path_info *mpinfo, *mpnext;
-
- if (!dmed_best)
- return;
-
- for (mpinfo = bgp_path_info_mpath_first(dmed_best); mpinfo;
- mpinfo = mpnext) {
- mpnext = bgp_path_info_mpath_next(mpinfo);
- bgp_path_info_mpath_dequeue(mpinfo);
- }
-
- bgp_path_info_mpath_count_set(dmed_best, 0);
- UNSET_FLAG(dmed_best->flags, BGP_PATH_MULTIPATH_CHG);
- UNSET_FLAG(dmed_best->flags, BGP_PATH_LINK_BW_CHG);
- assert(bgp_path_info_mpath_first(dmed_best) == NULL);
-}
-
-/*
* bgp_path_info_mpath_aggregate_update
*
* Set the multipath aggregate attribute. We need to see if the
@@ -816,7 +604,7 @@ void bgp_path_info_mpath_aggregate_update(struct bgp_path_info *new_best,
if (!new_best)
return;
- if (!bgp_path_info_mpath_count(new_best)) {
+ if (bgp_path_info_mpath_count(new_best) == 1) {
if ((new_attr = bgp_path_info_mpath_attr(new_best))) {
bgp_attr_unintern(&new_attr);
bgp_path_info_mpath_attr_set(new_best, NULL);
diff --git a/bgpd/bgp_mpath.h b/bgpd/bgp_mpath.h
index 129682d1..c5a009a4 100644
--- a/bgpd/bgp_mpath.h
+++ b/bgpd/bgp_mpath.h
@@ -2,8 +2,9 @@
/*
* BGP Multipath
* Copyright (C) 2010 Google Inc.
+ * 2024 Nvidia Corporation
*
- * This file is part of Quagga
+ * This file is part of FRR
*/
#ifndef _FRR_BGP_MPATH_H
@@ -13,27 +14,24 @@
* multipath selections, lazily allocated to save memory
*/
struct bgp_path_info_mpath {
- /* Points to the first multipath (on bestpath) or the next multipath */
- struct bgp_path_info_mpath *mp_next;
-
- /* Points to the previous multipath or NULL on bestpath */
- struct bgp_path_info_mpath *mp_prev;
-
/* Points to bgp_path_info associated with this multipath info */
struct bgp_path_info *mp_info;
/* When attached to best path, the number of selected multipaths */
uint16_t mp_count;
- /* Flags - relevant as noted. */
+ /* Flags - relevant as noted, attached to bestpath. */
uint16_t mp_flags;
#define BGP_MP_LB_PRESENT 0x1 /* Link-bandwidth present for >= 1 path */
#define BGP_MP_LB_ALL 0x2 /* Link-bandwidth present for all multipaths */
- /* Aggregated attribute for advertising multipath route */
+ /*
+ * Aggregated attribute for advertising multipath route,
+ * attached to bestpath
+ */
struct attr *mp_attr;
- /* Cumulative bandiwdth of all multipaths - attached to best path. */
+ /* Cumulative bandiwdth of all multipaths - attached to bestpath. */
uint64_t cum_bw;
};
@@ -47,23 +45,16 @@ extern int bgp_maximum_paths_unset(struct bgp *bgp, afi_t afi, safi_t safi,
/* Functions used by bgp_best_selection to record current
* multipath selections
*/
-extern int bgp_path_info_nexthop_cmp(struct bgp_path_info *bpi1,
- struct bgp_path_info *bpi2);
-extern void bgp_mp_list_init(struct list *mp_list);
-extern void bgp_mp_list_clear(struct list *mp_list);
-extern void bgp_mp_list_add(struct list *mp_list, struct bgp_path_info *mpinfo);
-extern void bgp_mp_dmed_deselect(struct bgp_path_info *dmed_best);
+extern int bgp_path_info_nexthop_cmp(struct bgp_path_info *bpi1, struct bgp_path_info *bpi2);
extern void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
struct bgp_path_info *new_best,
- struct bgp_path_info *old_best,
- struct list *mp_list,
+ struct bgp_path_info *old_best, uint32_t num_candidates,
struct bgp_maxpaths_cfg *mpath_cfg);
extern void
bgp_path_info_mpath_aggregate_update(struct bgp_path_info *new_best,
struct bgp_path_info *old_best);
/* Unlink and free multipath information associated with a bgp_path_info */
-extern void bgp_path_info_mpath_dequeue(struct bgp_path_info *path);
extern void bgp_path_info_mpath_free(struct bgp_path_info_mpath **mpath);
/* Walk list of multipaths associated with a best path */
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index e8951baf..df45cf23 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -34,6 +34,7 @@
#include "bgpd/bgp_nht.h"
#include "bgpd/bgp_evpn.h"
#include "bgpd/bgp_memory.h"
+#include "bgpd/bgp_aspath.h"
#ifdef ENABLE_BGP_VNC
#include "bgpd/rfapi/rfapi_backend.h"
@@ -245,7 +246,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr,
} else {
bgp_withdraw(peer, &p, addpath_id, packet->afi,
SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP,
- BGP_ROUTE_NORMAL, &prd, &label, 1, NULL);
+ BGP_ROUTE_NORMAL, &prd, &label, 1);
}
}
/* Packet length consistency check. */
@@ -280,7 +281,8 @@ done:
*
* Sending this vrf-label association is qualified by a) whether vrf->vpn
* exporting is active ("export vpn" is enabled, vpn-policy RD and RT list
- * are set) and b) whether vpn-policy label is set.
+ * are set), b) whether vpn-policy label is set and c) the vrf loopback
+ * interface is up.
*
* If any of these conditions do not hold, then we send MPLS_LABEL_NONE
* for this vrf, which zebra interprets to mean "delete this vrf-label
@@ -288,6 +290,7 @@ done:
*/
void vpn_leak_zebra_vrf_label_update(struct bgp *bgp, afi_t afi)
{
+ struct interface *ifp;
mpls_label_t label = MPLS_LABEL_NONE;
int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
@@ -301,7 +304,9 @@ void vpn_leak_zebra_vrf_label_update(struct bgp *bgp, afi_t afi)
}
if (vpn_leak_to_vpn_active(bgp, afi, NULL, false)) {
- label = bgp->vpn_policy[afi].tovpn_label;
+ ifp = if_get_vrf_loopback(bgp->vrf_id);
+ if (ifp && if_is_up(ifp))
+ label = bgp->vpn_policy[afi].tovpn_label;
}
if (debug) {
@@ -381,6 +386,18 @@ void vpn_leak_zebra_vrf_sid_update_per_af(struct bgp *bgp, afi_t afi)
if (!vrf)
return;
+ if (bgp->vpn_policy[afi].tovpn_sid_locator) {
+ ctx.block_len =
+ bgp->vpn_policy[afi].tovpn_sid_locator->block_bits_length;
+ ctx.node_len =
+ bgp->vpn_policy[afi].tovpn_sid_locator->node_bits_length;
+ ctx.function_len =
+ bgp->vpn_policy[afi]
+ .tovpn_sid_locator->function_bits_length;
+ ctx.argument_len =
+ bgp->vpn_policy[afi]
+ .tovpn_sid_locator->argument_bits_length;
+ }
ctx.table = vrf->data.l.table_id;
act = afi == AFI_IP ? ZEBRA_SEG6_LOCAL_ACTION_END_DT4
: ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
@@ -432,6 +449,12 @@ void vpn_leak_zebra_vrf_sid_update_per_vrf(struct bgp *bgp)
if (!vrf)
return;
+ if (bgp->tovpn_sid_locator) {
+ ctx.block_len = bgp->tovpn_sid_locator->block_bits_length;
+ ctx.node_len = bgp->tovpn_sid_locator->node_bits_length;
+ ctx.function_len = bgp->tovpn_sid_locator->function_bits_length;
+ ctx.argument_len = bgp->tovpn_sid_locator->argument_bits_length;
+ }
ctx.table = vrf->data.l.table_id;
act = ZEBRA_SEG6_LOCAL_ACTION_END_DT46;
zclient_send_localsid(zclient, tovpn_sid, bgp->vrf_id, act, &ctx);
@@ -470,6 +493,8 @@ void vpn_leak_zebra_vrf_sid_update(struct bgp *bgp, afi_t afi)
void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi)
{
int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
+ struct srv6_sid_ctx ctx = {};
+ struct seg6local_context seg6localctx = {};
if (bgp->vrf_id == VRF_UNKNOWN) {
if (debug)
@@ -482,12 +507,30 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi)
zlog_debug("%s: deleting sid for vrf %s afi (id=%d)", __func__,
bgp->name_pretty, bgp->vrf_id);
+ if (bgp->vpn_policy[afi].tovpn_sid_locator) {
+ seg6localctx.block_len =
+ bgp->vpn_policy[afi].tovpn_sid_locator->block_bits_length;
+ seg6localctx.node_len =
+ bgp->vpn_policy[afi].tovpn_sid_locator->node_bits_length;
+ seg6localctx.function_len =
+ bgp->vpn_policy[afi]
+ .tovpn_sid_locator->function_bits_length;
+ seg6localctx.argument_len =
+ bgp->vpn_policy[afi]
+ .tovpn_sid_locator->argument_bits_length;
+ }
zclient_send_localsid(zclient,
- bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent,
- bgp->vrf_id, ZEBRA_SEG6_LOCAL_ACTION_UNSPEC, NULL);
+ bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent,
+ bgp->vrf_id, ZEBRA_SEG6_LOCAL_ACTION_UNSPEC,
+ &seg6localctx);
XFREE(MTYPE_BGP_SRV6_SID,
bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent);
bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent = NULL;
+
+ ctx.vrf_id = bgp->vrf_id;
+ ctx.behavior = afi == AFI_IP ? ZEBRA_SEG6_LOCAL_ACTION_END_DT4
+ : ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
+ bgp_zebra_release_srv6_sid(&ctx);
}
/*
@@ -497,6 +540,8 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi)
void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp)
{
int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
+ struct srv6_sid_ctx ctx = {};
+ struct seg6local_context seg6localctx = {};
if (bgp->vrf_id == VRF_UNKNOWN) {
if (debug)
@@ -510,11 +555,24 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp)
zlog_debug("%s: deleting sid for vrf %s (id=%d)", __func__,
bgp->name_pretty, bgp->vrf_id);
+ if (bgp->tovpn_sid_locator) {
+ seg6localctx.block_len =
+ bgp->tovpn_sid_locator->block_bits_length;
+ seg6localctx.node_len = bgp->tovpn_sid_locator->node_bits_length;
+ seg6localctx.function_len =
+ bgp->tovpn_sid_locator->function_bits_length;
+ seg6localctx.argument_len =
+ bgp->tovpn_sid_locator->argument_bits_length;
+ }
zclient_send_localsid(zclient, bgp->tovpn_zebra_vrf_sid_last_sent,
bgp->vrf_id, ZEBRA_SEG6_LOCAL_ACTION_UNSPEC,
- NULL);
+ &seg6localctx);
XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_zebra_vrf_sid_last_sent);
bgp->tovpn_zebra_vrf_sid_last_sent = NULL;
+
+ ctx.vrf_id = bgp->vrf_id;
+ ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_DT46;
+ bgp_zebra_release_srv6_sid(&ctx);
}
/*
@@ -591,8 +649,8 @@ int vpn_leak_label_callback(
return 0;
}
-static void sid_register(struct bgp *bgp, const struct in6_addr *sid,
- const char *locator_name)
+void sid_register(struct bgp *bgp, const struct in6_addr *sid,
+ const char *locator_name)
{
struct bgp_srv6_function *func;
func = XCALLOC(MTYPE_BGP_SRV6_FUNCTION,
@@ -631,108 +689,97 @@ static bool sid_exist(struct bgp *bgp, const struct in6_addr *sid)
return false;
}
-/*
- * This function generates a new SID based on bgp->srv6_locator_chunks and
- * index. The locator and generated SID are stored in arguments sid_locator
- * and sid, respectively.
+/**
+ * Return the SRv6 SID value obtained by composing the LOCATOR and FUNCTION.
*
- * if index != 0: try to allocate as index-mode
- * else: try to allocate as auto-mode
+ * @param sid_value SRv6 SID value returned
+ * @param locator Parent locator of the SRv6 SID
+ * @param sid_func Function part of the SID
+ * @return True if success, False otherwise
*/
-static uint32_t alloc_new_sid(struct bgp *bgp, uint32_t index,
- struct srv6_locator_chunk *sid_locator_chunk,
- struct in6_addr *sid)
+static bool srv6_sid_compose(struct in6_addr *sid_value,
+ struct srv6_locator *locator, uint32_t sid_func)
{
int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
- struct listnode *node;
- struct srv6_locator_chunk *chunk;
- bool alloced = false;
int label = 0;
uint8_t offset = 0;
uint8_t func_len = 0, shift_len = 0;
- uint32_t index_max = 0;
+ uint32_t sid_func_max = 0;
- if (!bgp || !sid_locator_chunk || !sid)
+ if (!locator || !sid_value)
return false;
- for (ALL_LIST_ELEMENTS_RO(bgp->srv6_locator_chunks, node, chunk)) {
- if (chunk->function_bits_length >
- BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH) {
- if (debug)
- zlog_debug(
- "%s: invalid SRv6 Locator chunk (%pFX): Function Length must be less or equal to %d",
- __func__, &chunk->prefix,
- BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH);
- continue;
- }
+ if (locator->function_bits_length >
+ BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH) {
+ if (debug)
+ zlog_debug("%s: invalid SRv6 Locator (%pFX): Function Length must be less or equal to %d",
+ __func__, &locator->prefix,
+ BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH);
+ return false;
+ }
- index_max = (1 << chunk->function_bits_length) - 1;
+ /* Max value that can be encoded in the Function part of the SID */
+ sid_func_max = (1 << locator->function_bits_length) - 1;
- if (index > index_max) {
- if (debug)
- zlog_debug(
- "%s: skipped SRv6 Locator chunk (%pFX): Function Length is too short to support specified index (%u)",
- __func__, &chunk->prefix, index);
- continue;
- }
+ if (sid_func > sid_func_max) {
+ if (debug)
+ zlog_debug("%s: invalid SRv6 Locator (%pFX): Function Length is too short to support specified function (%u)",
+ __func__, &locator->prefix, sid_func);
+ return false;
+ }
- *sid = chunk->prefix.prefix;
- *sid_locator_chunk = *chunk;
- offset = chunk->block_bits_length + chunk->node_bits_length;
- func_len = chunk->function_bits_length;
- shift_len = BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH - func_len;
+ /**
+ * Let's build the SID value.
+ * sid_value = LOC:FUNC::
+ */
- if (index != 0) {
- label = index << shift_len;
- if (label < MPLS_LABEL_UNRESERVED_MIN) {
- if (debug)
- zlog_debug(
- "%s: skipped to allocate SRv6 SID (%pFX): Label (%u) is too small to use",
- __func__, &chunk->prefix,
- label);
- continue;
- }
+ /* First, we put the locator (LOC) in the most significant bits of sid_value */
+ *sid_value = locator->prefix.prefix;
- transpose_sid(sid, label, offset, func_len);
- if (sid_exist(bgp, sid))
- continue;
- alloced = true;
- break;
- }
+ /*
+ * Then, we compute the offset at which we have to place the function (FUNC).
+ * FUNC will be placed immediately after LOC, i.e. at block_bits_length + node_bits_length
+ */
+ offset = locator->block_bits_length + locator->node_bits_length;
- for (uint32_t i = 1; i < index_max; i++) {
- label = i << shift_len;
- if (label < MPLS_LABEL_UNRESERVED_MIN) {
- if (debug)
- zlog_debug(
- "%s: skipped to allocate SRv6 SID (%pFX): Label (%u) is too small to use",
- __func__, &chunk->prefix,
- label);
- continue;
- }
- transpose_sid(sid, label, offset, func_len);
- if (sid_exist(bgp, sid))
- continue;
- alloced = true;
- break;
- }
+ /*
+ * The FUNC part of the SID is advertised in the label field of SRv6 Service TLV.
+ * (see SID Transposition Scheme, RFC 9252 section #4).
+ * Therefore, we need to encode the FUNC in the most significant bits of the
+ * 20-bit label.
+ */
+ func_len = locator->function_bits_length;
+ shift_len = BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH - func_len;
+
+ label = sid_func << shift_len;
+ if (label < MPLS_LABEL_UNRESERVED_MIN) {
+ if (debug)
+ zlog_debug("%s: skipped to allocate SRv6 SID (%pFX): Label (%u) is too small to use",
+ __func__, &locator->prefix, label);
+ return false;
}
- if (!alloced)
- return 0;
+ if (sid_exist(bgp_get_default(), sid_value)) {
+ zlog_warn("%s: skipped to allocate SRv6 SID (%pFX): SID %pI6 already in use",
+ __func__, &locator->prefix, sid_value);
+ return false;
+ }
- sid_register(bgp, sid, bgp->srv6_locator_name);
- return label;
+ /* Finally, we put the FUNC in sid_value at the computed offset */
+ transpose_sid(sid_value, label, offset, func_len);
+
+ return true;
}
void ensure_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
afi_t afi)
{
int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
- struct srv6_locator_chunk *tovpn_sid_locator;
- struct in6_addr *tovpn_sid;
- uint32_t tovpn_sid_index = 0, tovpn_sid_transpose_label;
+ struct in6_addr tovpn_sid = {};
+ uint32_t tovpn_sid_index = 0;
bool tovpn_sid_auto = false;
+ struct srv6_sid_ctx ctx = {};
+ uint32_t sid_func;
if (debug)
zlog_debug("%s: try to allocate new SID for vrf %s: afi %s",
@@ -744,11 +791,18 @@ void ensure_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
/*
* skip when bgp vpn instance ins't allocated
- * or srv6 locator chunk isn't allocated
+ * or srv6 locator isn't allocated
*/
- if (!bgp_vpn || !bgp_vpn->srv6_locator_chunks)
+ if (!bgp_vpn || !bgp_vpn->srv6_locator)
return;
+ if (bgp_vrf->vrf_id == VRF_UNKNOWN) {
+ if (debug)
+ zlog_debug("%s: vrf %s: vrf_id not set, can't set zebra vrf SRv6 SID",
+ __func__, bgp_vrf->name_pretty);
+ return;
+ }
+
tovpn_sid_index = bgp_vrf->vpn_policy[afi].tovpn_sid_index;
tovpn_sid_auto = CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
BGP_VPN_POLICY_TOVPN_SID_AUTO);
@@ -764,40 +818,34 @@ void ensure_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
return;
}
- tovpn_sid_locator = srv6_locator_chunk_alloc();
- tovpn_sid = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
-
- tovpn_sid_transpose_label = alloc_new_sid(bgp_vpn, tovpn_sid_index,
- tovpn_sid_locator, tovpn_sid);
+ if (!tovpn_sid_auto) {
+ if (!srv6_sid_compose(&tovpn_sid, bgp_vpn->srv6_locator,
+ tovpn_sid_index)) {
+ zlog_err("%s: failed to compose sid for vrf %s: afi %s",
+ __func__, bgp_vrf->name_pretty, afi2str(afi));
+ return;
+ }
+ }
- if (tovpn_sid_transpose_label == 0) {
- if (debug)
- zlog_debug(
- "%s: not allocated new sid for vrf %s: afi %s",
- __func__, bgp_vrf->name_pretty, afi2str(afi));
- srv6_locator_chunk_free(&tovpn_sid_locator);
- XFREE(MTYPE_BGP_SRV6_SID, tovpn_sid);
+ ctx.vrf_id = bgp_vrf->vrf_id;
+ ctx.behavior = afi == AFI_IP ? ZEBRA_SEG6_LOCAL_ACTION_END_DT4
+ : ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
+ if (!bgp_zebra_request_srv6_sid(&ctx, &tovpn_sid,
+ bgp_vpn->srv6_locator_name, &sid_func)) {
+ zlog_err("%s: failed to request sid for vrf %s: afi %s",
+ __func__, bgp_vrf->name_pretty, afi2str(afi));
return;
}
-
- if (debug)
- zlog_debug("%s: new sid %pI6 allocated for vrf %s: afi %s",
- __func__, tovpn_sid, bgp_vrf->name_pretty,
- afi2str(afi));
-
- bgp_vrf->vpn_policy[afi].tovpn_sid = tovpn_sid;
- bgp_vrf->vpn_policy[afi].tovpn_sid_locator = tovpn_sid_locator;
- bgp_vrf->vpn_policy[afi].tovpn_sid_transpose_label =
- tovpn_sid_transpose_label;
}
void ensure_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
{
int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
- struct srv6_locator_chunk *tovpn_sid_locator;
- struct in6_addr *tovpn_sid;
- uint32_t tovpn_sid_index = 0, tovpn_sid_transpose_label;
+ struct in6_addr tovpn_sid = {};
+ uint32_t tovpn_sid_index = 0;
bool tovpn_sid_auto = false;
+ struct srv6_sid_ctx ctx = {};
+ uint32_t sid_func;
if (debug)
zlog_debug("%s: try to allocate new SID for vrf %s", __func__,
@@ -809,10 +857,17 @@ void ensure_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
/*
* skip when bgp vpn instance ins't allocated
- * or srv6 locator chunk isn't allocated
+ * or srv6 locator isn't allocated
*/
- if (!bgp_vpn || !bgp_vpn->srv6_locator_chunks)
+ if (!bgp_vpn || !bgp_vpn->srv6_locator)
+ return;
+
+ if (bgp_vrf->vrf_id == VRF_UNKNOWN) {
+ if (debug)
+ zlog_debug("%s: vrf %s: vrf_id not set, can't set zebra vrf SRv6 SID",
+ __func__, bgp_vrf->name_pretty);
return;
+ }
tovpn_sid_index = bgp_vrf->tovpn_sid_index;
tovpn_sid_auto = CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_AUTO);
@@ -828,28 +883,23 @@ void ensure_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
return;
}
- tovpn_sid_locator = srv6_locator_chunk_alloc();
- tovpn_sid = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
-
- tovpn_sid_transpose_label = alloc_new_sid(bgp_vpn, tovpn_sid_index,
- tovpn_sid_locator, tovpn_sid);
+ if (!tovpn_sid_auto) {
+ if (!srv6_sid_compose(&tovpn_sid, bgp_vpn->srv6_locator,
+ bgp_vrf->tovpn_sid_index)) {
+ zlog_err("%s: failed to compose new sid for vrf %s",
+ __func__, bgp_vrf->name_pretty);
+ return;
+ }
+ }
- if (tovpn_sid_transpose_label == 0) {
- if (debug)
- zlog_debug("%s: not allocated new sid for vrf %s",
- __func__, bgp_vrf->name_pretty);
- srv6_locator_chunk_free(&tovpn_sid_locator);
- XFREE(MTYPE_BGP_SRV6_SID, tovpn_sid);
+ ctx.vrf_id = bgp_vrf->vrf_id;
+ ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_DT46;
+ if (!bgp_zebra_request_srv6_sid(&ctx, &tovpn_sid,
+ bgp_vpn->srv6_locator_name, &sid_func)) {
+ zlog_err("%s: failed to request new sid for vrf %s", __func__,
+ bgp_vrf->name_pretty);
return;
}
-
- if (debug)
- zlog_debug("%s: new sid %pI6 allocated for vrf %s", __func__,
- tovpn_sid, bgp_vrf->name_pretty);
-
- bgp_vrf->tovpn_sid = tovpn_sid;
- bgp_vrf->tovpn_sid_locator = tovpn_sid_locator;
- bgp_vrf->tovpn_sid_transpose_label = tovpn_sid_transpose_label;
}
void ensure_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi)
@@ -872,6 +922,7 @@ void delete_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
uint32_t tovpn_sid_index = 0;
bool tovpn_sid_auto = false;
+ struct srv6_sid_ctx ctx = {};
if (debug)
zlog_debug("%s: try to remove SID for vrf %s: afi %s", __func__,
@@ -885,9 +936,22 @@ void delete_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
if (tovpn_sid_index != 0 || tovpn_sid_auto)
return;
- srv6_locator_chunk_free(&bgp_vrf->vpn_policy[afi].tovpn_sid_locator);
+ if (bgp_vrf->vrf_id == VRF_UNKNOWN) {
+ if (debug)
+ zlog_debug("%s: vrf %s: vrf_id not set, can't set zebra vrf label",
+ __func__, bgp_vrf->name_pretty);
+ return;
+ }
+
+ srv6_locator_free(bgp_vrf->vpn_policy[afi].tovpn_sid_locator);
+ bgp_vrf->vpn_policy[afi].tovpn_sid_locator = NULL;
if (bgp_vrf->vpn_policy[afi].tovpn_sid) {
+ ctx.vrf_id = bgp_vrf->vrf_id;
+ ctx.behavior = afi == AFI_IP ? ZEBRA_SEG6_LOCAL_ACTION_END_DT4
+ : ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
+ bgp_zebra_release_srv6_sid(&ctx);
+
sid_unregister(bgp_vpn, bgp_vrf->vpn_policy[afi].tovpn_sid);
XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->vpn_policy[afi].tovpn_sid);
}
@@ -899,6 +963,7 @@ void delete_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
uint32_t tovpn_sid_index = 0;
bool tovpn_sid_auto = false;
+ struct srv6_sid_ctx ctx = {};
if (debug)
zlog_debug("%s: try to remove SID for vrf %s", __func__,
@@ -912,9 +977,21 @@ void delete_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
if (tovpn_sid_index != 0 || tovpn_sid_auto)
return;
- srv6_locator_chunk_free(&bgp_vrf->tovpn_sid_locator);
+ if (bgp_vrf->vrf_id == VRF_UNKNOWN) {
+ if (debug)
+ zlog_debug("%s: vrf %s: vrf_id not set, can't set zebra vrf label",
+ __func__, bgp_vrf->name_pretty);
+ return;
+ }
+
+ srv6_locator_free(bgp_vrf->tovpn_sid_locator);
+ bgp_vrf->tovpn_sid_locator = NULL;
if (bgp_vrf->tovpn_sid) {
+ ctx.vrf_id = bgp_vrf->vrf_id;
+ ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_DT46;
+ bgp_zebra_release_srv6_sid(&ctx);
+
sid_unregister(bgp_vpn, bgp_vrf->tovpn_sid);
XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid);
}
@@ -1536,8 +1613,8 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */
struct attr static_attr = {0};
struct attr *new_attr = NULL;
safi_t safi = SAFI_MPLS_VPN;
- mpls_label_t label_val;
- mpls_label_t label;
+ mpls_label_t label_val = { 0 };
+ mpls_label_t label = { 0 };
struct bgp_dest *bn;
const char *debugmsg;
int nexthop_self_flag = 0;
@@ -1759,8 +1836,9 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */
/* Set SID for SRv6 VPN */
if (from_bgp->vpn_policy[afi].tovpn_sid_locator) {
- struct srv6_locator_chunk *locator =
+ struct srv6_locator *locator =
from_bgp->vpn_policy[afi].tovpn_sid_locator;
+
encode_label(
from_bgp->vpn_policy[afi].tovpn_sid_transpose_label,
&label);
@@ -1801,8 +1879,8 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */
.tovpn_sid_locator->prefix.prefix,
sizeof(struct in6_addr));
} else if (from_bgp->tovpn_sid_locator) {
- struct srv6_locator_chunk *locator =
- from_bgp->tovpn_sid_locator;
+ struct srv6_locator *locator = from_bgp->tovpn_sid_locator;
+
encode_label(from_bgp->tovpn_sid_transpose_label, &label);
static_attr.srv6_l3vpn =
XCALLOC(MTYPE_BGP_SRV6_L3VPN,
@@ -2079,6 +2157,7 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
struct bgp *src_vrf;
struct interface *ifp = NULL;
char rd_buf[RD_ADDRSTRLEN];
+ struct aspath *new_aspath;
int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
@@ -2136,6 +2215,32 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
return;
}
+ bn = bgp_afi_node_get(to_bgp->rib[afi][safi], afi, safi, p, NULL);
+
+ /* Check if leaked route has our asn. If so, don't import it. */
+ if (aspath_loop_check(path_vpn->attr->aspath, to_bgp->as)) {
+ for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
+ bpi = bpi->next) {
+ if (bpi->extra && bpi->extra->vrfleak &&
+ (struct bgp_path_info *)bpi->extra->vrfleak->parent ==
+ path_vpn) {
+ break;
+ }
+ }
+
+ if (bpi) {
+ if (debug)
+ zlog_debug("%s: blocking import of %p, as-path match",
+ __func__, bpi);
+ bgp_aggregate_decrement(to_bgp, p, bpi, afi, safi);
+ bgp_path_info_delete(bn, bpi);
+ bgp_process(to_bgp, bn, bpi, afi, safi);
+ }
+ bgp_dest_unlock_node(bn);
+
+ return;
+ }
+
if (debug)
zlog_debug("%s: updating RD %s, %pFX to %s", __func__, rd_buf,
p, to_bgp->name_pretty);
@@ -2288,6 +2393,21 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
nexthop_self_flag = 0;
}
+ /*
+ * if the asn values are different, copy the asn of the source vrf
+ * into the entry before importing. This helps with as-path loop
+ * detection
+ */
+ if (path_vpn->extra && path_vpn->extra->vrfleak &&
+ path_vpn->extra->vrfleak->bgp_orig &&
+ (to_bgp->as != path_vpn->extra->vrfleak->bgp_orig->as)) {
+ new_aspath = aspath_dup(static_attr.aspath);
+ new_aspath =
+ aspath_add_seq(new_aspath,
+ path_vpn->extra->vrfleak->bgp_orig->as);
+ static_attr.aspath = new_aspath;
+ }
+
new_attr = bgp_attr_intern(&static_attr);
bgp_attr_flush(&static_attr);
@@ -3789,7 +3909,8 @@ void bgp_vpn_leak_unimport(struct bgp *from_bgp)
bool is_vrf_leak_bind;
int debug;
- if (from_bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
+ if (from_bgp->inst_type != BGP_INSTANCE_TYPE_VRF &&
+ from_bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT)
return;
debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h
index 92a9fba8..39fed667 100644
--- a/bgpd/bgp_mplsvpn.h
+++ b/bgpd/bgp_mplsvpn.h
@@ -419,6 +419,8 @@ struct bgp_mplsvpn_nh_label_bind_cache *bgp_mplsvpn_nh_label_bind_find(
struct bgp_mplsvpn_nh_label_bind_cache_head *tree, struct prefix *p,
mpls_label_t orig_label);
void bgp_mplsvpn_nexthop_init(void);
+extern void sid_register(struct bgp *bgp, const struct in6_addr *sid,
+ const char *locator_name);
extern void sid_unregister(struct bgp *bgp, const struct in6_addr *sid);
#endif /* _QUAGGA_BGP_MPLSVPN_H */
diff --git a/bgpd/bgp_mplsvpn_snmp.c b/bgpd/bgp_mplsvpn_snmp.c
index 3344e9e0..93d9f672 100644
--- a/bgpd/bgp_mplsvpn_snmp.c
+++ b/bgpd/bgp_mplsvpn_snmp.c
@@ -590,6 +590,11 @@ static int bgp_vrf_check_update_active(struct bgp *bgp, struct interface *ifp)
/* add trap in here */
bgp->snmp_stats->active = new_active;
+ if (!CHECK_FLAG(bm->options, BGP_OPT_TRAPS_RFC4382)) {
+ bgp_mpls_l3vpn_update_last_changed(bgp);
+ return 0;
+ }
+
/* send relevent trap */
if (bgp->snmp_stats->active)
trap = MPLSL3VPNVRFUP;
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index e09dbc22..de57d918 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -861,8 +861,7 @@ int bgp_connect(struct peer_connection *connection)
htons(peer->port), ifindex);
}
-/* After TCP connection is established. Get local address and port. */
-int bgp_getsockname(struct peer *peer)
+void bgp_updatesockname(struct peer *peer)
{
if (peer->su_local) {
sockunion_free(peer->su_local);
@@ -876,6 +875,12 @@ int bgp_getsockname(struct peer *peer)
peer->su_local = sockunion_getsockname(peer->connection->fd);
peer->su_remote = sockunion_getpeername(peer->connection->fd);
+}
+
+/* After TCP connection is established. Get local address and port. */
+int bgp_getsockname(struct peer *peer)
+{
+ bgp_updatesockname(peer);
if (!bgp_zebra_nexthop_set(peer->su_local, peer->su_remote,
&peer->nexthop, peer)) {
diff --git a/bgpd/bgp_network.h b/bgpd/bgp_network.h
index 7a0b3cc6..ceb6b6f0 100644
--- a/bgpd/bgp_network.h
+++ b/bgpd/bgp_network.h
@@ -23,6 +23,7 @@ extern void bgp_close_vrf_socket(struct bgp *bgp);
extern void bgp_close(void);
extern int bgp_connect(struct peer_connection *connection);
extern int bgp_getsockname(struct peer *peer);
+extern void bgp_updatesockname(struct peer *peer);
extern int bgp_md5_set_prefix(struct bgp *bgp, struct prefix *p,
const char *password);
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index 98eb9565..ba6d7071 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -1003,7 +1003,7 @@ static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
if (bnc->is_evpn_gwip_nexthop)
json_object_boolean_true_add(json_nexthop,
"isEvpnGatewayIp");
- json_object_string_addf(json, "resolvedPrefix", "%pFX",
+ json_object_string_addf(json_nexthop, "resolvedPrefix", "%pFX",
&bnc->resolved_prefix);
} else {
vty_out(vty, " %s valid [IGP metric %d], #paths %d",
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h
index 430c8f17..5014eb8f 100644
--- a/bgpd/bgp_nexthop.h
+++ b/bgpd/bgp_nexthop.h
@@ -38,7 +38,7 @@ struct bgp_nexthop_cache {
uint32_t metric;
/* Nexthop number and nexthop linked list.*/
- uint8_t nexthop_num;
+ uint16_t nexthop_num;
/* This flag is set to TRUE for a bnc that is gateway IP overlay index
* nexthop.
@@ -66,6 +66,7 @@ struct bgp_nexthop_cache {
#define BGP_STATIC_ROUTE (1 << 4)
#define BGP_STATIC_ROUTE_EXACT_MATCH (1 << 5)
#define BGP_NEXTHOP_LABELED_VALID (1 << 6)
+#define BGP_NEXTHOP_ULTIMATE (1 << 7)
/*
* This flag is added for EVPN gateway IP nexthops.
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index bdaf9459..9b633b71 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -347,12 +347,11 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
&p.u.prefix6))
ifindex = pi->peer->connection->su.sin6.sin6_scope_id;
- if (!is_bgp_static_route && orig_prefix
- && prefix_same(&p, orig_prefix)) {
+ if (!is_bgp_static_route && orig_prefix && prefix_same(&p, orig_prefix) &&
+ CHECK_FLAG(bgp_route->flags, BGP_FLAG_IMPORT_CHECK)) {
if (BGP_DEBUG(nht, NHT)) {
- zlog_debug(
- "%s(%pFX): prefix loops through itself",
- __func__, &p);
+ zlog_debug("%s(%pFX): prefix loops through itself (import-check enabled)",
+ __func__, &p);
}
return 0;
}
@@ -405,12 +404,11 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
peer);
} else {
if (BGP_DEBUG(nht, NHT))
- zlog_debug(
- "Found existing bnc %pFX(%d)(%s) flags 0x%x ifindex %d #paths %d peer %p",
- &bnc->prefix, bnc->ifindex_ipv6_ll,
- bnc->bgp->name_pretty, bnc->flags,
- bnc->ifindex_ipv6_ll, bnc->path_count,
- bnc->nht_info);
+ zlog_debug("Found existing bnc %pFX(%d)(%s) flags 0x%x ifindex %d #paths %d peer %p, resolved prefix %pFX",
+ &bnc->prefix, bnc->ifindex_ipv6_ll,
+ bnc->bgp->name_pretty, bnc->flags,
+ bnc->ifindex_ipv6_ll, bnc->path_count,
+ bnc->nht_info, &bnc->resolved_prefix);
}
if (pi && is_route_parent_evpn(pi))
@@ -485,6 +483,8 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
bnc->metric;
else if (bpi_ultimate->extra)
bpi_ultimate->extra->igpmetric = 0;
+
+ SET_FLAG(bnc->flags, BGP_NEXTHOP_ULTIMATE);
} else if (peer) {
/*
* Let's not accidentally save the peer data for a peer
@@ -505,6 +505,10 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
return 1;
else if (safi == SAFI_UNICAST && pi &&
pi->sub_type == BGP_ROUTE_IMPORTED &&
+ CHECK_FLAG(bnc->flags, BGP_NEXTHOP_ULTIMATE))
+ return bgp_isvalid_nexthop(bnc);
+ else if (safi == SAFI_UNICAST && pi &&
+ pi->sub_type == BGP_ROUTE_IMPORTED &&
BGP_PATH_INFO_NUM_LABELS(pi) && !bnc->is_evpn_gwip_nexthop)
return bgp_isvalid_nexthop_for_l3vpn(bnc, pi);
else if (safi == SAFI_MPLS_VPN && pi &&
@@ -602,10 +606,10 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
}
if (nhr->metric != bnc->metric)
- bnc->change_flags |= BGP_NEXTHOP_METRIC_CHANGED;
+ SET_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED);
if (nhr->nexthop_num != bnc->nexthop_num)
- bnc->change_flags |= BGP_NEXTHOP_CHANGED;
+ SET_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED);
if (import_check && (nhr->type == ZEBRA_ROUTE_BGP ||
!prefix_same(&bnc->prefix, &nhr->prefix))) {
@@ -631,11 +635,12 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
if (!bnc->is_evpn_gwip_nexthop)
- bnc->flags |= BGP_NEXTHOP_VALID;
+ SET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
bnc->metric = nhr->metric;
bnc->nexthop_num = nhr->nexthop_num;
- bnc->flags &= ~BGP_NEXTHOP_LABELED_VALID; /* check below */
+ UNSET_FLAG(bnc->flags,
+ BGP_NEXTHOP_LABELED_VALID); /* check below */
for (i = 0; i < nhr->nexthop_num; i++) {
int num_labels = 0;
@@ -647,11 +652,12 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
* we receive from bgp. This is to allow us
* to work with v4 routing over v6 nexthops
*/
- if (peer && !peer->ifp
- && CHECK_FLAG(peer->flags,
- PEER_FLAG_CAPABILITY_ENHE)
- && nhr->prefix.family == AF_INET6
- && nexthop->type != NEXTHOP_TYPE_BLACKHOLE) {
+ if (peer && !peer->ifp &&
+ CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE) &&
+ !CHECK_FLAG(bnc->bgp->flags,
+ BGP_FLAG_IPV6_NO_AUTO_RA) &&
+ nhr->prefix.family == AF_INET6 &&
+ nexthop->type != NEXTHOP_TYPE_BLACKHOLE) {
struct interface *ifp;
ifp = if_lookup_by_index(nexthop->ifindex,
@@ -665,8 +671,7 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
/* There is at least one label-switched path */
if (nexthop->nh_label &&
nexthop->nh_label->num_labels) {
-
- bnc->flags |= BGP_NEXTHOP_LABELED_VALID;
+ SET_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID);
num_labels = nexthop->nh_label->num_labels;
}
@@ -690,7 +695,7 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
* determined
* that there has been a change.
*/
- if (bnc->change_flags & BGP_NEXTHOP_CHANGED)
+ if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED))
continue;
for (oldnh = bnc->nexthop; oldnh; oldnh = oldnh->next)
@@ -698,7 +703,7 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
break;
if (!oldnh)
- bnc->change_flags |= BGP_NEXTHOP_CHANGED;
+ SET_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED);
}
bnc_nexthop_free(bnc);
bnc->nexthop = nhlist_head;
@@ -722,19 +727,22 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
: "failed"));
if (evpn_resolved) {
- bnc->flags |= BGP_NEXTHOP_VALID;
- bnc->flags &= ~BGP_NEXTHOP_EVPN_INCOMPLETE;
- bnc->change_flags |= BGP_NEXTHOP_MACIP_CHANGED;
+ SET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
+ UNSET_FLAG(bnc->flags,
+ BGP_NEXTHOP_EVPN_INCOMPLETE);
+ SET_FLAG(bnc->change_flags,
+ BGP_NEXTHOP_MACIP_CHANGED);
} else {
- bnc->flags |= BGP_NEXTHOP_EVPN_INCOMPLETE;
- bnc->flags &= ~BGP_NEXTHOP_VALID;
+ SET_FLAG(bnc->flags,
+ BGP_NEXTHOP_EVPN_INCOMPLETE);
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
}
}
} else {
memset(&bnc->resolved_prefix, 0, sizeof(bnc->resolved_prefix));
- bnc->flags &= ~BGP_NEXTHOP_EVPN_INCOMPLETE;
- bnc->flags &= ~BGP_NEXTHOP_VALID;
- bnc->flags &= ~BGP_NEXTHOP_LABELED_VALID;
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_EVPN_INCOMPLETE);
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID);
bnc->nexthop_num = nhr->nexthop_num;
/* notify bgp fsm if nbr ip goes from valid->invalid */
@@ -753,7 +761,7 @@ static void bgp_nht_ifp_table_handle(struct bgp *bgp,
{
struct bgp_nexthop_cache *bnc;
struct nexthop *nhop;
- uint8_t other_nh_count;
+ uint16_t other_nh_count;
bool nhop_ll_found = false;
bool nhop_found = false;
@@ -1176,7 +1184,7 @@ static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command)
static void register_zebra_rnh(struct bgp_nexthop_cache *bnc)
{
/* Check if we have already registered */
- if (bnc->flags & BGP_NEXTHOP_REGISTERED)
+ if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
return;
if (bnc->ifindex_ipv6_ll) {
@@ -1305,11 +1313,13 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc)
bool bnc_is_valid_nexthop = false;
bool path_valid = false;
+ struct bgp_route_evpn *bre =
+ bgp_attr_get_evpn_overlay(path->attr);
if (safi == SAFI_UNICAST &&
path->sub_type == BGP_ROUTE_IMPORTED &&
BGP_PATH_INFO_NUM_LABELS(path) &&
- (path->attr->evpn_overlay.type != OVERLAY_INDEX_GATEWAY_IP)) {
+ !(bre && bre->type == OVERLAY_INDEX_GATEWAY_IP)) {
bnc_is_valid_nexthop =
bgp_isvalid_nexthop_for_l3vpn(bnc, path)
? true
@@ -1520,6 +1530,10 @@ void bgp_nht_reg_enhe_cap_intfs(struct peer *peer)
return;
bgp = peer->bgp;
+
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_IPV6_NO_AUTO_RA))
+ return;
+
if (!sockunion2hostprefix(&peer->connection->su, &p)) {
zlog_warn("%s: Unable to convert sockunion to prefix for %s",
__func__, peer->host);
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index 248d478f..6451c7cf 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -519,20 +519,17 @@ static int bgp_capability_restart(struct peer *peer,
UNSET_FLAG(restart_flag_time, 0xF000);
peer->v_gr_restart = restart_flag_time;
- if (bgp_debug_neighbor_events(peer)) {
- zlog_debug(
- "%s Peer has%srestarted. Restart Time: %d, N-bit set: %s",
- peer->host,
- CHECK_FLAG(peer->cap,
- PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV)
- ? " "
- : " not ",
- peer->v_gr_restart,
- CHECK_FLAG(peer->cap,
- PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV)
- ? "yes"
- : "no");
- }
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%pBP OPEN has GR capability, Restart time %d R-bit %s N-bit %s",
+ peer, peer->v_gr_restart,
+ CHECK_FLAG(peer->cap,
+ PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV)
+ ? "SET"
+ : "NOT-SET",
+ CHECK_FLAG(peer->cap,
+ PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV)
+ ? "SET"
+ : "NOT-SET");
while (stream_get_getp(s) + 4 <= end) {
afi_t afi;
@@ -556,14 +553,12 @@ static int bgp_capability_restart(struct peer *peer,
iana_safi2str(pkt_safi));
} else {
if (bgp_debug_neighbor_events(peer))
- zlog_debug(
- "%s Address family %s is%spreserved",
- peer->host, get_afi_safi_str(afi, safi, false),
- CHECK_FLAG(
- peer->af_cap[afi][safi],
- PEER_CAP_RESTART_AF_PRESERVE_RCV)
- ? " "
- : " not ");
+ zlog_debug("%pBP F-bit %s for %s", peer,
+ CHECK_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_RESTART_AF_PRESERVE_RCV)
+ ? "SET"
+ : "NOT-SET",
+ get_afi_safi_str(afi, safi, false));
SET_FLAG(peer->af_cap[afi][safi],
PEER_CAP_RESTART_AF_RCV);
@@ -1379,7 +1374,7 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length,
* Check that we can read the opt_type and fetch it
*/
if (STREAM_READABLE(s) < 1) {
- zlog_info("%s Option length error", peer->host);
+ zlog_err("%s Option length error", peer->host);
bgp_notify_send(peer->connection, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_MALFORMED_ATTR);
return -1;
@@ -1392,7 +1387,7 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length,
*/
if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)) {
if (STREAM_READABLE(s) < 2) {
- zlog_info("%s Option length error", peer->host);
+ zlog_err("%s Option length error", peer->host);
bgp_notify_send(peer->connection,
BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_MALFORMED_ATTR);
@@ -1402,7 +1397,7 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length,
opt_length = stream_getw(s);
} else {
if (STREAM_READABLE(s) < 1) {
- zlog_info("%s Option length error", peer->host);
+ zlog_err("%s Option length error", peer->host);
bgp_notify_send(peer->connection,
BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_MALFORMED_ATTR);
@@ -1414,8 +1409,8 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length,
/* Option length check. */
if (STREAM_READABLE(s) < opt_length) {
- zlog_info("%s Option length error (%d)", peer->host,
- opt_length);
+ zlog_err("%s Option length error (%d)", peer->host,
+ opt_length);
bgp_notify_send(peer->connection, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_MALFORMED_ATTR);
return -1;
@@ -1587,15 +1582,12 @@ static void bgp_peer_send_gr_capability(struct stream *s, struct peer *peer,
uint32_t restart_time;
unsigned long capp = 0;
unsigned long rcapp = 0;
+ struct bgp *bgp = peer->bgp;
if (!CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)
&& !CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART_HELPER))
return;
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("[BGP_GR] Sending helper Capability for Peer :%s :",
- peer->host);
-
SET_FLAG(peer->cap, PEER_CAP_RESTART_ADV);
stream_putc(s, BGP_OPEN_OPT_CAP);
capp = stream_get_endp(s); /* Set Capability Len Pointer */
@@ -1605,42 +1597,41 @@ static void bgp_peer_send_gr_capability(struct stream *s, struct peer *peer,
/* Set Restart Capability Len Pointer */
rcapp = stream_get_endp(s);
stream_putc(s, 0);
- restart_time = peer->bgp->restart_time;
- if (peer->bgp->t_startup) {
+ restart_time = bgp->restart_time;
+ if (peer->bgp->t_startup || bgp_in_graceful_restart()) {
SET_FLAG(restart_time, GRACEFUL_RESTART_R_BIT);
SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_ADV);
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("[BGP_GR] Sending R-Bit for peer: %s",
- peer->host);
}
- if (CHECK_FLAG(peer->bgp->flags, BGP_FLAG_GRACEFUL_NOTIFICATION)) {
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_NOTIFICATION)) {
SET_FLAG(restart_time, GRACEFUL_RESTART_N_BIT);
SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_ADV);
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("[BGP_GR] Sending N-Bit for peer: %s",
- peer->host);
}
stream_putw(s, restart_time);
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug("%s: Sending GR Capability, Restart time %d R-bit %s, N-bit %s",
+ peer->host, bgp->restart_time,
+ CHECK_FLAG(peer->cap,
+ PEER_CAP_GRACEFUL_RESTART_R_BIT_ADV)
+ ? "SET"
+ : "NOT-SET",
+ CHECK_FLAG(peer->cap,
+ PEER_CAP_GRACEFUL_RESTART_N_BIT_ADV)
+ ? "SET"
+ : "NOT-SET");
+
/* Send address-family specific graceful-restart capability
* only when GR config is present
*/
if (CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)) {
- if (CHECK_FLAG(peer->bgp->flags, BGP_FLAG_GR_PRESERVE_FWD)
- && BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("[BGP_GR] F bit Set");
-
FOREACH_AFI_SAFI (afi, safi) {
+ bool f_bit = false;
+
if (!peer->afc[afi][safi])
continue;
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] Sending GR Capability for AFI :%d :, SAFI :%d:",
- afi, safi);
-
/* Convert AFI, SAFI to values for
* packet.
*/
@@ -1648,11 +1639,15 @@ static void bgp_peer_send_gr_capability(struct stream *s, struct peer *peer,
&pkt_safi);
stream_putw(s, pkt_afi);
stream_putc(s, pkt_safi);
- if (CHECK_FLAG(peer->bgp->flags,
- BGP_FLAG_GR_PRESERVE_FWD))
- stream_putc(s, GRACEFUL_RESTART_F_BIT);
- else
- stream_putc(s, 0);
+
+ f_bit = bgp_gr_is_forwarding_preserved(bgp);
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug("... F-bit %s for %s",
+ f_bit ? "SET" : "NOT-SET",
+ get_afi_safi_str(afi, safi, false));
+
+ stream_putc(s, f_bit ? GRACEFUL_RESTART_F_BIT : 0);
}
}
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 010a31a3..62be7ffb 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -651,6 +651,7 @@ void bgp_open_send(struct peer_connection *connection)
uint16_t send_holdtime;
as_t local_as;
struct peer *peer = connection->peer;
+ bool ext_opt_params = false;
if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER))
send_holdtime = peer->holdtime;
@@ -677,15 +678,17 @@ void bgp_open_send(struct peer_connection *connection)
/* Set capabilities */
if (CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_OPT_PARAMS)) {
- (void)bgp_open_capability(s, peer, true);
+ ext_opt_params = true;
+ (void)bgp_open_capability(s, peer, ext_opt_params);
} else {
struct stream *tmp = stream_new(STREAM_SIZE(s));
stream_copy(tmp, s);
- if (bgp_open_capability(tmp, peer, false)
- > BGP_OPEN_NON_EXT_OPT_LEN) {
+ if (bgp_open_capability(tmp, peer, ext_opt_params) >
+ BGP_OPEN_NON_EXT_OPT_LEN) {
stream_free(tmp);
- (void)bgp_open_capability(s, peer, true);
+ ext_opt_params = true;
+ (void)bgp_open_capability(s, peer, ext_opt_params);
} else {
stream_copy(s, tmp);
stream_free(tmp);
@@ -696,10 +699,10 @@ void bgp_open_send(struct peer_connection *connection)
bgp_packet_set_size(s);
if (bgp_debug_neighbor_events(peer))
- zlog_debug(
- "%s sending OPEN, version %d, my as %u, holdtime %d, id %pI4",
- peer->host, BGP_VERSION_4, local_as, send_holdtime,
- &peer->local_id);
+ zlog_debug("%pBP fd %d sending OPEN%s, version %d, my as %u, holdtime %d, id %pI4",
+ peer, peer->connection->fd,
+ ext_opt_params ? " (Extended)" : "", BGP_VERSION_4,
+ local_as, send_holdtime, &peer->local_id);
/* Dump packet if debug option is set. */
/* bgp_packet_dump (s); */
@@ -982,6 +985,7 @@ static void bgp_notify_send_internal(struct peer_connection *connection,
peer->notify.code = bgp_notify.code;
peer->notify.subcode = bgp_notify.subcode;
peer->notify.length = bgp_notify.length;
+ peer->notify.hard_reset = hard_reset;
if (bgp_notify.length && data) {
bgp_notify.data = XMALLOC(MTYPE_BGP_NOTIFICATION,
@@ -1112,10 +1116,10 @@ void bgp_route_refresh_send(struct peer *peer, afi_t afi, safi_t safi,
s = stream_new(peer->max_packet_size);
/* Make BGP update packet. */
- if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_RCV))
- bgp_packet_set_marker(s, BGP_MSG_ROUTE_REFRESH_NEW);
- else
- bgp_packet_set_marker(s, BGP_MSG_ROUTE_REFRESH_OLD);
+ if (!CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_RCV))
+ return;
+
+ bgp_packet_set_marker(s, BGP_MSG_ROUTE_REFRESH_NEW);
/* Encode Route Refresh message. */
stream_putw(s, pkt_afi);
@@ -1295,7 +1299,7 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
stream_putc(s, 0);
gr_restart_time = peer->bgp->restart_time;
- if (peer->bgp->t_startup) {
+ if (peer->bgp->t_startup || bgp_in_graceful_restart()) {
SET_FLAG(gr_restart_time, GRACEFUL_RESTART_R_BIT);
SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_ADV);
}
@@ -1800,6 +1804,23 @@ static int bgp_open_receive(struct peer_connection *connection,
mp_capability = 0;
optlen = stream_getc(peer->curr);
+ /* If we previously had some more capabilities e.g.:
+ * FQDN, SOFT_VERSION, we MUST clear the values we used
+ * before, to avoid using stale data.
+ * Checking peer->cap is enough before checking for the real
+ * data, but we don't have this check everywhere in the code,
+ * thus let's clear the data here too before parsing the
+ * capabilities.
+ */
+ if (peer->hostname)
+ XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
+
+ if (peer->domainname)
+ XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
+
+ if (peer->soft_version)
+ XFREE(MTYPE_BGP_SOFT_VERSION, peer->soft_version);
+
/* Extended Optional Parameters Length for BGP OPEN Message */
if (optlen == BGP_OPEN_NON_EXT_OPT_LEN
|| CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_OPT_PARAMS)) {
@@ -1977,6 +1998,14 @@ static int bgp_open_receive(struct peer_connection *connection,
BGP_NOTIFY_OPEN_BAD_PEER_AS,
notify_data_remote_as, 2);
return BGP_Stop;
+ } else if (peer->as_type == AS_AUTO) {
+ if (remote_as == peer->bgp->as) {
+ peer->as = peer->local_as;
+ SET_FLAG(peer->as_type, AS_INTERNAL);
+ } else {
+ peer->as = remote_as;
+ SET_FLAG(peer->as_type, AS_EXTERNAL);
+ }
} else if (peer->as_type == AS_INTERNAL) {
if (remote_as != peer->bgp->as) {
if (bgp_debug_neighbor_events(peer))
@@ -2378,13 +2407,13 @@ static int bgp_update_receive(struct peer_connection *connection,
ret = bgp_dump_attr(&attr, peer->rcvd_attr_str,
sizeof(peer->rcvd_attr_str));
- peer->stat_upd_7606++;
-
- if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
+ if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW) {
+ peer->stat_upd_7606++;
flog_err(
EC_BGP_UPDATE_RCV,
"%pBP rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
peer);
+ }
if (ret && bgp_debug_update(peer, NULL, NULL, 1) &&
BGP_DEBUG(update, UPDATE_DETAIL)) {
@@ -2673,6 +2702,19 @@ static int bgp_notify_receive(struct peer_connection *connection,
inner.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM)
UNSET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
+ /* Resend the next OPEN message with a global AS number if we received
+ * a `Bad Peer AS` notification. This is only valid if `dual-as` is
+ * configured.
+ */
+ if (inner.code == BGP_NOTIFY_OPEN_ERR &&
+ inner.subcode == BGP_NOTIFY_OPEN_BAD_PEER_AS &&
+ CHECK_FLAG(peer->flags, PEER_FLAG_DUAL_AS)) {
+ if (peer->change_local_as != peer->bgp->as)
+ peer->change_local_as = peer->bgp->as;
+ else
+ peer->change_local_as = peer->local_as;
+ }
+
/* If Graceful-Restart N-bit (Notification) is exchanged,
* and it's not a Hard Reset, let's retain the routes.
*/
diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c
index 43682de4..2d61c0f0 100644
--- a/bgpd/bgp_pbr.c
+++ b/bgpd/bgp_pbr.c
@@ -173,33 +173,33 @@ static int snprintf_bgp_pbr_match_val(char *str, int len,
ptr += delta;
len -= delta;
} else {
- if (mval->unary_operator & OPERATOR_UNARY_OR) {
+ if (CHECK_FLAG(mval->unary_operator, OPERATOR_UNARY_OR)) {
delta = snprintf(ptr, len, ", or ");
ptr += delta;
len -= delta;
}
- if (mval->unary_operator & OPERATOR_UNARY_AND) {
+ if (CHECK_FLAG(mval->unary_operator, OPERATOR_UNARY_AND)) {
delta = snprintf(ptr, len, ", and ");
ptr += delta;
len -= delta;
}
}
- if (mval->compare_operator & OPERATOR_COMPARE_LESS_THAN) {
+ if (CHECK_FLAG(mval->compare_operator, OPERATOR_COMPARE_LESS_THAN)) {
delta = snprintf(ptr, len, "<");
ptr += delta;
len -= delta;
}
- if (mval->compare_operator & OPERATOR_COMPARE_GREATER_THAN) {
+ if (CHECK_FLAG(mval->compare_operator, OPERATOR_COMPARE_GREATER_THAN)) {
delta = snprintf(ptr, len, ">");
ptr += delta;
len -= delta;
}
- if (mval->compare_operator & OPERATOR_COMPARE_EQUAL_TO) {
+ if (CHECK_FLAG(mval->compare_operator, OPERATOR_COMPARE_EQUAL_TO)) {
delta = snprintf(ptr, len, "=");
ptr += delta;
len -= delta;
}
- if (mval->compare_operator & OPERATOR_COMPARE_EXACT_MATCH) {
+ if (CHECK_FLAG(mval->compare_operator, OPERATOR_COMPARE_EXACT_MATCH)) {
delta = snprintf(ptr, len, "match");
ptr += delta;
len -= delta;
@@ -287,9 +287,7 @@ static bool bgp_pbr_extract_enumerate_unary_opposite(
{
if (unary_operator == OPERATOR_UNARY_AND && and_valmask) {
if (type_entry == FLOWSPEC_TCP_FLAGS) {
- and_valmask->mask |=
- TCP_HEADER_ALL_FLAGS &
- ~(value);
+ SET_FLAG(and_valmask->mask, CHECK_FLAG(TCP_HEADER_ALL_FLAGS, ~(value)));
} else if (type_entry == FLOWSPEC_DSCP ||
type_entry == FLOWSPEC_FLOW_LABEL ||
type_entry == FLOWSPEC_PKT_LEN ||
@@ -302,9 +300,7 @@ static bool bgp_pbr_extract_enumerate_unary_opposite(
sizeof(struct bgp_pbr_val_mask));
if (type_entry == FLOWSPEC_TCP_FLAGS) {
and_valmask->val = TCP_HEADER_ALL_FLAGS;
- and_valmask->mask |=
- TCP_HEADER_ALL_FLAGS &
- ~(value);
+ SET_FLAG(and_valmask->mask, CHECK_FLAG(TCP_HEADER_ALL_FLAGS, ~(value)));
} else if (type_entry == FLOWSPEC_DSCP ||
type_entry == FLOWSPEC_FLOW_LABEL ||
type_entry == FLOWSPEC_FRAGMENT ||
@@ -346,14 +342,10 @@ static bool bgp_pbr_extract_enumerate_unary(struct bgp_pbr_match_val list[],
if (i != 0 && list[i].unary_operator !=
unary_operator)
return false;
- if (!(list[i].compare_operator &
- OPERATOR_COMPARE_EQUAL_TO) &&
- !(list[i].compare_operator &
- OPERATOR_COMPARE_EXACT_MATCH)) {
- if ((list[i].compare_operator &
- OPERATOR_COMPARE_LESS_THAN) &&
- (list[i].compare_operator &
- OPERATOR_COMPARE_GREATER_THAN)) {
+ if (!CHECK_FLAG(list[i].compare_operator, OPERATOR_COMPARE_EQUAL_TO) &&
+ !CHECK_FLAG(list[i].compare_operator, OPERATOR_COMPARE_EXACT_MATCH)) {
+ if (CHECK_FLAG(list[i].compare_operator, OPERATOR_COMPARE_LESS_THAN) &&
+ CHECK_FLAG(list[i].compare_operator, OPERATOR_COMPARE_GREATER_THAN)) {
ret = bgp_pbr_extract_enumerate_unary_opposite(
unary_operator, and_valmask,
or_valmask, list[i].value,
@@ -366,15 +358,15 @@ static bool bgp_pbr_extract_enumerate_unary(struct bgp_pbr_match_val list[],
}
if (unary_operator == OPERATOR_UNARY_AND && and_valmask) {
if (type_entry == FLOWSPEC_TCP_FLAGS)
- and_valmask->mask |=
- TCP_HEADER_ALL_FLAGS & list[i].value;
+ SET_FLAG(and_valmask->mask,
+ CHECK_FLAG(TCP_HEADER_ALL_FLAGS, list[i].value));
} else if (unary_operator == OPERATOR_UNARY_OR && or_valmask) {
and_valmask = XCALLOC(MTYPE_PBR_VALMASK,
sizeof(struct bgp_pbr_val_mask));
if (type_entry == FLOWSPEC_TCP_FLAGS) {
and_valmask->val = TCP_HEADER_ALL_FLAGS;
- and_valmask->mask |=
- TCP_HEADER_ALL_FLAGS & list[i].value;
+ SET_FLAG(and_valmask->mask,
+ CHECK_FLAG(TCP_HEADER_ALL_FLAGS, list[i].value));
} else if (type_entry == FLOWSPEC_DSCP ||
type_entry == FLOWSPEC_FLOW_LABEL ||
type_entry == FLOWSPEC_ICMP_TYPE ||
@@ -402,8 +394,8 @@ static bool bgp_pbr_extract_enumerate(struct bgp_pbr_match_val list[],
uint8_t unary_operator_val;
bool double_check = false;
- if ((unary_operator & OPERATOR_UNARY_OR) &&
- (unary_operator & OPERATOR_UNARY_AND)) {
+ if (CHECK_FLAG(unary_operator, OPERATOR_UNARY_OR) &&
+ CHECK_FLAG(unary_operator, OPERATOR_UNARY_AND)) {
unary_operator_val = OPERATOR_UNARY_AND;
double_check = true;
} else
@@ -431,12 +423,12 @@ static uint8_t bgp_pbr_match_val_get_operator(struct bgp_pbr_match_val list[],
for (i = 0; i < num; i++) {
if (i == 0)
continue;
- if (list[i].unary_operator & OPERATOR_UNARY_OR)
+ if (CHECK_FLAG(list[i].unary_operator, OPERATOR_UNARY_OR))
unary_operator = OPERATOR_UNARY_OR;
- if ((list[i].unary_operator & OPERATOR_UNARY_AND
- && unary_operator == OPERATOR_UNARY_OR) ||
- (list[i].unary_operator & OPERATOR_UNARY_OR
- && unary_operator == OPERATOR_UNARY_AND))
+ if ((CHECK_FLAG(list[i].unary_operator, OPERATOR_UNARY_AND) &&
+ unary_operator == OPERATOR_UNARY_OR) ||
+ (CHECK_FLAG(list[i].unary_operator, OPERATOR_UNARY_OR) &&
+ unary_operator == OPERATOR_UNARY_AND))
return 0;
}
return unary_operator;
@@ -723,8 +715,8 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
}
}
- } else if (!(api->match_bitmask & PREFIX_SRC_PRESENT) &&
- !(api->match_bitmask & PREFIX_DST_PRESENT)) {
+ } else if (!CHECK_FLAG(api->match_bitmask, PREFIX_SRC_PRESENT) &&
+ !CHECK_FLAG(api->match_bitmask, PREFIX_DST_PRESENT)) {
if (BGP_DEBUG(pbr, PBR)) {
bgp_pbr_print_policy_route(api);
zlog_debug("BGP: match actions without src or dst address can not operate. ignoring.");
@@ -775,21 +767,18 @@ int bgp_pbr_build_and_validate_entry(const struct prefix *p,
}
api_action = &api->actions[action_count - 1];
- if ((ecom_eval->val[1] ==
- (char)ECOMMUNITY_REDIRECT_VRF) &&
- (ecom_eval->val[0] ==
- (char)ECOMMUNITY_ENCODE_TRANS_EXP ||
+ if ((ecom_eval->val[1] == ECOMMUNITY_REDIRECT_VRF) &&
+ (ecom_eval->val[0] == ECOMMUNITY_ENCODE_TRANS_EXP ||
ecom_eval->val[0] ==
- (char)ECOMMUNITY_EXTENDED_COMMUNITY_PART_2 ||
+ ECOMMUNITY_EXTENDED_COMMUNITY_PART_2 ||
ecom_eval->val[0] ==
- (char)ECOMMUNITY_EXTENDED_COMMUNITY_PART_3)) {
+ ECOMMUNITY_EXTENDED_COMMUNITY_PART_3)) {
struct ecommunity *eckey = ecommunity_new();
struct ecommunity_val ecom_copy;
memcpy(&ecom_copy, ecom_eval,
sizeof(struct ecommunity_val));
- ecom_copy.val[0] &=
- ~ECOMMUNITY_ENCODE_TRANS_EXP;
+ UNSET_FLAG(ecom_copy.val[0], ECOMMUNITY_ENCODE_TRANS_EXP);
ecom_copy.val[1] = ECOMMUNITY_ROUTE_TARGET;
ecommunity_add_val(eckey, &ecom_copy,
false, false);
@@ -800,9 +789,9 @@ int bgp_pbr_build_and_validate_entry(const struct prefix *p,
eckey);
ecommunity_free(&eckey);
} else if ((ecom_eval->val[0] ==
- (char)ECOMMUNITY_ENCODE_REDIRECT_IP_NH) &&
+ ECOMMUNITY_ENCODE_REDIRECT_IP_NH) &&
(ecom_eval->val[1] ==
- (char)ECOMMUNITY_REDIRECT_IP_NH)) {
+ ECOMMUNITY_REDIRECT_IP_NH)) {
/* in case the 2 ecom present,
* do not overwrite
* draft-ietf-idr-flowspec-redirect
@@ -861,10 +850,9 @@ int bgp_pbr_build_and_validate_entry(const struct prefix *p,
= ecom_eval->val[7];
api_action_redirect_ip = api_action;
}
- } else if ((ecom_eval->val[0] ==
- (char)ECOMMUNITY_ENCODE_IP) &&
+ } else if ((ecom_eval->val[0] == ECOMMUNITY_ENCODE_IP) &&
(ecom_eval->val[1] ==
- (char)ECOMMUNITY_FLOWSPEC_REDIRECT_IPV4)) {
+ ECOMMUNITY_FLOWSPEC_REDIRECT_IPV4)) {
/* in case the 2 ecom present,
* overwrite simpson draft
* update redirect ip fields
@@ -888,7 +876,7 @@ int bgp_pbr_build_and_validate_entry(const struct prefix *p,
}
} else {
if (ecom_eval->val[0] !=
- (char)ECOMMUNITY_ENCODE_TRANS_EXP)
+ ECOMMUNITY_ENCODE_TRANS_EXP)
continue;
ret = ecommunity_fill_pbr_action(ecom_eval,
api_action,
@@ -920,9 +908,9 @@ int bgp_pbr_build_and_validate_entry(const struct prefix *p,
}
api_action = &api->actions[action_count - 1];
if ((ipv6_ecom_eval->val[1] ==
- (char)ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6) &&
+ ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6) &&
(ipv6_ecom_eval->val[0] ==
- (char)ECOMMUNITY_ENCODE_TRANS_EXP)) {
+ ECOMMUNITY_ENCODE_TRANS_EXP)) {
struct ecommunity *eckey = ecommunity_new();
struct ecommunity_val_ipv6 ecom_copy;
@@ -958,12 +946,12 @@ int bgp_pbr_build_and_validate_entry(const struct prefix *p,
return -1;
/* check inconsistency in the match rule */
- if (api->match_bitmask & PREFIX_SRC_PRESENT) {
+ if (CHECK_FLAG(api->match_bitmask, PREFIX_SRC_PRESENT)) {
src = &api->src_prefix;
afi = family2afi(src->family);
valid_prefix = 1;
}
- if (api->match_bitmask & PREFIX_DST_PRESENT) {
+ if (CHECK_FLAG(api->match_bitmask, PREFIX_DST_PRESENT)) {
dst = &api->dst_prefix;
if (valid_prefix && afi != family2afi(dst->family)) {
if (BGP_DEBUG(pbr, PBR)) {
@@ -1207,12 +1195,10 @@ bool bgp_pbr_rule_hash_equal(const void *arg1, const void *arg2)
if (r1->action != r2->action)
return false;
- if ((r1->flags & MATCH_IP_SRC_SET) &&
- !prefix_same(&r1->src, &r2->src))
+ if (CHECK_FLAG(r1->flags, MATCH_IP_SRC_SET) && !prefix_same(&r1->src, &r2->src))
return false;
- if ((r1->flags & MATCH_IP_DST_SET) &&
- !prefix_same(&r1->dst, &r2->dst))
+ if (CHECK_FLAG(r1->flags, MATCH_IP_DST_SET) && !prefix_same(&r1->dst, &r2->dst))
return false;
return true;
@@ -1429,7 +1415,7 @@ void bgp_pbr_print_policy_route(struct bgp_pbr_entry_main *api)
delta = snprintf(ptr, sizeof(return_string), "MATCH : ");
len -= delta;
ptr += delta;
- if (api->match_bitmask & PREFIX_SRC_PRESENT) {
+ if (CHECK_FLAG(api->match_bitmask, PREFIX_SRC_PRESENT)) {
struct prefix *p = &(api->src_prefix);
if (api->src_prefix_offset)
@@ -1441,7 +1427,7 @@ void bgp_pbr_print_policy_route(struct bgp_pbr_entry_main *api)
ptr += delta;
INCREMENT_DISPLAY(ptr, nb_items, len);
}
- if (api->match_bitmask & PREFIX_DST_PRESENT) {
+ if (CHECK_FLAG(api->match_bitmask, PREFIX_DST_PRESENT)) {
struct prefix *p = &(api->dst_prefix);
INCREMENT_DISPLAY(ptr, nb_items, len);
@@ -1584,21 +1570,18 @@ void bgp_pbr_print_policy_route(struct bgp_pbr_entry_main *api)
delta = snprintf(ptr, len, "@action ");
len -= delta;
ptr += delta;
- if (api->actions[i].u.za.filter
- & TRAFFIC_ACTION_TERMINATE) {
+ if (CHECK_FLAG(api->actions[i].u.za.filter, TRAFFIC_ACTION_TERMINATE)) {
delta = snprintf(ptr, len,
" terminate (apply filter(s))");
len -= delta;
ptr += delta;
}
- if (api->actions[i].u.za.filter
- & TRAFFIC_ACTION_DISTRIBUTE) {
+ if (CHECK_FLAG(api->actions[i].u.za.filter, TRAFFIC_ACTION_DISTRIBUTE)) {
delta = snprintf(ptr, len, " distribute");
len -= delta;
ptr += delta;
}
- if (api->actions[i].u.za.filter
- & TRAFFIC_ACTION_SAMPLE) {
+ if (CHECK_FLAG(api->actions[i].u.za.filter, TRAFFIC_ACTION_SAMPLE)) {
delta = snprintf(ptr, len, " sample");
len -= delta;
ptr += delta;
@@ -1749,12 +1732,10 @@ static int bgp_pbr_get_same_rule(struct hash_bucket *bucket, void *arg)
if (r1->flags != r2->flags)
return HASHWALK_CONTINUE;
- if ((r1->flags & MATCH_IP_SRC_SET) &&
- !prefix_same(&r1->src, &r2->src))
+ if (CHECK_FLAG(r1->flags, MATCH_IP_SRC_SET) && !prefix_same(&r1->src, &r2->src))
return HASHWALK_CONTINUE;
- if ((r1->flags & MATCH_IP_DST_SET) &&
- !prefix_same(&r1->dst, &r2->dst))
+ if (CHECK_FLAG(r1->flags, MATCH_IP_DST_SET) && !prefix_same(&r1->dst, &r2->dst))
return HASHWALK_CONTINUE;
/* this function is used for two cases:
@@ -1843,11 +1824,11 @@ static void bgp_pbr_policyroute_remove_from_zebra_unit(
pbr_rule.vrf_id = bpf->vrf_id;
if (bpf->src) {
prefix_copy(&pbr_rule.src, bpf->src);
- pbr_rule.flags |= MATCH_IP_SRC_SET;
+ SET_FLAG(pbr_rule.flags, MATCH_IP_SRC_SET);
}
if (bpf->dst) {
prefix_copy(&pbr_rule.dst, bpf->dst);
- pbr_rule.flags |= MATCH_IP_DST_SET;
+ SET_FLAG(pbr_rule.flags, MATCH_IP_DST_SET);
}
bpr = &pbr_rule;
/* A previous entry may already exist
@@ -1870,32 +1851,32 @@ static void bgp_pbr_policyroute_remove_from_zebra_unit(
temp.family = bpf->family;
if (bpf->src) {
- temp.flags |= MATCH_IP_SRC_SET;
+ SET_FLAG(temp.flags, MATCH_IP_SRC_SET);
prefix_copy(&temp2.src, bpf->src);
} else
temp2.src.family = bpf->family;
if (bpf->dst) {
- temp.flags |= MATCH_IP_DST_SET;
+ SET_FLAG(temp.flags, MATCH_IP_DST_SET);
prefix_copy(&temp2.dst, bpf->dst);
} else
temp2.dst.family = bpf->family;
if (src_port && (src_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
if (bpf->protocol == IPPROTO_ICMP)
- temp.flags |= MATCH_ICMP_SET;
- temp.flags |= MATCH_PORT_SRC_SET;
+ SET_FLAG(temp.flags, MATCH_ICMP_SET);
+ SET_FLAG(temp.flags, MATCH_PORT_SRC_SET);
temp2.src_port_min = src_port->min_port;
if (src_port->max_port) {
- temp.flags |= MATCH_PORT_SRC_RANGE_SET;
+ SET_FLAG(temp.flags, MATCH_PORT_SRC_RANGE_SET);
temp2.src_port_max = src_port->max_port;
}
}
if (dst_port && (dst_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
if (bpf->protocol == IPPROTO_ICMP)
- temp.flags |= MATCH_ICMP_SET;
- temp.flags |= MATCH_PORT_DST_SET;
+ SET_FLAG(temp.flags, MATCH_ICMP_SET);
+ SET_FLAG(temp.flags, MATCH_PORT_DST_SET);
temp2.dst_port_min = dst_port->min_port;
if (dst_port->max_port) {
- temp.flags |= MATCH_PORT_DST_RANGE_SET;
+ SET_FLAG(temp.flags, MATCH_PORT_DST_RANGE_SET);
temp2.dst_port_max = dst_port->max_port;
}
}
@@ -1907,7 +1888,7 @@ static void bgp_pbr_policyroute_remove_from_zebra_unit(
temp.pkt_len_max = pkt_len->max_port;
} else if (bpf->pkt_len_val) {
if (bpf->pkt_len_val->mask)
- temp.flags |= MATCH_PKT_LEN_INVERSE_SET;
+ SET_FLAG(temp.flags, MATCH_PKT_LEN_INVERSE_SET);
temp.pkt_len_min = bpf->pkt_len_val->val;
}
if (bpf->tcp_flags) {
@@ -1916,32 +1897,32 @@ static void bgp_pbr_policyroute_remove_from_zebra_unit(
}
if (bpf->dscp) {
if (bpf->dscp->mask)
- temp.flags |= MATCH_DSCP_INVERSE_SET;
+ SET_FLAG(temp.flags, MATCH_DSCP_INVERSE_SET);
else
- temp.flags |= MATCH_DSCP_SET;
+ SET_FLAG(temp.flags, MATCH_DSCP_SET);
temp.dscp_value = bpf->dscp->val;
}
if (bpf->flow_label) {
if (bpf->flow_label->mask)
- temp.flags |= MATCH_FLOW_LABEL_INVERSE_SET;
+ SET_FLAG(temp.flags, MATCH_FLOW_LABEL_INVERSE_SET);
else
- temp.flags |= MATCH_FLOW_LABEL_SET;
+ SET_FLAG(temp.flags, MATCH_FLOW_LABEL_SET);
temp.flow_label = bpf->flow_label->val;
}
if (bpf->fragment) {
if (bpf->fragment->mask)
- temp.flags |= MATCH_FRAGMENT_INVERSE_SET;
+ SET_FLAG(temp.flags, MATCH_FRAGMENT_INVERSE_SET);
temp.fragment = bpf->fragment->val;
}
if (bpf->src == NULL || bpf->dst == NULL) {
- if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
+ if (CHECK_FLAG(temp.flags, (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET)))
temp.type = IPSET_NET_PORT;
else
temp.type = IPSET_NET;
} else {
- if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
+ if (CHECK_FLAG(temp.flags, (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET)))
temp.type = IPSET_NET_PORT_NET;
else
temp.type = IPSET_NET_NET;
@@ -2319,11 +2300,11 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
pbr_rule.vrf_id = bpf->vrf_id;
pbr_rule.priority = 20;
if (bpf->src) {
- pbr_rule.flags |= MATCH_IP_SRC_SET;
+ SET_FLAG(pbr_rule.flags, MATCH_IP_SRC_SET);
prefix_copy(&pbr_rule.src, bpf->src);
}
if (bpf->dst) {
- pbr_rule.flags |= MATCH_IP_DST_SET;
+ SET_FLAG(pbr_rule.flags, MATCH_IP_DST_SET);
prefix_copy(&pbr_rule.dst, bpf->dst);
}
pbr_rule.action = bpa;
@@ -2380,32 +2361,32 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
temp.vrf_id = bpf->vrf_id;
temp.family = bpf->family;
if (bpf->src)
- temp.flags |= MATCH_IP_SRC_SET;
+ SET_FLAG(temp.flags, MATCH_IP_SRC_SET);
if (bpf->dst)
- temp.flags |= MATCH_IP_DST_SET;
+ SET_FLAG(temp.flags, MATCH_IP_DST_SET);
if (src_port && (src_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
if (bpf->protocol == IPPROTO_ICMP)
- temp.flags |= MATCH_ICMP_SET;
- temp.flags |= MATCH_PORT_SRC_SET;
+ SET_FLAG(temp.flags, MATCH_ICMP_SET);
+ SET_FLAG(temp.flags, MATCH_PORT_SRC_SET);
}
if (dst_port && (dst_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
if (bpf->protocol == IPPROTO_ICMP)
- temp.flags |= MATCH_ICMP_SET;
- temp.flags |= MATCH_PORT_DST_SET;
+ SET_FLAG(temp.flags, MATCH_ICMP_SET);
+ SET_FLAG(temp.flags, MATCH_PORT_DST_SET);
}
if (src_port && src_port->max_port)
- temp.flags |= MATCH_PORT_SRC_RANGE_SET;
+ SET_FLAG(temp.flags, MATCH_PORT_SRC_RANGE_SET);
if (dst_port && dst_port->max_port)
- temp.flags |= MATCH_PORT_DST_RANGE_SET;
+ SET_FLAG(temp.flags, MATCH_PORT_DST_RANGE_SET);
if (bpf->src == NULL || bpf->dst == NULL) {
- if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
+ if (CHECK_FLAG(temp.flags, (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET)))
temp.type = IPSET_NET_PORT;
else
temp.type = IPSET_NET;
} else {
- if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
+ if (CHECK_FLAG(temp.flags, (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET)))
temp.type = IPSET_NET_PORT_NET;
else
temp.type = IPSET_NET_NET;
@@ -2416,7 +2397,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
temp.pkt_len_max = pkt_len->max_port;
} else if (bpf->pkt_len_val) {
if (bpf->pkt_len_val->mask)
- temp.flags |= MATCH_PKT_LEN_INVERSE_SET;
+ SET_FLAG(temp.flags, MATCH_PKT_LEN_INVERSE_SET);
temp.pkt_len_min = bpf->pkt_len_val->val;
}
if (bpf->tcp_flags) {
@@ -2425,26 +2406,26 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
}
if (bpf->dscp) {
if (bpf->dscp->mask)
- temp.flags |= MATCH_DSCP_INVERSE_SET;
+ SET_FLAG(temp.flags, MATCH_DSCP_INVERSE_SET);
else
- temp.flags |= MATCH_DSCP_SET;
+ SET_FLAG(temp.flags, MATCH_DSCP_SET);
temp.dscp_value = bpf->dscp->val;
}
if (bpf->flow_label) {
if (bpf->flow_label->mask)
- temp.flags |= MATCH_FLOW_LABEL_INVERSE_SET;
+ SET_FLAG(temp.flags, MATCH_FLOW_LABEL_INVERSE_SET);
else
- temp.flags |= MATCH_FLOW_LABEL_SET;
+ SET_FLAG(temp.flags, MATCH_FLOW_LABEL_SET);
temp.flow_label = bpf->flow_label->val;
}
if (bpf->fragment) {
if (bpf->fragment->mask)
- temp.flags |= MATCH_FRAGMENT_INVERSE_SET;
+ SET_FLAG(temp.flags, MATCH_FRAGMENT_INVERSE_SET);
temp.fragment = bpf->fragment->val;
}
if (bpf->protocol) {
temp.protocol = bpf->protocol;
- temp.flags |= MATCH_PROTOCOL_SET;
+ SET_FLAG(temp.flags, MATCH_PROTOCOL_SET);
}
temp.action = bpa;
bpm = hash_get(bgp->pbr_match_hash, &temp,
@@ -2661,13 +2642,13 @@ static void bgp_pbr_handle_entry(struct bgp *bgp, struct bgp_path_info *path,
memset(&nh, 0, sizeof(nh));
memset(&bpf, 0, sizeof(bpf));
memset(&bpof, 0, sizeof(bpof));
- if (api->match_bitmask & PREFIX_SRC_PRESENT ||
+ if (CHECK_FLAG(api->match_bitmask, PREFIX_SRC_PRESENT) ||
(api->type == BGP_PBR_IPRULE &&
- api->match_bitmask_iprule & PREFIX_SRC_PRESENT))
+ CHECK_FLAG(api->match_bitmask_iprule, PREFIX_SRC_PRESENT)))
src = &api->src_prefix;
- if (api->match_bitmask & PREFIX_DST_PRESENT ||
+ if (CHECK_FLAG(api->match_bitmask, PREFIX_DST_PRESENT) ||
(api->type == BGP_PBR_IPRULE &&
- api->match_bitmask_iprule & PREFIX_DST_PRESENT))
+ CHECK_FLAG(api->match_bitmask_iprule, PREFIX_DST_PRESENT)))
dst = &api->dst_prefix;
if (api->type == BGP_PBR_IPRULE)
bpf.type = api->type;
@@ -2812,8 +2793,7 @@ static void bgp_pbr_handle_entry(struct bgp *bgp, struct bgp_path_info *path,
}
break;
case ACTION_TRAFFIC_ACTION:
- if (api->actions[i].u.za.filter
- & TRAFFIC_ACTION_SAMPLE) {
+ if (CHECK_FLAG(api->actions[i].u.za.filter, TRAFFIC_ACTION_SAMPLE)) {
if (BGP_DEBUG(pbr, PBR)) {
bgp_pbr_print_policy_route(api);
zlog_warn("PBR: Sample action Ignored");
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 666adc47..619252b0 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -525,8 +525,6 @@ struct bgp_dest *bgp_path_info_reap(struct bgp_dest *dest,
else
bgp_dest_set_bgp_path_info(dest, pi->next);
- bgp_path_info_mpath_dequeue(pi);
-
pi->next = NULL;
pi->prev = NULL;
@@ -541,8 +539,6 @@ struct bgp_dest *bgp_path_info_reap(struct bgp_dest *dest,
static struct bgp_dest *bgp_path_info_reap_unsorted(struct bgp_dest *dest,
struct bgp_path_info *pi)
{
- bgp_path_info_mpath_dequeue(pi);
-
pi->next = NULL;
pi->prev = NULL;
@@ -837,8 +833,13 @@ int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
* with the
* sticky flag.
*/
- if (newattr->sticky != existattr->sticky) {
- if (newattr->sticky && !existattr->sticky) {
+ bool new_sticky = CHECK_FLAG(newattr->evpn_flags,
+ ATTR_EVPN_FLAG_STICKY);
+ bool exist_sticky = CHECK_FLAG(existattr->evpn_flags,
+ ATTR_EVPN_FLAG_STICKY);
+
+ if (new_sticky != exist_sticky) {
+ if (new_sticky && !exist_sticky) {
*reason = bgp_path_selection_evpn_sticky_mac;
if (debug)
zlog_debug(
@@ -847,7 +848,7 @@ int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
return 1;
}
- if (!newattr->sticky && existattr->sticky) {
+ if (!new_sticky && exist_sticky) {
*reason = bgp_path_selection_evpn_sticky_mac;
if (debug)
zlog_debug(
@@ -1063,12 +1064,37 @@ int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
}
}
- /* Tie-breaker - AIGP (Metric TLV) attribute */
+ /* 3. Local route check. We prefer:
+ * - BGP_ROUTE_STATIC
+ * - BGP_ROUTE_AGGREGATE
+ * - BGP_ROUTE_REDISTRIBUTE
+ */
+ new_origin = !(new->sub_type == BGP_ROUTE_NORMAL || new->sub_type == BGP_ROUTE_IMPORTED);
+ exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
+ exist->sub_type == BGP_ROUTE_IMPORTED);
+
+ if (new_origin && !exist_origin) {
+ *reason = bgp_path_selection_local_route;
+ if (debug)
+ zlog_debug("%s: %s wins over %s due to preferred BGP_ROUTE type", pfx_buf,
+ new_buf, exist_buf);
+ return 1;
+ }
+
+ if (!new_origin && exist_origin) {
+ *reason = bgp_path_selection_local_route;
+ if (debug)
+ zlog_debug("%s: %s loses to %s due to preferred BGP_ROUTE type", pfx_buf,
+ new_buf, exist_buf);
+ return 0;
+ }
+
+ /* 3.5. Tie-breaker - AIGP (Metric TLV) attribute */
if (CHECK_FLAG(newattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
CHECK_FLAG(existattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_AIGP)) {
- uint64_t new_aigp = bgp_attr_get_aigp_metric(newattr);
- uint64_t exist_aigp = bgp_attr_get_aigp_metric(existattr);
+ uint64_t new_aigp = bgp_aigp_metric_total(new);
+ uint64_t exist_aigp = bgp_aigp_metric_total(exist);
if (new_aigp < exist_aigp) {
*reason = bgp_path_selection_aigp;
@@ -1093,34 +1119,6 @@ int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
}
}
- /* 3. Local route check. We prefer:
- * - BGP_ROUTE_STATIC
- * - BGP_ROUTE_AGGREGATE
- * - BGP_ROUTE_REDISTRIBUTE
- */
- new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
- new->sub_type == BGP_ROUTE_IMPORTED);
- exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
- exist->sub_type == BGP_ROUTE_IMPORTED);
-
- if (new_origin && !exist_origin) {
- *reason = bgp_path_selection_local_route;
- if (debug)
- zlog_debug(
- "%s: %s wins over %s due to preferred BGP_ROUTE type",
- pfx_buf, new_buf, exist_buf);
- return 1;
- }
-
- if (!new_origin && exist_origin) {
- *reason = bgp_path_selection_local_route;
- if (debug)
- zlog_debug(
- "%s: %s loses to %s due to preferred BGP_ROUTE type",
- pfx_buf, new_buf, exist_buf);
- return 0;
- }
-
/* Here if these are imported routes then get ultimate pi for
* path compare.
*/
@@ -1588,18 +1586,16 @@ int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
if (ret == 1) {
*reason = bgp_path_selection_neighbor_ip;
if (debug)
- zlog_debug(
- "%s: %s loses to %s due to Neighor IP comparison",
- pfx_buf, new_buf, exist_buf);
+ zlog_debug("%s: %s loses to %s due to Neighbor IP comparison",
+ pfx_buf, new_buf, exist_buf);
return 0;
}
if (ret == -1) {
*reason = bgp_path_selection_neighbor_ip;
if (debug)
- zlog_debug(
- "%s: %s wins over %s due to Neighor IP comparison",
- pfx_buf, new_buf, exist_buf);
+ zlog_debug("%s: %s wins over %s due to Neighbor IP comparison",
+ pfx_buf, new_buf, exist_buf);
return 1;
}
@@ -1780,14 +1776,13 @@ static bool bgp_community_filter(struct peer *peer, struct attr *attr)
return true;
/* NO_EXPORT check. */
- if (peer->sort == BGP_PEER_EBGP &&
- community_include(bgp_attr_get_community(attr),
- COMMUNITY_NO_EXPORT))
+ if (peer->sort == BGP_PEER_EBGP && peer->sub_sort != BGP_PEER_EBGP_OAD &&
+ community_include(bgp_attr_get_community(attr), COMMUNITY_NO_EXPORT))
return true;
/* NO_EXPORT_SUBCONFED check. */
- if (peer->sort == BGP_PEER_EBGP
- || peer->sort == BGP_PEER_CONFED)
+ if ((peer->sort == BGP_PEER_EBGP && peer->sub_sort != BGP_PEER_EBGP_OAD) ||
+ peer->sort == BGP_PEER_CONFED)
if (community_include(bgp_attr_get_community(attr),
COMMUNITY_NO_EXPORT_SUBCONFED))
return true;
@@ -2156,6 +2151,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
bool nh_reset = false;
uint64_t cum_bw;
mpls_label_t label;
+ bool global_and_ll = false;
if (DISABLE_BGP_ANNOUNCE)
return false;
@@ -2170,8 +2166,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
from = pi->peer;
filter = &peer->filter[afi][safi];
bgp = SUBGRP_INST(subgrp);
- piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
- : pi->attr;
+ piattr = bgp_path_info_mpath_count(pi) > 1 ? bgp_path_info_mpath_attr(pi) : pi->attr;
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
peer->pmax_out[afi][safi] != 0 &&
@@ -2467,30 +2462,37 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
* we do not announce LL address as `::`.
*/
if (NEXTHOP_IS_V6) {
- attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
- if ((CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
- && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
- || (!reflect && !transparent
- && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
- && peer->shared_network
- && (from == bgp->peer_self
- || peer->sort == BGP_PEER_EBGP))) {
+ if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) {
+ /* nexthop local unchanged: only include the link-local nexthop if it
+ * was already present.
+ */
+ if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
+ global_and_ll = true;
+ } else if (!reflect && !transparent &&
+ IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local) && peer->shared_network &&
+ (from == bgp->peer_self || peer->sort == BGP_PEER_EBGP))
+ global_and_ll = true;
+
+ if (global_and_ll) {
if (safi == SAFI_MPLS_VPN)
attr->mp_nexthop_len =
BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL;
else
attr->mp_nexthop_len =
BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
- }
+ } else
+ attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
/* Clear off link-local nexthop in source, whenever it is not
* needed to
* ensure more prefixes share the same attribute for
* announcement.
*/
- if (!(CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
+ if (!(CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) ||
+ !IPV6_ADDR_SAME(&peer->nexthop.v6_global, &from->nexthop.v6_global))
+ /* Reset if "nexthop-local unchanged" is not set or originating and destination peer
+ * does not share the same subnet.
+ */
memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
}
@@ -2814,6 +2816,21 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
false));
}
+ /*
+ * Adjust AIGP for propagation when the nexthop is set to ourselves,
+ * e.g., using "set ip nexthop peer-address" or when advertising to
+ * EBGP. Note in route reflection the nexthop is usually unmodified
+ * and the AIGP should not be adjusted in that case.
+ */
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) && AIGP_TRANSMIT_ALLOWED(peer)) {
+ if (nh_reset ||
+ CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_NEXTHOP_PEER_ADDRESS)) {
+ uint64_t aigp = bgp_aigp_metric_total(pi);
+
+ bgp_attr_set_aigp_metric(attr, aigp);
+ }
+ }
+
return true;
}
@@ -2848,13 +2865,12 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
struct bgp_path_info *pi2;
int paths_eq, do_mpath;
bool debug, any_comparisons;
- struct list mp_list;
char pfx_buf[PREFIX2STR_BUFFER] = {};
char path_buf[PATH_ADDPATH_STR_BUFFER];
enum bgp_path_selection_reason reason = bgp_path_selection_none;
bool unsorted_items = true;
+ uint32_t num_candidates = 0;
- bgp_mp_list_init(&mp_list);
do_mpath =
(mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
@@ -3229,7 +3245,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
"%pBD(%s): %s is the bestpath, add to the multipath list",
dest, bgp->name_pretty,
path_buf);
- bgp_mp_list_add(&mp_list, pi);
+ SET_FLAG(pi->flags, BGP_PATH_MULTIPATH_NEW);
+ num_candidates++;
continue;
}
@@ -3242,15 +3259,6 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
if (!peer_established(pi->peer->connection))
continue;
- if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
- if (debug)
- zlog_debug(
- "%pBD(%s): %s has the same nexthop as the bestpath, skip it",
- dest, bgp->name_pretty,
- path_buf);
- continue;
- }
-
bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
mpath_cfg, debug, pfx_buf, afi, safi,
&dest->reason);
@@ -3261,15 +3269,14 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
"%pBD(%s): %s is equivalent to the bestpath, add to the multipath list",
dest, bgp->name_pretty,
path_buf);
- bgp_mp_list_add(&mp_list, pi);
+ SET_FLAG(pi->flags, BGP_PATH_MULTIPATH_NEW);
+ num_candidates++;
}
}
}
- bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
- mpath_cfg);
+ bgp_path_info_mpath_update(bgp, dest, new_select, old_select, num_candidates, mpath_cfg);
bgp_path_info_mpath_aggregate_update(new_select, old_select);
- bgp_mp_list_clear(&mp_list);
bgp_addpath_update_ids(bgp, dest, afi, safi);
@@ -3624,7 +3631,16 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
struct bgp_path_info_pair old_and_new;
int debug = 0;
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
+ /*
+ * For default bgp instance, which is deleted i.e. marked hidden
+ * we are skipping SAFI_MPLS_VPN route table deletion
+ * in bgp_cleanup_routes.
+ * So, we need to delete routes from VPNV4 table.
+ * Here for !IS_BGP_INSTANCE_HIDDEN,
+ * !(SAFI_MPLS_VPN && AF_IP/AF_IP6),
+ * we ignore the event for the prefix.
+ */
+ if (BGP_INSTANCE_HIDDEN_DELETE_IN_PROGRESS(bgp, afi, safi)) {
if (dest)
debug = bgp_debug_bestpath(dest);
if (debug)
@@ -3763,7 +3779,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
if (old_select || new_select) {
bgp_bump_version(dest);
- if (!bgp->t_rmap_def_originate_eval)
+ if (!bgp->t_rmap_def_originate_eval &&
+ bgp->rmap_def_originate_eval_timer)
event_add_timer(
bm->master,
update_group_refresh_default_originate_route_map,
@@ -3872,6 +3889,7 @@ void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
struct bgp_dest *dest;
int cnt = 0;
struct afi_safi_info *thread_info;
+ bool route_sync_pending = false;
if (bgp->gr_info[afi][safi].t_route_select) {
struct event *t = bgp->gr_info[afi][safi].t_route_select;
@@ -3881,7 +3899,7 @@ void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
EVENT_OFF(bgp->gr_info[afi][safi].t_route_select);
}
- if (BGP_DEBUG(update, UPDATE_OUT)) {
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) {
zlog_debug("%s: processing route for %s : cnt %d", __func__,
get_afi_safi_str(afi, safi, false),
bgp->gr_info[afi][safi].gr_deferred);
@@ -3914,6 +3932,21 @@ void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
/* Send route processing complete message to RIB */
bgp_zebra_update(bgp, afi, safi,
ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
+ bgp->gr_info[afi][safi].route_sync = true;
+
+ /* If this instance is all done, check for GR completion overall */
+ FOREACH_AFI_SAFI_NSF (afi, safi) {
+ if (bgp->gr_info[afi][safi].af_enabled &&
+ !bgp->gr_info[afi][safi].route_sync) {
+ route_sync_pending = true;
+ break;
+ }
+ }
+
+ if (!route_sync_pending) {
+ bgp->gr_route_sync_pending = false;
+ bgp_update_gr_completion();
+ }
return;
}
@@ -4001,8 +4034,9 @@ static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
return pqnode;
}
-void bgp_process(struct bgp *bgp, struct bgp_dest *dest,
- struct bgp_path_info *pi, afi_t afi, safi_t safi)
+static void bgp_process_internal(struct bgp *bgp, struct bgp_dest *dest,
+ struct bgp_path_info *pi, afi_t afi,
+ safi_t safi, bool early_process)
{
#define ARBITRARY_PROCESS_QLEN 10000
struct work_queue *wq = bgp->process_queue;
@@ -4065,9 +4099,8 @@ void bgp_process(struct bgp *bgp, struct bgp_dest *dest,
struct work_queue_item *item = work_queue_last_item(wq);
pqnode = item->data;
- if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
- || pqnode->bgp != bgp
- || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
+ if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER) ||
+ (pqnode->queued >= ARBITRARY_PROCESS_QLEN && !early_process))
pqnode = bgp_processq_alloc(bgp);
else
pqnode_reuse = 1;
@@ -4081,7 +4114,10 @@ void bgp_process(struct bgp *bgp, struct bgp_dest *dest,
/* can't be enqueued twice */
assert(STAILQ_NEXT(dest, pq) == NULL);
- STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
+ if (early_process)
+ STAILQ_INSERT_HEAD(&pqnode->pqueue, dest, pq);
+ else
+ STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
pqnode->queued++;
if (!pqnode_reuse)
@@ -4090,6 +4126,18 @@ void bgp_process(struct bgp *bgp, struct bgp_dest *dest,
return;
}
+void bgp_process(struct bgp *bgp, struct bgp_dest *dest,
+ struct bgp_path_info *pi, afi_t afi, safi_t safi)
+{
+ bgp_process_internal(bgp, dest, pi, afi, safi, false);
+}
+
+void bgp_process_early(struct bgp *bgp, struct bgp_dest *dest,
+ struct bgp_path_info *pi, afi_t afi, safi_t safi)
+{
+ bgp_process_internal(bgp, dest, pi, afi, safi, true);
+}
+
void bgp_add_eoiu_mark(struct bgp *bgp)
{
struct bgp_process_queue *pqnode;
@@ -4582,10 +4630,10 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
* will not be interned. In which case, it is ok to update the
* attr->evpn_overlay, so that, this can be stored in adj_in.
*/
- if ((afi == AFI_L2VPN) && evpn) {
- memcpy(&attr->evpn_overlay, evpn,
- sizeof(struct bgp_route_evpn));
- }
+ if ((afi == AFI_L2VPN) && evpn)
+ bgp_attr_set_evpn_overlay(attr, evpn);
+ else
+ evpn_overlay_free(evpn);
bgp_adj_in_set(dest, peer, attr, addpath_id, &bgp_labels);
}
@@ -4624,7 +4672,22 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (aspath_get_last_as(attr->aspath) == bgp->as)
do_loop_check = 0;
- if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
+ /* When using bgp ipv4 labeled session, the local prefix is
+ * received by a peer, and finds out that the proposed prefix
+ * and its next-hop are the same. To avoid a route loop locally,
+ * no nexthop entry is referenced for that prefix, and the route
+ * will not be selected.
+ *
+ * As it has been done for ipv4-unicast, apply the following fix
+ * for labeled address families: when the received peer is
+ * a route reflector, the prefix has to be selected, even if the
+ * route can not be installed locally.
+ */
+ if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT) ||
+ (safi == SAFI_UNICAST && !peer->afc[afi][safi] &&
+ peer->afc[afi][SAFI_LABELED_UNICAST] &&
+ CHECK_FLAG(peer->af_flags[afi][SAFI_LABELED_UNICAST],
+ PEER_FLAG_REFLECTOR_CLIENT)))
bgp_nht_param_prefix = NULL;
else
bgp_nht_param_prefix = p;
@@ -4747,8 +4810,9 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
* evpn to new_atr.evpn_overlay before it is interned.
*/
if (soft_reconfig && (afi == AFI_L2VPN) && evpn)
- memcpy(&new_attr.evpn_overlay, evpn,
- sizeof(struct bgp_route_evpn));
+ bgp_attr_set_evpn_overlay(&new_attr, evpn);
+ else
+ evpn_overlay_free(evpn);
/* Apply incoming route-map.
* NB: new_attr may now contain newly allocated values from route-map
@@ -4772,22 +4836,21 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
false);
}
- if (peer->sort == BGP_PEER_EBGP) {
-
- /* rfc7999:
- * A BGP speaker receiving an announcement tagged with the
- * BLACKHOLE community SHOULD add the NO_ADVERTISE or
- * NO_EXPORT community as defined in RFC1997, or a
- * similar community, to prevent propagation of the
- * prefix outside the local AS. The community to prevent
- * propagation SHOULD be chosen according to the operator's
- * routing policy.
- */
- if (bgp_attr_get_community(&new_attr) &&
- community_include(bgp_attr_get_community(&new_attr),
- COMMUNITY_BLACKHOLE))
- bgp_attr_add_no_export_community(&new_attr);
+ /* rfc7999:
+ * A BGP speaker receiving an announcement tagged with the
+ * BLACKHOLE community SHOULD add the NO_ADVERTISE or
+ * NO_EXPORT community as defined in RFC1997, or a
+ * similar community, to prevent propagation of the
+ * prefix outside the local AS. The community to prevent
+ * propagation SHOULD be chosen according to the operator's
+ * routing policy.
+ */
+ if (bgp_attr_get_community(&new_attr) &&
+ community_include(bgp_attr_get_community(&new_attr),
+ COMMUNITY_BLACKHOLE))
+ bgp_attr_add_no_export_community(&new_attr);
+ if (peer->sort == BGP_PEER_EBGP) {
/* If we receive the graceful-shutdown community from an eBGP
* peer we must lower local-preference */
if (bgp_attr_get_community(&new_attr) &&
@@ -5424,7 +5487,7 @@ filtered:
void bgp_withdraw(struct peer *peer, const struct prefix *p,
uint32_t addpath_id, afi_t afi, safi_t safi, int type,
int sub_type, struct prefix_rd *prd, mpls_label_t *label,
- uint8_t num_labels, struct bgp_route_evpn *evpn)
+ uint8_t num_labels)
{
struct bgp *bgp;
char pfx_buf[BGP_PRD_PATH_STRLEN];
@@ -5653,7 +5716,7 @@ static void bgp_soft_reconfig_table_update(struct peer *peer,
struct bgp_path_info *pi;
uint8_t num_labels;
mpls_label_t *label_pnt;
- struct bgp_route_evpn evpn;
+ struct bgp_route_evpn *bre = NULL;
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
if (pi->peer == peer)
@@ -5661,15 +5724,13 @@ static void bgp_soft_reconfig_table_update(struct peer *peer,
num_labels = ain->labels ? ain->labels->num_labels : 0;
label_pnt = num_labels ? &ain->labels->label[0] : NULL;
+
if (pi)
- memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
- sizeof(evpn));
- else
- memset(&evpn, 0, sizeof(evpn));
+ bre = bgp_attr_get_evpn_overlay(pi->attr);
bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd,
- label_pnt, num_labels, 1, &evpn);
+ label_pnt, num_labels, 1, bre);
}
static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
@@ -6218,7 +6279,6 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
vpn_leak_to_vrf_withdraw(pi);
bgp_rib_remove(rm, pi, peer, afi, safi);
- break;
}
}
} else {
@@ -6247,7 +6307,6 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
pi);
bgp_rib_remove(dest, pi, peer, afi, safi);
- break;
}
}
}
@@ -6405,16 +6464,21 @@ void bgp_cleanup_routes(struct bgp *bgp)
if (afi != AFI_L2VPN) {
safi_t safi;
safi = SAFI_MPLS_VPN;
- for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
- dest = bgp_route_next(dest)) {
- table = bgp_dest_get_bgp_table_info(dest);
- if (table != NULL) {
- bgp_cleanup_table(bgp, table, afi, safi);
- bgp_table_finish(&table);
- bgp_dest_set_bgp_table_info(dest, NULL);
- dest = bgp_dest_unlock_node(dest);
-
- assert(dest);
+ if (!IS_BGP_INSTANCE_HIDDEN(bgp)) {
+ for (dest = bgp_table_top(bgp->rib[afi][safi]);
+ dest; dest = bgp_route_next(dest)) {
+ table = bgp_dest_get_bgp_table_info(
+ dest);
+ if (table != NULL) {
+ bgp_cleanup_table(bgp, table,
+ afi, safi);
+ bgp_table_finish(&table);
+ bgp_dest_set_bgp_table_info(dest,
+ NULL);
+ dest = bgp_dest_unlock_node(
+ dest);
+ assert(dest);
+ }
}
}
safi = SAFI_ENCAP;
@@ -6588,7 +6652,7 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
else
bgp_withdraw(peer, &p, addpath_id, afi, safi,
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
- NULL, 0, NULL);
+ NULL, 0);
/* Do not send BGP notification twice when maximum-prefix count
* overflow. */
@@ -6698,9 +6762,6 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
if (afi == AFI_IP)
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
- if (bgp_static->igpmetric)
- bgp_attr_set_aigp_metric(&attr, bgp_static->igpmetric);
-
if (bgp_static->atomic)
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
@@ -6719,15 +6780,25 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
if (afi == AFI_L2VPN) {
if (bgp_static->gatewayIp.family == AF_INET) {
- SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
- memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
+ struct bgp_route_evpn *bre =
+ XCALLOC(MTYPE_BGP_EVPN_OVERLAY,
+ sizeof(struct bgp_route_evpn));
+
+ SET_IPADDR_V4(&bre->gw_ip);
+ memcpy(&bre->gw_ip.ipaddr_v4,
&bgp_static->gatewayIp.u.prefix4,
IPV4_MAX_BYTELEN);
+ bgp_attr_set_evpn_overlay(&attr, bre);
} else if (bgp_static->gatewayIp.family == AF_INET6) {
- SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
- memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
+ struct bgp_route_evpn *bre =
+ XCALLOC(MTYPE_BGP_EVPN_OVERLAY,
+ sizeof(struct bgp_route_evpn));
+
+ SET_IPADDR_V6(&bre->gw_ip);
+ memcpy(&bre->gw_ip.ipaddr_v6,
&bgp_static->gatewayIp.u.prefix6,
IPV6_MAX_BYTELEN);
+ bgp_attr_set_evpn_overlay(&attr, bre);
}
memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
@@ -8955,9 +9026,6 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
attr.tag = tag;
- if (metric)
- bgp_attr_set_aigp_metric(&attr, metric);
-
afi = family2afi(p->family);
red = bgp_redist_lookup(bgp, afi, type, instance);
@@ -8967,16 +9035,15 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
/* Copy attribute for modification. */
attr_new = attr;
- if (red->redist_metric_flag) {
+ if (red->redist_metric_flag)
attr_new.med = red->redist_metric;
- bgp_attr_set_aigp_metric(&attr_new, red->redist_metric);
- }
/* Apply route-map. */
if (red->rmap.name) {
memset(&rmap_path, 0, sizeof(rmap_path));
rmap_path.peer = bgp->peer_self;
rmap_path.attr = &attr_new;
+ rmap_path.type = type;
SET_FLAG(bgp->peer_self->rmap_type,
PEER_RMAP_TYPE_REDISTRIBUTE);
@@ -10091,6 +10158,7 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
json_object *json_path = NULL;
json_object *json_nexthop = NULL;
json_object *json_overlay = NULL;
+ struct bgp_route_evpn *bre = NULL;
if (!path->extra)
return;
@@ -10156,12 +10224,14 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
}
}
- const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
-
- if (!json_path)
- vty_out(vty, "/%pIA", &eo->gw_ip);
- else
- json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
+ bre = bgp_attr_get_evpn_overlay(attr);
+ if (bre) {
+ if (!json_path)
+ vty_out(vty, "/%pIA", &bre->gw_ip);
+ else
+ json_object_string_addf(json_overlay, "gw", "%pIA",
+ &bre->gw_ip);
+ }
if (bgp_attr_get_ecommunity(attr)) {
char *mac = NULL;
@@ -10496,6 +10566,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
mpls_label_t label = MPLS_INVALID_LABEL;
struct bgp_path_info *bpi_ultimate =
bgp_get_imported_bpi_ultimate(path);
+ struct bgp_route_evpn *bre = bgp_attr_get_evpn_overlay(attr);
if (json_paths) {
json_path = json_object_new_object();
@@ -10522,12 +10593,10 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
}
}
- if (safi == SAFI_EVPN
- && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
+ if (safi == SAFI_EVPN && bre && bre->type == OVERLAY_INDEX_GATEWAY_IP) {
char gwip_buf[INET6_ADDRSTRLEN];
- ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
- sizeof(gwip_buf));
+ ipaddr2str(&bre->gw_ip, gwip_buf, sizeof(gwip_buf));
if (json_paths)
json_object_string_add(json_path, "gatewayIP",
@@ -10540,8 +10609,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
vty_out(vty, "\n");
- if (path->extra && path->extra->vrfleak &&
- path->extra->vrfleak->parent && !json_paths) {
+ if (path->extra && path->extra->vrfleak && path->extra->vrfleak->parent) {
struct bgp_path_info *parent_ri;
struct bgp_dest *dest, *pdest;
@@ -10551,31 +10619,68 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
if (dest && dest->pdest) {
pdest = dest->pdest;
if (is_pi_family_evpn(parent_ri)) {
- vty_out(vty, " Imported from ");
- vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
- (struct prefix_rd *)bgp_dest_get_prefix(
- pdest));
- vty_out(vty, ":%pFX, VNI %s",
- (struct prefix_evpn *)
- bgp_dest_get_prefix(dest),
- vni_buf);
- if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
+ if (json_paths) {
+ json_object_string_addf(
+ json_path, "importedFrom",
+ BGP_RD_AS_FORMAT(bgp->asnotation),
+ (struct prefix_rd *)
+ bgp_dest_get_prefix(
+ pdest));
+ if (safi != SAFI_EVPN)
+ json_object_string_add(json_path,
+ "vni",
+ vni_buf);
+ } else {
+ vty_out(vty, " Imported from ");
+ vty_out(vty,
+ BGP_RD_AS_FORMAT(bgp->asnotation),
+ (struct prefix_rd *)
+ bgp_dest_get_prefix(
+ pdest));
+ vty_out(vty, ":%pFX, VNI %s",
+ (struct prefix_evpn *)
+ bgp_dest_get_prefix(dest),
+ vni_buf);
+ }
+ if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG) &&
+ !json_paths) {
vty_out(vty, ", L3NHG %s",
CHECK_FLAG(
attr->es_flags,
ATTR_ES_L3_NHG_ACTIVE)
? "active"
: "inactive");
- vty_out(vty, "\n");
-
+ vty_out(vty, "\n");
+ } else if (json_paths) {
+ json_object_boolean_add(
+ json_path, "l3nhg",
+ CHECK_FLAG(attr->es_flags,
+ ATTR_ES_L3_NHG));
+ json_object_boolean_add(
+ json_path, "l3nhgActive",
+ CHECK_FLAG(attr->es_flags,
+ ATTR_ES_L3_NHG_ACTIVE));
+ }
} else {
- vty_out(vty, " Imported from ");
- vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
- (struct prefix_rd *)bgp_dest_get_prefix(
- pdest));
- vty_out(vty, ":%pFX\n",
- (struct prefix_evpn *)
- bgp_dest_get_prefix(dest));
+ if (json_paths) {
+ json_object_string_addf(
+ json_path, "importedFrom",
+ BGP_RD_AS_FORMAT(bgp->asnotation),
+ (struct prefix_rd *)
+ bgp_dest_get_prefix(
+ pdest));
+ } else {
+ vty_out(vty, " Imported from ");
+ vty_out(vty,
+ BGP_RD_AS_FORMAT(bgp->asnotation),
+ (struct prefix_rd *)
+ bgp_dest_get_prefix(
+ pdest));
+ vty_out(vty, ":%pFX\n",
+ (struct prefix_evpn *)
+ bgp_dest_get_prefix(
+ dest));
+ }
}
}
}
@@ -11085,9 +11190,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
vty_out(vty, ", otc %u", attr->otc);
}
- if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
- || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
- && bgp_path_info_mpath_count(path))) {
+ if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH) ||
+ (CHECK_FLAG(path->flags, BGP_PATH_SELECTED) && bgp_path_info_mpath_count(path) > 1)) {
if (json_paths)
json_object_boolean_true_add(json_path, "multipath");
else
@@ -11862,10 +11966,9 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t sa
if (!use_json)
route_vty_out_detail_header(
vty, bgp, dest,
- bgp_dest_get_prefix(
- dest),
+ bgp_dest_get_prefix(dest),
prd, table->afi, safi,
- NULL, false);
+ NULL, false, false);
route_vty_out_detail(
vty, bgp, dest, dest_p, pi,
@@ -11938,10 +12041,12 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t sa
prd = bgp_rd_from_dest(dest, safi);
- route_vty_out_detail_header(
- vty, bgp, dest,
- bgp_dest_get_prefix(dest), prd,
- table->afi, safi, json_paths, true);
+ route_vty_out_detail_header(vty, bgp, dest,
+ bgp_dest_get_prefix(
+ dest),
+ prd, table->afi,
+ safi, json_paths,
+ true, false);
vty_out(vty, "\"paths\": ");
json_detail_header_used = true;
@@ -12069,7 +12174,7 @@ static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
bgp = bgp_get_default();
}
- if (bgp == NULL) {
+ if (bgp == NULL || IS_BGP_INSTANCE_HIDDEN(bgp)) {
if (!use_json)
vty_out(vty, "No BGP process is configured\n");
else
@@ -12115,6 +12220,8 @@ static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
vty_out(vty, "{\n");
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ if (IS_BGP_INSTANCE_HIDDEN(bgp))
+ continue;
route_output = true;
if (use_json) {
if (!is_first)
@@ -12147,7 +12254,7 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
struct bgp_dest *dest, const struct prefix *p,
const struct prefix_rd *prd, afi_t afi,
safi_t safi, json_object *json,
- bool incremental_print)
+ bool incremental_print, bool local_table)
{
struct bgp_path_info *pi;
struct peer *peer;
@@ -12179,7 +12286,7 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
- has_valid_label = bgp_is_valid_label(&label);
+ has_valid_label = bgp_is_valid_label(&dest->local_label);
if (safi == SAFI_EVPN) {
if (!json) {
@@ -12365,8 +12472,14 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
json_object_object_add(json, "advertisedTo",
json_adv_to);
} else {
- if (!json && first)
- vty_out(vty, " Not advertised to any peer");
+ if (!json && first) {
+ if (!local_table)
+ vty_out(vty,
+ " Not advertised to any peer");
+ else
+ vty_out(vty,
+ " Local BGP table not advertised");
+ }
vty_out(vty, "\n");
}
}
@@ -12405,10 +12518,10 @@ static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
}
if (header) {
- route_vty_out_detail_header(
- vty, bgp, bgp_node,
- bgp_dest_get_prefix(bgp_node), pfx_rd, AFI_IP,
- safi, json_header, false);
+ route_vty_out_detail_header(vty, bgp, bgp_node,
+ bgp_dest_get_prefix(bgp_node),
+ pfx_rd, AFI_IP, safi,
+ json_header, false, false);
header = 0;
}
(*display)++;
@@ -12627,7 +12740,7 @@ static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
{
if (!bgp) {
bgp = bgp_get_default();
- if (!bgp) {
+ if (!bgp || IS_BGP_INSTANCE_HIDDEN(bgp)) {
if (!use_json)
vty_out(vty, "No BGP process is configured\n");
else
@@ -12878,7 +12991,7 @@ DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
struct json_object *json_afi_safi = NULL, *json = NULL;
bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
- &bgp, false);
+ &bgp, uj);
if (!idx)
return CMD_WARNING;
@@ -12916,7 +13029,7 @@ DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
struct json_object *json_afi_safi = NULL, *json = NULL;
bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
- &bgp, false);
+ &bgp, uj);
if (!idx)
return CMD_WARNING;
@@ -13579,6 +13692,8 @@ enum bgp_stats {
BGP_STATS_ASPATH_MAXSIZE,
BGP_STATS_ASPATH_TOTSIZE,
BGP_STATS_ASN_HIGHEST,
+ BGP_STATS_REDISTRIBUTED,
+ BGP_STATS_LOCAL_AGGREGATES,
BGP_STATS_MAX,
};
@@ -13608,6 +13723,8 @@ static const char *table_stats_strs[][2] = {
[BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
"averageAsPathSizeBytes"},
[BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
+ [BGP_STATS_REDISTRIBUTED] = {"Redistributed routes", "totalRedistributed"},
+ [BGP_STATS_LOCAL_AGGREGATES] = {"Local aggregates", "totalLocalAggregates"},
[BGP_STATS_MAX] = {NULL, NULL}
};
@@ -13657,6 +13774,15 @@ static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
ts->counts[BGP_STATS_AGGREGATES]++;
+ if (pi->peer == ts->table->bgp->peer_self) {
+ if (pi->sub_type == BGP_ROUTE_REDISTRIBUTE)
+ ts->counts[BGP_STATS_REDISTRIBUTED]++;
+
+ if ((pi->type == ZEBRA_ROUTE_BGP) &&
+ (pi->sub_type == BGP_ROUTE_AGGREGATE))
+ ts->counts[BGP_STATS_LOCAL_AGGREGATES]++;
+ }
+
/* as-path stats */
if (pi->attr->aspath) {
unsigned int hops = aspath_count_hops(pi->attr->aspath);
@@ -14272,7 +14398,7 @@ DEFUN (show_ip_bgp_vpn_all_route_prefix,
int idx = 0;
char *network = NULL;
struct bgp *bgp = bgp_get_default();
- if (!bgp) {
+ if (!bgp || IS_BGP_INSTANCE_HIDDEN(bgp)) {
vty_out(vty, "Can't find default instance\n");
return CMD_WARNING;
}
@@ -14387,7 +14513,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
struct bgp_adj_out *adj = NULL;
struct bgp_dest *dest;
struct bgp *bgp;
- struct attr attr;
+ struct attr attr, attr_unchanged;
int ret;
struct update_subgroup *subgrp;
struct peer_af *paf = NULL;
@@ -14567,6 +14693,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
}
attr = *ain->attr;
+ attr_unchanged = *ain->attr;
route_filtered = false;
/* Filter prefix using distribute list,
@@ -14622,9 +14749,8 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
json_ar, json_net,
"%pFX", rn_p);
} else
- route_vty_out_tmp(vty, bgp, dest, rn_p,
- &attr, safi, use_json,
- json_ar, wide);
+ route_vty_out_tmp(vty, bgp, dest, rn_p, &attr_unchanged,
+ safi, use_json, json_ar, wide);
bgp_attr_flush(&attr);
(*output_count)++;
}
@@ -15774,7 +15900,7 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
/* BGP structure lookup. */
if (view_name) {
bgp = bgp_lookup_by_name(view_name);
- if (bgp == NULL) {
+ if (bgp == NULL || IS_BGP_INSTANCE_HIDDEN(bgp)) {
vty_out(vty, "%% Can't find BGP instance %s\n",
view_name);
return CMD_WARNING;
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index efabbc79..d71bfd3e 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -313,6 +313,11 @@ struct bgp_path_info {
#define BGP_PATH_STALE (1 << 8)
#define BGP_PATH_REMOVED (1 << 9)
#define BGP_PATH_COUNTED (1 << 10)
+/*
+ * A BGP_PATH_MULTIPATH flag is not set on the best path
+ * it is set on every other node that is part of ECMP
+ * for that particular dest
+ */
#define BGP_PATH_MULTIPATH (1 << 11)
#define BGP_PATH_MULTIPATH_CHG (1 << 12)
#define BGP_PATH_RIB_ATTR_CHG (1 << 13)
@@ -322,6 +327,15 @@ struct bgp_path_info {
#define BGP_PATH_MPLSVPN_LABEL_NH (1 << 17)
#define BGP_PATH_MPLSVPN_NH_LABEL_BIND (1 << 18)
#define BGP_PATH_UNSORTED (1 << 19)
+/*
+ * BGP_PATH_MULTIPATH_NEW is set on those bgp_path_info
+ * nodes that we have decided should possibly be in the
+ * ecmp path for a particular dest. This flag is
+ * removed when the bgp_path_info's are looked at to
+ * decide on whether or not a bgp_path_info is on
+ * the actual ecmp path.
+ */
+#define BGP_PATH_MULTIPATH_NEW (1 << 20)
/* BGP route type. This can be static, RIP, OSPF, BGP etc. */
uint8_t type;
@@ -802,13 +816,22 @@ extern void bgp_update(struct peer *peer, const struct prefix *p,
extern void bgp_withdraw(struct peer *peer, const struct prefix *p,
uint32_t addpath_id, afi_t afi, safi_t safi, int type,
int sub_type, struct prefix_rd *prd,
- mpls_label_t *label, uint8_t num_labels,
- struct bgp_route_evpn *evpn);
+ mpls_label_t *label, uint8_t num_labels);
-/* for bgp_nexthop and bgp_damp */
+/*
+ * Add a route to be processed for bgp bestpath through the bgp
+ * workqueue. This route is added to the end of all other routes
+ * queued for processing
+ *
+ * bgp_process_early adds the route for processing at the beginning
+ * of the current queue for processing.
+ */
extern void bgp_process(struct bgp *bgp, struct bgp_dest *dest,
struct bgp_path_info *pi, afi_t afi, safi_t safi);
+extern void bgp_process_early(struct bgp *bgp, struct bgp_dest *dest,
+ struct bgp_path_info *pi, afi_t afi, safi_t safi);
+
/*
* Add an end-of-initial-update marker to the process queue. This is just a
* queue element with NULL bgp node.
@@ -904,7 +927,8 @@ extern void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
const struct prefix *p,
const struct prefix_rd *prd, afi_t afi,
safi_t safi, json_object *json,
- bool incremental_print);
+ bool incremental_print,
+ bool local_table);
extern void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
struct bgp_dest *bn, const struct prefix *p,
struct bgp_path_info *path, afi_t afi,
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 4895ddbc..61586ea9 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -251,7 +251,7 @@ route_match_peer(void *rule, const struct prefix *prefix, void *object)
peer = ((struct bgp_path_info *)object)->peer;
if (pc->interface) {
- if (!peer->conf_if || !peer->group)
+ if (!peer->conf_if && !peer->group)
return RMAP_NOMATCH;
if (peer->conf_if && strcmp(peer->conf_if, pc->interface) == 0)
@@ -680,9 +680,8 @@ route_match_address_prefix_list(void *rule, afi_t afi,
plist = prefix_list_lookup(afi, (char *)rule);
if (plist == NULL) {
if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
- zlog_debug(
- "%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
- __func__, (char *)rule);
+ zlog_debug("%s: Prefix List %s (%s) specified does not exist defaulting to NO_MATCH",
+ __func__, (char *)rule, afi2str(afi));
return RMAP_NOMATCH;
}
@@ -1237,6 +1236,8 @@ route_set_evpn_gateway_ip(void *rule, const struct prefix *prefix, void *object)
struct ipaddr *gw_ip = rule;
struct bgp_path_info *path;
struct prefix_evpn *evp;
+ struct bgp_route_evpn *bre = XCALLOC(MTYPE_BGP_EVPN_OVERLAY,
+ sizeof(struct bgp_route_evpn));
if (prefix->family != AF_EVPN)
return RMAP_OKAY;
@@ -1252,9 +1253,9 @@ route_set_evpn_gateway_ip(void *rule, const struct prefix *prefix, void *object)
path = object;
/* Set gateway-ip value. */
- path->attr->evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP;
- memcpy(&path->attr->evpn_overlay.gw_ip, &gw_ip->ip.addr,
- IPADDRSZ(gw_ip));
+ bre->type = OVERLAY_INDEX_GATEWAY_IP;
+ memcpy(&bre->gw_ip, &gw_ip->ip.addr, IPADDRSZ(gw_ip));
+ bgp_attr_set_evpn_overlay(path->attr, bre);
return RMAP_OKAY;
}
@@ -1991,10 +1992,9 @@ route_set_ip_nexthop(void *rule, const struct prefix *prefix, void *object)
SET_FLAG(path->attr->rmap_change_flags,
BATTR_RMAP_NEXTHOP_UNCHANGED);
} else if (rins->peer_address) {
- if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
- || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
- && peer->su_remote
- && sockunion_family(peer->su_remote) == AF_INET) {
+ if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)) &&
+ peer->su_remote &&
+ sockunion_family(peer->su_remote) == AF_INET) {
path->attr->nexthop.s_addr =
sockunion2ip(peer->su_remote);
path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
@@ -3220,7 +3220,7 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
return RMAP_OKAY;
bw_bytes = (peer->bgp->lb_ref_bw * 1000 * 1000) / 8;
- mpath_count = bgp_path_info_mpath_count(path) + 1;
+ mpath_count = bgp_path_info_mpath_count(path);
bw_bytes *= mpath_count;
}
@@ -3451,19 +3451,15 @@ route_set_aigp_metric(void *rule, const struct prefix *pfx, void *object)
{
const char *aigp_metric = rule;
struct bgp_path_info *path = object;
- uint32_t aigp = 0;
-
- if (strmatch(aigp_metric, "igp-metric")) {
- if (!path->nexthop)
- return RMAP_NOMATCH;
+ uint32_t aigp;
- bgp_attr_set_aigp_metric(path->attr, path->nexthop->metric);
- } else {
+ /* Note: the metric is stored as MED for a locally redistributed. */
+ if (strmatch(aigp_metric, "igp-metric"))
+ aigp = path->nexthop ? path->nexthop->metric : path->attr->med;
+ else
aigp = atoi(aigp_metric);
- bgp_attr_set_aigp_metric(path->attr, aigp);
- }
- path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AIGP);
+ bgp_attr_set_aigp_metric(path->attr, aigp);
return RMAP_OKAY;
}
@@ -3949,8 +3945,7 @@ route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
path = object;
peer = path->peer;
- if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
- || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) {
+ if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)) {
/* Set next hop preference to global */
SET_FLAG(path->attr->nh_flags, BGP_ATTR_NH_MP_PREFER_GLOBAL);
SET_FLAG(path->attr->rmap_change_flags,
@@ -4076,10 +4071,8 @@ route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx, void *object)
path = object;
peer = path->peer;
- if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
- || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
- && peer->su_remote
- && sockunion_family(peer->su_remote) == AF_INET6) {
+ if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)) &&
+ peer->su_remote && sockunion_family(peer->su_remote) == AF_INET6) {
peer_address = peer->su_remote->sin6.sin6_addr;
/* Set next hop value and length in attribute. */
if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
@@ -4094,7 +4087,6 @@ route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx, void *object)
path->attr->mp_nexthop_len =
BGP_ATTR_NHLEN_IPV6_GLOBAL;
}
-
} else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
/* The next hop value will be set as part of packet
* rewrite.
@@ -7144,7 +7136,7 @@ DEFUN_YANG (no_set_atomic_aggregate,
DEFPY_YANG (set_aigp_metric,
set_aigp_metric_cmd,
- "set aigp-metric <igp-metric|(1-4294967295)>$aigp_metric",
+ "set aigp-metric <igp-metric|(0-4294967295)>$aigp_metric",
SET_STR
"BGP AIGP attribute (AIGP Metric TLV)\n"
"AIGP Metric value from IGP protocol\n"
@@ -7164,7 +7156,7 @@ DEFPY_YANG (set_aigp_metric,
DEFPY_YANG (no_set_aigp_metric,
no_set_aigp_metric_cmd,
- "no set aigp-metric [<igp-metric|(1-4294967295)>]",
+ "no set aigp-metric [<igp-metric|(0-4294967295)>]",
NO_STR
SET_STR
"BGP AIGP attribute (AIGP Metric TLV)\n"
@@ -7236,43 +7228,6 @@ DEFUN_YANG (no_set_aggregator_as,
return nb_cli_apply_changes(vty, NULL);
}
-DEFUN_YANG (match_ipv6_next_hop,
- match_ipv6_next_hop_cmd,
- "match ipv6 next-hop ACCESSLIST6_NAME",
- MATCH_STR
- IPV6_STR
- "Match IPv6 next-hop address of route\n"
- "IPv6 access-list name\n")
-{
- const char *xpath =
- "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
- char xpath_value[XPATH_MAXLEN];
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
- snprintf(xpath_value, sizeof(xpath_value),
- "%s/rmap-match-condition/list-name", xpath);
- nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
- argv[argc - 1]->arg);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFUN_YANG (no_match_ipv6_next_hop,
- no_match_ipv6_next_hop_cmd,
- "no match ipv6 next-hop [ACCESSLIST6_NAME]",
- NO_STR
- MATCH_STR
- IPV6_STR
- "Match IPv6 next-hop address of route\n"
- "IPv6 access-list name\n")
-{
- const char *xpath =
- "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
- return nb_cli_apply_changes(vty, NULL);
-}
-
DEFUN_YANG (match_ipv6_next_hop_address,
match_ipv6_next_hop_address_cmd,
"match ipv6 next-hop address X:X::X:X",
@@ -7330,45 +7285,6 @@ ALIAS_HIDDEN (no_match_ipv6_next_hop_address,
"Match IPv6 next-hop address of route\n"
"IPv6 address of next hop\n")
-DEFUN_YANG (match_ipv6_next_hop_prefix_list,
- match_ipv6_next_hop_prefix_list_cmd,
- "match ipv6 next-hop prefix-list PREFIXLIST_NAME",
- MATCH_STR
- IPV6_STR
- "Match IPv6 next-hop address of route\n"
- "Match entries by prefix-list\n"
- "IPv6 prefix-list name\n")
-{
- const char *xpath =
- "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
- char xpath_value[XPATH_MAXLEN];
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
- snprintf(xpath_value, sizeof(xpath_value),
- "%s/rmap-match-condition/list-name", xpath);
- nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
- argv[argc - 1]->arg);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFUN_YANG (no_match_ipv6_next_hop_prefix_list,
- no_match_ipv6_next_hop_prefix_list_cmd,
- "no match ipv6 next-hop prefix-list [PREFIXLIST_NAME]",
- NO_STR
- MATCH_STR
- IPV6_STR
- "Match IPv6 next-hop address of route\n"
- "Match entries by prefix-list\n"
- "IPv6 prefix-list name\n")
-{
- const char *xpath =
- "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
- return nb_cli_apply_changes(vty, NULL);
-}
-
DEFPY_YANG (match_ipv4_next_hop,
match_ipv4_next_hop_cmd,
"match ip next-hop address A.B.C.D",
@@ -8041,12 +7957,8 @@ void bgp_route_map_init(void)
route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
route_map_install_match(&route_match_rpki_extcommunity_cmd);
- install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
install_element(RMAP_NODE, &match_ipv6_next_hop_address_cmd);
- install_element(RMAP_NODE, &match_ipv6_next_hop_prefix_list_cmd);
- install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
install_element(RMAP_NODE, &no_match_ipv6_next_hop_address_cmd);
- install_element(RMAP_NODE, &no_match_ipv6_next_hop_prefix_list_cmd);
install_element(RMAP_NODE, &match_ipv6_next_hop_old_cmd);
install_element(RMAP_NODE, &no_match_ipv6_next_hop_old_cmd);
install_element(RMAP_NODE, &match_ipv4_next_hop_cmd);
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index f9cbf240..347c5d02 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -1920,81 +1920,6 @@ DEFUN (no_rpki_retry_interval,
return CMD_SUCCESS;
}
-#if CONFDATE > 20240916
-CPP_NOTICE("Remove rpki_cache_cmd")
-#endif
-DEFPY(rpki_cache, rpki_cache_cmd,
- "rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY [KNOWN_HOSTS_PATH]> [source <A.B.C.D>$bindaddr] preference (1-255)",
- RPKI_OUTPUT_STRING
- "Install a cache server to current group\n"
- "IP address of cache server\n"
- "Hostname of cache server\n"
- "TCP port number\n"
- "SSH port number\n"
- "SSH user name\n"
- "Path to own SSH private key\n"
- "Path to the known hosts file\n"
- "Configure source IP address of RPKI connection\n"
- "Define a Source IP Address\n"
- "Preference of the cache server\n"
- "Preference value\n")
-{
- int return_value;
- struct listnode *cache_node;
- struct cache *current_cache;
- struct rpki_vrf *rpki_vrf;
- bool init;
-
- if (vty->node == RPKI_VRF_NODE)
- rpki_vrf = VTY_GET_CONTEXT_SUB(rpki_vrf);
- else
- rpki_vrf = VTY_GET_CONTEXT(rpki_vrf);
-
- if (!rpki_vrf)
- return CMD_WARNING_CONFIG_FAILED;
-
- if (!rpki_vrf || !rpki_vrf->cache_list)
- return CMD_WARNING;
-
- init = !!list_isempty(rpki_vrf->cache_list);
-
- for (ALL_LIST_ELEMENTS_RO(rpki_vrf->cache_list, cache_node,
- current_cache)) {
- if (current_cache->preference == preference) {
- vty_out(vty,
- "Cache with preference %ld is already configured\n",
- preference);
- return CMD_WARNING;
- }
- }
-
- // use ssh connection
- if (ssh_uname) {
-#if defined(FOUND_SSH)
- return_value = add_ssh_cache(rpki_vrf, cache, sshport, ssh_uname,
- ssh_privkey, known_hosts_path,
- preference, bindaddr_str);
-#else
- return_value = SUCCESS;
- vty_out(vty,
- "ssh sockets are not supported. Please recompile rtrlib and frr with ssh support. If you want to use it\n");
-#endif
- } else { // use tcp connection
- return_value = add_tcp_cache(rpki_vrf, cache, tcpport,
- preference, bindaddr_str);
- }
-
- if (return_value == ERROR) {
- vty_out(vty, "Could not create new rpki cache\n");
- return CMD_WARNING;
- }
-
- if (init)
- start(rpki_vrf);
-
- return CMD_SUCCESS;
-}
-
DEFPY(rpki_cache_tcp, rpki_cache_tcp_cmd,
"rpki cache tcp <A.B.C.D|WORD>$cache TCPPORT [source <A.B.C.D>$bindaddr] preference (1-255)",
RPKI_OUTPUT_STRING
@@ -2820,7 +2745,6 @@ static void install_cli_commands(void)
/* Install rpki cache commands */
install_element(RPKI_NODE, &rpki_cache_tcp_cmd);
install_element(RPKI_NODE, &rpki_cache_ssh_cmd);
- install_element(RPKI_NODE, &rpki_cache_cmd);
install_element(RPKI_NODE, &no_rpki_cache_cmd);
/* RPKI_VRF_NODE commands */
@@ -2844,7 +2768,6 @@ static void install_cli_commands(void)
/* Install rpki cache commands */
install_element(RPKI_VRF_NODE, &rpki_cache_tcp_cmd);
install_element(RPKI_VRF_NODE, &rpki_cache_ssh_cmd);
- install_element(RPKI_VRF_NODE, &rpki_cache_cmd);
install_element(RPKI_VRF_NODE, &no_rpki_cache_cmd);
/* Install show commands */
diff --git a/bgpd/bgp_script.h b/bgpd/bgp_script.h
index f2f47e94..9feb5501 100644
--- a/bgpd/bgp_script.h
+++ b/bgpd/bgp_script.h
@@ -7,7 +7,6 @@
#define __BGP_SCRIPT__
#include <zebra.h>
-#include "bgpd.h"
#ifdef HAVE_SCRIPTING
@@ -18,6 +17,10 @@
*/
void bgp_script_init(void);
+/* Forward references */
+struct peer;
+struct attr;
+
void lua_pushpeer(lua_State *L, const struct peer *peer);
void lua_pushattr(lua_State *L, const struct attr *attr);
diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c
index 065ea767..eff7c5e0 100644
--- a/bgpd/bgp_snmp.c
+++ b/bgpd/bgp_snmp.c
@@ -50,6 +50,21 @@ DEFPY(bgp_snmp_traps_rfc4273, bgp_snmp_traps_rfc4273_cmd,
return CMD_SUCCESS;
}
+DEFPY(bgp_snmp_traps_rfc4382, bgp_snmp_traps_rfc4382_cmd,
+ "[no$no] bgp snmp traps rfc4382",
+ NO_STR BGP_STR
+ "Configure BGP SNMP\n"
+ "Configure SNMP traps for BGP\n"
+ "Configure use of rfc4382 SNMP traps for BGP\n")
+{
+ if (no) {
+ UNSET_FLAG(bm->options, BGP_OPT_TRAPS_RFC4382);
+ return CMD_SUCCESS;
+ }
+ SET_FLAG(bm->options, BGP_OPT_TRAPS_RFC4382);
+ return CMD_SUCCESS;
+}
+
DEFPY(bgp_snmp_traps_bgp4_mibv2, bgp_snmp_traps_bgp4_mibv2_cmd,
"[no$no] bgp snmp traps bgp4-mibv2",
NO_STR BGP_STR
@@ -69,9 +84,12 @@ static void bgp_snmp_traps_init(void)
{
install_element(CONFIG_NODE, &bgp_snmp_traps_rfc4273_cmd);
install_element(CONFIG_NODE, &bgp_snmp_traps_bgp4_mibv2_cmd);
+ install_element(CONFIG_NODE, &bgp_snmp_traps_rfc4382_cmd);
SET_FLAG(bm->options, BGP_OPT_TRAPS_RFC4273);
/* BGP4MIBv2 traps are disabled by default */
+
+ SET_FLAG(bm->options, BGP_OPT_TRAPS_RFC4382);
}
int bgp_cli_snmp_traps_config_write(struct vty *vty)
@@ -86,6 +104,10 @@ int bgp_cli_snmp_traps_config_write(struct vty *vty)
vty_out(vty, "bgp snmp traps bgp4-mibv2\n");
write++;
}
+ if (!CHECK_FLAG(bm->options, BGP_OPT_TRAPS_RFC4382)) {
+ vty_out(vty, "no bgp snmp traps rfc4382\n");
+ write++;
+ }
return write;
}
diff --git a/bgpd/bgp_snmp_bgp4v2.c b/bgpd/bgp_snmp_bgp4v2.c
index e8c3e651..5f36e298 100644
--- a/bgpd/bgp_snmp_bgp4v2.c
+++ b/bgpd/bgp_snmp_bgp4v2.c
@@ -933,7 +933,9 @@ static uint8_t *bgp4v2PathAttrTable(struct variable *v, oid name[],
else
return SNMP_IPADDRESS(bgp_empty_addr);
case BGP4V2_NLRI_AS_PATH_CALC_LENGTH:
- return SNMP_INTEGER(path->attr->aspath->segments->length);
+ return SNMP_INTEGER((path->attr->aspath && path->attr->aspath->segments)
+ ? path->attr->aspath->segments->length
+ : 0);
case BGP4V2_NLRI_AS_PATH:
return aspath_snmp_pathseg(path->attr->aspath, var_len);
case BGP4V2_NLRI_PATH_ATTR_UNKNOWN:
diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c
index 124e7a38..90c43b93 100644
--- a/bgpd/bgp_updgrp.c
+++ b/bgpd/bgp_updgrp.c
@@ -343,7 +343,12 @@ static unsigned int updgrp_hash_key_make(const void *p)
key = 0;
- key = jhash_1word(peer->sort, key); /* EBGP or IBGP */
+ /* `remote-as auto` technically uses identical peer->sort.
+ * After OPEN message is parsed, this is updated accordingly, but
+ * we need to call the peer_sort() here also to properly create
+ * separate subgroups.
+ */
+ key = jhash_1word(peer_sort((struct peer *)peer), key);
key = jhash_1word(peer->sub_sort, key); /* OAD */
key = jhash_1word((peer->flags & PEER_UPDGRP_FLAGS), key);
key = jhash_1word((flags & PEER_UPDGRP_AF_FLAGS), key);
@@ -778,8 +783,11 @@ static int update_group_show_walkcb(struct update_group *updgrp, void *arg)
json_updgrp, "replaceLocalAs",
CHECK_FLAG(updgrp->conf->flags,
PEER_FLAG_LOCAL_AS_REPLACE_AS));
+ json_object_boolean_add(json_updgrp, "dualAs",
+ CHECK_FLAG(updgrp->conf->flags,
+ PEER_FLAG_DUAL_AS));
} else {
- vty_out(vty, " Local AS %u%s%s\n",
+ vty_out(vty, " Local AS %u%s%s%s\n",
updgrp->conf->change_local_as,
CHECK_FLAG(updgrp->conf->flags,
PEER_FLAG_LOCAL_AS_NO_PREPEND)
@@ -788,6 +796,10 @@ static int update_group_show_walkcb(struct update_group *updgrp, void *arg)
CHECK_FLAG(updgrp->conf->flags,
PEER_FLAG_LOCAL_AS_REPLACE_AS)
? " replace-as"
+ : "",
+ CHECK_FLAG(updgrp->conf->flags,
+ PEER_FLAG_DUAL_AS)
+ ? " dual-as"
: "");
}
}
@@ -2011,6 +2023,8 @@ int update_group_adjust_soloness(struct peer *peer, int set)
struct peer_group *group;
struct listnode *node, *nnode;
+ peer_flag_set(peer, PEER_FLAG_LONESOUL);
+
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
peer_lonesoul_or_not(peer, set);
if (peer_established(peer->connection))
diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c
index 534bb752..3ce136ef 100644
--- a/bgpd/bgp_updgrp_packet.c
+++ b/bgpd/bgp_updgrp_packet.c
@@ -738,9 +738,9 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
/* 5: Encode all the attributes, except MP_REACH_NLRI
* attr. */
- total_attr_len = bgp_packet_attribute(
- NULL, peer, s, adv->baa->attr, &vecarr, NULL,
- afi, safi, from, NULL, NULL, 0, 0, 0, path);
+ total_attr_len = bgp_packet_attribute(NULL, peer, s, adv->baa->attr,
+ &vecarr, NULL, afi, safi, from, NULL,
+ NULL, 0, 0, 0);
space_remaining =
STREAM_CONCAT_REMAIN(s, snlri, STREAM_SIZE(s))
@@ -861,7 +861,8 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
bgp_debug_rdpfxpath2str(afi, safi, prd, dest_p,
label_pnt, num_labels,
addpath_capable, addpath_tx_id,
- &adv->baa->attr->evpn_overlay,
+ bgp_attr_get_evpn_overlay(
+ adv->baa->attr),
pfx_buf, sizeof(pfx_buf));
zlog_debug("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s",
subgrp->update_group->id, subgrp->id,
@@ -1148,12 +1149,9 @@ void subgroup_default_update_packet(struct update_subgroup *subgrp,
/* Make place for total attribute length. */
pos = stream_get_endp(s);
stream_putw(s, 0);
- total_attr_len =
- bgp_packet_attribute(NULL, peer, s, attr, &vecarr, &p, afi,
- safi, from, NULL, &label, num_labels,
- addpath_capable,
- BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE,
- NULL);
+ total_attr_len = bgp_packet_attribute(NULL, peer, s, attr, &vecarr, &p, afi, safi, from,
+ NULL, &label, num_labels, addpath_capable,
+ BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
/* Set Total Path Attribute Length. */
stream_putw_at(s, pos, total_attr_len);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 1a87799a..68ced14d 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -302,18 +302,11 @@ static const char *get_afi_safi_json_str(afi_t afi, safi_t safi)
/* unset srv6 locator */
static int bgp_srv6_locator_unset(struct bgp *bgp)
{
- int ret;
struct listnode *node, *nnode;
struct srv6_locator_chunk *chunk;
struct bgp_srv6_function *func;
struct bgp *bgp_vrf;
- /* release chunk notification via ZAPI */
- ret = bgp_zebra_srv6_manager_release_locator_chunk(
- bgp->srv6_locator_name);
- if (ret < 0)
- return -1;
-
/* refresh chunks */
for (ALL_LIST_ELEMENTS(bgp->srv6_locator_chunks, node, nnode, chunk)) {
listnode_delete(bgp->srv6_locator_chunks, chunk);
@@ -352,20 +345,28 @@ static int bgp_srv6_locator_unset(struct bgp *bgp)
continue;
/* refresh vpnv4 tovpn_sid_locator */
- srv6_locator_chunk_free(
- &bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator);
+ srv6_locator_free(bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator);
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator = NULL;
/* refresh vpnv6 tovpn_sid_locator */
- srv6_locator_chunk_free(
- &bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator);
+ srv6_locator_free(
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator);
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator = NULL;
/* refresh per-vrf tovpn_sid_locator */
- srv6_locator_chunk_free(&bgp_vrf->tovpn_sid_locator);
+ srv6_locator_free(bgp_vrf->tovpn_sid_locator);
+ bgp_vrf->tovpn_sid_locator = NULL;
}
/* clear locator name */
memset(bgp->srv6_locator_name, 0, sizeof(bgp->srv6_locator_name));
+ /* clear SRv6 locator */
+ if (bgp->srv6_locator) {
+ srv6_locator_free(bgp->srv6_locator);
+ bgp->srv6_locator = NULL;
+ }
+
return 0;
}
@@ -878,6 +879,7 @@ int bgp_vty_return(struct vty *vty, enum bgp_create_error_code ret)
switch (ret) {
case BGP_SUCCESS:
case BGP_CREATED:
+ case BGP_INSTANCE_EXISTS:
case BGP_GR_NO_OPERATION:
break;
case BGP_ERR_INVALID_VALUE:
@@ -1417,7 +1419,7 @@ DEFUN_HIDDEN (bgp_local_mac,
seq = strtoul(argv[7]->arg, NULL, 10);
bgp = bgp_get_default();
- if (!bgp) {
+ if (!bgp || IS_BGP_INSTANCE_HIDDEN(bgp)) {
vty_out(vty, "Default BGP instance is not there\n");
return CMD_WARNING;
}
@@ -1457,7 +1459,7 @@ DEFUN_HIDDEN (no_bgp_local_mac,
memset(&ip, 0, sizeof(ip));
bgp = bgp_get_default();
- if (!bgp) {
+ if (!bgp || IS_BGP_INSTANCE_HIDDEN(bgp)) {
vty_out(vty, "Default BGP instance is not there\n");
return CMD_WARNING;
}
@@ -1600,8 +1602,12 @@ DEFUN_NOSH (router_bgp,
if (is_new_bgp && inst_type == BGP_INSTANCE_TYPE_DEFAULT)
vpn_leak_postchange_all();
- if (inst_type == BGP_INSTANCE_TYPE_VRF)
+ if (inst_type == BGP_INSTANCE_TYPE_VRF ||
+ IS_BGP_INSTANCE_HIDDEN(bgp)) {
bgp_vpn_leak_export(bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_INSTANCE_HIDDEN);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS);
+ }
/* Pending: handle when user tries to change a view to vrf n vv.
*/
/* for pre-existing bgp instance,
@@ -1673,7 +1679,7 @@ DEFUN (no_router_bgp,
argv[idx_asn]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
- if (argc > 4) {
+ if (argc > 4 && strncmp(argv[4]->arg, "vrf", 3) == 0) {
name = argv[idx_vrf]->arg;
if (strmatch(argv[idx_vrf - 1]->text, "vrf")
&& strmatch(name, VRF_DEFAULT_NAME))
@@ -1695,15 +1701,18 @@ DEFUN (no_router_bgp,
/* Cannot delete default instance if vrf instances exist */
if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
- struct listnode *node;
+ struct listnode *node, *nnode;
struct bgp *tmp_bgp;
- for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, tmp_bgp)) {
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, tmp_bgp)) {
if (tmp_bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
continue;
- if (CHECK_FLAG(tmp_bgp->vrf_flags, BGP_VRF_AUTO))
+ if (CHECK_FLAG(tmp_bgp->vrf_flags,
+ BGP_VRF_AUTO)) {
bgp_delete(tmp_bgp);
+ continue;
+ }
if (CHECK_FLAG(
tmp_bgp->af_flags[AFI_IP]
@@ -2267,9 +2276,9 @@ static int bgp_global_update_delay_config_vty(struct vty *vty,
* Note that we only need to check this if this is the first time
* setting the global config.
*/
- if (bm->v_update_delay == BGP_UPDATE_DELAY_DEF) {
+ if (bm->v_update_delay == BGP_UPDATE_DELAY_DEFAULT) {
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
- if (bgp->v_update_delay != BGP_UPDATE_DELAY_DEF) {
+ if (bgp->v_update_delay != BGP_UPDATE_DELAY_DEFAULT) {
vty_out(vty,
"%% update-delay configuration found in vrf %s\n",
bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
@@ -2314,7 +2323,7 @@ static int bgp_global_update_delay_deconfig_vty(struct vty *vty)
struct listnode *node, *nnode;
struct bgp *bgp;
- bm->v_update_delay = BGP_UPDATE_DELAY_DEF;
+ bm->v_update_delay = BGP_UPDATE_DELAY_DEFAULT;
bm->v_establish_wait = bm->v_update_delay;
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
@@ -2368,7 +2377,7 @@ static int bgp_update_delay_deconfig_vty(struct vty *vty)
"%%Failed: bgp update-delay configured globally. Delete per-vrf not permitted\n");
return CMD_WARNING_CONFIG_FAILED;
}
- bgp->v_update_delay = BGP_UPDATE_DELAY_DEF;
+ bgp->v_update_delay = BGP_UPDATE_DELAY_DEFAULT;
bgp->v_establish_wait = bgp->v_update_delay;
return CMD_SUCCESS;
@@ -2928,11 +2937,10 @@ DEFUN(bgp_reject_as_sets, bgp_reject_as_sets_cmd,
* with aspath containing AS_SET or AS_CONFED_SET.
*/
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
- peer->last_reset = PEER_DOWN_AS_SETS_REJECT;
+ peer->last_reset = PEER_DOWN_AS_SETS_REJECT;
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- }
}
return CMD_SUCCESS;
@@ -2954,11 +2962,10 @@ DEFUN(no_bgp_reject_as_sets, no_bgp_reject_as_sets_cmd,
* with aspath containing AS_SET or AS_CONFED_SET.
*/
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
- peer->last_reset = PEER_DOWN_AS_SETS_REJECT;
+ peer->last_reset = PEER_DOWN_AS_SETS_REJECT;
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- }
}
return CMD_SUCCESS;
@@ -3023,6 +3030,98 @@ DEFUN (no_bgp_deterministic_med,
return CMD_SUCCESS;
}
+static int bgp_inst_gr_config_vty(struct vty *vty, struct bgp *bgp, bool on,
+ bool disable)
+{
+ int ret = BGP_GR_FAILURE;
+
+ /*
+ * Update the instance and all its peers, if appropriate.
+ * Then, inform zebra of BGP's GR capabilities, if needed.
+ */
+ if (disable)
+ ret = bgp_gr_update_all(bgp, on ? GLOBAL_DISABLE_CMD
+ : NO_GLOBAL_DISABLE_CMD);
+ else
+ ret = bgp_gr_update_all(bgp,
+ on ? GLOBAL_GR_CMD : NO_GLOBAL_GR_CMD);
+
+ VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer,
+ ret);
+ return ret;
+}
+
+static int bgp_global_gr_config_vty(struct vty *vty, bool on, bool disable)
+{
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+ bool vrf_cfg = false;
+ int ret = BGP_GR_FAILURE;
+
+ if (disable) {
+ if ((on && CHECK_FLAG(bm->flags, BM_FLAG_GR_DISABLED)) ||
+ (!on && !CHECK_FLAG(bm->flags, BM_FLAG_GR_DISABLED)))
+ return CMD_SUCCESS;
+ } else {
+ if ((on && CHECK_FLAG(bm->flags, BM_FLAG_GR_RESTARTER)) ||
+ (!on && !CHECK_FLAG(bm->flags, BM_FLAG_GR_RESTARTER)))
+ return CMD_SUCCESS;
+ }
+
+ /* See if GR is set per-vrf and warn user to delete */
+ if (!CHECK_FLAG(bm->flags, BM_FLAG_GR_CONFIGURED)) {
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ enum global_mode gr_mode = bgp_global_gr_mode_get(bgp);
+
+ if (gr_mode != GLOBAL_HELPER) {
+ vty_out(vty,
+ "%% graceful-restart configuration found in %s, mode %d\n",
+ bgp->name_pretty, gr_mode);
+ vrf_cfg = true;
+ }
+ }
+ }
+
+ if (vrf_cfg) {
+ vty_out(vty,
+ "%%Failed: global graceful-restart not permitted with per-vrf configuration\n");
+ return CMD_WARNING;
+ }
+
+ /* Set flag globally */
+ if (on) {
+ if (disable) {
+ UNSET_FLAG(bm->flags, BM_FLAG_GR_RESTARTER);
+ SET_FLAG(bm->flags, BM_FLAG_GR_DISABLED);
+ } else {
+ SET_FLAG(bm->flags, BM_FLAG_GR_RESTARTER);
+ UNSET_FLAG(bm->flags, BM_FLAG_GR_DISABLED);
+ }
+ } else {
+ if (disable)
+ UNSET_FLAG(bm->flags, BM_FLAG_GR_DISABLED);
+ else
+ UNSET_FLAG(bm->flags, BM_FLAG_GR_RESTARTER);
+ }
+
+ /* Initiate processing for all BGP instances. */
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ ret = bgp_inst_gr_config_vty(vty, bgp, on, disable);
+ if (ret != BGP_GR_SUCCESS)
+ vty_out(vty,
+ "%% Applying global graceful-restart %s config to vrf %s failed, error %d\n",
+ (disable) ? "disable" : "",
+ bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
+ ? "Default"
+ : bgp->name,
+ ret);
+ }
+
+ vty_out(vty,
+ "Graceful restart configuration changed, reset all peers to take effect\n");
+ return bgp_vty_return(vty, ret);
+}
+
/* "bgp graceful-restart mode" configuration. */
DEFUN (bgp_graceful_restart,
bgp_graceful_restart_cmd,
@@ -3031,25 +3130,18 @@ DEFUN (bgp_graceful_restart,
GR_CMD
)
{
- int ret = BGP_GR_FAILURE;
-
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("[BGP_GR] bgp_graceful_restart_cmd : START ");
+ if (vty->node == CONFIG_NODE)
+ return bgp_global_gr_config_vty(vty, true, false);
+ int ret = BGP_GR_FAILURE;
VTY_DECLVAR_CONTEXT(bgp, bgp);
- ret = bgp_gr_update_all(bgp, GLOBAL_GR_CMD);
+ ret = bgp_inst_gr_config_vty(vty, bgp, true, false);
if (ret == BGP_GR_SUCCESS) {
- VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
- bgp->peer,
- ret);
vty_out(vty,
"Graceful restart configuration changed, reset all peers to take effect\n");
}
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("[BGP_GR] bgp_graceful_restart_cmd : END ");
-
return bgp_vty_return(vty, ret);
}
@@ -3061,14 +3153,13 @@ DEFUN (no_bgp_graceful_restart,
NO_GR_CMD
)
{
- VTY_DECLVAR_CONTEXT(bgp, bgp);
-
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("[BGP_GR] no_bgp_graceful_restart_cmd : START ");
+ if (vty->node == CONFIG_NODE)
+ return bgp_global_gr_config_vty(vty, false, false);
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
int ret = BGP_GR_FAILURE;
- ret = bgp_gr_update_all(bgp, NO_GLOBAL_GR_CMD);
+ ret = bgp_inst_gr_config_vty(vty, bgp, false, false);
if (ret == BGP_GR_SUCCESS) {
VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
bgp->peer,
@@ -3077,9 +3168,6 @@ DEFUN (no_bgp_graceful_restart,
"Graceful restart configuration changed, reset all peers to take effect\n");
}
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("[BGP_GR] no_bgp_graceful_restart_cmd : END ");
-
return bgp_vty_return(vty, ret);
}
@@ -3091,12 +3179,21 @@ DEFUN (bgp_graceful_restart_stalepath_time,
"Set the max time to hold onto restarting peer's stale paths\n"
"Delay value (seconds)\n")
{
- VTY_DECLVAR_CONTEXT(bgp, bgp);
int idx_number = 3;
uint32_t stalepath;
stalepath = strtoul(argv[idx_number]->arg, NULL, 10);
- bgp->stalepath_time = stalepath;
+ if (vty->node == CONFIG_NODE) {
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+
+ bm->stalepath_time = stalepath;
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
+ bgp->stalepath_time = stalepath;
+ } else {
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp->stalepath_time = stalepath;
+ }
return CMD_SUCCESS;
}
@@ -3108,20 +3205,32 @@ DEFUN (bgp_graceful_restart_restart_time,
"Set the time to wait to delete stale routes before a BGP open message is received\n"
"Delay value (seconds)\n")
{
- VTY_DECLVAR_CONTEXT(bgp, bgp);
int idx_number = 3;
uint32_t restart;
struct listnode *node, *nnode;
struct peer *peer;
restart = strtoul(argv[idx_number]->arg, NULL, 10);
- bgp->restart_time = restart;
- for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
- bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
- CAPABILITY_CODE_RESTART,
- CAPABILITY_ACTION_SET);
+ if (vty->node == CONFIG_NODE) {
+ struct bgp *bgp;
+ bm->restart_time = restart;
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ bgp->restart_time = restart;
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_RESTART,
+ CAPABILITY_ACTION_SET);
+ }
+ } else {
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp->restart_time = restart;
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_RESTART,
+ CAPABILITY_ACTION_SET);
+ }
return CMD_SUCCESS;
}
@@ -3133,16 +3242,32 @@ DEFUN (bgp_graceful_restart_select_defer_time,
"Set the time to defer the BGP route selection after restart\n"
"Delay value (seconds, 0 - disable)\n")
{
- VTY_DECLVAR_CONTEXT(bgp, bgp);
int idx_number = 3;
uint32_t defer_time;
defer_time = strtoul(argv[idx_number]->arg, NULL, 10);
- bgp->select_defer_time = defer_time;
- if (defer_time == 0)
- SET_FLAG(bgp->flags, BGP_FLAG_SELECT_DEFER_DISABLE);
- else
- UNSET_FLAG(bgp->flags, BGP_FLAG_SELECT_DEFER_DISABLE);
+ if (vty->node == CONFIG_NODE) {
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+
+ bm->select_defer_time = defer_time;
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ bgp->select_defer_time = defer_time;
+ if (defer_time == 0)
+ SET_FLAG(bgp->flags,
+ BGP_FLAG_SELECT_DEFER_DISABLE);
+ else
+ UNSET_FLAG(bgp->flags,
+ BGP_FLAG_SELECT_DEFER_DISABLE);
+ }
+ } else {
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp->select_defer_time = defer_time;
+ if (defer_time == 0)
+ SET_FLAG(bgp->flags, BGP_FLAG_SELECT_DEFER_DISABLE);
+ else
+ UNSET_FLAG(bgp->flags, BGP_FLAG_SELECT_DEFER_DISABLE);
+ }
return CMD_SUCCESS;
}
@@ -3156,9 +3281,17 @@ DEFUN (no_bgp_graceful_restart_stalepath_time,
"Set the max time to hold onto restarting peer's stale paths\n"
"Delay value (seconds)\n")
{
- VTY_DECLVAR_CONTEXT(bgp, bgp);
+ if (vty->node == CONFIG_NODE) {
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
- bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
+ bm->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
+ bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
+ } else {
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
+ }
return CMD_SUCCESS;
}
@@ -3171,17 +3304,30 @@ DEFUN (no_bgp_graceful_restart_restart_time,
"Set the time to wait to delete stale routes before a BGP open message is received\n"
"Delay value (seconds)\n")
{
- VTY_DECLVAR_CONTEXT(bgp, bgp);
struct listnode *node, *nnode;
struct peer *peer;
- bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
+ if (vty->node == CONFIG_NODE) {
+ struct bgp *bgp;
- for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
- bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
- CAPABILITY_CODE_RESTART,
- CAPABILITY_ACTION_UNSET);
+ bm->restart_time = BGP_DEFAULT_RESTART_TIME;
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
+
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_RESTART,
+ CAPABILITY_ACTION_UNSET);
+ }
+ } else {
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_RESTART,
+ CAPABILITY_ACTION_UNSET);
+ }
return CMD_SUCCESS;
}
@@ -3194,10 +3340,21 @@ DEFUN (no_bgp_graceful_restart_select_defer_time,
"Set the time to defer the BGP route selection after restart\n"
"Delay value (seconds)\n")
{
- VTY_DECLVAR_CONTEXT(bgp, bgp);
+ if (vty->node == CONFIG_NODE) {
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
- bgp->select_defer_time = BGP_DEFAULT_SELECT_DEFERRAL_TIME;
- UNSET_FLAG(bgp->flags, BGP_FLAG_SELECT_DEFER_DISABLE);
+ bm->select_defer_time = BGP_DEFAULT_SELECT_DEFERRAL_TIME;
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ bgp->select_defer_time =
+ BGP_DEFAULT_SELECT_DEFERRAL_TIME;
+ UNSET_FLAG(bgp->flags, BGP_FLAG_SELECT_DEFER_DISABLE);
+ }
+ } else {
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp->select_defer_time = BGP_DEFAULT_SELECT_DEFERRAL_TIME;
+ UNSET_FLAG(bgp->flags, BGP_FLAG_SELECT_DEFER_DISABLE);
+ }
return CMD_SUCCESS;
}
@@ -3209,8 +3366,17 @@ DEFUN (bgp_graceful_restart_preserve_fw,
"Graceful restart capability parameters\n"
"Sets F-bit indication that fib is preserved while doing Graceful Restart\n")
{
- VTY_DECLVAR_CONTEXT(bgp, bgp);
- SET_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD);
+ if (vty->node == CONFIG_NODE) {
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+
+ SET_FLAG(bm->flags, BM_FLAG_GR_PRESERVE_FWD);
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
+ SET_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD);
+ } else {
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ SET_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD);
+ }
return CMD_SUCCESS;
}
@@ -3222,8 +3388,17 @@ DEFUN (no_bgp_graceful_restart_preserve_fw,
"Graceful restart capability parameters\n"
"Unsets F-bit indication that fib is preserved while doing Graceful Restart\n")
{
- VTY_DECLVAR_CONTEXT(bgp, bgp);
- UNSET_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD);
+ if (vty->node == CONFIG_NODE) {
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+
+ UNSET_FLAG(bm->flags, BM_FLAG_GR_PRESERVE_FWD);
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
+ UNSET_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD);
+ } else {
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD);
+ }
return CMD_SUCCESS;
}
@@ -3275,21 +3450,17 @@ DEFUN (bgp_graceful_restart_disable,
BGP_STR
GR_DISABLE)
{
+ if (vty->node == CONFIG_NODE)
+ return bgp_global_gr_config_vty(vty, true, true);
+
int ret = BGP_GR_FAILURE;
struct listnode *node, *nnode;
struct peer *peer;
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] bgp_graceful_restart_disable_cmd : START ");
-
VTY_DECLVAR_CONTEXT(bgp, bgp);
- ret = bgp_gr_update_all(bgp, GLOBAL_DISABLE_CMD);
+ ret = bgp_inst_gr_config_vty(vty, bgp, true, true);
if (ret == BGP_GR_SUCCESS) {
- VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
- bgp->peer,
- ret);
vty_out(vty,
"Graceful restart configuration changed, reset all peers to take effect\n");
@@ -3303,9 +3474,6 @@ DEFUN (bgp_graceful_restart_disable,
}
}
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("[BGP_GR] bgp_graceful_restart_disable_cmd : END ");
-
return bgp_vty_return(vty, ret);
}
@@ -3317,27 +3485,18 @@ DEFUN (no_bgp_graceful_restart_disable,
NO_GR_DISABLE
)
{
- VTY_DECLVAR_CONTEXT(bgp, bgp);
-
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] no_bgp_graceful_restart_disable_cmd : START ");
+ if (vty->node == CONFIG_NODE)
+ return bgp_global_gr_config_vty(vty, false, true);
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
int ret = BGP_GR_FAILURE;
- ret = bgp_gr_update_all(bgp, NO_GLOBAL_DISABLE_CMD);
+ ret = bgp_inst_gr_config_vty(vty, bgp, false, true);
if (ret == BGP_GR_SUCCESS) {
- VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
- bgp->peer,
- ret);
vty_out(vty,
"Graceful restart configuration changed, reset all peers to take effect\n");
}
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] no_bgp_graceful_restart_disable_cmd : END ");
-
return bgp_vty_return(vty, ret);
}
@@ -3355,13 +3514,14 @@ DEFUN (bgp_neighbor_graceful_restart_set,
VTY_BGP_GR_DEFINE_LOOP_VARIABLE;
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] bgp_neighbor_graceful_restart_set_cmd : START ");
-
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ vty_out(vty,
+ "Per peer-group graceful-restart configuration is not yet supported\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
result = bgp_neighbor_graceful_restart(peer, PEER_GR_CMD);
if (result == BGP_GR_SUCCESS) {
@@ -3371,15 +3531,7 @@ DEFUN (bgp_neighbor_graceful_restart_set,
"Graceful restart configuration changed, reset this peer to take effect\n");
}
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] bgp_neighbor_graceful_restart_set_cmd : END ");
-
- if (ret != BGP_GR_SUCCESS)
- vty_out(vty,
- "As part of configuring graceful-restart, capability send to zebra failed\n");
-
- return bgp_vty_return(vty, result);
+ return bgp_vty_return(vty, ret);
}
DEFUN (no_bgp_neighbor_graceful_restart,
@@ -3400,10 +3552,11 @@ DEFUN (no_bgp_neighbor_graceful_restart,
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
-
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] no_bgp_neighbor_graceful_restart_set_cmd : START ");
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ vty_out(vty,
+ "Per peer-group graceful-restart configuration is not yet supported\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
result = bgp_neighbor_graceful_restart(peer, NO_PEER_GR_CMD);
if (ret == BGP_GR_SUCCESS) {
@@ -3413,14 +3566,6 @@ DEFUN (no_bgp_neighbor_graceful_restart,
"Graceful restart configuration changed, reset this peer to take effect\n");
}
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] no_bgp_neighbor_graceful_restart_set_cmd : END ");
-
- if (ret != BGP_GR_SUCCESS)
- vty_out(vty,
- "As part of configuring graceful-restart, capability send to zebra failed\n");
-
return bgp_vty_return(vty, result);
}
@@ -3438,15 +3583,14 @@ DEFUN (bgp_neighbor_graceful_restart_helper_set,
VTY_BGP_GR_DEFINE_LOOP_VARIABLE;
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] bgp_neighbor_graceful_restart_helper_set_cmd : START ");
-
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
-
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
-
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ vty_out(vty,
+ "Per peer-group graceful-restart configuration is not yet supported\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
ret = bgp_neighbor_graceful_restart(peer, PEER_HELPER_CMD);
if (ret == BGP_GR_SUCCESS) {
@@ -3456,10 +3600,6 @@ DEFUN (bgp_neighbor_graceful_restart_helper_set,
"Graceful restart configuration changed, reset this peer to take effect\n");
}
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] bgp_neighbor_graceful_restart_helper_set_cmd : END ");
-
return bgp_vty_return(vty, ret);
}
@@ -3481,10 +3621,11 @@ DEFUN (no_bgp_neighbor_graceful_restart_helper,
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
-
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] no_bgp_neighbor_graceful_restart_helper_set_cmd : START ");
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ vty_out(vty,
+ "Per peer-group graceful-restart configuration is not yet supported\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
ret = bgp_neighbor_graceful_restart(peer, NO_PEER_HELPER_CMD);
if (ret == BGP_GR_SUCCESS) {
@@ -3494,10 +3635,6 @@ DEFUN (no_bgp_neighbor_graceful_restart_helper,
"Graceful restart configuration changed, reset this peer to take effect\n");
}
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] no_bgp_neighbor_graceful_restart_helper_set_cmd : END ");
-
return bgp_vty_return(vty, ret);
}
@@ -3515,29 +3652,24 @@ DEFUN (bgp_neighbor_graceful_restart_disable_set,
VTY_BGP_GR_DEFINE_LOOP_VARIABLE;
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] bgp_neighbor_graceful_restart_disable_set_cmd : START ");
-
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ vty_out(vty,
+ "Per peer-group graceful-restart configuration is not yet supported\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
ret = bgp_neighbor_graceful_restart(peer, PEER_DISABLE_CMD);
if (ret == BGP_GR_SUCCESS) {
- if (peer->bgp->t_startup)
+ if (peer->bgp->t_startup || bgp_in_graceful_restart())
bgp_peer_gr_flags_update(peer);
VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
}
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR]bgp_neighbor_graceful_restart_disable_set_cmd : END ");
-
return bgp_vty_return(vty, ret);
}
@@ -3559,23 +3691,18 @@ DEFUN (no_bgp_neighbor_graceful_restart_disable,
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
-
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] no_bgp_neighbor_graceful_restart_disable_set_cmd : START ");
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ vty_out(vty,
+ "Per peer-group graceful-restart configuration is not yet supported\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
ret = bgp_neighbor_graceful_restart(peer, NO_PEER_DISABLE_CMD);
if (ret == BGP_GR_SUCCESS) {
VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
}
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] no_bgp_neighbor_graceful_restart_disable_set_cmd : END ");
-
return bgp_vty_return(vty, ret);
}
@@ -3590,9 +3717,10 @@ DEFPY (neighbor_graceful_shutdown,
afi_t afi;
safi_t safi;
struct peer *peer;
- VTY_DECLVAR_CONTEXT(bgp, bgp);
int ret;
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
peer = peer_and_group_lookup_vty(vty, neighbor);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
@@ -4745,7 +4873,7 @@ static int peer_remote_as_vty(struct vty *vty, const char *peer_str,
VTY_DECLVAR_CONTEXT(bgp, bgp);
int ret;
as_t as;
- int as_type = AS_SPECIFIED;
+ enum peer_asn_type as_type = AS_SPECIFIED;
union sockunion su;
if (as_str[0] == 'i') {
@@ -4754,6 +4882,9 @@ static int peer_remote_as_vty(struct vty *vty, const char *peer_str,
} else if (as_str[0] == 'e') {
as = 0;
as_type = AS_EXTERNAL;
+ } else if (as_str[0] == 'a') {
+ as = 0;
+ as_type = AS_AUTO;
} else if (!asn_str2asn(as_str, &as))
as_type = AS_UNSPECIFIED;
@@ -4859,13 +4990,14 @@ ALIAS(no_bgp_shutdown, no_bgp_shutdown_msg_cmd,
DEFUN (neighbor_remote_as,
neighbor_remote_as_cmd,
- "neighbor <A.B.C.D|X:X::X:X|WORD> remote-as <ASNUM|internal|external>",
+ "neighbor <A.B.C.D|X:X::X:X|WORD> remote-as <ASNUM|internal|external|auto>",
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Specify a BGP neighbor\n"
AS_STR
"Internal BGP peer\n"
- "External BGP peer\n")
+ "External BGP peer\n"
+ "Automatically detect remote ASN\n")
{
int idx_peer = 1;
int idx_remote_as = 3;
@@ -4913,6 +5045,27 @@ DEFUN(no_bgp_fast_convergence, no_bgp_fast_convergence_cmd,
return CMD_SUCCESS;
}
+DEFPY (bgp_ipv6_auto_ra,
+ bgp_ipv6_auto_ra_cmd,
+ "[no] bgp ipv6-auto-ra",
+ NO_STR
+ BGP_STR
+ "Allow enabling IPv6 ND RA sending\n")
+{
+ if (vty->node == CONFIG_NODE) {
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+
+ COND_FLAG(bm->flags, BM_FLAG_IPV6_NO_AUTO_RA, no);
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
+ COND_FLAG(bgp->flags, BGP_FLAG_IPV6_NO_AUTO_RA, no);
+ } else {
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ COND_FLAG(bgp->flags, BGP_FLAG_IPV6_NO_AUTO_RA, no);
+ }
+ return CMD_SUCCESS;
+}
+
static int peer_conf_interface_get(struct vty *vty, const char *conf_if,
int v6only,
const char *peer_group_name,
@@ -4920,7 +5073,7 @@ static int peer_conf_interface_get(struct vty *vty, const char *conf_if,
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
as_t as = 0;
- int as_type = AS_UNSPECIFIED;
+ enum peer_asn_type as_type = AS_UNSPECIFIED;
struct peer *peer;
struct peer_group *group;
int ret = 0;
@@ -4937,6 +5090,8 @@ static int peer_conf_interface_get(struct vty *vty, const char *conf_if,
as_type = AS_INTERNAL;
} else if (as_str[0] == 'e') {
as_type = AS_EXTERNAL;
+ } else if (as_str[0] == 'a') {
+ as_type = AS_AUTO;
} else {
/* Get AS number. */
if (asn_str2asn(as_str, &as))
@@ -4980,12 +5135,13 @@ static int peer_conf_interface_get(struct vty *vty, const char *conf_if,
else
peer_flag_unset(peer, PEER_FLAG_IFPEER_V6ONLY);
+ peer->last_reset = PEER_DOWN_V6ONLY_CHANGE;
+
/* v6only flag changed. Reset bgp seesion */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
- peer->last_reset = PEER_DOWN_V6ONLY_CHANGE;
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- } else
+ else
bgp_session_reset(peer);
}
@@ -5053,14 +5209,15 @@ DEFUN (neighbor_interface_config_v6only,
DEFUN (neighbor_interface_config_remote_as,
neighbor_interface_config_remote_as_cmd,
- "neighbor WORD interface remote-as <ASNUM|internal|external>",
+ "neighbor WORD interface remote-as <ASNUM|internal|external|auto>",
NEIGHBOR_STR
"Interface name or neighbor tag\n"
"Enable BGP on interface\n"
"Specify a BGP neighbor\n"
AS_STR
"Internal BGP peer\n"
- "External BGP peer\n")
+ "External BGP peer\n"
+ "Automatically detect remote ASN\n")
{
int idx_word = 1;
int idx_remote_as = 4;
@@ -5070,7 +5227,7 @@ DEFUN (neighbor_interface_config_remote_as,
DEFUN (neighbor_interface_v6only_config_remote_as,
neighbor_interface_v6only_config_remote_as_cmd,
- "neighbor WORD interface v6only remote-as <ASNUM|internal|external>",
+ "neighbor WORD interface v6only remote-as <ASNUM|internal|external|auto>",
NEIGHBOR_STR
"Interface name or neighbor tag\n"
"Enable BGP with v6 link-local only\n"
@@ -5078,7 +5235,8 @@ DEFUN (neighbor_interface_v6only_config_remote_as,
"Specify a BGP neighbor\n"
AS_STR
"Internal BGP peer\n"
- "External BGP peer\n")
+ "External BGP peer\n"
+ "Automatically detect remote ASN\n")
{
int idx_word = 1;
int idx_remote_as = 5;
@@ -5115,14 +5273,15 @@ DEFUN (neighbor_peer_group,
DEFUN (no_neighbor,
no_neighbor_cmd,
- "no neighbor <WORD|<A.B.C.D|X:X::X:X> [remote-as <(1-4294967295)|internal|external>]>",
+ "no neighbor <WORD|<A.B.C.D|X:X::X:X> [remote-as <(1-4294967295)|internal|external|auto>]>",
NO_STR
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Specify a BGP neighbor\n"
AS_STR
"Internal BGP peer\n"
- "External BGP peer\n")
+ "External BGP peer\n"
+ "Automatically detect remote ASN\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
int idx_peer = 2;
@@ -5193,7 +5352,7 @@ DEFUN (no_neighbor,
DEFUN (no_neighbor_interface_config,
no_neighbor_interface_config_cmd,
- "no neighbor WORD interface [v6only] [peer-group PGNAME] [remote-as <(1-4294967295)|internal|external>]",
+ "no neighbor WORD interface [v6only] [peer-group PGNAME] [remote-as <(1-4294967295)|internal|external|auto>]",
NO_STR
NEIGHBOR_STR
"Interface name\n"
@@ -5204,7 +5363,8 @@ DEFUN (no_neighbor_interface_config,
"Specify a BGP neighbor\n"
AS_STR
"Internal BGP peer\n"
- "External BGP peer\n")
+ "External BGP peer\n"
+ "Automatically detect remote ASN\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
int idx_word = 2;
@@ -5261,14 +5421,15 @@ DEFUN (no_neighbor_peer_group,
DEFUN (no_neighbor_interface_peer_group_remote_as,
no_neighbor_interface_peer_group_remote_as_cmd,
- "no neighbor WORD remote-as <ASNUM|internal|external>",
+ "no neighbor WORD remote-as <ASNUM|internal|external|auto>",
NO_STR
NEIGHBOR_STR
"Interface name or neighbor tag\n"
"Specify a BGP neighbor\n"
AS_STR
"Internal BGP peer\n"
- "External BGP peer\n")
+ "External BGP peer\n"
+ "Automatically detect remote ASN\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
int idx_word = 2;
@@ -5316,7 +5477,7 @@ DEFUN (neighbor_local_as,
return CMD_WARNING_CONFIG_FAILED;
}
- ret = peer_local_as_set(peer, as, 0, 0, argv[idx_number]->arg);
+ ret = peer_local_as_set(peer, as, 0, 0, 0, argv[idx_number]->arg);
return bgp_vty_return(vty, ret);
}
@@ -5345,19 +5506,20 @@ DEFUN (neighbor_local_as_no_prepend,
return CMD_WARNING_CONFIG_FAILED;
}
- ret = peer_local_as_set(peer, as, 1, 0, argv[idx_number]->arg);
+ ret = peer_local_as_set(peer, as, 1, 0, 0, argv[idx_number]->arg);
return bgp_vty_return(vty, ret);
}
-DEFUN (neighbor_local_as_no_prepend_replace_as,
+DEFPY (neighbor_local_as_no_prepend_replace_as,
neighbor_local_as_no_prepend_replace_as_cmd,
- "neighbor <A.B.C.D|X:X::X:X|WORD> local-as ASNUM no-prepend replace-as",
+ "neighbor <A.B.C.D|X:X::X:X|WORD> local-as ASNUM no-prepend replace-as [dual-as$dual_as]",
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Specify a local-as number\n"
"AS number expressed in dotted or plain format used as local AS\n"
"Do not prepend local-as to updates from ebgp peers\n"
- "Do not prepend local-as to updates from ibgp peers\n")
+ "Do not prepend local-as to updates from ibgp peers\n"
+ "Allow peering with a global AS number or local-as number\n")
{
int idx_peer = 1;
int idx_number = 3;
@@ -5375,20 +5537,21 @@ DEFUN (neighbor_local_as_no_prepend_replace_as,
return CMD_WARNING_CONFIG_FAILED;
}
- ret = peer_local_as_set(peer, as, 1, 1, argv[idx_number]->arg);
+ ret = peer_local_as_set(peer, as, 1, 1, dual_as, argv[idx_number]->arg);
return bgp_vty_return(vty, ret);
}
DEFUN (no_neighbor_local_as,
no_neighbor_local_as_cmd,
- "no neighbor <A.B.C.D|X:X::X:X|WORD> local-as [ASNUM [no-prepend [replace-as]]]",
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> local-as [ASNUM [no-prepend [replace-as] [dual-as]]]",
NO_STR
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Specify a local-as number\n"
"AS number expressed in dotted or plain format used as local AS\n"
"Do not prepend local-as to updates from ebgp peers\n"
- "Do not prepend local-as to updates from ibgp peers\n")
+ "Do not prepend local-as to updates from ibgp peers\n"
+ "Allow peering with a global AS number or local-as number\n")
{
int idx_peer = 2;
struct peer *peer;
@@ -8282,7 +8445,7 @@ DEFPY (bgp_condadv_period,
DEFPY (bgp_def_originate_eval,
bgp_def_originate_eval_cmd,
- "[no$no] bgp default-originate timer (0-3600)$timer",
+ "[no$no] bgp default-originate timer (0-65535)$timer",
NO_STR
BGP_STR
"Control default-originate\n"
@@ -8291,8 +8454,7 @@ DEFPY (bgp_def_originate_eval,
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
- bgp->rmap_def_originate_eval_timer =
- no ? RMAP_DEFAULT_ORIGINATE_EVAL_TIMER : timer;
+ bgp->rmap_def_originate_eval_timer = no ? 0 : timer;
if (bgp->t_rmap_def_originate_eval)
EVENT_OFF(bgp->t_rmap_def_originate_eval);
@@ -10310,9 +10472,9 @@ DEFPY(af_import_vrf_route_map, af_import_vrf_route_map_cmd,
bgp_default = bgp_get_default();
if (!bgp_default) {
int32_t ret;
- as_t as = bgp->as;
+ as_t as = AS_UNSPECIFIED;
- /* Auto-create assuming the same AS */
+ /* Auto-create with AS_UNSPECIFIED, to be filled in later */
ret = bgp_get_vty(&bgp_default, &as, NULL,
BGP_INSTANCE_TYPE_DEFAULT, NULL,
ASNOTATION_UNDEFINED);
@@ -10322,6 +10484,8 @@ DEFPY(af_import_vrf_route_map, af_import_vrf_route_map_cmd,
"VRF default is not configured as a bgp instance\n");
return CMD_WARNING;
}
+
+ SET_FLAG(bgp_default->flags, BGP_FLAG_INSTANCE_HIDDEN);
}
vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
@@ -10425,7 +10589,9 @@ DEFPY(bgp_imexport_vrf, bgp_imexport_vrf_cmd,
bgp_default = bgp_get_default();
if (!bgp_default) {
- /* Auto-create assuming the same AS */
+ as = AS_UNSPECIFIED;
+
+ /* Auto-create with AS_UNSPECIFIED, to be filled in later */
ret = bgp_get_vty(&bgp_default, &as, NULL,
BGP_INSTANCE_TYPE_DEFAULT, NULL,
ASNOTATION_UNDEFINED);
@@ -10435,6 +10601,8 @@ DEFPY(bgp_imexport_vrf, bgp_imexport_vrf_cmd,
"VRF default is not configured as a bgp instance\n");
return CMD_WARNING;
}
+
+ SET_FLAG(bgp_default->flags, BGP_FLAG_INSTANCE_HIDDEN);
}
vrf_bgp = bgp_lookup_by_name(import_name);
@@ -10442,9 +10610,19 @@ DEFPY(bgp_imexport_vrf, bgp_imexport_vrf_cmd,
if (strcmp(import_name, VRF_DEFAULT_NAME) == 0) {
vrf_bgp = bgp_default;
} else {
- /* Auto-create assuming the same AS */
+ as = AS_UNSPECIFIED;
+
+ /* Auto-create with AS_UNSPECIFIED, fill in later */
ret = bgp_get_vty(&vrf_bgp, &as, import_name, bgp_type,
NULL, ASNOTATION_UNDEFINED);
+ if (ret) {
+ vty_out(vty,
+ "VRF %s is not configured as a bgp instance\n",
+ import_name);
+ return CMD_WARNING;
+ }
+
+ SET_FLAG(vrf_bgp->flags, BGP_FLAG_INSTANCE_HIDDEN);
/* Auto created VRF instances should be marked
* properly, otherwise we have a state after bgpd
@@ -10452,13 +10630,6 @@ DEFPY(bgp_imexport_vrf, bgp_imexport_vrf_cmd,
*/
SET_FLAG(vrf_bgp->vrf_flags, BGP_VRF_AUTO);
}
-
- if (ret) {
- vty_out(vty,
- "VRF %s is not configured as a bgp instance\n",
- import_name);
- return CMD_WARNING;
- }
}
if (remove) {
@@ -10744,7 +10915,7 @@ DEFPY (bgp_srv6_locator,
snprintf(bgp->srv6_locator_name,
sizeof(bgp->srv6_locator_name), "%s", name);
- ret = bgp_zebra_srv6_manager_get_locator_chunk(name);
+ ret = bgp_zebra_srv6_manager_get_locator(name);
if (ret < 0)
return CMD_WARNING_CONFIG_FAILED;
@@ -10795,6 +10966,17 @@ DEFPY (show_bgp_srv6,
return CMD_SUCCESS;
vty_out(vty, "locator_name: %s\n", bgp->srv6_locator_name);
+ if (bgp->srv6_locator) {
+ vty_out(vty, " prefix: %pFX\n", &bgp->srv6_locator->prefix);
+ vty_out(vty, " block-length: %d\n",
+ bgp->srv6_locator->block_bits_length);
+ vty_out(vty, " node-length: %d\n",
+ bgp->srv6_locator->node_bits_length);
+ vty_out(vty, " func-length: %d\n",
+ bgp->srv6_locator->function_bits_length);
+ vty_out(vty, " arg-length: %d\n",
+ bgp->srv6_locator->argument_bits_length);
+ }
vty_out(vty, "locator_chunks:\n");
for (ALL_LIST_ELEMENTS_RO(bgp->srv6_locator_chunks, node, chunk)) {
vty_out(vty, "- %pFX\n", &chunk->prefix);
@@ -11404,7 +11586,7 @@ DEFUN(show_bgp_martian_nexthop_db, show_bgp_martian_nexthop_db_cmd,
else
bgp = bgp_get_default();
- if (!bgp) {
+ if (!bgp || IS_BGP_INSTANCE_HIDDEN(bgp)) {
vty_out(vty, "%% No BGP process is configured\n");
return CMD_WARNING;
}
@@ -11767,7 +11949,8 @@ static char *bgp_peer_description_stripped(char *desc, uint32_t size)
/* Determine whether var peer should be filtered out of the summary. */
static bool bgp_show_summary_is_peer_filtered(struct peer *peer,
- struct peer *fpeer, int as_type,
+ struct peer *fpeer,
+ enum peer_asn_type as_type,
as_t as)
{
@@ -11778,7 +11961,7 @@ static bool bgp_show_summary_is_peer_filtered(struct peer *peer,
/* filter remote-as (internal|external) */
if (as_type != AS_UNSPECIFIED) {
if (peer->as_type == AS_SPECIFIED) {
- if (as_type == AS_INTERNAL) {
+ if (CHECK_FLAG(as_type, AS_INTERNAL)) {
if (peer->as != peer->local_as)
return true;
} else if (peer->as == peer->local_as)
@@ -11801,8 +11984,8 @@ static bool bgp_show_summary_is_peer_filtered(struct peer *peer,
* whitespaces and the whole output will be tricky.
*/
static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
- struct peer *fpeer, int as_type, as_t as,
- uint16_t show_flags)
+ struct peer *fpeer, enum peer_asn_type as_type,
+ as_t as, uint16_t show_flags)
{
struct peer *peer;
struct listnode *node, *nnode;
@@ -11914,6 +12097,8 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
if (show_failed && !failed_count) {
if (use_json) {
+ json_object_free(json_peers);
+
json_object_int_add(json, "failedPeersCount", 0);
json_object_int_add(json, "dynamicPeers", dn_count);
json_object_int_add(json, "totalPeers", count);
@@ -12196,6 +12381,12 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
json_object_string_add(json_peer, "domainname",
peer->domainname);
+ json_object_string_add(json_peer,
+ "softwareVersion",
+ peer->soft_version
+ ? peer->soft_version
+ : "n/a");
+
asn_asn2json(json_peer, "remoteAs", peer->as,
bgp->asnotation);
asn_asn2json(json_peer, "localAs",
@@ -12609,10 +12800,9 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
}
static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi,
- safi_t safi,
- const char *neighbor,
- int as_type, as_t as,
- uint16_t show_flags)
+ safi_t safi, const char *neighbor,
+ enum peer_asn_type as_type,
+ as_t as, uint16_t show_flags)
{
struct listnode *node, *nnode;
struct bgp *bgp;
@@ -12628,6 +12818,9 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi,
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
continue;
+ if (IS_BGP_INSTANCE_HIDDEN(bgp))
+ continue;
+
nbr_output = true;
if (use_json) {
if (!is_first)
@@ -12657,8 +12850,9 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi,
}
int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
- safi_t safi, const char *neighbor, int as_type,
- as_t as, uint16_t show_flags)
+ safi_t safi, const char *neighbor,
+ enum peer_asn_type as_type, as_t as,
+ uint16_t show_flags)
{
struct bgp *bgp;
bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
@@ -12773,6 +12967,8 @@ DEFPY(show_ip_bgp_summary, show_ip_bgp_summary_cmd,
as_type = AS_INTERNAL;
else if (argv[idx + 1]->arg[0] == 'e')
as_type = AS_EXTERNAL;
+ else if (argv[idx + 1]->arg[0] == 'a')
+ as_type = AS_AUTO;
else if (!asn_str2asn(argv[idx + 1]->arg, &as)) {
vty_out(vty,
"%% Invalid neighbor remote-as value: %s\n",
@@ -13895,10 +14091,15 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
if (CHECK_FLAG(p->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS))
json_object_boolean_true_add(json_neigh,
"localAsReplaceAs");
+
+ json_object_boolean_add(json_neigh, "localAsReplaceAsDualAs",
+ !!CHECK_FLAG(p->flags,
+ PEER_FLAG_DUAL_AS));
} else {
- if ((p->as_type == AS_SPECIFIED) ||
- (p->as_type == AS_EXTERNAL) ||
- (p->as_type == AS_INTERNAL)) {
+ if (p->as_type == AS_SPECIFIED ||
+ CHECK_FLAG(p->as_type, AS_AUTO) ||
+ CHECK_FLAG(p->as_type, AS_EXTERNAL) ||
+ CHECK_FLAG(p->as_type, AS_INTERNAL)) {
vty_out(vty, "remote AS ");
vty_out(vty, ASN_FORMAT(bgp->asnotation), &p->as);
vty_out(vty, ", ");
@@ -13908,16 +14109,18 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
vty_out(vty, ASN_FORMAT(bgp->asnotation),
p->change_local_as ? &p->change_local_as
: &p->local_as);
- vty_out(vty, "%s%s, ",
+ vty_out(vty, "%s%s%s, ",
CHECK_FLAG(p->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)
? " no-prepend"
: "",
CHECK_FLAG(p->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS)
? " replace-as"
- : "");
+ : "",
+ CHECK_FLAG(p->flags, PEER_FLAG_DUAL_AS) ? " dual-as"
+ : "");
}
/* peer type internal or confed-internal */
- if ((p->as == p->local_as) || (p->as_type == AS_INTERNAL)) {
+ if ((p->as == p->local_as) || (CHECK_FLAG(p->as_type, AS_INTERNAL))) {
if (use_json) {
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
json_object_boolean_true_add(
@@ -16012,6 +16215,9 @@ static void bgp_show_all_instances_neighbors_vty(struct vty *vty,
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
continue;
+ if (IS_BGP_INSTANCE_HIDDEN(bgp))
+ continue;
+
nbr_output = true;
if (use_json) {
if (!(json = json_object_new_object())) {
@@ -16667,6 +16873,9 @@ static void bgp_show_all_instances_updgrps_vty(struct vty *vty, afi_t afi,
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
continue;
+ if (IS_BGP_INSTANCE_HIDDEN(bgp))
+ continue;
+
if (!uj)
vty_out(vty, "\nInstance %s:\n",
(bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
@@ -16789,7 +16998,7 @@ DEFUN (show_bgp_updgrps_stats,
struct bgp *bgp;
bgp = bgp_get_default();
- if (bgp)
+ if (bgp && !IS_BGP_INSTANCE_HIDDEN(bgp))
update_group_show_stats(bgp, vty);
return CMD_SUCCESS;
@@ -16914,7 +17123,7 @@ static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group,
&conf->as);
vty_out(vty, "\n");
}
- } else if (conf->as_type == AS_INTERNAL) {
+ } else if (CHECK_FLAG(conf->as_type, AS_INTERNAL)) {
if (json)
asn_asn2json(json, "remoteAs", group->bgp->as,
group->bgp->asnotation);
@@ -16926,7 +17135,13 @@ static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group,
vty_out(vty, "\nBGP peer-group %s\n", group->name);
}
- if ((group->bgp->as == conf->as) || (conf->as_type == AS_INTERNAL)) {
+ if (CHECK_FLAG(conf->as_type, AS_AUTO)) {
+ if (json)
+ json_object_string_add(json_peer_group, "type", "auto");
+ else
+ vty_out(vty, " Peer-group type is auto\n");
+ } else if ((group->bgp->as == conf->as) ||
+ CHECK_FLAG(conf->as_type, AS_INTERNAL)) {
if (json)
json_object_string_add(json_peer_group, "type",
"internal");
@@ -18428,6 +18643,9 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
} else if (peer->as_type == AS_EXTERNAL) {
vty_out(vty, " remote-as external");
if_ras_printed = true;
+ } else if (CHECK_FLAG(peer->as_type, AS_AUTO)) {
+ vty_out(vty, " remote-as auto");
+ if_ras_printed = true;
}
vty_out(vty, "\n");
@@ -18450,6 +18668,9 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
vty_out(vty,
" neighbor %s remote-as external\n",
addr);
+ } else if (CHECK_FLAG(peer->as_type, AS_AUTO)) {
+ vty_out(vty, " neighbor %s remote-as auto\n",
+ addr);
}
}
@@ -18479,6 +18700,9 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
vty_out(vty,
" neighbor %s remote-as external\n",
addr);
+ } else if (CHECK_FLAG(peer->as_type, AS_AUTO)) {
+ vty_out(vty, " neighbor %s remote-as auto\n",
+ addr);
}
}
}
@@ -18491,6 +18715,8 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
vty_out(vty, " no-prepend");
if (peergroup_flag_check(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS))
vty_out(vty, " replace-as");
+ if (peergroup_flag_check(peer, PEER_FLAG_DUAL_AS))
+ vty_out(vty, " dual-as");
vty_out(vty, "\n");
}
@@ -18522,11 +18748,8 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
peer->password);
/* neighbor solo */
- if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL)) {
- if (!peer_group_active(peer)) {
- vty_out(vty, " neighbor %s solo\n", addr);
- }
- }
+ if (peergroup_flag_check(peer, PEER_FLAG_LONESOUL))
+ vty_out(vty, " neighbor %s solo\n", addr);
/* BGP port */
if (peer->port != BGP_PORT_DEFAULT) {
@@ -18539,7 +18762,7 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
}
/* TCP max segment size */
- if (CHECK_FLAG(peer->flags, PEER_FLAG_TCP_MSS))
+ if (peergroup_flag_check(peer, PEER_FLAG_TCP_MSS))
vty_out(vty, " neighbor %s tcp-mss %d\n", addr, peer->tcp_mss);
/* passive */
@@ -18772,6 +18995,10 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
char *addr;
bool flag_scomm, flag_secomm, flag_slcomm;
+ /* skip hidden default vrf bgp instance */
+ if (IS_BGP_INSTANCE_HIDDEN(bgp))
+ return;
+
/* Skip dynamic neighbors. */
if (peer_dynamic_neighbor(peer))
return;
@@ -19077,6 +19304,9 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
struct peer_group *group;
struct listnode *node, *nnode;
+ /* skip hidden default vrf bgp instance */
+ if (IS_BGP_INSTANCE_HIDDEN(bgp))
+ return;
vty_frame(vty, " !\n address-family ");
if (afi == AFI_IP) {
@@ -19190,11 +19420,12 @@ int bgp_config_write(struct vty *vty)
hook_call(bgp_snmp_traps_config_write, vty);
+ vty_out(vty, "!\n");
if (bm->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER)
vty_out(vty, "bgp route-map delay-timer %u\n",
bm->rmap_update_timer);
- if (bm->v_update_delay != BGP_UPDATE_DELAY_DEF) {
+ if (bm->v_update_delay != BGP_UPDATE_DELAY_DEFAULT) {
vty_out(vty, "bgp update-delay %d", bm->v_update_delay);
if (bm->v_update_delay != bm->v_establish_wait)
vty_out(vty, " %d", bm->v_establish_wait);
@@ -19204,6 +19435,30 @@ int bgp_config_write(struct vty *vty)
if (bm->wait_for_fib)
vty_out(vty, "bgp suppress-fib-pending\n");
+ if (bm->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
+ vty_out(vty, "bgp graceful-restart stalepath-time %u\n",
+ bm->stalepath_time);
+
+ if (bm->restart_time != BGP_DEFAULT_RESTART_TIME)
+ vty_out(vty, "bgp graceful-restart restart-time %u\n",
+ bm->restart_time);
+
+ if (bm->select_defer_time != BGP_DEFAULT_SELECT_DEFERRAL_TIME)
+ vty_out(vty, "bgp graceful-restart select-defer-time %u\n",
+ bm->select_defer_time);
+
+ if (CHECK_FLAG(bm->flags, BM_FLAG_GR_RESTARTER))
+ vty_out(vty, "bgp graceful-restart\n");
+ else if (CHECK_FLAG(bm->flags, BM_FLAG_GR_DISABLED))
+ vty_out(vty, "bgp graceful-restart-disable\n");
+
+ if (CHECK_FLAG(bm->flags, BM_FLAG_GR_PRESERVE_FWD))
+ vty_out(vty, "bgp graceful-restart preserve-fw-state\n");
+
+ if (bm->rib_stale_time != BGP_DEFAULT_RIB_STALE_TIME)
+ vty_out(vty, "bgp graceful-restart rib-stale-time %u\n",
+ bm->rib_stale_time);
+
if (CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN))
vty_out(vty, "bgp graceful-shutdown\n");
@@ -19214,6 +19469,9 @@ int bgp_config_write(struct vty *vty)
if (CHECK_FLAG(bm->flags, BM_FLAG_SEND_EXTRA_DATA_TO_ZEBRA))
vty_out(vty, "bgp send-extra-data zebra\n");
+ if (CHECK_FLAG(bm->flags, BM_FLAG_IPV6_NO_AUTO_RA))
+ vty_out(vty, "no bgp ipv6-auto-ra\n");
+
/* DSCP value for outgoing packets in BGP connections */
if (bm->ip_tos != IPTOS_PREC_INTERNETCONTROL)
vty_out(vty, "bgp session-dscp %u\n", bm->ip_tos >> 2);
@@ -19225,6 +19483,8 @@ int bgp_config_write(struct vty *vty)
if (bm->outq_limit != BM_DEFAULT_Q_LIMIT)
vty_out(vty, "bgp output-queue-limit %u\n", bm->outq_limit);
+ vty_out(vty, "!\n");
+
/* BGP configuration. */
for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
@@ -19232,6 +19492,10 @@ int bgp_config_write(struct vty *vty)
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
continue;
+ /* skip hidden default vrf bgp instance */
+ if (IS_BGP_INSTANCE_HIDDEN(bgp))
+ continue;
+
/* Router bgp ASN */
vty_out(vty, "router bgp %s", bgp->as_pretty);
@@ -19466,15 +19730,21 @@ int bgp_config_write(struct vty *vty)
" bgp long-lived-graceful-restart stale-time %u\n",
bgp->llgr_stale_time);
- /* BGP graceful-restart. */
- if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
- vty_out(vty,
- " bgp graceful-restart stalepath-time %u\n",
- bgp->stalepath_time);
+ /* BGP per-instance graceful-restart. */
+ /* BGP-wide settings and per-instance settings are mutually
+ * exclusive.
+ */
+ if (bm->stalepath_time == BGP_DEFAULT_STALEPATH_TIME)
+ if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
+ vty_out(vty,
+ " bgp graceful-restart stalepath-time %u\n",
+ bgp->stalepath_time);
- if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME)
- vty_out(vty, " bgp graceful-restart restart-time %u\n",
- bgp->restart_time);
+ if (bm->restart_time == BGP_DEFAULT_RESTART_TIME)
+ if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME)
+ vty_out(vty,
+ " bgp graceful-restart restart-time %u\n",
+ bgp->restart_time);
if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_NOTIFICATION) !=
SAVE_BGP_GRACEFUL_NOTIFICATION)
@@ -19484,30 +19754,34 @@ int bgp_config_write(struct vty *vty)
? ""
: "no ");
- if (bgp->select_defer_time != BGP_DEFAULT_SELECT_DEFERRAL_TIME)
- vty_out(vty,
- " bgp graceful-restart select-defer-time %u\n",
- bgp->select_defer_time);
+ if (bm->select_defer_time == BGP_DEFAULT_SELECT_DEFERRAL_TIME)
+ if (bgp->select_defer_time !=
+ BGP_DEFAULT_SELECT_DEFERRAL_TIME)
+ vty_out(vty,
+ " bgp graceful-restart select-defer-time %u\n",
+ bgp->select_defer_time);
- if (bgp_global_gr_mode_get(bgp) == GLOBAL_GR)
- vty_out(vty, " bgp graceful-restart\n");
+ if (!CHECK_FLAG(bm->flags, BM_FLAG_GR_CONFIGURED)) {
+ if (bgp_global_gr_mode_get(bgp) == GLOBAL_GR)
+ vty_out(vty, " bgp graceful-restart\n");
- if (bgp_global_gr_mode_get(bgp) == GLOBAL_DISABLE)
- vty_out(vty, " bgp graceful-restart-disable\n");
+ if (bgp_global_gr_mode_get(bgp) == GLOBAL_DISABLE)
+ vty_out(vty, " bgp graceful-restart-disable\n");
+ }
- /* BGP graceful-restart Preserve State F bit. */
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD))
- vty_out(vty,
- " bgp graceful-restart preserve-fw-state\n");
+ if (!CHECK_FLAG(bm->flags, BM_FLAG_GR_PRESERVE_FWD))
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD))
+ vty_out(vty,
+ " bgp graceful-restart preserve-fw-state\n");
/* BGP TCP keepalive */
bgp_config_tcp_keepalive(vty, bgp);
- /* Stale timer for RIB */
- if (bgp->rib_stale_time != BGP_DEFAULT_RIB_STALE_TIME)
- vty_out(vty,
- " bgp graceful-restart rib-stale-time %u\n",
- bgp->rib_stale_time);
+ if (bm->rib_stale_time == BGP_DEFAULT_RIB_STALE_TIME)
+ if (bgp->rib_stale_time != BGP_DEFAULT_RIB_STALE_TIME)
+ vty_out(vty,
+ " bgp graceful-restart rib-stale-time %u\n",
+ bgp->rib_stale_time);
/* BGP bestpath method. */
if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE))
@@ -19585,8 +19859,9 @@ int bgp_config_write(struct vty *vty)
bgp->condition_check_period);
/* default-originate timer configuration */
- if (bgp->rmap_def_originate_eval_timer !=
- RMAP_DEFAULT_ORIGINATE_EVAL_TIMER)
+ if (bgp->rmap_def_originate_eval_timer &&
+ bgp->rmap_def_originate_eval_timer !=
+ RMAP_DEFAULT_ORIGINATE_EVAL_TIMER)
vty_out(vty, " bgp default-originate timer %u\n",
bgp->rmap_def_originate_eval_timer);
@@ -19618,6 +19893,11 @@ int bgp_config_write(struct vty *vty)
if (CHECK_FLAG(bgp->flags, BGP_FLAG_SHUTDOWN))
vty_out(vty, " bgp shutdown\n");
+ /* Automatic RA enabling by BGP */
+ if (!CHECK_FLAG(bm->flags, BM_FLAG_IPV6_NO_AUTO_RA))
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_IPV6_NO_AUTO_RA))
+ vty_out(vty, " no bgp ipv6-auto-ra\n");
+
if (bgp->allow_martian)
vty_out(vty, " bgp allow-martian-nexthop\n");
@@ -20158,6 +20438,12 @@ void bgp_vty_init(void)
install_element(BGP_NODE, &bgp_fast_convergence_cmd);
install_element(BGP_NODE, &no_bgp_fast_convergence_cmd);
+ /* global bgp ipv6-auto-ra command */
+ install_element(CONFIG_NODE, &bgp_ipv6_auto_ra_cmd);
+
+ /* bgp ipv6-auto-ra command */
+ install_element(BGP_NODE, &bgp_ipv6_auto_ra_cmd);
+
/* global bgp update-delay command */
install_element(CONFIG_NODE, &bgp_global_update_delay_cmd);
install_element(CONFIG_NODE, &no_bgp_global_update_delay_cmd);
@@ -20166,6 +20452,26 @@ void bgp_vty_init(void)
install_element(CONFIG_NODE, &bgp_graceful_shutdown_cmd);
install_element(CONFIG_NODE, &no_bgp_graceful_shutdown_cmd);
+ /* BGP-wide graceful-restart commands. */
+ install_element(CONFIG_NODE, &bgp_graceful_restart_cmd);
+ install_element(CONFIG_NODE, &no_bgp_graceful_restart_cmd);
+ install_element(CONFIG_NODE, &bgp_graceful_restart_disable_cmd);
+ install_element(CONFIG_NODE, &no_bgp_graceful_restart_disable_cmd);
+ install_element(CONFIG_NODE, &bgp_graceful_restart_stalepath_time_cmd);
+ install_element(CONFIG_NODE,
+ &no_bgp_graceful_restart_stalepath_time_cmd);
+ install_element(CONFIG_NODE, &bgp_graceful_restart_restart_time_cmd);
+ install_element(CONFIG_NODE, &no_bgp_graceful_restart_restart_time_cmd);
+ install_element(CONFIG_NODE,
+ &bgp_graceful_restart_select_defer_time_cmd);
+ install_element(CONFIG_NODE,
+ &no_bgp_graceful_restart_select_defer_time_cmd);
+ install_element(CONFIG_NODE, &bgp_graceful_restart_preserve_fw_cmd);
+ install_element(CONFIG_NODE, &no_bgp_graceful_restart_preserve_fw_cmd);
+ install_element(CONFIG_NODE, &bgp_graceful_restart_rib_stale_time_cmd);
+ install_element(CONFIG_NODE,
+ &no_bgp_graceful_restart_rib_stale_time_cmd);
+
/* Dummy commands (Currently not supported) */
install_element(BGP_NODE, &no_synchronization_cmd);
install_element(BGP_NODE, &no_auto_summary_cmd);
diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h
index addd7175..f88f5c81 100644
--- a/bgpd/bgp_vty.h
+++ b/bgpd/bgp_vty.h
@@ -60,8 +60,6 @@ struct bgp;
#define VTY_BGP_GR_ROUTER_DETECT(_bgp, _peer, _peer_list) \
do { \
- if (_peer->bgp->t_startup) \
- bgp_peer_gr_flags_update(_peer); \
for (ALL_LIST_ELEMENTS(_peer_list, node, nnode, peer_loop)) { \
if (CHECK_FLAG(peer_loop->flags, \
PEER_FLAG_GRACEFUL_RESTART)) \
@@ -84,30 +82,27 @@ struct bgp;
} \
} while (0)
-#define VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA( \
- _bgp, _peer_list, _ret) \
- do { \
- struct peer *peer_loop; \
- bool gr_router_detected = false; \
- struct listnode *node = {0}; \
- struct listnode *nnode = {0}; \
- for (ALL_LIST_ELEMENTS(_peer_list, node, nnode, peer_loop)) { \
- if (peer_loop->bgp->t_startup) \
- bgp_peer_gr_flags_update(peer_loop); \
- if (CHECK_FLAG(peer_loop->flags, \
- PEER_FLAG_GRACEFUL_RESTART)) \
- gr_router_detected = true; \
- } \
- if (gr_router_detected \
- && _bgp->present_zebra_gr_state == ZEBRA_GR_DISABLE) { \
- if (bgp_zebra_send_capabilities(_bgp, false)) \
- _ret = BGP_ERR_INVALID_VALUE; \
- } else if (!gr_router_detected \
- && _bgp->present_zebra_gr_state \
- == ZEBRA_GR_ENABLE) { \
- if (bgp_zebra_send_capabilities(_bgp, true)) \
- _ret = BGP_ERR_INVALID_VALUE; \
- } \
+#define VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(_bgp, \
+ _peer_list, _ret) \
+ do { \
+ struct peer *peer_loop; \
+ bool gr_router_detected = false; \
+ struct listnode *node = { 0 }; \
+ struct listnode *nnode = { 0 }; \
+ for (ALL_LIST_ELEMENTS(_peer_list, node, nnode, peer_loop)) { \
+ if (CHECK_FLAG(peer_loop->flags, \
+ PEER_FLAG_GRACEFUL_RESTART)) \
+ gr_router_detected = true; \
+ } \
+ if (gr_router_detected && \
+ _bgp->present_zebra_gr_state == ZEBRA_GR_DISABLE) { \
+ if (bgp_zebra_send_capabilities(_bgp, false)) \
+ _ret = BGP_ERR_INVALID_VALUE; \
+ } else if (!gr_router_detected && \
+ _bgp->present_zebra_gr_state == ZEBRA_GR_ENABLE) { \
+ if (bgp_zebra_send_capabilities(_bgp, true)) \
+ _ret = BGP_ERR_INVALID_VALUE; \
+ } \
} while (0)
@@ -166,8 +161,9 @@ extern int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty,
int bgp_vty_find_and_parse_bgp(struct vty *vty, struct cmd_token **argv,
int argc, struct bgp **bgp, bool use_json);
extern int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
- safi_t safi, const char *neighbor, int as_type,
- as_t as, uint16_t show_flags);
+ safi_t safi, const char *neighbor,
+ enum peer_asn_type as_type, as_t as,
+ uint16_t show_flags);
extern bool peergroup_flag_check(struct peer *peer, uint64_t flag);
extern bool peergroup_af_flag_check(struct peer *peer, afi_t afi, safi_t safi,
uint64_t flag);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 7d1e9835..9053df31 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -195,7 +195,7 @@ static int bgp_ifp_destroy(struct interface *ifp)
bgp = ifp->vrf->info;
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Rx Intf del VRF %u IF %s", ifp->vrf->vrf_id,
+ zlog_debug("Rx Intf del VRF %s IF %s", ifp->vrf->name,
ifp->name);
if (bgp) {
@@ -220,8 +220,7 @@ static int bgp_ifp_up(struct interface *ifp)
bgp_mac_add_mac_entry(ifp);
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Rx Intf up VRF %u IF %s", ifp->vrf->vrf_id,
- ifp->name);
+ zlog_debug("Rx Intf up VRF %s IF %s", ifp->vrf->name, ifp->name);
if (!bgp)
return 0;
@@ -235,7 +234,7 @@ static int bgp_ifp_up(struct interface *ifp)
hook_call(bgp_vrf_status_changed, bgp, ifp);
bgp_nht_ifp_up(ifp);
- if (bgp_get_default() && if_is_loopback(ifp)) {
+ if (bgp_get_default() && if_is_vrf(ifp)) {
vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP);
@@ -259,7 +258,7 @@ static int bgp_ifp_down(struct interface *ifp)
bgp_mac_del_mac_entry(ifp);
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Rx Intf down VRF %u IF %s", ifp->vrf->vrf_id,
+ zlog_debug("Rx Intf down VRF %s IF %s", ifp->vrf->name,
ifp->name);
if (!bgp)
@@ -290,7 +289,7 @@ static int bgp_ifp_down(struct interface *ifp)
hook_call(bgp_vrf_status_changed, bgp, ifp);
bgp_nht_ifp_down(ifp);
- if (bgp_get_default() && if_is_loopback(ifp)) {
+ if (bgp_get_default() && if_is_vrf(ifp)) {
vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP);
vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP6);
vpn_leak_zebra_vrf_sid_withdraw(bgp, AFI_IP);
@@ -319,8 +318,8 @@ static int bgp_interface_address_add(ZAPI_CALLBACK_ARGS)
return 0;
if (bgp_debug_zebra(ifc->address))
- zlog_debug("Rx Intf address add VRF %u IF %s addr %pFX", vrf_id,
- ifc->ifp->name, ifc->address);
+ zlog_debug("Rx Intf address add VRF %s IF %s addr %pFX",
+ ifc->ifp->vrf->name, ifc->ifp->name, ifc->address);
if (!bgp)
return 0;
@@ -398,8 +397,8 @@ static int bgp_interface_address_delete(ZAPI_CALLBACK_ARGS)
return 0;
if (bgp_debug_zebra(ifc->address))
- zlog_debug("Rx Intf address del VRF %u IF %s addr %pFX", vrf_id,
- ifc->ifp->name, ifc->address);
+ zlog_debug("Rx Intf address del VRF %s IF %s addr %pFX",
+ ifc->ifp->vrf->name, ifc->ifp->name, ifc->address);
if (bgp && if_is_operative(ifc->ifp)) {
bgp_connected_delete(bgp, ifc);
@@ -450,8 +449,8 @@ static int bgp_interface_nbr_address_add(ZAPI_CALLBACK_ARGS)
return 0;
if (bgp_debug_zebra(ifc->address))
- zlog_debug("Rx Intf neighbor add VRF %u IF %s addr %pFX",
- vrf_id, ifc->ifp->name, ifc->address);
+ zlog_debug("Rx Intf neighbor add VRF %s IF %s addr %pFX",
+ ifc->ifp->vrf->name, ifc->ifp->name, ifc->address);
if (if_is_operative(ifc->ifp)) {
bgp = bgp_lookup_by_vrf_id(vrf_id);
@@ -473,8 +472,8 @@ static int bgp_interface_nbr_address_delete(ZAPI_CALLBACK_ARGS)
return 0;
if (bgp_debug_zebra(ifc->address))
- zlog_debug("Rx Intf neighbor del VRF %u IF %s addr %pFX",
- vrf_id, ifc->ifp->name, ifc->address);
+ zlog_debug("Rx Intf neighbor del VRF %s IF %s addr %pFX",
+ ifc->ifp->vrf->name, ifc->ifp->name, ifc->address);
if (if_is_operative(ifc->ifp)) {
bgp = bgp_lookup_by_vrf_id(vrf_id);
@@ -543,7 +542,7 @@ static int zebra_read_route(ZAPI_CALLBACK_ARGS)
/* Now perform the add/update. */
bgp_redistribute_add(bgp, &api.prefix, &nexthop, ifindex,
- nhtype, bhtype, api.distance, api.metric,
+ nhtype, api.distance, bhtype, api.metric,
api.type, api.instance, api.tag);
} else {
bgp_redistribute_delete(bgp, &api.prefix, api.type,
@@ -556,13 +555,14 @@ static int zebra_read_route(ZAPI_CALLBACK_ARGS)
if (add) {
inet_ntop(api.prefix.family, &nexthop, buf,
sizeof(buf));
- zlog_debug(
- "Rx route ADD VRF %u %s[%d] %pFX nexthop %s (type %d if %u) metric %u distance %u tag %" ROUTE_TAG_PRI,
- vrf_id, zebra_route_string(api.type),
- api.instance, &api.prefix, buf, nhtype, ifindex,
- api.metric, api.distance, api.tag);
+ zlog_debug("Rx route ADD %s %s[%d] %pFX nexthop %s (type %d if %u) metric %u distance %u tag %" ROUTE_TAG_PRI,
+ bgp->name_pretty,
+ zebra_route_string(api.type), api.instance,
+ &api.prefix, buf, nhtype, ifindex,
+ api.metric, api.distance, api.tag);
} else {
- zlog_debug("Rx route DEL VRF %u %s[%d] %pFX", vrf_id,
+ zlog_debug("Rx route DEL %s %s[%d] %pFX",
+ bgp->name_pretty,
zebra_route_string(api.type), api.instance,
&api.prefix);
}
@@ -1098,6 +1098,8 @@ static bool update_ipv4nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
struct attr *attr, bool is_evpn,
struct zapi_nexthop *api_nh)
{
+ struct bgp_route_evpn *bre = bgp_attr_get_evpn_overlay(attr);
+
api_nh->gate.ipv4 = *nexthop;
api_nh->vrf_id = nh_bgp->vrf_id;
@@ -1114,7 +1116,7 @@ static bool update_ipv4nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
* treat the nexthop as NEXTHOP_TYPE_IPV4
* Else, mark the nexthop as onlink.
*/
- if (attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP)
+ if (bre && bre->type == OVERLAY_INDEX_GATEWAY_IP)
api_nh->type = NEXTHOP_TYPE_IPV4;
else {
api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
@@ -1140,9 +1142,11 @@ static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
struct zapi_nexthop *api_nh)
{
struct attr *attr;
+ struct bgp_route_evpn *bre;
attr = pi->attr;
api_nh->vrf_id = nh_bgp->vrf_id;
+ bre = bgp_attr_get_evpn_overlay(attr);
if (attr->nh_type == NEXTHOP_TYPE_BLACKHOLE) {
api_nh->type = attr->nh_type;
@@ -1153,7 +1157,7 @@ static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
* treat the nexthop as NEXTHOP_TYPE_IPV4
* Else, mark the nexthop as onlink.
*/
- if (attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP)
+ if (bre && bre->type == OVERLAY_INDEX_GATEWAY_IP)
api_nh->type = NEXTHOP_TYPE_IPV6;
else {
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
@@ -1251,6 +1255,7 @@ static void bgp_zebra_announce_parse_nexthop(
uint32_t ttl = 0;
uint32_t bos = 0;
uint32_t exp = 0;
+ struct bgp_route_evpn *bre = NULL;
/* Determine if we're doing weighted ECMP or not */
do_wt_ecmp = bgp_path_info_mpath_chkwtd(bgp, info);
@@ -1365,6 +1370,7 @@ static void bgp_zebra_announce_parse_nexthop(
}
is_evpn = !!CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN);
+ bre = bgp_attr_get_evpn_overlay(mpinfo->attr);
/* Did we get proper nexthop info to update zebra? */
if (!nh_updated)
@@ -1400,9 +1406,7 @@ static void bgp_zebra_announce_parse_nexthop(
api_nh->labels[0] = nh_label;
}
- if (is_evpn
- && mpinfo->attr->evpn_overlay.type
- != OVERLAY_INDEX_GATEWAY_IP)
+ if (is_evpn && !(bre && bre->type == OVERLAY_INDEX_GATEWAY_IP))
memcpy(&api_nh->rmac, &(mpinfo->attr->rmac),
sizeof(struct ethaddr));
@@ -1526,7 +1530,6 @@ bgp_zebra_announce_actual(struct bgp_dest *dest, struct bgp_path_info *info,
struct peer *peer;
uint32_t metric;
route_tag_t tag;
- bool is_add;
uint32_t nhg_id = 0;
struct bgp_table *table = bgp_dest_table(dest);
const struct prefix *p = bgp_dest_get_prefix(dest);
@@ -1580,9 +1583,7 @@ bgp_zebra_announce_actual(struct bgp_dest *dest, struct bgp_path_info *info,
table->afi, table->safi, &nhg_id,
&metric, &tag, &allow_recursion);
- is_add = (valid_nh_count || nhg_id) ? true : false;
-
- if (is_add && CHECK_FLAG(bm->flags, BM_FLAG_SEND_EXTRA_DATA_TO_ZEBRA)) {
+ if (CHECK_FLAG(bm->flags, BM_FLAG_SEND_EXTRA_DATA_TO_ZEBRA)) {
struct bgp_zebra_opaque bzo = {};
const char *reason =
bgp_path_selection_reason2str(dest->reason);
@@ -1638,18 +1639,17 @@ bgp_zebra_announce_actual(struct bgp_dest *dest, struct bgp_path_info *info,
}
if (bgp_debug_zebra(p)) {
- zlog_debug(
- "Tx route %s VRF %u %pFX metric %u tag %" ROUTE_TAG_PRI
- " count %d nhg %d",
- is_add ? "add" : "delete", bgp->vrf_id, &api.prefix,
- api.metric, api.tag, api.nexthop_num, nhg_id);
+ zlog_debug("Tx route add %s (table id %u) %pFX metric %u tag %" ROUTE_TAG_PRI
+ " count %d nhg %d",
+ bgp->name_pretty, api.tableid, &api.prefix,
+ api.metric, api.tag, api.nexthop_num, nhg_id);
bgp_debug_zebra_nh(&api);
zlog_debug("%s: %pFX: announcing to zebra (recursion %sset)",
__func__, p, (allow_recursion ? "" : "NOT "));
}
- return zclient_route_send(is_add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
- zclient, &api);
+
+ return zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
}
@@ -1731,8 +1731,8 @@ enum zclient_send_status bgp_zebra_withdraw_actual(struct bgp_dest *dest,
}
if (bgp_debug_zebra(p))
- zlog_debug("Tx route delete VRF %u %pFX", bgp->vrf_id,
- &api.prefix);
+ zlog_debug("Tx route delete %s (table id %u) %pFX",
+ bgp->name_pretty, api.tableid, &api.prefix);
return zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
}
@@ -1778,8 +1778,9 @@ static void bgp_handle_route_announcements_to_zebra(struct event *e)
}
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("BGP %s route %pBD(%s) with dest %p and flags 0x%x to zebra",
- install ? "announcing" : "withdrawing", dest,
+ zlog_debug("BGP %s%s route %pBD(%s) with dest %p and flags 0x%x to zebra",
+ install ? "announcing" : "withdrawing",
+ is_evpn ? " evpn" : " ", dest,
table->bgp->name_pretty, dest, dest->flags);
if (install) {
@@ -2069,8 +2070,8 @@ int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type,
return CMD_SUCCESS;
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Tx redistribute add VRF %u afi %d %s %d",
- bgp->vrf_id, afi, zebra_route_string(type),
+ zlog_debug("Tx redistribute add %s afi %d %s %d",
+ bgp->name_pretty, afi, zebra_route_string(type),
instance);
/* Send distribute add message to zebra. */
@@ -2090,8 +2091,8 @@ int bgp_redistribute_resend(struct bgp *bgp, afi_t afi, int type,
return -1;
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Tx redistribute del/add VRF %u afi %d %s %d",
- bgp->vrf_id, afi, zebra_route_string(type),
+ zlog_debug("Tx redistribute del/add %s afi %d %s %d",
+ bgp->name_pretty, afi, zebra_route_string(type),
instance);
/* Send distribute add message to zebra. */
@@ -2185,9 +2186,9 @@ int bgp_redistribute_unreg(struct bgp *bgp, afi_t afi, int type,
if (bgp_install_info_to_zebra(bgp)) {
/* Send distribute delete message to zebra. */
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Tx redistribute del VRF %u afi %d %s %d",
- bgp->vrf_id, afi, zebra_route_string(type),
- instance);
+ zlog_debug("Tx redistribute del %s afi %d %s %d",
+ bgp->name_pretty, afi,
+ zebra_route_string(type), instance);
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi,
type, instance, bgp->vrf_id);
}
@@ -2290,7 +2291,7 @@ void bgp_zebra_instance_register(struct bgp *bgp)
return;
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Registering VRF %u", bgp->vrf_id);
+ zlog_debug("Registering %s", bgp->name_pretty);
/* Register for router-id, interfaces, redistributed routes. */
zclient_send_reg_requests(zclient, bgp->vrf_id);
@@ -2312,7 +2313,7 @@ void bgp_zebra_instance_deregister(struct bgp *bgp)
return;
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Deregistering VRF %u", bgp->vrf_id);
+ zlog_debug("Deregistering %s", bgp->name_pretty);
/* For EVPN instance, unregister learning about VNIs, if appropriate. */
if (bgp->advertise_all_vni)
@@ -2326,6 +2327,9 @@ void bgp_zebra_initiate_radv(struct bgp *bgp, struct peer *peer)
{
uint32_t ra_interval = BGP_UNNUM_DEFAULT_RA_INTERVAL;
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_IPV6_NO_AUTO_RA))
+ return;
+
/* Don't try to initiate if we're not connected to Zebra */
if (zclient->sock < 0)
return;
@@ -3325,7 +3329,7 @@ static int bgp_ifp_create(struct interface *ifp)
struct bgp *bgp;
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Rx Intf add VRF %u IF %s", ifp->vrf->vrf_id,
+ zlog_debug("Rx Intf add VRF %s IF %s", ifp->vrf->name,
ifp->name);
bgp = ifp->vrf->info;
@@ -3378,11 +3382,278 @@ static int bgp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)
return 0;
}
+/**
+ * Internal function to process an SRv6 locator
+ *
+ * @param locator The locator to be processed
+ */
+static int bgp_zebra_process_srv6_locator_internal(struct srv6_locator *locator)
+{
+ struct bgp *bgp = bgp_get_default();
+
+ if (!bgp || !bgp->srv6_enabled || !locator)
+ return -1;
+
+ /*
+ * Check if the main BGP instance is configured to use the received
+ * locator
+ */
+ if (strcmp(bgp->srv6_locator_name, locator->name) != 0) {
+ zlog_err("%s: SRv6 Locator name unmatch %s:%s", __func__,
+ bgp->srv6_locator_name, locator->name);
+ return 0;
+ }
+
+ zlog_info("%s: Received SRv6 locator %s %pFX, loc-block-len=%u, loc-node-len=%u func-len=%u, arg-len=%u",
+ __func__, locator->name, &locator->prefix,
+ locator->block_bits_length, locator->node_bits_length,
+ locator->function_bits_length, locator->argument_bits_length);
+
+ /* Store the locator in the main BGP instance */
+ bgp->srv6_locator = srv6_locator_alloc(locator->name);
+ srv6_locator_copy(bgp->srv6_locator, locator);
+
+ /*
+ * Process VPN-to-VRF and VRF-to-VPN leaks to advertise new locator
+ * and SIDs.
+ */
+ vpn_leak_postchange_all();
+
+ return 0;
+}
+
+static int bgp_zebra_srv6_sid_notify(ZAPI_CALLBACK_ARGS)
+{
+ struct bgp *bgp = bgp_get_default();
+ struct srv6_locator *locator;
+ struct srv6_sid_ctx ctx;
+ struct in6_addr sid_addr;
+ enum zapi_srv6_sid_notify note;
+ struct bgp *bgp_vrf;
+ struct vrf *vrf;
+ struct listnode *node, *nnode;
+ char buf[256];
+ struct in6_addr *tovpn_sid;
+ struct prefix_ipv6 tmp_prefix;
+ uint32_t sid_func;
+ bool found = false;
+
+ if (!bgp || !bgp->srv6_enabled)
+ return -1;
+
+ if (!bgp->srv6_locator) {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: ignoring SRv6 SID notify: locator not set",
+ __func__);
+ return -1;
+ }
+
+ /* Decode the received notification message */
+ if (!zapi_srv6_sid_notify_decode(zclient->ibuf, &ctx, &sid_addr,
+ &sid_func, NULL, &note, NULL)) {
+ zlog_err("%s : error in msg decode", __func__);
+ return -1;
+ }
+
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: received SRv6 SID notify: ctx %s sid_value %pI6 %s",
+ __func__, srv6_sid_ctx2str(buf, sizeof(buf), &ctx),
+ &sid_addr, zapi_srv6_sid_notify2str(note));
+
+ /* Get the BGP instance for which the SID has been requested, if any */
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp_vrf)) {
+ vrf = vrf_lookup_by_id(bgp_vrf->vrf_id);
+ if (!vrf)
+ continue;
+
+ if (vrf->vrf_id == ctx.vrf_id) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: ignoring SRv6 SID notify: No VRF suitable for received SID ctx %s sid_value %pI6",
+ __func__,
+ srv6_sid_ctx2str(buf, sizeof(buf), &ctx),
+ &sid_addr);
+ return -1;
+ }
+
+ /* Handle notification */
+ switch (note) {
+ case ZAPI_SRV6_SID_ALLOCATED:
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("SRv6 SID %pI6 %s : ALLOCATED", &sid_addr,
+ srv6_sid_ctx2str(buf, sizeof(buf), &ctx));
+
+ /* Verify that the received SID belongs to the configured locator */
+ tmp_prefix.family = AF_INET6;
+ tmp_prefix.prefixlen = IPV6_MAX_BITLEN;
+ tmp_prefix.prefix = sid_addr;
+
+ if (!prefix_match((struct prefix *)&bgp->srv6_locator->prefix,
+ (struct prefix *)&tmp_prefix))
+ return -1;
+
+ /* Get label */
+ uint8_t func_len = bgp->srv6_locator->function_bits_length;
+ uint8_t shift_len = BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH -
+ func_len;
+
+ int label = sid_func << shift_len;
+
+ /* Un-export VPN to VRF routes */
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP, bgp,
+ bgp_vrf);
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP6, bgp,
+ bgp_vrf);
+
+ locator = srv6_locator_alloc(bgp->srv6_locator_name);
+ srv6_locator_copy(locator, bgp->srv6_locator);
+
+ /* Store SID, locator, and label */
+ tovpn_sid = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
+ *tovpn_sid = sid_addr;
+ if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT6) {
+ XFREE(MTYPE_BGP_SRV6_SID,
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid);
+ srv6_locator_free(
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator);
+ sid_unregister(bgp,
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid);
+
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid = tovpn_sid;
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator = locator;
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_transpose_label =
+ label;
+ } else if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT4) {
+ XFREE(MTYPE_BGP_SRV6_SID,
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid);
+ srv6_locator_free(
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator);
+ sid_unregister(bgp,
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid);
+
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid = tovpn_sid;
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator = locator;
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_transpose_label =
+ label;
+ } else if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT46) {
+ XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid);
+ srv6_locator_free(bgp_vrf->tovpn_sid_locator);
+ sid_unregister(bgp, bgp_vrf->tovpn_sid);
+
+ bgp_vrf->tovpn_sid = tovpn_sid;
+ bgp_vrf->tovpn_sid_locator = locator;
+ bgp_vrf->tovpn_sid_transpose_label = label;
+ } else {
+ srv6_locator_free(locator);
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("Unsupported behavior. Not assigned SRv6 SID: %s %pI6",
+ srv6_sid_ctx2str(buf, sizeof(buf),
+ &ctx),
+ &sid_addr);
+ return -1;
+ }
+
+ /* Register the new SID */
+ sid_register(bgp, tovpn_sid, bgp->srv6_locator_name);
+
+ /* Export VPN to VRF routes */
+ vpn_leak_postchange_all();
+
+ break;
+ case ZAPI_SRV6_SID_RELEASED:
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("SRv6 SID %pI6 %s: RELEASED", &sid_addr,
+ srv6_sid_ctx2str(buf, sizeof(buf), &ctx));
+
+ /* Un-export VPN to VRF routes */
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP, bgp,
+ bgp_vrf);
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP6, bgp,
+ bgp_vrf);
+
+ /* Remove SID, locator, and label */
+ if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT6) {
+ XFREE(MTYPE_BGP_SRV6_SID,
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid);
+ if (bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator) {
+ srv6_locator_free(bgp->vpn_policy[AFI_IP6]
+ .tovpn_sid_locator);
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator =
+ NULL;
+ }
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_transpose_label =
+ 0;
+
+ /* Unregister the SID */
+ sid_unregister(bgp,
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid);
+ } else if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT4) {
+ XFREE(MTYPE_BGP_SRV6_SID,
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid);
+ if (bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator) {
+ srv6_locator_free(bgp->vpn_policy[AFI_IP]
+ .tovpn_sid_locator);
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator =
+ NULL;
+ }
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_transpose_label =
+ 0;
+
+ /* Unregister the SID */
+ sid_unregister(bgp,
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid);
+ } else if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT46) {
+ XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid);
+ if (bgp_vrf->tovpn_sid_locator) {
+ srv6_locator_free(bgp_vrf->tovpn_sid_locator);
+ bgp_vrf->tovpn_sid_locator = NULL;
+ }
+ bgp_vrf->tovpn_sid_transpose_label = 0;
+
+ /* Unregister the SID */
+ sid_unregister(bgp, bgp_vrf->tovpn_sid);
+ } else {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("Unsupported behavior. Not assigned SRv6 SID: %s %pI6",
+ srv6_sid_ctx2str(buf, sizeof(buf),
+ &ctx),
+ &sid_addr);
+ return -1;
+ }
+
+ /* Export VPN to VRF routes*/
+ vpn_leak_postchange_all();
+ break;
+ case ZAPI_SRV6_SID_FAIL_ALLOC:
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("SRv6 SID %pI6 %s: Failed to allocate",
+ &sid_addr,
+ srv6_sid_ctx2str(buf, sizeof(buf), &ctx));
+
+ /* Error will be logged by zebra module */
+ break;
+ case ZAPI_SRV6_SID_FAIL_RELEASE:
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: SRv6 SID %pI6 %s failure to release",
+ __func__, &sid_addr,
+ srv6_sid_ctx2str(buf, sizeof(buf), &ctx));
+
+ /* Error will be logged by zebra module */
+ break;
+ }
+
+ return 0;
+}
+
static int bgp_zebra_process_srv6_locator_add(ZAPI_CALLBACK_ARGS)
{
struct srv6_locator loc = {};
struct bgp *bgp = bgp_get_default();
- const char *loc_name = bgp->srv6_locator_name;
if (!bgp || !bgp->srv6_enabled)
return 0;
@@ -3390,10 +3661,7 @@ static int bgp_zebra_process_srv6_locator_add(ZAPI_CALLBACK_ARGS)
if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0)
return -1;
- if (bgp_zebra_srv6_manager_get_locator_chunk(loc_name) < 0)
- return -1;
-
- return 0;
+ return bgp_zebra_process_srv6_locator_internal(&loc);
}
static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
@@ -3401,7 +3669,8 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
struct srv6_locator loc = {};
struct bgp *bgp = bgp_get_default();
struct listnode *node, *nnode;
- struct srv6_locator_chunk *chunk, *tovpn_sid_locator;
+ struct srv6_locator_chunk *chunk;
+ struct srv6_locator *tovpn_sid_locator;
struct bgp_srv6_function *func;
struct bgp *bgp_vrf;
struct in6_addr *tovpn_sid;
@@ -3413,6 +3682,12 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0)
return -1;
+ // clear SRv6 locator
+ if (bgp->srv6_locator) {
+ srv6_locator_free(bgp->srv6_locator);
+ bgp->srv6_locator = NULL;
+ }
+
// refresh chunks
for (ALL_LIST_ELEMENTS(bgp->srv6_locator_chunks, node, nnode, chunk))
if (prefix_match((struct prefix *)&loc.prefix,
@@ -3489,10 +3764,12 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
tmp_prefi.prefixlen = IPV6_MAX_BITLEN;
tmp_prefi.prefix = tovpn_sid_locator->prefix.prefix;
if (prefix_match((struct prefix *)&loc.prefix,
- (struct prefix *)&tmp_prefi))
- srv6_locator_chunk_free(
- &bgp_vrf->vpn_policy[AFI_IP]
- .tovpn_sid_locator);
+ (struct prefix *)&tmp_prefi)) {
+ srv6_locator_free(bgp_vrf->vpn_policy[AFI_IP]
+ .tovpn_sid_locator);
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator =
+ NULL;
+ }
}
/* refresh vpnv6 tovpn_sid_locator */
@@ -3503,10 +3780,12 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
tmp_prefi.prefixlen = IPV6_MAX_BITLEN;
tmp_prefi.prefix = tovpn_sid_locator->prefix.prefix;
if (prefix_match((struct prefix *)&loc.prefix,
- (struct prefix *)&tmp_prefi))
- srv6_locator_chunk_free(
- &bgp_vrf->vpn_policy[AFI_IP6]
- .tovpn_sid_locator);
+ (struct prefix *)&tmp_prefi)) {
+ srv6_locator_free(bgp_vrf->vpn_policy[AFI_IP6]
+ .tovpn_sid_locator);
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator =
+ NULL;
+ }
}
/* refresh per-vrf tovpn_sid_locator */
@@ -3516,9 +3795,10 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
tmp_prefi.prefixlen = IPV6_MAX_BITLEN;
tmp_prefi.prefix = tovpn_sid_locator->prefix.prefix;
if (prefix_match((struct prefix *)&loc.prefix,
- (struct prefix *)&tmp_prefi))
- srv6_locator_chunk_free(
- &bgp_vrf->tovpn_sid_locator);
+ (struct prefix *)&tmp_prefi)) {
+ srv6_locator_free(bgp_vrf->tovpn_sid_locator);
+ bgp_vrf->tovpn_sid_locator = NULL;
+ }
}
}
@@ -3555,6 +3835,7 @@ static zclient_handler *const bgp_handlers[] = {
[ZEBRA_SRV6_LOCATOR_DELETE] = bgp_zebra_process_srv6_locator_delete,
[ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] =
bgp_zebra_process_srv6_locator_chunk,
+ [ZEBRA_SRV6_SID_NOTIFY] = bgp_zebra_srv6_sid_notify,
};
static int bgp_if_new_hook(struct interface *ifp)
@@ -3582,14 +3863,17 @@ void bgp_if_init(void)
hook_register_prio(if_del, 0, bgp_if_delete_hook);
}
-static void bgp_start_label_manager(struct event *start)
+static bool bgp_zebra_label_manager_ready(void)
{
- bgp_zebra_label_manager_connect();
+ return (zclient_sync->sock > 0);
}
-static bool bgp_zebra_label_manager_ready(void)
+static void bgp_start_label_manager(struct event *start)
{
- return (zclient_sync->sock > 0);
+ if (!bgp_zebra_label_manager_ready() &&
+ !bgp_zebra_label_manager_connect())
+ event_add_timer(bm->master, bgp_start_label_manager, NULL, 1,
+ &bm->t_bgp_start_label_manager);
}
static bool bgp_zebra_label_manager_connect(void)
@@ -3963,6 +4247,11 @@ int bgp_zebra_send_capabilities(struct bgp *bgp, bool disable)
return BGP_GR_FAILURE;
}
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s(%d): Sending GR capability %s to zebra",
+ bgp->name_pretty, bgp->vrf_id,
+ disable ? "disabled" : "enabled");
+
/* Check if capability is already sent. If the flag force is set
* send the capability since this can be initial bgp configuration
*/
@@ -3978,8 +4267,8 @@ int bgp_zebra_send_capabilities(struct bgp *bgp, bool disable)
if (zclient_capabilities_send(ZEBRA_CLIENT_CAPABILITIES, zclient, &api)
== ZCLIENT_SEND_FAILURE) {
- zlog_err("%s: %s error sending capability", __func__,
- bgp->name_pretty);
+ zlog_err("%s(%d): Error sending GR capability to zebra",
+ bgp->name_pretty, bgp->vrf_id);
ret = BGP_GR_FAILURE;
} else {
if (disable)
@@ -3987,9 +4276,6 @@ int bgp_zebra_send_capabilities(struct bgp *bgp, bool disable)
else
bgp->present_zebra_gr_state = ZEBRA_GR_ENABLE;
- if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("%s: %s send capabilty success", __func__,
- bgp->name_pretty);
ret = BGP_GR_SUCCESS;
}
return ret;
@@ -4087,6 +4373,89 @@ int bgp_zebra_srv6_manager_release_locator_chunk(const char *name)
return srv6_manager_release_locator_chunk(zclient, name);
}
+/**
+ * Ask the SRv6 Manager (zebra) about a specific locator
+ *
+ * @param name Locator name
+ * @return 0 on success, -1 otherwise
+ */
+int bgp_zebra_srv6_manager_get_locator(const char *name)
+{
+ if (!name)
+ return -1;
+
+ /*
+ * Send the Get Locator request to the SRv6 Manager and return the
+ * result
+ */
+ return srv6_manager_get_locator(zclient, name);
+}
+
+/**
+ * Ask the SRv6 Manager (zebra) to allocate a SID.
+ *
+ * Optionally, it is possible to provide an IPv6 address (sid_value parameter).
+ *
+ * When sid_value is provided, the SRv6 Manager allocates the requested SID
+ * address, if the request can be satisfied (explicit allocation).
+ *
+ * When sid_value is not provided, the SRv6 Manager allocates any available SID
+ * from the provided locator (dynamic allocation).
+ *
+ * @param ctx Context to be associated with the request SID
+ * @param sid_value IPv6 address to be associated with the requested SID (optional)
+ * @param locator_name Name of the locator from which the SID must be allocated
+ * @param sid_func SID Function allocated by the SRv6 Manager.
+ */
+bool bgp_zebra_request_srv6_sid(const struct srv6_sid_ctx *ctx,
+ struct in6_addr *sid_value,
+ const char *locator_name, uint32_t *sid_func)
+{
+ int ret;
+
+ if (!ctx || !locator_name)
+ return false;
+
+ /*
+ * Send the Get SRv6 SID request to the SRv6 Manager and check the
+ * result
+ */
+ ret = srv6_manager_get_sid(zclient, ctx, sid_value, locator_name,
+ sid_func);
+ if (ret < 0) {
+ zlog_warn("%s: error getting SRv6 SID!", __func__);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Ask the SRv6 Manager (zebra) to release a previously allocated SID.
+ *
+ * This function is used to tell the SRv6 Manager that BGP no longer intends
+ * to use the SID.
+ *
+ * @param ctx Context to be associated with the SID to be released
+ */
+void bgp_zebra_release_srv6_sid(const struct srv6_sid_ctx *ctx)
+{
+ int ret;
+
+ if (!ctx)
+ return;
+
+ /*
+ * Send the Release SRv6 SID request to the SRv6 Manager and check the
+ * result
+ */
+ ret = srv6_manager_release_sid(zclient, ctx);
+ if (ret < 0) {
+ zlog_warn("%s: error releasing SRv6 SID!", __func__);
+ return;
+ }
+}
+
void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
ifindex_t ifindex, vrf_id_t vrf_id,
enum lsp_types_t ltype, struct prefix *p,
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
index 55a4185b..8deecba7 100644
--- a/bgpd/bgp_zebra.h
+++ b/bgpd/bgp_zebra.h
@@ -117,6 +117,13 @@ extern int bgp_zebra_update(struct bgp *bgp, afi_t afi, safi_t safi,
extern int bgp_zebra_stale_timer_update(struct bgp *bgp);
extern int bgp_zebra_srv6_manager_get_locator_chunk(const char *name);
extern int bgp_zebra_srv6_manager_release_locator_chunk(const char *name);
+extern int bgp_zebra_srv6_manager_get_locator(const char *name);
+extern bool bgp_zebra_request_srv6_sid(const struct srv6_sid_ctx *ctx,
+ struct in6_addr *sid_value,
+ const char *locator_name,
+ uint32_t *sid_func);
+extern void bgp_zebra_release_srv6_sid(const struct srv6_sid_ctx *ctx);
+
extern void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
ifindex_t index, vrf_id_t vrfid,
enum lsp_types_t ltype,
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 894226ad..58183818 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -149,7 +149,7 @@ void bgp_session_reset(struct peer *peer)
* during walk of peer list, we would end up accessing the freed next
* node. This function moves the next node along.
*/
-static void bgp_session_reset_safe(struct peer *peer, struct listnode **nnode)
+void bgp_session_reset_safe(struct peer *peer, struct listnode **nnode)
{
struct listnode *n;
struct peer *npeer;
@@ -306,11 +306,11 @@ static int bgp_router_id_set(struct bgp *bgp, const struct in_addr *id,
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
IPV4_ADDR_COPY(&peer->local_id, id);
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
- peer->last_reset = PEER_DOWN_RID_CHANGE;
+ peer->last_reset = PEER_DOWN_RID_CHANGE;
+
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- }
}
/* EVPN uses router id in RD, update them */
@@ -440,11 +440,12 @@ void bm_wait_for_fib_set(bool set)
*/
for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {
for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
+ peer->last_reset = PEER_DOWN_SUPPRESS_FIB_PENDING;
+
if (!BGP_IS_VALID_STATE_FOR_NOTIF(
peer->connection->status))
continue;
- peer->last_reset = PEER_DOWN_SUPPRESS_FIB_PENDING;
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
@@ -496,10 +497,11 @@ void bgp_suppress_fib_pending_set(struct bgp *bgp, bool set)
* let's just start over
*/
for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
+ peer->last_reset = PEER_DOWN_SUPPRESS_FIB_PENDING;
+
if (!BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
continue;
- peer->last_reset = PEER_DOWN_SUPPRESS_FIB_PENDING;
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
@@ -523,11 +525,11 @@ void bgp_cluster_id_set(struct bgp *bgp, struct in_addr *cluster_id)
if (peer->sort != BGP_PEER_IBGP)
continue;
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
- peer->last_reset = PEER_DOWN_CLID_CHANGE;
+ peer->last_reset = PEER_DOWN_CLID_CHANGE;
+
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- }
}
}
@@ -547,11 +549,11 @@ void bgp_cluster_id_unset(struct bgp *bgp)
if (peer->sort != BGP_PEER_IBGP)
continue;
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
- peer->last_reset = PEER_DOWN_CLID_CHANGE;
+ peer->last_reset = PEER_DOWN_CLID_CHANGE;
+
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- }
}
}
@@ -676,14 +678,12 @@ void bgp_confederation_id_unset(struct bgp *bgp)
/* We're looking for peers who's AS is not local */
if (peer_sort(peer) != BGP_PEER_IBGP) {
peer->local_as = bgp->as;
+ peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
if (BGP_IS_VALID_STATE_FOR_NOTIF(
- peer->connection->status)) {
- peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
+ peer->connection->status))
bgp_notify_send(peer->connection,
BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- }
-
else
bgp_session_reset_safe(peer, &nnode);
}
@@ -1074,10 +1074,10 @@ static inline enum bgp_peer_sort peer_calc_sort(struct peer *peer)
/* Peer-group */
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- if (peer->as_type == AS_INTERNAL)
+ if (CHECK_FLAG(peer->as_type, AS_INTERNAL))
return BGP_PEER_IBGP;
- else if (peer->as_type == AS_EXTERNAL)
+ if (CHECK_FLAG(peer->as_type, AS_EXTERNAL))
return BGP_PEER_EBGP;
else if (peer->as_type == AS_SPECIFIED && peer->as) {
@@ -1132,17 +1132,20 @@ static inline enum bgp_peer_sort peer_calc_sort(struct peer *peer)
return BGP_PEER_IBGP;
else
return BGP_PEER_EBGP;
- } else if (peer->group->conf->as_type
- == AS_INTERNAL)
+ } else if (CHECK_FLAG(peer->group->conf->as_type,
+ AS_INTERNAL))
return BGP_PEER_IBGP;
else
return BGP_PEER_EBGP;
}
/* no AS information anywhere, let caller know */
return BGP_PEER_UNSPECIFIED;
- } else if (peer->as_type != AS_SPECIFIED)
- return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP
- : BGP_PEER_EBGP);
+ } else if (peer->as_type != AS_SPECIFIED) {
+ if (CHECK_FLAG(peer->as_type, AS_INTERNAL))
+ return BGP_PEER_IBGP;
+ else if (CHECK_FLAG(peer->as_type, AS_EXTERNAL))
+ return BGP_PEER_EBGP;
+ }
return (local_as == 0 ? BGP_PEER_INTERNAL
: local_as == peer->as ? BGP_PEER_IBGP
@@ -1252,7 +1255,6 @@ static void peer_free(struct peer *peer)
EVENT_OFF(peer->t_revalidate_all[afi][safi]);
assert(!peer->connection->t_write);
assert(!peer->connection->t_read);
- event_cancel_event_ready(bm->master, peer->connection);
/* Free connected nexthop, if present */
if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)
@@ -1391,9 +1393,33 @@ int bgp_global_gr_init(struct bgp *bgp)
memcpy(bgp->GLOBAL_GR_FSM, local_GLOBAL_GR_FSM,
sizeof(local_GLOBAL_GR_FSM));
- bgp->global_gr_present_state = GLOBAL_HELPER;
+ /* Inherit any BGP-wide configuration. */
+ if (CHECK_FLAG(bm->flags, BM_FLAG_GR_RESTARTER))
+ bgp->global_gr_present_state = GLOBAL_GR;
+ else if (CHECK_FLAG(bm->flags, BM_FLAG_GR_DISABLED))
+ bgp->global_gr_present_state = GLOBAL_DISABLE;
+ else
+ bgp->global_gr_present_state = GLOBAL_HELPER;
+
+ if (bm->restart_time != BGP_DEFAULT_RESTART_TIME)
+ bgp->restart_time = bm->restart_time;
+ if (bm->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
+ bgp->stalepath_time = bm->stalepath_time;
+ if (bm->select_defer_time != BGP_DEFAULT_SELECT_DEFERRAL_TIME)
+ bgp->select_defer_time = bm->select_defer_time;
+ if (bm->rib_stale_time != BGP_DEFAULT_RIB_STALE_TIME)
+ bgp->rib_stale_time = bm->rib_stale_time;
+ if (CHECK_FLAG(bm->flags, BM_FLAG_GR_PRESERVE_FWD))
+ SET_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD);
+ if (CHECK_FLAG(bm->flags, BM_FLAG_IPV6_NO_AUTO_RA))
+ SET_FLAG(bgp->flags, BGP_FLAG_IPV6_NO_AUTO_RA);
+
bgp->present_zebra_gr_state = ZEBRA_GR_DISABLE;
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug("%s: Global GR state is %s", bgp->name_pretty,
+ print_global_gr_mode(bgp->global_gr_present_state));
+
return BGP_GR_SUCCESS;
}
@@ -1453,9 +1479,7 @@ int bgp_peer_gr_init(struct peer *peer)
{ PEER_HELPER, bgp_peer_gr_action }, { PEER_GLOBAL_INHERIT, NULL }
}
};
- memcpy(&peer->PEER_GR_FSM, local_Peer_GR_FSM,
- sizeof(local_Peer_GR_FSM));
- peer->peer_gr_present_state = PEER_GLOBAL_INHERIT;
+ memcpy(&peer->PEER_GR_FSM, local_Peer_GR_FSM, sizeof(local_Peer_GR_FSM));
bgp_peer_move_to_gr_mode(peer, PEER_GLOBAL_INHERIT);
return BGP_GR_SUCCESS;
@@ -1474,9 +1498,11 @@ static void bgp_srv6_init(struct bgp *bgp)
static void bgp_srv6_cleanup(struct bgp *bgp)
{
for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) {
- if (bgp->vpn_policy[afi].tovpn_sid_locator != NULL)
- srv6_locator_chunk_free(
- &bgp->vpn_policy[afi].tovpn_sid_locator);
+ if (bgp->vpn_policy[afi].tovpn_sid_locator != NULL) {
+ srv6_locator_free(
+ bgp->vpn_policy[afi].tovpn_sid_locator);
+ bgp->vpn_policy[afi].tovpn_sid_locator = NULL;
+ }
if (bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent != NULL)
XFREE(MTYPE_BGP_SRV6_SID,
bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent);
@@ -1487,8 +1513,10 @@ static void bgp_srv6_cleanup(struct bgp *bgp)
}
}
- if (bgp->tovpn_sid_locator != NULL)
- srv6_locator_chunk_free(&bgp->tovpn_sid_locator);
+ if (bgp->tovpn_sid_locator != NULL) {
+ srv6_locator_free(bgp->tovpn_sid_locator);
+ bgp->tovpn_sid_locator = NULL;
+ }
if (bgp->tovpn_zebra_vrf_sid_last_sent != NULL)
XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_zebra_vrf_sid_last_sent);
if (bgp->tovpn_sid != NULL) {
@@ -1500,6 +1528,9 @@ static void bgp_srv6_cleanup(struct bgp *bgp)
list_delete(&bgp->srv6_locator_chunks);
if (bgp->srv6_functions)
list_delete(&bgp->srv6_functions);
+
+ srv6_locator_free(bgp->srv6_locator);
+ bgp->srv6_locator = NULL;
}
/* Allocate new peer object, implicitely locked. */
@@ -1929,7 +1960,7 @@ void bgp_recalculate_all_bestpaths(struct bgp *bgp)
*/
struct peer *peer_create(union sockunion *su, const char *conf_if,
struct bgp *bgp, as_t local_as, as_t remote_as,
- int as_type, struct peer_group *group,
+ enum peer_asn_type as_type, struct peer_group *group,
bool config_node, const char *as_str)
{
int active;
@@ -2061,29 +2092,29 @@ bool bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi)
}
/* Change peer's AS number. */
-void peer_as_change(struct peer *peer, as_t as, int as_specified,
+void peer_as_change(struct peer *peer, as_t as, enum peer_asn_type as_type,
const char *as_str)
{
enum bgp_peer_sort origtype, newtype;
/* Stop peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
- peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
+ peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- } else
+ else
bgp_session_reset(peer);
}
origtype = peer_sort_lookup(peer);
peer->as = as;
- if (as_specified == AS_SPECIFIED && as_str) {
+ if (as_type == AS_SPECIFIED && as_str) {
if (peer->as_pretty)
XFREE(MTYPE_BGP_NAME, peer->as_pretty);
peer->as_pretty = XSTRDUP(MTYPE_BGP_NAME, as_str);
} else if (peer->as_type == AS_UNSPECIFIED && peer->as_pretty)
XFREE(MTYPE_BGP_NAME, peer->as_pretty);
- peer->as_type = as_specified;
+ peer->as_type = as_type;
if (bgp_config_check(peer->bgp, BGP_CONFIG_CONFEDERATION)
&& !bgp_confederation_peers_check(peer->bgp, as)
@@ -2140,7 +2171,7 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified,
/* If peer does not exist, create new one. If peer already exists,
set AS number to the peer. */
int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if,
- as_t *as, int as_type, const char *as_str)
+ as_t *as, enum peer_asn_type as_type, const char *as_str)
{
struct peer *peer;
as_t local_as;
@@ -2181,10 +2212,10 @@ int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if,
}
} else {
/* internal/external used, compare as-types */
- if (((peer_sort_type == BGP_PEER_IBGP)
- && (as_type != AS_INTERNAL))
- || ((peer_sort_type == BGP_PEER_EBGP)
- && (as_type != AS_EXTERNAL))) {
+ if (((peer_sort_type == BGP_PEER_IBGP) &&
+ !CHECK_FLAG(as_type, AS_INTERNAL)) ||
+ ((peer_sort_type == BGP_PEER_EBGP) &&
+ !CHECK_FLAG(as_type, AS_EXTERNAL))) {
*as = peer->as;
return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
}
@@ -2260,7 +2291,7 @@ static void peer_group2peer_config_copy_af(struct peer_group *group,
flags_tmp = conf->af_flags[afi][safi] & ~pflags_ovrd;
flags_tmp ^= conf->af_flags_invert[afi][safi]
^ peer->af_flags_invert[afi][safi];
- flags_tmp &= ~pflags_ovrd;
+ UNSET_FLAG(flags_tmp, pflags_ovrd);
UNSET_FLAG(peer->af_flags[afi][safi], ~pflags_ovrd);
SET_FLAG(peer->af_flags[afi][safi], flags_tmp);
@@ -2423,6 +2454,8 @@ static int peer_activate_af(struct peer *peer, afi_t afi, safi_t safi)
if (!active && peer_active(peer)) {
bgp_timer_set(peer->connection);
} else {
+ peer->last_reset = PEER_DOWN_AF_ACTIVATE;
+
if (peer_established(peer->connection)) {
if (CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV)) {
peer->afc_adv[afi][safi] = 1;
@@ -2435,18 +2468,15 @@ static int peer_activate_af(struct peer *peer, afi_t afi, safi_t safi)
false);
}
} else {
- peer->last_reset = PEER_DOWN_AF_ACTIVATE;
bgp_notify_send(peer->connection,
BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
}
if (peer->connection->status == OpenSent ||
- peer->connection->status == OpenConfirm) {
- peer->last_reset = PEER_DOWN_AF_ACTIVATE;
+ peer->connection->status == OpenConfirm)
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- }
/*
* If we are turning on a AFI/SAFI locally and we've
* started bringing a peer up, we need to tell
@@ -2458,11 +2488,9 @@ static int peer_activate_af(struct peer *peer, afi_t afi, safi_t safi)
*/
other = peer->doppelganger;
if (other && (other->connection->status == OpenSent ||
- other->connection->status == OpenConfirm)) {
- other->last_reset = PEER_DOWN_AF_ACTIVATE;
+ other->connection->status == OpenConfirm))
bgp_notify_send(other->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- }
}
return 0;
@@ -2500,10 +2528,10 @@ int peer_activate(struct peer *peer, afi_t afi, safi_t safi)
group = peer->group;
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) {
- ret |= peer_activate_af(tmp_peer, afi, safi);
+ SET_FLAG(ret, peer_activate_af(tmp_peer, afi, safi));
}
} else {
- ret |= peer_activate_af(peer, afi, safi);
+ SET_FLAG(ret, peer_activate_af(peer, afi, safi));
}
/* If this is the first peer to be activated for this
@@ -2556,6 +2584,8 @@ static bool non_peergroup_deactivate_af(struct peer *peer, afi_t afi,
}
if (peer_established(peer->connection)) {
+ peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
+
if (CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV)) {
peer->afc_adv[afi][safi] = 0;
peer->afc_nego[afi][safi] = 0;
@@ -2567,13 +2597,11 @@ static bool non_peergroup_deactivate_af(struct peer *peer, afi_t afi,
bgp_clear_route(peer, afi, safi);
peer->pcount[afi][safi] = 0;
} else {
- peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
bgp_notify_send(peer->connection,
BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
} else {
- peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
@@ -2602,10 +2630,11 @@ int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi)
group = peer->group;
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) {
- ret |= non_peergroup_deactivate_af(tmp_peer, afi, safi);
+ SET_FLAG(ret, non_peergroup_deactivate_af(tmp_peer, afi,
+ safi));
}
} else {
- ret |= non_peergroup_deactivate_af(peer, afi, safi);
+ SET_FLAG(ret, non_peergroup_deactivate_af(peer, afi, safi));
}
bgp = peer->bgp;
@@ -2907,9 +2936,9 @@ static void peer_group2peer_config_copy(struct peer_group *group,
peer->gtsm_hops = conf->gtsm_hops;
/* peer flags apply */
- flags_tmp = conf->flags & ~peer->flags_override;
+ flags_tmp = CHECK_FLAG(conf->flags, ~peer->flags_override);
flags_tmp ^= conf->flags_invert ^ peer->flags_invert;
- flags_tmp &= ~peer->flags_override;
+ UNSET_FLAG(flags_tmp, peer->flags_override);
UNSET_FLAG(peer->flags, ~peer->flags_override);
SET_FLAG(peer->flags, flags_tmp);
@@ -3001,11 +3030,14 @@ static void peer_group2peer_config_copy(struct peer_group *group,
bgp_peer_configure_bfd(peer, false);
bgp_peer_config_apply(peer, group);
}
+ /* peer tcp-mss */
+ if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_TCP_MSS))
+ PEER_ATTR_INHERIT(peer, group, tcp_mss);
}
/* Peer group's remote AS configuration. */
int peer_group_remote_as(struct bgp *bgp, const char *group_name, as_t *as,
- int as_type, const char *as_str)
+ enum peer_asn_type as_type, const char *as_str)
{
struct peer_group *group;
struct peer *peer;
@@ -3322,13 +3354,13 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
- peer->last_reset = PEER_DOWN_RMAP_BIND;
+ peer->last_reset = PEER_DOWN_RMAP_BIND;
+
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- } else {
+ else
bgp_session_reset(peer);
- }
}
/* Create a new peer. */
@@ -3393,12 +3425,18 @@ static void bgp_vrf_string_name_delete(void *data)
static struct bgp *bgp_create(as_t *as, const char *name,
enum bgp_instance_type inst_type,
const char *as_pretty,
- enum asnotation_mode asnotation)
+ enum asnotation_mode asnotation,
+ struct bgp *bgp_old, bool hidden)
{
struct bgp *bgp;
afi_t afi;
safi_t safi;
+ if (hidden) {
+ bgp = bgp_old;
+ goto peer_init;
+ }
+
bgp = XCALLOC(MTYPE_BGP, sizeof(struct bgp));
bgp->as = *as;
if (as_pretty)
@@ -3452,18 +3490,24 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp->peer_self->domainname =
XSTRDUP(MTYPE_BGP_PEER_HOST, cmd_domainname_get());
bgp->peer = list_new();
+
+peer_init:
bgp->peer->cmp = (int (*)(void *, void *))peer_cmp;
bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_same,
"BGP Peer Hash");
bgp->peerhash->max_size = BGP_PEER_MAX_HASH_SIZE;
- bgp->group = list_new();
+ if (!hidden)
+ bgp->group = list_new();
bgp->group->cmp = (int (*)(void *, void *))peer_group_cmp;
FOREACH_AFI_SAFI (afi, safi) {
- bgp->route[afi][safi] = bgp_table_init(bgp, afi, safi);
- bgp->aggregate[afi][safi] = bgp_table_init(bgp, afi, safi);
- bgp->rib[afi][safi] = bgp_table_init(bgp, afi, safi);
+ if (!hidden) {
+ bgp->route[afi][safi] = bgp_table_init(bgp, afi, safi);
+ bgp->aggregate[afi][safi] = bgp_table_init(bgp, afi,
+ safi);
+ bgp->rib[afi][safi] = bgp_table_init(bgp, afi, safi);
+ }
/* Enable maximum-paths */
bgp_maximum_paths_set(bgp, afi, safi, BGP_PEER_EBGP,
@@ -3484,7 +3528,8 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp->default_subgroup_pkt_queue_max =
BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX;
bgp_tcp_keepalive_unset(bgp);
- bgp_timers_unset(bgp);
+ if (!hidden)
+ bgp_timers_unset(bgp);
bgp->default_min_holdtime = 0;
bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
@@ -3499,10 +3544,10 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp_addpath_init_bgp_data(&bgp->tx_addpath);
bgp->fast_convergence = false;
bgp->llgr_stale_time = BGP_DEFAULT_LLGR_STALE_TIME;
- bgp->rmap_def_originate_eval_timer = RMAP_DEFAULT_ORIGINATE_EVAL_TIMER;
+ bgp->rmap_def_originate_eval_timer = 0;
#ifdef ENABLE_BGP_VNC
- if (inst_type != BGP_INSTANCE_TYPE_VRF) {
+ if (inst_type != BGP_INSTANCE_TYPE_VRF && !hidden) {
bgp->rfapi = bgp_rfapi_new(bgp);
assert(bgp->rfapi);
assert(bgp->rfapi_cfg);
@@ -3519,9 +3564,11 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp->vpn_policy[afi].import_vrf = list_new();
bgp->vpn_policy[afi].import_vrf->del =
bgp_vrf_string_name_delete;
- bgp->vpn_policy[afi].export_vrf = list_new();
- bgp->vpn_policy[afi].export_vrf->del =
- bgp_vrf_string_name_delete;
+ if (!hidden) {
+ bgp->vpn_policy[afi].export_vrf = list_new();
+ bgp->vpn_policy[afi].export_vrf->del =
+ bgp_vrf_string_name_delete;
+ }
SET_FLAG(bgp->af_flags[afi][SAFI_MPLS_VPN],
BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL);
}
@@ -3539,7 +3586,7 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp->restart_time, &bgp->t_startup);
/* printable name we can use in debug messages */
- if (inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
+ if (inst_type == BGP_INSTANCE_TYPE_DEFAULT && !hidden) {
bgp->name_pretty = XSTRDUP(MTYPE_BGP_NAME, "VRF default");
} else {
const char *n;
@@ -3567,17 +3614,20 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME;
bgp->default_af[AFI_IP][SAFI_UNICAST] = true;
- QOBJ_REG(bgp, bgp);
+ if (!hidden)
+ QOBJ_REG(bgp, bgp);
update_bgp_group_init(bgp);
- /* assign a unique rd id for auto derivation of vrf's RD */
- bf_assign_index(bm->rd_idspace, bgp->vrf_rd_id);
+ if (!hidden) {
+ /* assign a unique rd id for auto derivation of vrf's RD */
+ bf_assign_index(bm->rd_idspace, bgp->vrf_rd_id);
- bgp_evpn_init(bgp);
- bgp_evpn_vrf_es_init(bgp);
- bgp_pbr_init(bgp);
- bgp_srv6_init(bgp);
+ bgp_evpn_init(bgp);
+ bgp_evpn_vrf_es_init(bgp);
+ bgp_pbr_init(bgp);
+ bgp_srv6_init(bgp);
+ }
/*initilize global GR FSM */
bgp_global_gr_init(bgp);
@@ -3715,10 +3765,15 @@ int bgp_handle_socket(struct bgp *bgp, struct vrf *vrf, vrf_id_t old_vrf_id,
return bgp_check_main_socket(create, bgp);
}
-int bgp_lookup_by_as_name_type(struct bgp **bgp_val, as_t *as, const char *name,
+int bgp_lookup_by_as_name_type(struct bgp **bgp_val, as_t *as,
+ const char *as_pretty,
+ enum asnotation_mode asnotation, const char *name,
enum bgp_instance_type inst_type)
{
struct bgp *bgp;
+ struct peer *peer = NULL;
+ struct listnode *node, *nnode;
+ bool hidden = false;
/* Multiple instance check. */
if (name)
@@ -3727,14 +3782,41 @@ int bgp_lookup_by_as_name_type(struct bgp **bgp_val, as_t *as, const char *name,
bgp = bgp_get_default();
if (bgp) {
- *bgp_val = bgp;
+ if (IS_BGP_INSTANCE_HIDDEN(bgp) && *as != AS_UNSPECIFIED)
+ hidden = true;
+ /* Handle AS number change */
if (bgp->as != *as) {
+ if (hidden || CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO)) {
+ if (hidden) {
+ bgp_create(as, name, inst_type,
+ as_pretty, asnotation, bgp,
+ hidden);
+ UNSET_FLAG(bgp->flags,
+ BGP_FLAG_INSTANCE_HIDDEN);
+ } else {
+ bgp->as = *as;
+ UNSET_FLAG(bgp->vrf_flags, BGP_VRF_AUTO);
+ }
+
+ /* Set all peer's local AS with this ASN */
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode,
+ peer))
+ peer->local_as = *as;
+ *bgp_val = bgp;
+ return BGP_INSTANCE_EXISTS;
+ }
+
*as = bgp->as;
- return BGP_ERR_AS_MISMATCH;
+ *bgp_val = bgp;
+ return BGP_ERR_INSTANCE_MISMATCH;
}
if (bgp->inst_type != inst_type)
return BGP_ERR_INSTANCE_MISMATCH;
- return BGP_SUCCESS;
+ if (hidden)
+ bgp_create(as, name, inst_type, as_pretty, asnotation,
+ bgp, hidden);
+ *bgp_val = bgp;
+ return BGP_INSTANCE_EXISTS;
}
*bgp_val = NULL;
@@ -3750,11 +3832,13 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
struct vrf *vrf = NULL;
int ret = 0;
- ret = bgp_lookup_by_as_name_type(bgp_val, as, name, inst_type);
+ ret = bgp_lookup_by_as_name_type(bgp_val, as, as_pretty, asnotation,
+ name, inst_type);
if (ret || *bgp_val)
return ret;
- bgp = bgp_create(as, name, inst_type, as_pretty, asnotation);
+ bgp = bgp_create(as, name, inst_type, as_pretty, asnotation, NULL,
+ false);
/*
* view instances will never work inside of a vrf
@@ -3994,6 +4078,15 @@ int bgp_delete(struct bgp *bgp)
bgp_damp_disable(bgp, afi, safi);
}
+ if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT &&
+ (bgp_table_top(bgp->rib[AFI_IP][SAFI_MPLS_VPN]) ||
+ bgp_table_top(bgp->rib[AFI_IP6][SAFI_MPLS_VPN]))) {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug(
+ "Marking the deleting default bgp instance as hidden");
+ SET_FLAG(bgp->flags, BGP_FLAG_INSTANCE_HIDDEN);
+ }
+
if (BGP_DEBUG(zebra, ZEBRA)) {
if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
zlog_debug("Deleting Default VRF");
@@ -4006,7 +4099,8 @@ int bgp_delete(struct bgp *bgp)
}
/* unmap from RT list */
- bgp_evpn_vrf_delete(bgp);
+ if (!IS_BGP_INSTANCE_HIDDEN(bgp))
+ bgp_evpn_vrf_delete(bgp);
/* unmap bgp vrf label */
vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP);
@@ -4038,7 +4132,7 @@ int bgp_delete(struct bgp *bgp)
peer_delete(peer);
}
- if (bgp->peer_self) {
+ if (bgp->peer_self && !IS_BGP_INSTANCE_HIDDEN(bgp)) {
peer_delete(bgp->peer_self);
bgp->peer_self = NULL;
}
@@ -4048,7 +4142,8 @@ int bgp_delete(struct bgp *bgp)
/* TODO - Other memory may need to be freed - e.g., NHT */
#ifdef ENABLE_BGP_VNC
- rfapi_delete(bgp);
+ if (!IS_BGP_INSTANCE_HIDDEN(bgp))
+ rfapi_delete(bgp);
#endif
/* Free memory allocated with aggregate address configuration. */
@@ -4090,7 +4185,7 @@ int bgp_delete(struct bgp *bgp)
}
/* Deregister from Zebra, if needed */
- if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
+ if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp) && !IS_BGP_INSTANCE_HIDDEN(bgp)) {
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug(
"%s: deregistering this bgp %s instance from zebra",
@@ -4098,17 +4193,19 @@ int bgp_delete(struct bgp *bgp)
bgp_zebra_instance_deregister(bgp);
}
- /* Remove visibility via the master list - there may however still be
- * routes to be processed still referencing the struct bgp.
- */
- listnode_delete(bm->bgp, bgp);
-
- /* Free interfaces in this instance. */
- bgp_if_finish(bgp);
+ if (!IS_BGP_INSTANCE_HIDDEN(bgp)) {
+ /* Remove visibility via the master list -
+ * there may however still be routes to be processed
+ * still referencing the struct bgp.
+ */
+ listnode_delete(bm->bgp, bgp);
+ /* Free interfaces in this instance. */
+ bgp_if_finish(bgp);
+ }
vrf = bgp_vrf_lookup_by_instance_type(bgp);
bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, false);
- if (vrf)
+ if (vrf && !IS_BGP_INSTANCE_HIDDEN(bgp))
bgp_vrf_unlink(bgp, vrf);
/* Update EVPN VRF pointer */
@@ -4123,7 +4220,22 @@ int bgp_delete(struct bgp *bgp)
work_queue_free_and_null(&bgp->process_queue);
event_master_free_unused(bm->master);
- bgp_unlock(bgp); /* initial reference */
+
+ if (!IS_BGP_INSTANCE_HIDDEN(bgp))
+ bgp_unlock(bgp); /* initial reference */
+ else {
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ enum vpn_policy_direction dir;
+
+ if (bgp->vpn_policy[afi].import_vrf)
+ list_delete(&bgp->vpn_policy[afi].import_vrf);
+
+ dir = BGP_VPN_POLICY_DIR_FROMVPN;
+ if (bgp->vpn_policy[afi].rtlist[dir])
+ ecommunity_free(
+ &bgp->vpn_policy[afi].rtlist[dir]);
+ }
+ }
return 0;
}
@@ -4523,6 +4635,12 @@ bool peer_active(struct peer *peer)
{
if (BGP_CONNECTION_SU_UNSPEC(peer->connection))
return false;
+
+ if (peer->bfd_config) {
+ if (bfd_session_is_down(peer->bfd_config->session))
+ return false;
+ }
+
if (peer->afc[AFI_IP][SAFI_UNICAST] || peer->afc[AFI_IP][SAFI_MULTICAST]
|| peer->afc[AFI_IP][SAFI_LABELED_UNICAST]
|| peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP][SAFI_ENCAP]
@@ -4662,6 +4780,7 @@ static const struct peer_flag_action peer_flag_action_list[] = {
{PEER_FLAG_LOCAL_AS, 0, peer_change_reset},
{PEER_FLAG_LOCAL_AS_NO_PREPEND, 0, peer_change_reset},
{PEER_FLAG_LOCAL_AS_REPLACE_AS, 0, peer_change_reset},
+ {PEER_FLAG_DUAL_AS, 0, peer_change_reset},
{PEER_FLAG_UPDATE_SOURCE, 0, peer_change_none},
{PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE, 0, peer_change_none},
{PEER_FLAG_EXTENDED_OPT_PARAMS, 0, peer_change_reset},
@@ -4674,6 +4793,8 @@ static const struct peer_flag_action peer_flag_action_list[] = {
{PEER_FLAG_CAPABILITY_FQDN, 0, peer_change_none},
{PEER_FLAG_AS_LOOP_DETECTION, 0, peer_change_none},
{PEER_FLAG_EXTENDED_LINK_BANDWIDTH, 0, peer_change_none},
+ {PEER_FLAG_LONESOUL, 0, peer_change_reset_out},
+ {PEER_FLAG_TCP_MSS, 0, peer_change_none},
{0, 0, 0}};
static const struct peer_flag_action peer_af_flag_action_list[] = {
@@ -4729,7 +4850,7 @@ static int peer_flag_action_set(const struct peer_flag_action *action_list,
if (match->flag == 0)
break;
- if (match->flag & flag) {
+ if (CHECK_FLAG(match->flag, flag)) {
found = 1;
if (match->type == peer_change_reset_in)
@@ -4760,6 +4881,13 @@ static int peer_flag_action_set(const struct peer_flag_action *action_list,
static void peer_flag_modify_action(struct peer *peer, uint64_t flag)
{
+ if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
+ peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
+ else if (flag == PEER_FLAG_PASSIVE)
+ peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
+ else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
+ peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
+
if (flag == PEER_FLAG_SHUTDOWN) {
if (CHECK_FLAG(peer->flags, flag)) {
if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT))
@@ -4808,13 +4936,6 @@ static void peer_flag_modify_action(struct peer *peer, uint64_t flag)
BGP_EVENT_ADD(peer->connection, BGP_Stop);
}
} else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
- if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
- peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
- else if (flag == PEER_FLAG_PASSIVE)
- peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
- else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
- peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
-
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
} else
@@ -5056,15 +5177,17 @@ static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
ptype = peer_sort(peer);
/* Special check for reflector client. */
- if (flag & PEER_FLAG_REFLECTOR_CLIENT && ptype != BGP_PEER_IBGP)
+ if (CHECK_FLAG(flag, PEER_FLAG_REFLECTOR_CLIENT) &&
+ ptype != BGP_PEER_IBGP)
return BGP_ERR_NOT_INTERNAL_PEER;
/* Special check for remove-private-AS. */
- if (flag & PEER_FLAG_REMOVE_PRIVATE_AS && ptype == BGP_PEER_IBGP)
+ if (CHECK_FLAG(flag, PEER_FLAG_REMOVE_PRIVATE_AS) &&
+ ptype == BGP_PEER_IBGP)
return BGP_ERR_REMOVE_PRIVATE_AS;
/* as-override is not allowed for IBGP peers */
- if (flag & PEER_FLAG_AS_OVERRIDE && ptype == BGP_PEER_IBGP)
+ if (CHECK_FLAG(flag, PEER_FLAG_AS_OVERRIDE) && ptype == BGP_PEER_IBGP)
return BGP_ERR_AS_OVERRIDE;
/* Handle flag updates where desired state matches current state. */
@@ -5115,7 +5238,7 @@ static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
* If the peer is a route server client let's not
* muck with the nexthop on the way out the door
*/
- if (flag & PEER_FLAG_RSERVER_CLIENT) {
+ if (CHECK_FLAG(flag, PEER_FLAG_RSERVER_CLIENT)) {
if (set)
SET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_NEXTHOP_UNCHANGED);
@@ -5532,12 +5655,12 @@ int peer_update_source_if_set(struct peer *peer, const char *ifname)
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
/* Send notification or reset peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
- peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- } else
+ else
bgp_session_reset(peer);
/* Apply new source configuration to BFD session. */
@@ -5569,13 +5692,13 @@ int peer_update_source_if_set(struct peer *peer, const char *ifname)
member->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname);
sockunion_free(member->update_source);
member->update_source = NULL;
+ member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
/* Send notification or reset peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) {
- member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status))
bgp_notify_send(member->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- } else
+ else
bgp_session_reset(member);
/* Apply new source configuration to BFD session. */
@@ -5603,12 +5726,12 @@ void peer_update_source_addr_set(struct peer *peer, const union sockunion *su)
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
/* Send notification or reset peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
- peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- } else
+ else
bgp_session_reset(peer);
/* Apply new source configuration to BFD session. */
@@ -5639,13 +5762,13 @@ void peer_update_source_addr_set(struct peer *peer, const union sockunion *su)
SET_FLAG(member->flags, PEER_FLAG_UPDATE_SOURCE);
member->update_source = sockunion_dup(su);
XFREE(MTYPE_PEER_UPDATE_SOURCE, member->update_if);
+ member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
/* Send notification or reset peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) {
- member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status))
bgp_notify_send(member->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- } else
+ else
bgp_session_reset(member);
/* Apply new source configuration to BFD session. */
@@ -5691,12 +5814,12 @@ void peer_update_source_unset(struct peer *peer)
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
/* Send notification or reset peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
- peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- } else
+ else
bgp_session_reset(peer);
/* Apply new source configuration to BFD session. */
@@ -5726,13 +5849,13 @@ void peer_update_source_unset(struct peer *peer)
sockunion_free(member->update_source);
member->update_source = NULL;
XFREE(MTYPE_PEER_UPDATE_SOURCE, member->update_if);
+ member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
/* Send notification or reset peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) {
- member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status))
bgp_notify_send(member->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- } else
+ else
bgp_session_reset(member);
/* Apply new source configuration to BFD session. */
@@ -5754,6 +5877,10 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
subgrp = peer_subgroup(peer, afi, safi);
if (rmap) {
+ if (!peer->bgp->rmap_def_originate_eval_timer)
+ peer->bgp->rmap_def_originate_eval_timer =
+ RMAP_DEFAULT_ORIGINATE_EVAL_TIMER;
+
if (!peer->default_rmap[afi][safi].name
|| strcmp(rmap, peer->default_rmap[afi][safi].name) != 0) {
struct route_map *map = NULL;
@@ -5836,6 +5963,10 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
if (rmap) {
struct route_map *map = NULL;
+ if (!member->bgp->rmap_def_originate_eval_timer)
+ member->bgp->rmap_def_originate_eval_timer =
+ RMAP_DEFAULT_ORIGINATE_EVAL_TIMER;
+
if (member->default_rmap[afi][safi].name) {
map = route_map_lookup_by_name(
member->default_rmap[afi][safi].name);
@@ -5965,9 +6096,27 @@ void peer_port_unset(struct peer *peer)
*/
void peer_tcp_mss_set(struct peer *peer, uint32_t tcp_mss)
{
+ struct peer *member;
+ struct listnode *node, *nnode;
+
+ peer_flag_set(peer, PEER_FLAG_TCP_MSS);
peer->tcp_mss = tcp_mss;
- SET_FLAG(peer->flags, PEER_FLAG_TCP_MSS);
- bgp_tcp_mss_set(peer);
+
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ bgp_tcp_mss_set(peer);
+ return;
+ }
+
+ for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
+ /* Skip peers with overridden configuration. */
+ if (CHECK_FLAG(member->flags_override, PEER_FLAG_TCP_MSS))
+ continue;
+
+ /* Set flag and configuration on peer-group member. */
+ SET_FLAG(member->flags, PEER_FLAG_TCP_MSS);
+ PEER_ATTR_INHERIT(member, peer->group, tcp_mss);
+ bgp_tcp_mss_set(member);
+ }
}
/* Reset the TCP-MSS value in the peer structure,
@@ -5976,9 +6125,39 @@ void peer_tcp_mss_set(struct peer *peer, uint32_t tcp_mss)
*/
void peer_tcp_mss_unset(struct peer *peer)
{
- UNSET_FLAG(peer->flags, PEER_FLAG_TCP_MSS);
- peer->tcp_mss = 0;
- bgp_tcp_mss_set(peer);
+ struct peer *member;
+ struct listnode *node, *nnode;
+
+ /* Inherit configuration from peer-group if peer is member. */
+ if (peer_group_active(peer)) {
+ peer_flag_inherit(peer, PEER_FLAG_TCP_MSS);
+ PEER_ATTR_INHERIT(peer, peer->group, tcp_mss);
+ } else {
+ /* Otherwise remove flag and configuration from peer. */
+ peer_flag_unset(peer, PEER_FLAG_TCP_MSS);
+ peer->tcp_mss = 0;
+ }
+
+ /* Skip peer-group mechanics for regular peers. */
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ bgp_tcp_mss_set(peer);
+ return;
+ }
+
+ /*
+ * Remove flag and configuration from all peer-group members, unless
+ * they are explicitely overriding peer-group configuration.
+ */
+ for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
+ /* Skip peers with overridden configuration. */
+ if (CHECK_FLAG(member->flags_override, PEER_FLAG_TCP_MSS))
+ continue;
+
+ /* Remove flag and configuration on peer-group member. */
+ UNSET_FLAG(member->flags, PEER_FLAG_TCP_MSS);
+ member->tcp_mss = 0;
+ bgp_tcp_mss_set(member);
+ }
}
/*
@@ -6601,9 +6780,9 @@ int peer_allowas_in_unset(struct peer *peer, afi_t afi, safi_t safi)
}
int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend,
- bool replace_as, const char *as_str)
+ bool replace_as, bool dual_as, const char *as_str)
{
- bool old_no_prepend, old_replace_as;
+ bool old_no_prepend, old_replace_as, old_dual_as;
struct bgp *bgp = peer->bgp;
struct peer *member;
struct listnode *node, *nnode;
@@ -6616,14 +6795,16 @@ int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend,
!!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
old_replace_as =
!!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
+ old_dual_as = !!CHECK_FLAG(peer->flags, PEER_FLAG_DUAL_AS);
/* Set flag and configuration on peer. */
peer_flag_set(peer, PEER_FLAG_LOCAL_AS);
peer_flag_modify(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND, no_prepend);
peer_flag_modify(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS, replace_as);
+ peer_flag_modify(peer, PEER_FLAG_DUAL_AS, dual_as);
- if (peer->change_local_as == as && old_no_prepend == no_prepend
- && old_replace_as == replace_as)
+ if (peer->change_local_as == as && old_no_prepend == no_prepend &&
+ old_replace_as == replace_as && old_dual_as == dual_as)
return 0;
peer->change_local_as = as;
if (as_str) {
@@ -6652,10 +6833,11 @@ int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend,
PEER_FLAG_LOCAL_AS_NO_PREPEND);
old_replace_as = CHECK_FLAG(member->flags,
PEER_FLAG_LOCAL_AS_REPLACE_AS);
- if (member->change_local_as == as
- && CHECK_FLAG(member->flags, PEER_FLAG_LOCAL_AS)
- && old_no_prepend == no_prepend
- && old_replace_as == replace_as)
+ old_dual_as = !!CHECK_FLAG(member->flags, PEER_FLAG_DUAL_AS);
+ if (member->change_local_as == as &&
+ CHECK_FLAG(member->flags, PEER_FLAG_LOCAL_AS) &&
+ old_no_prepend == no_prepend &&
+ old_replace_as == replace_as && old_dual_as == dual_as)
continue;
/* Set flag and configuration on peer-group member. */
@@ -6664,6 +6846,7 @@ int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend,
no_prepend);
COND_FLAG(member->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS,
replace_as);
+ COND_FLAG(member->flags, PEER_FLAG_DUAL_AS, dual_as);
member->change_local_as = as;
if (as_str)
member->change_local_as_pretty = XSTRDUP(MTYPE_BGP_NAME,
@@ -6686,24 +6869,26 @@ int peer_local_as_unset(struct peer *peer)
peer_flag_inherit(peer, PEER_FLAG_LOCAL_AS);
peer_flag_inherit(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);
peer_flag_inherit(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS);
+ peer_flag_inherit(peer, PEER_FLAG_DUAL_AS);
PEER_ATTR_INHERIT(peer, peer->group, change_local_as);
} else {
/* Otherwise remove flag and configuration from peer. */
peer_flag_unset(peer, PEER_FLAG_LOCAL_AS);
peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);
peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS);
+ peer_flag_unset(peer, PEER_FLAG_DUAL_AS);
peer->change_local_as = 0;
XFREE(MTYPE_BGP_NAME, peer->change_local_as_pretty);
}
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
/* Send notification or stop peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
- peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- } else
+ else
BGP_EVENT_ADD(peer->connection, BGP_Stop);
/* Skip peer-group mechanics for regular peers. */
@@ -6723,15 +6908,16 @@ int peer_local_as_unset(struct peer *peer)
UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS);
UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
+ UNSET_FLAG(member->flags, PEER_FLAG_DUAL_AS);
member->change_local_as = 0;
XFREE(MTYPE_BGP_NAME, member->change_local_as_pretty);
+ member->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
/* Send notification or stop peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) {
- member->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status))
bgp_notify_send(member->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- } else
+ else
bgp_session_reset(member);
}
@@ -6758,6 +6944,7 @@ int peer_password_set(struct peer *peer, const char *password)
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ peer->last_reset = PEER_DOWN_PASSWORD_CHANGE;
/* Send notification or reset peer depending on state. */
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
@@ -6795,6 +6982,7 @@ int peer_password_set(struct peer *peer, const char *password)
XFREE(MTYPE_PEER_PASSWORD, member->password);
member->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
+ member->last_reset = PEER_DOWN_PASSWORD_CHANGE;
/* Send notification or reset peer depending on state. */
if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status))
bgp_notify_send(member->connection, BGP_NOTIFY_CEASE,
@@ -8401,8 +8589,8 @@ void bgp_master_init(struct event_loop *master, const int buffer_size,
bm->start_time = monotime(NULL);
bm->t_rmap_update = NULL;
bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER;
- bm->v_update_delay = BGP_UPDATE_DELAY_DEF;
- bm->v_establish_wait = BGP_UPDATE_DELAY_DEF;
+ bm->v_update_delay = BGP_UPDATE_DELAY_DEFAULT;
+ bm->v_establish_wait = BGP_UPDATE_DELAY_DEFAULT;
bm->terminating = false;
bm->socket_buffer = buffer_size;
bm->wait_for_fib = false;
@@ -8412,6 +8600,10 @@ void bgp_master_init(struct event_loop *master, const int buffer_size,
bm->t_bgp_sync_label_manager = NULL;
bm->t_bgp_start_label_manager = NULL;
bm->t_bgp_zebra_route = NULL;
+ bm->restart_time = BGP_DEFAULT_RESTART_TIME;
+ bm->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
+ bm->select_defer_time = BGP_DEFAULT_SELECT_DEFERRAL_TIME;
+ bm->rib_stale_time = BGP_DEFAULT_RIB_STALE_TIME;
bgp_mac_init();
/* init the rd id space.
@@ -8763,6 +8955,12 @@ static ssize_t printfrr_bp(struct fbuf *buf, struct printfrr_eargs *ea,
if (!peer)
return bputs(buf, "(null)");
+ if (!peer->host) {
+ if (peer->conf_if)
+ return bprintfrr(buf, "%s", peer->conf_if);
+ return bprintfrr(buf, "%pSU", &peer->connection->su);
+ }
+
return bprintfrr(buf, "%s(%s)", peer->host,
peer->hostname ? peer->hostname : "Unknown");
}
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 1f8cc533..8aeb0eb4 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -56,10 +56,12 @@ struct bgp_pbr_config;
* behavior
* in the system.
*/
-enum { AS_UNSPECIFIED = 0,
- AS_SPECIFIED,
- AS_INTERNAL,
- AS_EXTERNAL,
+enum peer_asn_type {
+ AS_UNSPECIFIED = 1,
+ AS_SPECIFIED = 2,
+ AS_INTERNAL = 4,
+ AS_EXTERNAL = 8,
+ AS_AUTO = 16,
};
/* Zebra Gracaful Restart states */
@@ -129,6 +131,7 @@ struct bgp_master {
#define BGP_OPT_NO_ZEBRA (1 << 2)
#define BGP_OPT_TRAPS_RFC4273 (1 << 3)
#define BGP_OPT_TRAPS_BGP4MIBV2 (1 << 4)
+#define BGP_OPT_TRAPS_RFC4382 (1 << 5)
uint64_t updgrp_idspace;
uint64_t subgrp_idspace;
@@ -163,6 +166,24 @@ struct bgp_master {
uint32_t flags;
#define BM_FLAG_GRACEFUL_SHUTDOWN (1 << 0)
#define BM_FLAG_SEND_EXTRA_DATA_TO_ZEBRA (1 << 1)
+#define BM_FLAG_MAINTENANCE_MODE (1 << 2)
+#define BM_FLAG_GR_RESTARTER (1 << 3)
+#define BM_FLAG_GR_DISABLED (1 << 4)
+#define BM_FLAG_GR_PRESERVE_FWD (1 << 5)
+#define BM_FLAG_GRACEFUL_RESTART (1 << 6)
+#define BM_FLAG_GR_COMPLETE (1 << 7)
+#define BM_FLAG_IPV6_NO_AUTO_RA (1 << 8)
+
+#define BM_FLAG_GR_CONFIGURED (BM_FLAG_GR_RESTARTER | BM_FLAG_GR_DISABLED)
+
+ /* BGP-wide graceful restart config params */
+ uint32_t restart_time;
+ uint32_t stalepath_time;
+ uint32_t select_defer_time;
+ uint32_t rib_stale_time;
+
+ time_t startup_time;
+ time_t gr_completion_time;
bool terminating; /* global flag that sigint terminate seen */
@@ -250,7 +271,7 @@ struct vpn_policy {
*/
uint32_t tovpn_sid_index; /* unset => set to 0 */
struct in6_addr *tovpn_sid;
- struct srv6_locator_chunk *tovpn_sid_locator;
+ struct srv6_locator *tovpn_sid_locator;
uint32_t tovpn_sid_transpose_label;
struct in6_addr *tovpn_zebra_vrf_sid_last_sent;
};
@@ -293,9 +314,9 @@ struct graceful_restart_info {
/* Best route select */
struct event *t_route_select;
/* AFI, SAFI enabled */
- bool af_enabled[AFI_MAX][SAFI_MAX];
+ bool af_enabled;
/* Route update completed */
- bool route_sync[AFI_MAX][SAFI_MAX];
+ bool route_sync;
};
enum global_mode {
@@ -470,9 +491,7 @@ struct bgp {
uint32_t restarted_peers;
uint32_t implicit_eors;
uint32_t explicit_eors;
-#define BGP_UPDATE_DELAY_DEF 0
-#define BGP_UPDATE_DELAY_MIN 0
-#define BGP_UPDATE_DELAY_MAX 3600
+#define BGP_UPDATE_DELAY_DEFAULT 0
/* Reference bandwidth for BGP link-bandwidth. Used when
* the LB value has to be computed based on some other
@@ -532,6 +551,9 @@ struct bgp {
#define BGP_FLAG_ENFORCE_FIRST_AS (1ULL << 36)
#define BGP_FLAG_DYNAMIC_CAPABILITY (1ULL << 37)
#define BGP_FLAG_VNI_DOWN (1ULL << 38)
+#define BGP_FLAG_INSTANCE_HIDDEN (1ULL << 39)
+/* Prohibit BGP from enabling IPv6 RA on interfaces */
+#define BGP_FLAG_IPV6_NO_AUTO_RA (1ULL << 40)
/* BGP default address-families.
* New peers inherit enabled afi/safis from bgp instance.
@@ -547,6 +569,9 @@ struct bgp {
*/
enum zebra_gr_mode present_zebra_gr_state;
+ /* Is deferred path selection still not complete? */
+ bool gr_route_sync_pending;
+
/* BGP Per AF flags */
uint16_t af_flags[AFI_MAX][SAFI_MAX];
#define BGP_CONFIG_DAMPENING (1 << 0)
@@ -815,11 +840,12 @@ struct bgp {
/* BGP VPN SRv6 backend */
bool srv6_enabled;
char srv6_locator_name[SRV6_LOCNAME_SIZE];
+ struct srv6_locator *srv6_locator;
struct list *srv6_locator_chunks;
struct list *srv6_functions;
uint32_t tovpn_sid_index; /* unset => set to 0 */
struct in6_addr *tovpn_sid;
- struct srv6_locator_chunk *tovpn_sid_locator;
+ struct srv6_locator *tovpn_sid_locator;
uint32_t tovpn_sid_transpose_label;
struct in6_addr *tovpn_zebra_vrf_sid_last_sent;
@@ -1226,7 +1252,7 @@ struct peer {
struct peer_af *peer_af_array[BGP_AF_MAX];
/* Peer's remote AS number. */
- int as_type;
+ enum peer_asn_type as_type;
as_t as;
/* for vty as format */
char *as_pretty;
@@ -1485,6 +1511,7 @@ struct peer {
#define PEER_FLAG_CAPABILITY_FQDN (1ULL << 37) /* fqdn capability */
#define PEER_FLAG_AS_LOOP_DETECTION (1ULL << 38) /* as path loop detection */
#define PEER_FLAG_EXTENDED_LINK_BANDWIDTH (1ULL << 39)
+#define PEER_FLAG_DUAL_AS (1ULL << 40)
/*
*GR-Disabled mode means unset PEER_FLAG_GRACEFUL_RESTART
@@ -1797,6 +1824,7 @@ struct peer {
#define PEER_DOWN_SOCKET_ERROR 34U /* Some socket error happened */
#define PEER_DOWN_RTT_SHUTDOWN 35U /* Automatically shutdown due to RTT */
#define PEER_DOWN_SUPPRESS_FIB_PENDING 36U /* Suppress fib pending changed */
+#define PEER_DOWN_PASSWORD_CHANGE 37U /* neighbor password command */
/*
* Remember to update peer_down_str in bgp_fsm.c when you add
* a new value to the last_reset reason
@@ -1805,16 +1833,13 @@ struct peer {
struct stream *last_reset_cause;
/* The kind of route-map Flags.*/
- uint16_t rmap_type;
+ uint8_t rmap_type;
#define PEER_RMAP_TYPE_IN (1U << 0) /* neighbor route-map in */
#define PEER_RMAP_TYPE_OUT (1U << 1) /* neighbor route-map out */
#define PEER_RMAP_TYPE_NETWORK (1U << 2) /* network route-map */
#define PEER_RMAP_TYPE_REDISTRIBUTE (1U << 3) /* redistribute route-map */
#define PEER_RMAP_TYPE_DEFAULT (1U << 4) /* default-originate route-map */
-#define PEER_RMAP_TYPE_NOSET (1U << 5) /* not allow to set commands */
-#define PEER_RMAP_TYPE_IMPORT (1U << 6) /* neighbor route-map import */
-#define PEER_RMAP_TYPE_EXPORT (1U << 7) /* neighbor route-map export */
-#define PEER_RMAP_TYPE_AGGREGATE (1U << 8) /* aggregate-address route-map */
+#define PEER_RMAP_TYPE_AGGREGATE (1U << 5) /* aggregate-address route-map */
/** Peer overwrite configuration. */
struct bfd_session_config {
@@ -2132,6 +2157,7 @@ enum bgp_clear_type {
enum bgp_create_error_code {
BGP_SUCCESS = 0,
BGP_CREATED = 1,
+ BGP_INSTANCE_EXISTS = 2,
BGP_ERR_INVALID_VALUE = -1,
BGP_ERR_INVALID_FLAG = -2,
BGP_ERR_INVALID_AS = -3,
@@ -2261,8 +2287,9 @@ extern bool peer_afc_advertised(struct peer *peer);
extern void bgp_recalculate_all_bestpaths(struct bgp *bgp);
extern struct peer *peer_create(union sockunion *su, const char *conf_if,
struct bgp *bgp, as_t local_as, as_t remote_as,
- int as_type, struct peer_group *group,
- bool config_node, const char *as_str);
+ enum peer_asn_type as_type,
+ struct peer_group *group, bool config_node,
+ const char *as_str);
extern struct peer *peer_create_accept(struct bgp *);
extern void peer_xfer_config(struct peer *dst, struct peer *src);
extern char *peer_uptime(time_t uptime2, char *buf, size_t len, bool use_json,
@@ -2335,13 +2362,13 @@ extern void bgp_listen_limit_unset(struct bgp *bgp);
extern bool bgp_update_delay_active(struct bgp *);
extern bool bgp_update_delay_configured(struct bgp *);
extern bool bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi);
-extern void peer_as_change(struct peer *peer, as_t as, int as_type,
- const char *as_str);
+extern void peer_as_change(struct peer *peer, as_t as,
+ enum peer_asn_type as_type, const char *as_str);
extern int peer_remote_as(struct bgp *bgp, union sockunion *su,
- const char *conf_if, as_t *as, int as_type,
- const char *as_str);
+ const char *conf_if, as_t *as,
+ enum peer_asn_type as_type, const char *as_str);
extern int peer_group_remote_as(struct bgp *bgp, const char *peer_str, as_t *as,
- int as_type, const char *as_str);
+ enum peer_asn_type as_type, const char *as_str);
extern int peer_delete(struct peer *peer);
extern void peer_notify_unconfig(struct peer *peer);
extern int peer_group_delete(struct peer_group *);
@@ -2422,7 +2449,7 @@ extern int peer_allowas_in_set(struct peer *, afi_t, safi_t, int, int);
extern int peer_allowas_in_unset(struct peer *, afi_t, safi_t);
extern int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend,
- bool replace_as, const char *as_str);
+ bool replace_as, bool dual_as, const char *as_str);
extern int peer_local_as_unset(struct peer *);
extern int peer_prefix_list_set(struct peer *, afi_t, safi_t, int,
@@ -2742,12 +2769,67 @@ static inline bool bgp_in_graceful_shutdown(struct bgp *bgp)
!!CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN));
}
+static inline bool bgp_in_graceful_restart(void)
+{
+ /* True if BGP has (re)started gracefully (based on flags
+ * noted at startup) and GR is not complete.
+ */
+ return (CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_RESTART) &&
+ !CHECK_FLAG(bm->flags, BM_FLAG_GR_COMPLETE));
+}
+
+static inline bool bgp_is_graceful_restart_complete(void)
+{
+ /* True if BGP has (re)started gracefully (based on flags
+ * noted at startup) and GR is marked as complete.
+ */
+ return (CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_RESTART) &&
+ CHECK_FLAG(bm->flags, BM_FLAG_GR_COMPLETE));
+}
+
+static inline void bgp_update_gr_completion(void)
+{
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+
+ /*
+ * Check and mark GR complete. This is done when deferred
+ * path selection has been completed for all instances and
+ * route-advertisement/EOR and route-sync with zebra has
+ * been invoked.
+ */
+ if (!CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_RESTART) ||
+ CHECK_FLAG(bm->flags, BM_FLAG_GR_COMPLETE))
+ return;
+
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ if (bgp->gr_route_sync_pending)
+ return;
+ }
+
+ SET_FLAG(bm->flags, BM_FLAG_GR_COMPLETE);
+ bm->gr_completion_time = monotime(NULL);
+}
+
+static inline bool bgp_gr_is_forwarding_preserved(struct bgp *bgp)
+{
+ /*
+ * Is forwarding state preserved? Based either on config
+ * or if BGP restarted gracefully.
+ * TBD: Additional AFI/SAFI based checks etc.
+ */
+ return (CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_RESTART) ||
+ CHECK_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD));
+}
+
/* For benefit of rfapi */
extern struct peer *peer_new(struct bgp *bgp);
extern struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp,
const char *ip_str, bool use_json);
extern int bgp_lookup_by_as_name_type(struct bgp **bgp_val, as_t *as,
+ const char *as_pretty,
+ enum asnotation_mode asnotation,
const char *name,
enum bgp_instance_type inst_type);
@@ -2781,10 +2863,25 @@ extern bool bgp_path_attribute_treat_as_withdraw(struct peer *peer, char *buf,
extern void srv6_function_free(struct bgp_srv6_function *func);
+extern void bgp_session_reset_safe(struct peer *peer, struct listnode **nnode);
+
#ifdef _FRR_ATTRIBUTE_PRINTFRR
/* clang-format off */
#pragma FRR printfrr_ext "%pBP" (struct peer *)
/* clang-format on */
#endif
+/* Macro to check if default bgp instance is hidden */
+#define IS_BGP_INSTANCE_HIDDEN(_bgp) \
+ (CHECK_FLAG(_bgp->flags, BGP_FLAG_INSTANCE_HIDDEN) && \
+ (_bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT || \
+ _bgp->inst_type == BGP_INSTANCE_TYPE_VRF))
+
+/* Macro to check if bgp instance delete in-progress and !hidden */
+#define BGP_INSTANCE_HIDDEN_DELETE_IN_PROGRESS(_bgp, _afi, _safi) \
+ (CHECK_FLAG(_bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) && \
+ !IS_BGP_INSTANCE_HIDDEN(_bgp) && \
+ !(_afi == AFI_IP && _safi == SAFI_MPLS_VPN) && \
+ !(_afi == AFI_IP6 && _safi == SAFI_MPLS_VPN))
+
#endif /* _QUAGGA_BGPD_H */
diff --git a/bgpd/rfapi/vnc_export_bgp.c b/bgpd/rfapi/vnc_export_bgp.c
index 7decb757..4de23066 100644
--- a/bgpd/rfapi/vnc_export_bgp.c
+++ b/bgpd/rfapi/vnc_export_bgp.c
@@ -388,7 +388,7 @@ void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn,
bgp_withdraw(bpi->peer, p, 0, /* addpath_id */
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
- NULL, 0, NULL); /* tag not used for unicast */
+ NULL, 0); /* tag not used for unicast */
}
static void vnc_direct_bgp_vpn_enable_ce(struct bgp *bgp, afi_t afi)
@@ -473,16 +473,14 @@ static void vnc_direct_bgp_vpn_disable_ce(struct bgp *bgp, afi_t afi)
if (ri->type == ZEBRA_ROUTE_VNC_DIRECT
&& ri->sub_type == BGP_ROUTE_REDISTRIBUTE) {
-
- bgp_withdraw(
- ri->peer, bgp_dest_get_prefix(dest),
- 0, /* addpath_id */
- AFI_IP, SAFI_UNICAST,
- ZEBRA_ROUTE_VNC_DIRECT,
- BGP_ROUTE_REDISTRIBUTE,
- NULL, /* RD not used for unicast */
- NULL, 0,
- NULL); /* tag not used for unicast */
+ bgp_withdraw(ri->peer, bgp_dest_get_prefix(dest),
+ 0, /* addpath_id */
+ AFI_IP, SAFI_UNICAST,
+ ZEBRA_ROUTE_VNC_DIRECT,
+ BGP_ROUTE_REDISTRIBUTE,
+ NULL, /* RD not used for unicast */
+ NULL,
+ 0); /* tag not used for unicast */
}
}
}
@@ -863,9 +861,8 @@ void vnc_direct_bgp_del_prefix(struct bgp *bgp,
0, /* addpath_id */
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
BGP_ROUTE_REDISTRIBUTE,
- NULL, /* RD not used for unicast */
- NULL, 0,
- NULL); /* tag not used for unicast */
+ NULL, /* RD not used for unicast */
+ NULL, 0); /* tag not used for unicast */
/*
* yuck!
* - but consistent with rest of function
@@ -892,9 +889,8 @@ void vnc_direct_bgp_del_prefix(struct bgp *bgp,
0, /* addpath_id */
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
BGP_ROUTE_REDISTRIBUTE,
- NULL, /* RD not used for unicast */
- NULL, 0,
- NULL); /* tag not used for unicast */
+ NULL, /* RD not used for unicast */
+ NULL, 0); /* tag not used for unicast */
}
}
}
@@ -1125,13 +1121,13 @@ void vnc_direct_bgp_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
continue;
bgp_withdraw(irfd->peer, p, /* prefix */
- 0, /* addpath_id */
+ 0, /* addpath_id */
afi, SAFI_UNICAST,
ZEBRA_ROUTE_VNC_DIRECT,
BGP_ROUTE_REDISTRIBUTE,
NULL, /* RD not used for
unicast */
- NULL, 0, NULL); /* tag not
+ NULL, 0); /* tag not
used for
unicast */
}
@@ -1359,7 +1355,7 @@ static void vnc_direct_del_rn_group_rd(struct bgp *bgp,
0, /* addpath_id */
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
- NULL, 0, NULL); /* tag not used for unicast */
+ NULL, 0); /* tag not used for unicast */
return;
}
@@ -1471,16 +1467,15 @@ static void vnc_direct_bgp_unexport_table(afi_t afi, struct agg_table *rt,
for (ALL_LIST_ELEMENTS_RO(nve_list, hln,
irfd)) {
-
bgp_withdraw(irfd->peer,
agg_node_get_prefix(rn),
- 0, /* addpath_id */
+ 0, /* addpath_id */
afi, SAFI_UNICAST,
ZEBRA_ROUTE_VNC_DIRECT,
BGP_ROUTE_REDISTRIBUTE,
NULL, /* RD not used for
unicast */
- NULL, 0, NULL); /* tag not
+ NULL, 0); /* tag not
used for
unicast,
EVPN
@@ -1715,8 +1710,7 @@ static void vncExportWithdrawTimer(struct event *t)
bgp_withdraw(eti->peer, p, 0, /* addpath_id */
family2afi(p->family), SAFI_UNICAST, eti->type,
eti->subtype, NULL, /* RD not used for unicast */
- NULL, 0,
- NULL); /* tag not used for unicast, EVPN neither */
+ NULL, 0); /* tag not used for unicast, EVPN neither */
/*
* Free the eti
@@ -2001,7 +1995,7 @@ void vnc_direct_bgp_rh_vpn_disable(struct bgp *bgp, afi_t afi)
ZEBRA_ROUTE_VNC_DIRECT_RH,
BGP_ROUTE_REDISTRIBUTE,
NULL, /* RD not used for unicast */
- NULL, 0, NULL); /* tag not used for
+ NULL, 0); /* tag not used for
unicast, EVPN
neither */
}