summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 04:24:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 04:24:31 +0000
commitacb594b1d825c6e12369cebb941968ec08c840ce (patch)
treed544788908e7353a4f117e2991f15f4236a0c963 /bgpd
parentAdding upstream version 9.1. (diff)
downloadfrr-acb594b1d825c6e12369cebb941968ec08c840ce.tar.xz
frr-acb594b1d825c6e12369cebb941968ec08c840ce.zip
Adding upstream version 10.0.upstream/10.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--bgpd/bgp_addpath.c33
-rw-r--r--bgpd/bgp_addpath.h8
-rw-r--r--bgpd/bgp_advertise.c34
-rw-r--r--bgpd/bgp_advertise.h38
-rw-r--r--bgpd/bgp_aspath.c5
-rw-r--r--bgpd/bgp_aspath.h8
-rw-r--r--bgpd/bgp_attr.c57
-rw-r--r--bgpd/bgp_attr.h96
-rw-r--r--bgpd/bgp_bmp.c548
-rw-r--r--bgpd/bgp_bmp.h10
-rw-r--r--bgpd/bgp_btoa.c1
-rw-r--r--bgpd/bgp_clist.c1
-rw-r--r--bgpd/bgp_conditional_adv.c5
-rw-r--r--bgpd/bgp_damp.h5
-rw-r--r--bgpd/bgp_debug.c188
-rw-r--r--bgpd/bgp_debug.h13
-rw-r--r--bgpd/bgp_dump.c1
-rw-r--r--bgpd/bgp_ecommunity.c32
-rw-r--r--bgpd/bgp_ecommunity.h7
-rw-r--r--bgpd/bgp_evpn.c166
-rw-r--r--bgpd/bgp_evpn.h29
-rw-r--r--bgpd/bgp_evpn_mh.c46
-rw-r--r--bgpd/bgp_evpn_mh.h5
-rw-r--r--bgpd/bgp_evpn_vty.c8
-rw-r--r--bgpd/bgp_filter.c20
-rw-r--r--bgpd/bgp_filter.h6
-rw-r--r--bgpd/bgp_flowspec_vty.c2
-rw-r--r--bgpd/bgp_fsm.c100
-rw-r--r--bgpd/bgp_fsm.h9
-rw-r--r--bgpd/bgp_label.c9
-rw-r--r--bgpd/bgp_labelpool.c32
-rw-r--r--bgpd/bgp_main.c47
-rw-r--r--bgpd/bgp_memory.c2
-rw-r--r--bgpd/bgp_memory.h2
-rw-r--r--bgpd/bgp_mpath.c63
-rw-r--r--bgpd/bgp_mplsvpn.c171
-rw-r--r--bgpd/bgp_mplsvpn.h43
-rw-r--r--bgpd/bgp_mplsvpn_snmp.c6
-rw-r--r--bgpd/bgp_network.c16
-rw-r--r--bgpd/bgp_nexthop.h27
-rw-r--r--bgpd/bgp_nhg.c99
-rw-r--r--bgpd/bgp_nhg.h18
-rw-r--r--bgpd/bgp_nht.c186
-rw-r--r--bgpd/bgp_nht.h11
-rw-r--r--bgpd/bgp_open.c87
-rw-r--r--bgpd/bgp_open.h2
-rw-r--r--bgpd/bgp_packet.c564
-rw-r--r--bgpd/bgp_pbr.h2
-rw-r--r--bgpd/bgp_rd.h2
-rw-r--r--bgpd/bgp_route.c365
-rw-r--r--bgpd/bgp_route.h88
-rw-r--r--bgpd/bgp_routemap.c60
-rw-r--r--bgpd/bgp_routemap_nb.c11
-rw-r--r--bgpd/bgp_routemap_nb.h17
-rw-r--r--bgpd/bgp_routemap_nb_config.c165
-rw-r--r--bgpd/bgp_rpki.c1382
-rw-r--r--bgpd/bgp_rpki.h2
-rw-r--r--bgpd/bgp_snmp.c85
-rw-r--r--bgpd/bgp_snmp.h3
-rw-r--r--bgpd/bgp_snmp_bgp4.c4
-rw-r--r--bgpd/bgp_snmp_bgp4.h4
-rw-r--r--bgpd/bgp_snmp_bgp4v2.c204
-rw-r--r--bgpd/bgp_snmp_bgp4v2.h10
-rw-r--r--bgpd/bgp_trace.h94
-rw-r--r--bgpd/bgp_updgrp.c35
-rw-r--r--bgpd/bgp_updgrp.h25
-rw-r--r--bgpd/bgp_updgrp_adv.c56
-rw-r--r--bgpd/bgp_vpn.c21
-rw-r--r--bgpd/bgp_vty.c536
-rw-r--r--bgpd/bgp_vty.h2
-rw-r--r--bgpd/bgp_zebra.c475
-rw-r--r--bgpd/bgp_zebra.h5
-rw-r--r--bgpd/bgpd.c172
-rw-r--r--bgpd/bgpd.h113
-rw-r--r--bgpd/rfapi/bgp_rfapi_cfg.c176
-rw-r--r--bgpd/rfapi/rfapi.c83
-rw-r--r--bgpd/rfapi/rfapi_import.c266
-rw-r--r--bgpd/rfapi/rfapi_import.h2
-rw-r--r--bgpd/rfapi/rfapi_monitor.c2
-rw-r--r--bgpd/rfapi/rfapi_rib.c29
-rw-r--r--bgpd/rfapi/rfapi_vty.c84
-rw-r--r--bgpd/rfapi/vnc_import_bgp.c32
-rw-r--r--bgpd/rfapi/vnc_zebra.c2
-rw-r--r--bgpd/subdir.am3
84 files changed, 5302 insertions, 2181 deletions
diff --git a/bgpd/bgp_addpath.c b/bgpd/bgp_addpath.c
index de4b4a4..f391c13 100644
--- a/bgpd/bgp_addpath.c
+++ b/bgpd/bgp_addpath.c
@@ -10,6 +10,8 @@
#include "bgp_addpath.h"
#include "bgp_route.h"
+#include "bgp_open.h"
+#include "bgp_packet.h"
static const struct bgp_addpath_strategy_names strat_names[BGP_ADDPATH_MAX] = {
{
@@ -359,6 +361,31 @@ void bgp_addpath_type_changed(struct bgp *bgp)
}
}
+int bgp_addpath_capability_action(enum bgp_addpath_strat addpath_type,
+ uint8_t paths)
+{
+ int action = CAPABILITY_ACTION_UNSET;
+
+ switch (addpath_type) {
+ case BGP_ADDPATH_ALL:
+ case BGP_ADDPATH_BEST_PER_AS:
+ action = CAPABILITY_ACTION_SET;
+ break;
+ case BGP_ADDPATH_BEST_SELECTED:
+ if (paths)
+ action = CAPABILITY_ACTION_SET;
+ else
+ action = CAPABILITY_ACTION_UNSET;
+ break;
+ case BGP_ADDPATH_NONE:
+ case BGP_ADDPATH_MAX:
+ action = CAPABILITY_ACTION_UNSET;
+ break;
+ }
+
+ return action;
+}
+
/*
* Change the addpath type assigned to a peer, or peer group. In addition to
* adjusting the counts, peer sessions will be reset as needed to make the
@@ -373,6 +400,7 @@ void bgp_addpath_set_peer_type(struct peer *peer, afi_t afi, safi_t safi,
struct listnode *node, *nnode;
struct peer *tmp_peer;
struct peer_group *group;
+ int action = bgp_addpath_capability_action(addpath_type, paths);
if (safi == SAFI_LABELED_UNICAST)
safi = SAFI_UNICAST;
@@ -430,9 +458,12 @@ void bgp_addpath_set_peer_type(struct peer *peer, afi_t afi, safi_t safi,
}
}
} else {
- peer_change_action(peer, afi, safi, peer_change_reset);
+ if (!CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV) &&
+ !CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV))
+ peer_change_action(peer, afi, safi, peer_change_reset);
}
+ bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_ADDPATH, action);
}
/*
diff --git a/bgpd/bgp_addpath.h b/bgpd/bgp_addpath.h
index 2b91d45..d562000 100644
--- a/bgpd/bgp_addpath.h
+++ b/bgpd/bgp_addpath.h
@@ -15,6 +15,12 @@
#include "bgpd/bgp_table.h"
#include "lib/json.h"
+struct bgp_addpath_capability {
+ uint16_t afi;
+ uint8_t safi;
+ uint8_t flags;
+};
+
#define BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE 1
void bgp_addpath_init_bgp_data(struct bgp_addpath_bgp_data *d);
@@ -57,4 +63,6 @@ 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);
#endif
diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c
index 17d6592..a81f288 100644
--- a/bgpd/bgp_advertise.c
+++ b/bgpd/bgp_advertise.c
@@ -36,6 +36,8 @@ struct bgp_advertise_attr *bgp_advertise_attr_new(void)
void bgp_advertise_attr_free(struct bgp_advertise_attr *baa)
{
+ bgp_advertise_attr_fifo_fini(&baa->fifo);
+
XFREE(MTYPE_BGP_ADVERTISE_ATTR, baa);
}
@@ -46,6 +48,9 @@ static void *bgp_advertise_attr_hash_alloc(void *p)
baa = bgp_advertise_attr_new();
baa->attr = ref->attr;
+
+ bgp_advertise_attr_fifo_init(&baa->fifo);
+
return baa;
}
@@ -83,36 +88,13 @@ void bgp_advertise_free(struct bgp_advertise *adv)
void bgp_advertise_add(struct bgp_advertise_attr *baa,
struct bgp_advertise *adv)
{
- struct bgp_advertise *spot, *prev = NULL;
-
- spot = baa->adv;
-
- while (spot) {
- prev = spot;
- spot = spot->next;
- }
-
- if (prev) {
- prev->next = adv;
- adv->prev = prev;
- } else
- adv->prev = NULL;
-
- adv->next = NULL;
-
- if (!baa->adv)
- baa->adv = adv;
+ bgp_advertise_attr_fifo_add_tail(&baa->fifo, adv);
}
void bgp_advertise_delete(struct bgp_advertise_attr *baa,
struct bgp_advertise *adv)
{
- if (adv->next)
- adv->next->prev = adv->prev;
- if (adv->prev)
- adv->prev->next = adv->next;
- else
- baa->adv = adv->next;
+ bgp_advertise_attr_fifo_del(&baa->fifo, adv);
}
struct bgp_advertise_attr *bgp_advertise_attr_intern(struct hash *hash,
@@ -187,7 +169,7 @@ void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr,
for (adj = dest->adj_in; adj; adj = adj->next) {
if (adj->peer == peer && adj->addpath_rx_id == addpath_id) {
- if (adj->attr != attr) {
+ if (!attrhash_cmp(adj->attr, attr)) {
bgp_attr_unintern(&adj->attr);
adj->attr = bgp_attr_intern(attr);
}
diff --git a/bgpd/bgp_advertise.h b/bgpd/bgp_advertise.h
index 94168e2..4982106 100644
--- a/bgpd/bgp_advertise.h
+++ b/bgpd/bgp_advertise.h
@@ -11,26 +11,19 @@
PREDECL_DLIST(bgp_adv_fifo);
struct update_subgroup;
+struct bgp_advertise;
-/* BGP advertise attribute. */
-struct bgp_advertise_attr {
- /* Head of advertisement pointer. */
- struct bgp_advertise *adv;
-
- /* Reference counter. */
- unsigned long refcnt;
+PREDECL_DLIST(bgp_advertise_attr_fifo);
- /* Attribute pointer to be announced. */
- struct attr *attr;
-};
+struct bgp_advertise_attr;
+/* BGP advertise attribute. */
struct bgp_advertise {
/* FIFO for advertisement. */
struct bgp_adv_fifo_item fifo;
- /* Link list for same attribute advertise. */
- struct bgp_advertise *next;
- struct bgp_advertise *prev;
+ /* FIFO for this item in the bgp_advertise_attr fifo */
+ struct bgp_advertise_attr_fifo_item item;
/* Prefix information. */
struct bgp_dest *dest;
@@ -45,8 +38,21 @@ struct bgp_advertise {
struct bgp_path_info *pathi;
};
+DECLARE_DLIST(bgp_advertise_attr_fifo, struct bgp_advertise, item);
DECLARE_DLIST(bgp_adv_fifo, struct bgp_advertise, fifo);
+/* BGP advertise attribute. */
+struct bgp_advertise_attr {
+ /* Head of advertisement pointer. */
+ struct bgp_advertise_attr_fifo_head fifo;
+
+ /* Reference counter. */
+ unsigned long refcnt;
+
+ /* Attribute pointer to be announced. */
+ struct attr *attr;
+};
+
/* BGP adjacency out. */
struct bgp_adj_out {
/* RB Tree of adjacency entries */
@@ -63,14 +69,14 @@ struct bgp_adj_out {
uint32_t addpath_tx_id;
+ /* Attribute hash */
+ uint32_t attr_hash;
+
/* Advertised attribute. */
struct attr *attr;
/* Advertisement information. */
struct bgp_advertise *adv;
-
- /* Attribute hash */
- uint32_t attr_hash;
};
RB_HEAD(bgp_adj_out_rb, bgp_adj_out);
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 0e70de9..bc7e893 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -1407,7 +1407,8 @@ struct aspath *aspath_remove_private_asns(struct aspath *aspath, as_t peer_asn)
last_new_seg = new_seg;
seg = seg->next;
}
-
+ if (!aspath->refcnt)
+ aspath_free(aspath);
aspath_str_update(new, false);
return new;
}
@@ -1892,7 +1893,7 @@ struct aspath *aspath_reconcile_as4(struct aspath *aspath,
"[AS4] AS4PATHmangle: AS_CONFED_SEQUENCE falls across 2/4 ASN boundary somewhere, broken..");
hops = seg->length;
}
- /* fallthru */
+ fallthrough;
case AS_SEQUENCE:
cpasns = MIN(seg->length, hops);
hops -= seg->length;
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index ebfc7d0..2a831c3 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -65,6 +65,14 @@ struct aspath {
#define ASPATH_STR_DEFAULT_LEN 32
+/* `set as-path exclude ASn' */
+struct aspath_exclude {
+ struct aspath *aspath;
+ bool exclude_all;
+ char *exclude_aspath_acl_name;
+ struct as_list *exclude_aspath_acl;
+};
+
/* Prototypes. */
extern void aspath_init(void);
extern void aspath_finish(void);
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 56e77eb..53420b4 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -864,6 +864,7 @@ bool attrhash_cmp(const void *p1, const void *p2)
attr1->df_alg == attr2->df_alg &&
attr1->nh_ifindex == attr2->nh_ifindex &&
attr1->nh_lla_ifindex == attr2->nh_lla_ifindex &&
+ attr1->nh_flags == attr2->nh_flags &&
attr1->distance == attr2->distance &&
srv6_l3vpn_same(attr1->srv6_l3vpn, attr2->srv6_l3vpn) &&
srv6_vpn_same(attr1->srv6_vpn, attr2->srv6_vpn) &&
@@ -1381,6 +1382,15 @@ bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode,
(args->startp - STREAM_DATA(BGP_INPUT(peer)))
+ args->total);
+ /* Partial optional attributes that are malformed should not cause
+ * the whole session to be reset. Instead treat it as a withdrawal
+ * of the routes, if possible.
+ */
+ if (CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS) &&
+ CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL) &&
+ CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL))
+ return BGP_ATTR_PARSE_WITHDRAW;
+
switch (args->type) {
/* where an attribute is relatively inconsequential, e.g. it does not
* affect route selection, and can be safely ignored, then any such
@@ -1390,6 +1400,7 @@ bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode,
case BGP_ATTR_AS4_AGGREGATOR:
case BGP_ATTR_AGGREGATOR:
case BGP_ATTR_ATOMIC_AGGREGATE:
+ case BGP_ATTR_PREFIX_SID:
return BGP_ATTR_PARSE_PROCEED;
/* Core attributes, particularly ones which may influence route
@@ -1417,19 +1428,21 @@ bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode,
BGP_NOTIFY_UPDATE_ERR, subcode,
notify_datap, length);
return BGP_ATTR_PARSE_ERROR;
+ default:
+ /* Unknown attributes, that are handled by this function
+ * should be treated as withdraw, to prevent one more CVE
+ * from being introduced.
+ * RFC 7606 says:
+ * The "treat-as-withdraw" approach is generally preferred
+ * and the "session reset" approach is discouraged.
+ */
+ flog_err(EC_BGP_ATTR_FLAG,
+ "%s(%u) attribute received, while it is not known how to handle it, treating as withdraw",
+ lookup_msg(attr_str, args->type, NULL), args->type);
+ break;
}
- /* Partial optional attributes that are malformed should not cause
- * the whole session to be reset. Instead treat it as a withdrawal
- * of the routes, if possible.
- */
- if (CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)
- && CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
- && CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL))
- return BGP_ATTR_PARSE_WITHDRAW;
-
- /* default to reset */
- return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
+ return BGP_ATTR_PARSE_WITHDRAW;
}
/* Find out what is wrong with the path attribute flag bits and log the error.
@@ -1839,7 +1852,9 @@ bgp_attr_local_pref(struct bgp_attr_parser_args *args)
* UPDATE message SHALL be handled using the approach of "treat-as-
* withdraw".
*/
- if (peer->sort == BGP_PEER_IBGP && length != 4) {
+ if ((peer->sort == BGP_PEER_IBGP ||
+ peer->sub_sort == BGP_PEER_EBGP_OAD) &&
+ length != 4) {
flog_err(EC_BGP_ATTR_LEN,
"LOCAL_PREF attribute length isn't 4 [%u]", length);
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
@@ -1849,7 +1864,7 @@ bgp_attr_local_pref(struct bgp_attr_parser_args *args)
/* If it is contained in an UPDATE message that is received from an
external peer, then this attribute MUST be ignored by the
receiving speaker. */
- if (peer->sort == BGP_PEER_EBGP) {
+ if (peer->sort == BGP_PEER_EBGP && peer->sub_sort != BGP_PEER_EBGP_OAD) {
STREAM_FORWARD_GETP(peer->curr, length);
return BGP_ATTR_PARSE_PROCEED;
}
@@ -2321,11 +2336,8 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
/*
* NOTE: intentional fall through
* - for consistency in rx processing
- *
- * The following comment is to signal GCC this intention
- * and suppress the warning
*/
- /* FALLTHRU */
+ fallthrough;
case BGP_ATTR_NHLEN_IPV4:
stream_get(&attr->mp_nexthop_global_in, s, IPV4_MAX_BYTELEN);
/* Probably needed for RFC 2283 */
@@ -3144,8 +3156,6 @@ enum bgp_attr_parse_ret bgp_attr_prefix_sid(struct bgp_attr_parser_args *args)
struct attr *const attr = args->attr;
enum bgp_attr_parse_ret ret;
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
-
uint8_t type;
uint16_t length;
size_t headersz = sizeof(type) + sizeof(length);
@@ -3195,6 +3205,8 @@ 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;
}
@@ -3267,7 +3279,8 @@ static enum bgp_attr_parse_ret bgp_attr_aigp(struct bgp_attr_parser_args *args)
* the default value of AIGP_SESSION SHOULD be "enabled".
*/
if (peer->sort == BGP_PEER_EBGP &&
- !CHECK_FLAG(peer->flags, PEER_FLAG_AIGP)) {
+ (!CHECK_FLAG(peer->flags, PEER_FLAG_AIGP) ||
+ peer->sub_sort != BGP_PEER_EBGP_OAD)) {
zlog_warn(
"%pBP received AIGP attribute, but eBGP peer do not support it",
peer);
@@ -4492,7 +4505,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
}
/* Local preference. */
- if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) {
+ if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED ||
+ peer->sub_sort == BGP_PEER_EBGP_OAD) {
stream_putc(s, BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_LOCAL_PREF);
stream_putc(s, 4);
@@ -4858,6 +4872,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)) {
/* At the moment only AIGP Metric TLV exists for AIGP
* attribute. If more comes in, do not forget to update
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index d30155e..d78f04c 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -155,10 +155,56 @@ struct attr {
uint32_t med;
uint32_t local_pref;
ifindex_t nh_ifindex;
+ uint8_t nh_flags;
+
+#define BGP_ATTR_NH_VALID 0x01
/* Path origin attribute */
uint8_t origin;
+ /* ES info */
+ uint8_t es_flags;
+ /* Path is not "locally-active" on the advertising VTEP. This is
+ * translated into an ARP-ND ECOM.
+ */
+#define ATTR_ES_PROXY_ADVERT (1 << 0)
+ /* Destination ES is present locally. This flag is set on local
+ * paths and sync paths
+ */
+#define ATTR_ES_IS_LOCAL (1 << 1)
+ /* There are one or more non-best paths from ES peers. Note that
+ * this flag is only set on the local MAC-IP paths in the VNI
+ * route table (not set in the global routing table). And only
+ * non-proxy advertisements from an ES peer can result in this
+ * flag being set.
+ */
+#define ATTR_ES_PEER_ACTIVE (1 << 2)
+ /* There are one or more non-best proxy paths from ES peers */
+#define ATTR_ES_PEER_PROXY (1 << 3)
+ /* An ES peer has router bit set - only applicable if
+ * ATTR_ES_PEER_ACTIVE is set
+ */
+#define ATTR_ES_PEER_ROUTER (1 << 4)
+
+ /* These two flags are only set on L3 routes installed in a
+ * VRF as a result of EVPN MAC-IP route
+ * XXX - while splitting up per-family attrs these need to be
+ * classified as non-EVPN
+ */
+#define ATTR_ES_L3_NHG_USE (1 << 5)
+#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;
+
+ /* EVPN DF preference for DF election on local ESs */
+ uint8_t df_alg;
+ uint16_t df_pref;
+
/* PMSI tunnel type (RFC 6514). */
enum pta_type pmsi_tnl_type;
@@ -173,6 +219,9 @@ struct attr {
/* ifIndex corresponding to mp_nexthop_local. */
ifindex_t nh_lla_ifindex;
+ /* MPLS label */
+ mpls_label_t label;
+
/* Extended Communities attribute. */
struct ecommunity *ecommunity;
@@ -214,58 +263,18 @@ struct attr {
/* Flag for default gateway extended community in EVPN */
uint8_t default_gw;
- /* NA router flag (R-bit) support in EVPN */
- uint8_t router_flag;
-
- /* ES info */
- uint8_t es_flags;
- /* Path is not "locally-active" on the advertising VTEP. This is
- * translated into an ARP-ND ECOM.
- */
-#define ATTR_ES_PROXY_ADVERT (1 << 0)
- /* Destination ES is present locally. This flag is set on local
- * paths and sync paths
- */
-#define ATTR_ES_IS_LOCAL (1 << 1)
- /* There are one or more non-best paths from ES peers. Note that
- * this flag is only set on the local MAC-IP paths in the VNI
- * route table (not set in the global routing table). And only
- * non-proxy advertisements from an ES peer can result in this
- * flag being set.
- */
-#define ATTR_ES_PEER_ACTIVE (1 << 2)
- /* There are one or more non-best proxy paths from ES peers */
-#define ATTR_ES_PEER_PROXY (1 << 3)
- /* An ES peer has router bit set - only applicable if
- * ATTR_ES_PEER_ACTIVE is set
- */
-#define ATTR_ES_PEER_ROUTER (1 << 4)
-
- /* These two flags are only set on L3 routes installed in a
- * VRF as a result of EVPN MAC-IP route
- * XXX - while splitting up per-family attrs these need to be
- * classified as non-EVPN
- */
-#define ATTR_ES_L3_NHG_USE (1 << 5)
-#define ATTR_ES_L3_NHG_ACTIVE (1 << 6)
-#define ATTR_ES_L3_NHG (ATTR_ES_L3_NHG_USE | ATTR_ES_L3_NHG_ACTIVE)
-
/* route tag */
route_tag_t tag;
/* Label index */
uint32_t label_index;
- /* MPLS label */
- mpls_label_t label;
-
/* SRv6 VPN SID */
struct bgp_attr_srv6_vpn *srv6_vpn;
/* SRv6 L3VPN SID */
struct bgp_attr_srv6_l3vpn *srv6_l3vpn;
- uint16_t encap_tunneltype; /* grr */
struct bgp_attr_encap_subtlv *encap_subtlvs; /* rfc5512 */
#ifdef ENABLE_BGP_VNC
@@ -287,8 +296,7 @@ struct attr {
/* EVPN local router-mac */
struct ethaddr rmac;
- /* Distance as applied by Route map */
- uint8_t distance;
+ uint16_t encap_tunneltype;
/* rmap set table */
uint32_t rmap_table_id;
@@ -302,10 +310,6 @@ struct attr {
/* SR-TE Color */
uint32_t srte_color;
- /* EVPN DF preference and algorithm for DF election on local ESs */
- uint16_t df_pref;
- uint8_t df_alg;
-
/* Nexthop type */
enum nexthop_types_t nh_type;
diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c
index 7270802..1de48a0 100644
--- a/bgpd/bgp_bmp.c
+++ b/bgpd/bgp_bmp.c
@@ -240,60 +240,115 @@ static void bmp_free(struct bmp *bmp)
XFREE(MTYPE_BMP_CONN, bmp);
}
+#define BMP_PEER_TYPE_GLOBAL_INSTANCE 0
+#define BMP_PEER_TYPE_RD_INSTANCE 1
+#define BMP_PEER_TYPE_LOCAL_INSTANCE 2
+#define BMP_PEER_TYPE_LOC_RIB_INSTANCE 3
+
+static inline int bmp_get_peer_distinguisher(struct bmp *bmp, afi_t afi,
+ uint8_t peer_type,
+ uint64_t *result_ref)
+{
+
+ /* remove this check when the other peer types get correct peer dist.
+ *(RFC7854) impl.
+ * for now, always return no error and 0 peer distinguisher as before
+ */
+ if (peer_type != BMP_PEER_TYPE_LOC_RIB_INSTANCE)
+ return (*result_ref = 0);
+
+ /* sending vrf_id or rd could be turned into an option at some point */
+ struct bgp *bgp = bmp->targets->bgp;
+
+ /* vrf default => ok, distinguisher 0 */
+ if (bgp->inst_type == VRF_DEFAULT)
+ return (*result_ref = 0);
+
+ /* use RD if set in VRF config for this AFI */
+ struct prefix_rd *prd = &bgp->vpn_policy[afi].tovpn_rd;
+
+ if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_RD_SET)) {
+ memcpy(result_ref, prd->val, sizeof(prd->val));
+ return 0;
+ }
+
+ /* VRF has no id => error => message should be skipped */
+ if (bgp->vrf_id == VRF_UNKNOWN)
+ return 1;
+
+ /* use VRF id converted to ::vrf_id 64bits format */
+ *result_ref = ((uint64_t)htonl(bgp->vrf_id)) << 32;
+ return 0;
+}
+
static void bmp_common_hdr(struct stream *s, uint8_t ver, uint8_t type)
{
stream_putc(s, ver);
- stream_putl(s, 0); //dummy message length. will be set later.
+ stream_putl(s, 0); /* dummy message length. will be set later. */
stream_putc(s, type);
}
-static void bmp_per_peer_hdr(struct stream *s, struct peer *peer,
- uint8_t flags, const struct timeval *tv)
+static void bmp_per_peer_hdr(struct stream *s, struct bgp *bgp,
+ struct peer *peer, uint8_t flags,
+ uint8_t peer_type_flag,
+ uint64_t peer_distinguisher,
+ const struct timeval *tv)
{
- char peer_distinguisher[8];
-
-#define BMP_PEER_TYPE_GLOBAL_INSTANCE 0
-#define BMP_PEER_TYPE_RD_INSTANCE 1
-#define BMP_PEER_TYPE_LOCAL_INSTANCE 2
-
#define BMP_PEER_FLAG_V (1 << 7)
#define BMP_PEER_FLAG_L (1 << 6)
#define BMP_PEER_FLAG_A (1 << 5)
+ bool is_locrib = peer_type_flag == BMP_PEER_TYPE_LOC_RIB_INSTANCE;
+
/* Peer Type */
- stream_putc(s, BMP_PEER_TYPE_GLOBAL_INSTANCE);
+ stream_putc(s, peer_type_flag);
/* Peer Flags */
- if (peer->connection->su.sa.sa_family == AF_INET6)
+ if (!is_locrib && peer->connection->su.sa.sa_family == AF_INET6)
SET_FLAG(flags, BMP_PEER_FLAG_V);
else
UNSET_FLAG(flags, BMP_PEER_FLAG_V);
stream_putc(s, flags);
/* Peer Distinguisher */
- memset (&peer_distinguisher[0], 0, 8);
- stream_put(s, &peer_distinguisher[0], 8);
+ stream_put(s, (uint8_t *)&peer_distinguisher, 8);
/* Peer Address */
- if (peer->connection->su.sa.sa_family == AF_INET6)
- stream_put(s, &peer->connection->su.sin6.sin6_addr, 16);
- else if (peer->connection->su.sa.sa_family == AF_INET) {
+ /* Set to 0 if it's a LOC-RIB INSTANCE (RFC 9069) or if it's not an
+ * IPv4/6 address
+ */
+ if (is_locrib || (peer->connection->su.sa.sa_family != AF_INET6 &&
+ peer->connection->su.sa.sa_family != AF_INET)) {
stream_putl(s, 0);
stream_putl(s, 0);
stream_putl(s, 0);
- stream_put_in_addr(s, &peer->connection->su.sin.sin_addr);
- } else {
stream_putl(s, 0);
+ } else if (peer->connection->su.sa.sa_family == AF_INET6)
+ stream_put(s, &peer->connection->su.sin6.sin6_addr, IPV6_MAX_BYTELEN);
+ else if (peer->connection->su.sa.sa_family == AF_INET) {
stream_putl(s, 0);
stream_putl(s, 0);
stream_putl(s, 0);
+ stream_put_in_addr(s, &peer->connection->su.sin.sin_addr);
}
/* Peer AS */
- stream_putl(s, peer->as);
+ /* set peer ASN but for LOC-RIB INSTANCE (RFC 9069) put the local bgp
+ * ASN
+ */
+ as_t asn = !is_locrib ? peer->as : bgp->as;
+
+ stream_putl(s, asn);
/* Peer BGP ID */
- stream_put_in_addr(s, &peer->remote_id);
+ /* set router-id but for LOC-RIB INSTANCE (RFC 9069) put the instance
+ * router-id
+ */
+ struct in_addr *bgp_id =
+ !is_locrib ? &peer->remote_id : &bgp->router_id;
+
+ stream_put_in_addr(s, bgp_id);
/* Timestamp */
if (tv) {
@@ -314,11 +369,26 @@ static void bmp_put_info_tlv(struct stream *s, uint16_t type,
stream_put(s, string, len);
}
+static void __attribute__((unused))
+bmp_put_vrftablename_info_tlv(struct stream *s, struct bmp *bmp)
+{
+
+#define BMP_INFO_TYPE_VRFTABLENAME 3
+ const char *vrftablename = "global";
+ if (bmp->targets->bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
+ struct vrf *vrf = vrf_lookup_by_id(bmp->targets->bgp->vrf_id);
+
+ vrftablename = vrf ? vrf->name : NULL;
+ }
+ if (vrftablename != NULL)
+ bmp_put_info_tlv(s, BMP_INFO_TYPE_VRFTABLENAME, vrftablename);
+}
+
static int bmp_send_initiation(struct bmp *bmp)
{
int len;
- struct stream *s;
- s = stream_new(BGP_MAX_PACKET_SIZE);
+ struct stream *s = stream_new(BGP_MAX_PACKET_SIZE);
+
bmp_common_hdr(s, BMP_VERSION_3, BMP_TYPE_INITIATION);
#define BMP_INFO_TYPE_SYSDESCR 1
@@ -328,7 +398,7 @@ static int bmp_send_initiation(struct bmp *bmp)
bmp_put_info_tlv(s, BMP_INFO_TYPE_SYSNAME, cmd_hostname_get());
len = stream_get_endp(s);
- stream_putl_at(s, BMP_LENGTH_POS, len); //message length is set.
+ stream_putl_at(s, BMP_LENGTH_POS, len); /* message length is set. */
pullwr_write_stream(bmp->pullwr, s);
stream_free(s);
@@ -375,7 +445,9 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down)
bmp_common_hdr(s, BMP_VERSION_3,
BMP_TYPE_PEER_UP_NOTIFICATION);
- bmp_per_peer_hdr(s, peer, 0, &uptime_real);
+ bmp_per_peer_hdr(s, peer->bgp, peer, 0,
+ BMP_PEER_TYPE_GLOBAL_INSTANCE, 0,
+ &uptime_real);
/* Local Address (16 bytes) */
if (peer->su_local->sa.sa_family == AF_INET6)
@@ -428,7 +500,9 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down)
bmp_common_hdr(s, BMP_VERSION_3,
BMP_TYPE_PEER_DOWN_NOTIFICATION);
- bmp_per_peer_hdr(s, peer, 0, &uptime_real);
+ bmp_per_peer_hdr(s, peer->bgp, peer, 0,
+ BMP_PEER_TYPE_GLOBAL_INSTANCE, 0,
+ &uptime_real);
type_pos = stream_get_endp(s);
stream_putc(s, 0); /* placeholder for down reason */
@@ -460,7 +534,7 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down)
}
len = stream_get_endp(s);
- stream_putl_at(s, BMP_LENGTH_POS, len); //message length is set.
+ stream_putl_at(s, BMP_LENGTH_POS, len); /* message length is set. */
return s;
}
@@ -618,7 +692,8 @@ static void bmp_wrmirror_lost(struct bmp *bmp, struct pullwr *pullwr)
s = stream_new(BGP_MAX_PACKET_SIZE);
bmp_common_hdr(s, BMP_VERSION_3, BMP_TYPE_ROUTE_MIRRORING);
- bmp_per_peer_hdr(s, bmp->targets->bgp->peer_self, 0, &tv);
+ bmp_per_peer_hdr(s, bmp->targets->bgp, bmp->targets->bgp->peer_self, 0,
+ BMP_PEER_TYPE_GLOBAL_INSTANCE, 0, &tv);
stream_putw(s, BMP_MIRROR_TLV_TYPE_INFO);
stream_putw(s, 2);
@@ -656,7 +731,8 @@ static bool bmp_wrmirror(struct bmp *bmp, struct pullwr *pullwr)
s = stream_new(BGP_MAX_PACKET_SIZE);
bmp_common_hdr(s, BMP_VERSION_3, BMP_TYPE_ROUTE_MIRRORING);
- bmp_per_peer_hdr(s, peer, 0, &bmq->tv);
+ bmp_per_peer_hdr(s, bmp->targets->bgp, peer, 0,
+ BMP_PEER_TYPE_GLOBAL_INSTANCE, 0, &bmq->tv);
/* BMP Mirror TLV. */
stream_putw(s, BMP_MIRROR_TLV_TYPE_BGP_MESSAGE);
@@ -763,7 +839,8 @@ static int bmp_peer_backward(struct peer *peer)
return 0;
}
-static void bmp_eor(struct bmp *bmp, afi_t afi, safi_t safi, uint8_t flags)
+static void bmp_eor(struct bmp *bmp, afi_t afi, safi_t safi, uint8_t flags,
+ uint8_t peer_type_flag)
{
struct peer *peer;
struct listnode *node;
@@ -771,7 +848,7 @@ static void bmp_eor(struct bmp *bmp, afi_t afi, safi_t safi, uint8_t flags)
iana_afi_t pkt_afi = IANA_AFI_IPV4;
iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
- frrtrace(3, frr_bgp, bmp_eor, afi, safi, flags);
+ frrtrace(4, frr_bgp, bmp_eor, afi, safi, flags, peer_type_flag);
s = stream_new(BGP_MAX_PACKET_SIZE);
@@ -803,11 +880,22 @@ static void bmp_eor(struct bmp *bmp, afi_t afi, safi_t safi, uint8_t flags)
if (!peer->afc_nego[afi][safi])
continue;
+ uint64_t peer_distinguisher = 0;
+ /* skip this message if peer distinguisher is not available */
+ if (bmp_get_peer_distinguisher(bmp, afi, peer_type_flag,
+ &peer_distinguisher)) {
+ zlog_warn(
+ "skipping bmp message for reason: can't get peer distinguisher");
+ continue;
+ }
+
s2 = stream_new(BGP_MAX_PACKET_SIZE);
bmp_common_hdr(s2, BMP_VERSION_3,
BMP_TYPE_ROUTE_MONITORING);
- bmp_per_peer_hdr(s2, peer, flags, NULL);
+
+ bmp_per_peer_hdr(s2, bmp->targets->bgp, peer, flags,
+ peer_type_flag, peer_distinguisher, NULL);
stream_putl_at(s2, BMP_LENGTH_POS,
stream_get_endp(s) + stream_get_endp(s2));
@@ -912,14 +1000,23 @@ static struct stream *bmp_withdraw(const struct prefix *p,
}
static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags,
- const struct prefix *p, struct prefix_rd *prd,
- struct attr *attr, afi_t afi, safi_t safi,
- time_t uptime)
+ uint8_t peer_type_flag, const struct prefix *p,
+ struct prefix_rd *prd, struct attr *attr, afi_t afi,
+ safi_t safi, time_t uptime)
{
struct stream *hdr, *msg;
struct timeval tv = { .tv_sec = uptime, .tv_usec = 0 };
struct timeval uptime_real;
+ uint64_t peer_distinguisher = 0;
+ /* skip this message if peer distinguisher is not available */
+ if (bmp_get_peer_distinguisher(bmp, afi, peer_type_flag,
+ &peer_distinguisher)) {
+ zlog_warn(
+ "skipping bmp message for reason: can't get peer distinguisher");
+ return;
+ }
+
monotime_to_realtime(&tv, &uptime_real);
if (attr)
msg = bmp_update(p, prd, peer, attr, afi, safi);
@@ -928,7 +1025,9 @@ static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags,
hdr = stream_new(BGP_MAX_PACKET_SIZE);
bmp_common_hdr(hdr, BMP_VERSION_3, BMP_TYPE_ROUTE_MONITORING);
- bmp_per_peer_hdr(hdr, peer, flags, &uptime_real);
+ bmp_per_peer_hdr(hdr, bmp->targets->bgp, peer, flags, peer_type_flag,
+ peer_distinguisher,
+ uptime == (time_t)(-1L) ? NULL : &uptime_real);
stream_putl_at(hdr, BMP_LENGTH_POS,
stream_get_endp(hdr) + stream_get_endp(msg));
@@ -1039,8 +1138,13 @@ afibreak:
zlog_info("bmp[%s] %s %s table completed (EoR)",
bmp->remote, afi2str(afi),
safi2str(safi));
- bmp_eor(bmp, afi, safi, BMP_PEER_FLAG_L);
- bmp_eor(bmp, afi, safi, 0);
+
+ bmp_eor(bmp, afi, safi, BMP_PEER_FLAG_L,
+ BMP_PEER_TYPE_GLOBAL_INSTANCE);
+ bmp_eor(bmp, afi, safi, 0,
+ BMP_PEER_TYPE_GLOBAL_INSTANCE);
+ bmp_eor(bmp, afi, safi, 0,
+ BMP_PEER_TYPE_LOC_RIB_INSTANCE);
bmp->afistate[afi][safi] = BMP_AFI_LIVE;
bmp->syncafi = AFI_MAX;
@@ -1051,10 +1155,16 @@ afibreak:
prefix_copy(&bmp->syncpos, bgp_dest_get_prefix(bn));
}
- if (bmp->targets->afimon[afi][safi] & BMP_MON_POSTPOLICY) {
+ if (CHECK_FLAG(bmp->targets->afimon[afi][safi],
+ BMP_MON_POSTPOLICY) ||
+ CHECK_FLAG(bmp->targets->afimon[afi][safi],
+ BMP_MON_LOC_RIB)) {
for (bpiter = bgp_dest_get_bgp_path_info(bn); bpiter;
bpiter = bpiter->next) {
- if (!CHECK_FLAG(bpiter->flags, BGP_PATH_VALID))
+ if (!CHECK_FLAG(bpiter->flags,
+ BGP_PATH_VALID) &&
+ !CHECK_FLAG(bpiter->flags,
+ BGP_PATH_SELECTED))
continue;
if (bpiter->peer->qobj_node.nid
<= bmp->syncpeerid)
@@ -1065,7 +1175,8 @@ afibreak:
bpi = bpiter;
}
}
- if (bmp->targets->afimon[afi][safi] & BMP_MON_PREPOLICY) {
+ if (CHECK_FLAG(bmp->targets->afimon[afi][safi],
+ BMP_MON_PREPOLICY)) {
for (adjiter = bn->adj_in; adjiter;
adjiter = adjiter->next) {
if (adjiter->peer->qobj_node.nid
@@ -1103,12 +1214,23 @@ afibreak:
(safi == SAFI_MPLS_VPN))
prd = (struct prefix_rd *)bgp_dest_get_prefix(bmp->syncrdpos);
- if (bpi)
- bmp_monitor(bmp, bpi->peer, BMP_PEER_FLAG_L, bn_p, prd,
- bpi->attr, afi, safi, bpi->uptime);
+ if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_SELECTED) &&
+ CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_LOC_RIB)) {
+ bmp_monitor(bmp, bpi->peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE,
+ bn_p, prd, bpi->attr, afi, safi,
+ bpi && bpi->extra ? bpi->extra->bgp_rib_uptime
+ : (time_t)(-1L));
+ }
+
+ if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_VALID) &&
+ CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_POSTPOLICY))
+ bmp_monitor(bmp, bpi->peer, BMP_PEER_FLAG_L,
+ BMP_PEER_TYPE_GLOBAL_INSTANCE, bn_p, prd, bpi->attr,
+ afi, safi, bpi->uptime);
+
if (adjin)
- bmp_monitor(bmp, adjin->peer, 0, bn_p, prd, adjin->attr, afi,
- safi, adjin->uptime);
+ bmp_monitor(bmp, adjin->peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE,
+ bn_p, prd, adjin->attr, afi, safi, adjin->uptime);
if (bn)
bgp_dest_unlock_node(bn);
@@ -1116,24 +1238,124 @@ afibreak:
return true;
}
-static struct bmp_queue_entry *bmp_pull(struct bmp *bmp)
+static struct bmp_queue_entry *
+bmp_pull_from_queue(struct bmp_qlist_head *list, struct bmp_qhash_head *hash,
+ struct bmp_queue_entry **queuepos_ptr)
{
struct bmp_queue_entry *bqe;
- bqe = bmp->queuepos;
+ bqe = *queuepos_ptr;
if (!bqe)
return NULL;
- bmp->queuepos = bmp_qlist_next(&bmp->targets->updlist, bqe);
+ *queuepos_ptr = bmp_qlist_next(list, bqe);
bqe->refcount--;
if (!bqe->refcount) {
- bmp_qhash_del(&bmp->targets->updhash, bqe);
- bmp_qlist_del(&bmp->targets->updlist, bqe);
+ bmp_qhash_del(hash, bqe);
+ bmp_qlist_del(list, bqe);
}
return bqe;
}
+static inline struct bmp_queue_entry *bmp_pull(struct bmp *bmp)
+{
+ return bmp_pull_from_queue(&bmp->targets->updlist,
+ &bmp->targets->updhash, &bmp->queuepos);
+}
+
+static inline struct bmp_queue_entry *bmp_pull_locrib(struct bmp *bmp)
+{
+ return bmp_pull_from_queue(&bmp->targets->locupdlist,
+ &bmp->targets->locupdhash,
+ &bmp->locrib_queuepos);
+}
+
+/* TODO BMP_MON_LOCRIB find a way to merge properly this function with
+ * bmp_wrqueue or abstract it if possible
+ */
+static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr)
+{
+
+ struct bmp_queue_entry *bqe;
+ struct peer *peer;
+ struct bgp_dest *bn = NULL;
+ bool written = false;
+
+ bqe = bmp_pull_locrib(bmp);
+ if (!bqe)
+ return false;
+
+ afi_t afi = bqe->afi;
+ safi_t safi = bqe->safi;
+
+ if (!CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_LOC_RIB))
+ goto out;
+
+ switch (bmp->afistate[afi][safi]) {
+ case BMP_AFI_INACTIVE:
+ case BMP_AFI_NEEDSYNC:
+ goto out;
+ case BMP_AFI_SYNC:
+ if (prefix_cmp(&bqe->p, &bmp->syncpos) <= 0)
+ /* currently syncing but have already passed this
+ * prefix => send it.
+ */
+ break;
+
+ /* currently syncing & haven't reached this prefix yet
+ * => it'll be sent as part of the table sync, no need here
+ */
+ goto out;
+ case BMP_AFI_LIVE:
+ break;
+ }
+
+ peer = QOBJ_GET_TYPESAFE(bqe->peerid, peer);
+ if (!peer) {
+ /* skipping queued item for deleted peer
+ */
+ goto out;
+ }
+ if (peer != bmp->targets->bgp->peer_self && !peer_established(peer->connection)) {
+ /* peer is neither self, nor established
+ */
+ goto out;
+ }
+
+ bool is_vpn = (bqe->afi == AFI_L2VPN && bqe->safi == SAFI_EVPN) ||
+ (bqe->safi == SAFI_MPLS_VPN);
+
+ struct prefix_rd *prd = is_vpn ? &bqe->rd : NULL;
+
+ bn = bgp_safi_node_lookup(bmp->targets->bgp->rib[afi][safi], safi,
+ &bqe->p, prd);
+
+ struct bgp_path_info *bpi;
+
+ for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) {
+ if (!CHECK_FLAG(bpi->flags, BGP_PATH_SELECTED))
+ continue;
+ if (bpi->peer == peer)
+ break;
+ }
+
+ bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE, &bqe->p, prd,
+ bpi ? bpi->attr : NULL, afi, safi,
+ bpi && bpi->extra ? bpi->extra->bgp_rib_uptime
+ : (time_t)(-1L));
+ written = true;
+
+out:
+ if (!bqe->refcount)
+ XFREE(MTYPE_BMP_QUEUE, bqe);
+
+ if (bn)
+ bgp_dest_unlock_node(bn);
+
+ return written;
+}
+
static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
{
struct bmp_queue_entry *bqe;
@@ -1180,11 +1402,10 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
bn = bgp_safi_node_lookup(bmp->targets->bgp->rib[afi][safi], safi,
&bqe->p, prd);
-
- if (bmp->targets->afimon[afi][safi] & BMP_MON_POSTPOLICY) {
+ if (CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_POSTPOLICY)) {
struct bgp_path_info *bpi;
- for (bpi = bn ? bgp_dest_get_bgp_path_info(bn) : NULL; bpi;
+ for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
bpi = bpi->next) {
if (!CHECK_FLAG(bpi->flags, BGP_PATH_VALID))
continue;
@@ -1192,13 +1413,14 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
break;
}
- bmp_monitor(bmp, peer, BMP_PEER_FLAG_L, &bqe->p, prd,
+ bmp_monitor(bmp, peer, BMP_PEER_FLAG_L,
+ BMP_PEER_TYPE_GLOBAL_INSTANCE, &bqe->p, prd,
bpi ? bpi->attr : NULL, afi, safi,
bpi ? bpi->uptime : monotime(NULL));
written = true;
}
- if (bmp->targets->afimon[afi][safi] & BMP_MON_PREPOLICY) {
+ if (CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_PREPOLICY)) {
struct bgp_adj_in *adjin;
for (adjin = bn ? bn->adj_in : NULL; adjin;
@@ -1206,8 +1428,8 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
if (adjin->peer == peer)
break;
}
- bmp_monitor(bmp, peer, 0, &bqe->p, prd,
- adjin ? adjin->attr : NULL, afi, safi,
+ bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE,
+ &bqe->p, prd, adjin ? adjin->attr : NULL, afi, safi,
adjin ? adjin->uptime : monotime(NULL));
written = true;
}
@@ -1235,6 +1457,8 @@ static void bmp_wrfill(struct bmp *bmp, struct pullwr *pullwr)
break;
if (bmp_wrqueue(bmp, pullwr))
break;
+ if (bmp_wrqueue_locrib(bmp, pullwr))
+ break;
if (bmp_wrsync(bmp, pullwr))
break;
break;
@@ -1253,16 +1477,17 @@ static void bmp_wrerr(struct bmp *bmp, struct pullwr *pullwr, bool eof)
bmp_free(bmp);
}
-static void bmp_process_one(struct bmp_targets *bt, struct bgp *bgp, afi_t afi,
- safi_t safi, struct bgp_dest *bn, struct peer *peer)
+static struct bmp_queue_entry *
+bmp_process_one(struct bmp_targets *bt, struct bmp_qhash_head *updhash,
+ struct bmp_qlist_head *updlist, struct bgp *bgp, afi_t afi,
+ safi_t safi, struct bgp_dest *bn, struct peer *peer)
{
- struct bmp *bmp;
struct bmp_queue_entry *bqe, bqeref;
size_t refcount;
refcount = bmp_session_count(&bt->sessions);
if (refcount == 0)
- return;
+ return NULL;
memset(&bqeref, 0, sizeof(bqeref));
prefix_copy(&bqeref.p, bgp_dest_get_prefix(bn));
@@ -1275,26 +1500,28 @@ static void bmp_process_one(struct bmp_targets *bt, struct bgp *bgp, afi_t afi,
prefix_copy(&bqeref.rd,
(struct prefix_rd *)bgp_dest_get_prefix(bn->pdest));
- bqe = bmp_qhash_find(&bt->updhash, &bqeref);
+ bqe = bmp_qhash_find(updhash, &bqeref);
if (bqe) {
if (bqe->refcount >= refcount)
/* nothing to do here */
- return;
+ return NULL;
- bmp_qlist_del(&bt->updlist, bqe);
+ bmp_qlist_del(updlist, bqe);
} else {
bqe = XMALLOC(MTYPE_BMP_QUEUE, sizeof(*bqe));
memcpy(bqe, &bqeref, sizeof(*bqe));
- bmp_qhash_add(&bt->updhash, bqe);
+ bmp_qhash_add(updhash, bqe);
}
bqe->refcount = refcount;
- bmp_qlist_add_tail(&bt->updlist, bqe);
+ bmp_qlist_add_tail(updlist, bqe);
+
+ return bqe;
- frr_each (bmp_session, &bt->sessions, bmp)
- if (!bmp->queuepos)
- bmp->queuepos = bqe;
+ /* need to update correct queue pos for all sessions of the target after
+ * a call to this function
+ */
}
static int bmp_process(struct bgp *bgp, afi_t afi, safi_t safi,
@@ -1316,12 +1543,26 @@ static int bmp_process(struct bgp *bgp, afi_t afi, safi_t safi,
return 0;
frr_each(bmp_targets, &bmpbgp->targets, bt) {
- if (!bt->afimon[afi][safi])
+ /* check if any monitoring is enabled (ignoring loc-rib since it
+ * uses another hook & queue
+ */
+ if (!CHECK_FLAG(bt->afimon[afi][safi], ~BMP_MON_LOC_RIB))
continue;
- bmp_process_one(bt, bgp, afi, safi, bn, peer);
+ struct bmp_queue_entry *last_item =
+ bmp_process_one(bt, &bt->updhash, &bt->updlist, bgp,
+ afi, safi, bn, peer);
+
+ /* if bmp_process_one returns NULL
+ * we don't have anything to do next
+ */
+ if (!last_item)
+ continue;
frr_each(bmp_session, &bt->sessions, bmp) {
+ if (!bmp->queuepos)
+ bmp->queuepos = last_item;
+
pullwr_bump(bmp->pullwr);
}
}
@@ -1360,7 +1601,8 @@ static void bmp_stats(struct event *thread)
s = stream_new(BGP_MAX_PACKET_SIZE);
bmp_common_hdr(s, BMP_VERSION_3, BMP_TYPE_STATISTICS_REPORT);
- bmp_per_peer_hdr(s, peer, 0, &tv);
+ bmp_per_peer_hdr(s, bt->bgp, peer, 0,
+ BMP_PEER_TYPE_GLOBAL_INSTANCE, 0, &tv);
count_pos = stream_get_endp(s);
stream_putl(s, 0);
@@ -1530,6 +1772,9 @@ static void bmp_close(struct bmp *bmp)
while ((bqe = bmp_pull(bmp)))
if (!bqe->refcount)
XFREE(MTYPE_BMP_QUEUE, bqe);
+ while ((bqe = bmp_pull_locrib(bmp)))
+ if (!bqe->refcount)
+ XFREE(MTYPE_BMP_QUEUE, bqe);
EVENT_OFF(bmp->t_read);
pullwr_del(bmp->pullwr);
@@ -1633,6 +1878,8 @@ static struct bmp_targets *bmp_targets_get(struct bgp *bgp, const char *name)
bmp_session_init(&bt->sessions);
bmp_qhash_init(&bt->updhash);
bmp_qlist_init(&bt->updlist);
+ bmp_qhash_init(&bt->locupdhash);
+ bmp_qlist_init(&bt->locupdlist);
bmp_actives_init(&bt->actives);
bmp_listeners_init(&bt->listeners);
@@ -1663,6 +1910,8 @@ static void bmp_targets_put(struct bmp_targets *bt)
bmp_actives_fini(&bt->actives);
bmp_qhash_fini(&bt->updhash);
bmp_qlist_fini(&bt->updlist);
+ bmp_qhash_fini(&bt->locupdhash);
+ bmp_qlist_fini(&bt->locupdlist);
XFREE(MTYPE_BMP_ACLNAME, bt->acl_name);
XFREE(MTYPE_BMP_ACLNAME, bt->acl6_name);
@@ -2206,21 +2455,17 @@ DEFPY(bmp_stats_cfg,
return CMD_SUCCESS;
}
-DEFPY(bmp_monitor_cfg,
- bmp_monitor_cmd,
- "[no] bmp monitor <ipv4|ipv6|l2vpn> <unicast|multicast|evpn|vpn> <pre-policy|post-policy>$policy",
- NO_STR
- BMP_STR
- "Send BMP route monitoring messages\n"
- BGP_AF_STR
- BGP_AF_STR
- BGP_AF_STR
- BGP_AF_STR
- BGP_AF_STR
- BGP_AF_STR
- BGP_AF_STR
+#define BMP_POLICY_IS_LOCRIB(str) ((str)[0] == 'l') /* __l__oc-rib */
+#define BMP_POLICY_IS_PRE(str) ((str)[1] == 'r') /* p__r__e-policy */
+
+DEFPY(bmp_monitor_cfg, bmp_monitor_cmd,
+ "[no] bmp monitor <ipv4|ipv6|l2vpn> <unicast|multicast|evpn|vpn> <pre-policy|post-policy|loc-rib>$policy",
+ NO_STR BMP_STR
+ "Send BMP route monitoring messages\n" BGP_AF_STR BGP_AF_STR BGP_AF_STR
+ BGP_AF_STR BGP_AF_STR BGP_AF_STR BGP_AF_STR
"Send state before policy and filter processing\n"
- "Send state with policy and filters applied\n")
+ "Send state with policy and filters applied\n"
+ "Send state after decision process is applied\n")
{
int index = 0;
uint8_t flag, prev;
@@ -2233,7 +2478,9 @@ DEFPY(bmp_monitor_cfg,
argv_find_and_parse_afi(argv, argc, &index, &afi);
argv_find_and_parse_safi(argv, argc, &index, &safi);
- if (policy[1] == 'r')
+ if (BMP_POLICY_IS_LOCRIB(policy))
+ flag = BMP_MON_LOC_RIB;
+ else if (BMP_POLICY_IS_PRE(policy))
flag = BMP_MON_PREPOLICY;
else
flag = BMP_MON_POSTPOLICY;
@@ -2364,23 +2611,31 @@ DEFPY(show_bmp,
safi_t safi;
FOREACH_AFI_SAFI (afi, safi) {
- const char *str = NULL;
-
- switch (bt->afimon[afi][safi]) {
- case BMP_MON_PREPOLICY:
- str = "pre-policy";
- break;
- case BMP_MON_POSTPOLICY:
- str = "post-policy";
- break;
- case BMP_MON_PREPOLICY | BMP_MON_POSTPOLICY:
- str = "pre-policy and post-policy";
- break;
- }
- if (!str)
+
+ uint8_t afimon_flag = bt->afimon[afi][safi];
+
+ if (!afimon_flag)
continue;
- vty_out(vty, " Route Monitoring %s %s %s\n",
- afi2str(afi), safi2str(safi), str);
+
+ const char *pre_str =
+ CHECK_FLAG(afimon_flag,
+ BMP_MON_PREPOLICY)
+ ? "pre-policy "
+ : "";
+ const char *post_str =
+ CHECK_FLAG(afimon_flag,
+ BMP_MON_POSTPOLICY)
+ ? "post-policy "
+ : "";
+ const char *locrib_str =
+ CHECK_FLAG(afimon_flag, BMP_MON_LOC_RIB)
+ ? "loc-rib"
+ : "";
+
+ vty_out(vty,
+ " Route Monitoring %s %s %s%s%s\n",
+ afi2str(afi), safi2str(safi), pre_str,
+ post_str, locrib_str);
}
vty_out(vty, " Listeners:\n");
@@ -2500,13 +2755,18 @@ static int bmp_config_write(struct bgp *bgp, struct vty *vty)
vty_out(vty, " bmp mirror\n");
FOREACH_AFI_SAFI (afi, safi) {
- if (bt->afimon[afi][safi] & BMP_MON_PREPOLICY)
+ if (CHECK_FLAG(bt->afimon[afi][safi],
+ BMP_MON_PREPOLICY))
vty_out(vty, " bmp monitor %s %s pre-policy\n",
afi2str_lower(afi), safi2str(safi));
- if (bt->afimon[afi][safi] & BMP_MON_POSTPOLICY)
+ if (CHECK_FLAG(bt->afimon[afi][safi],
+ BMP_MON_POSTPOLICY))
vty_out(vty,
" bmp monitor %s %s post-policy\n",
afi2str_lower(afi), safi2str(safi));
+ if (CHECK_FLAG(bt->afimon[afi][safi], BMP_MON_LOC_RIB))
+ vty_out(vty, " bmp monitor %s %s loc-rib\n",
+ afi2str_lower(afi), safi2str(safi));
}
frr_each (bmp_listeners, &bt->listeners, bl)
vty_out(vty, " \n bmp listener %pSU port %d\n",
@@ -2555,6 +2815,82 @@ static int bgp_bmp_init(struct event_loop *tm)
return 0;
}
+static int bmp_route_update(struct bgp *bgp, afi_t afi, safi_t safi,
+ struct bgp_dest *bn,
+ struct bgp_path_info *old_route,
+ struct bgp_path_info *new_route)
+{
+ bool is_locribmon_enabled = false;
+ bool is_withdraw = old_route && !new_route;
+ struct bgp_path_info *updated_route =
+ is_withdraw ? old_route : new_route;
+
+
+ /* this should never happen */
+ if (!updated_route) {
+ zlog_warn("%s: no updated route found!", __func__);
+ return 0;
+ }
+
+ struct bmp_bgp *bmpbgp = bmp_bgp_get(bgp);
+ struct peer *peer = updated_route->peer;
+ struct bmp_targets *bt;
+ struct bmp *bmp;
+
+ frr_each (bmp_targets, &bmpbgp->targets, bt) {
+ if (CHECK_FLAG(bt->afimon[afi][safi], BMP_MON_LOC_RIB)) {
+ is_locribmon_enabled = true;
+ break;
+ }
+ }
+
+ if (!is_locribmon_enabled)
+ return 0;
+
+ /* route is not installed in locrib anymore and rib uptime was saved */
+ if (old_route && old_route->extra)
+ bgp_path_info_extra_get(old_route)->bgp_rib_uptime =
+ (time_t)(-1L);
+
+ /* route is installed in locrib from now on so
+ * save rib uptime in bgp_path_info_extra
+ */
+ if (new_route)
+ bgp_path_info_extra_get(new_route)->bgp_rib_uptime =
+ monotime(NULL);
+
+ frr_each (bmp_targets, &bmpbgp->targets, bt) {
+ if (CHECK_FLAG(bt->afimon[afi][safi], BMP_MON_LOC_RIB)) {
+
+ struct bmp_queue_entry *last_item = bmp_process_one(
+ bt, &bt->locupdhash, &bt->locupdlist, bgp, afi,
+ safi, bn, peer);
+
+ /* if bmp_process_one returns NULL
+ * we don't have anything to do next
+ */
+ if (!last_item)
+ continue;
+
+ frr_each (bmp_session, &bt->sessions, bmp) {
+ if (!bmp->locrib_queuepos)
+ bmp->locrib_queuepos = last_item;
+
+ pullwr_bump(bmp->pullwr);
+ };
+ }
+ };
+
+ return 0;
+}
+
+static int bgp_bmp_early_fini(void)
+{
+ resolver_terminate();
+
+ return 0;
+}
+
static int bgp_bmp_module_init(void)
{
hook_register(bgp_packet_dump, bmp_mirror_packet);
@@ -2565,6 +2901,8 @@ static int bgp_bmp_module_init(void)
hook_register(bgp_inst_config_write, bmp_config_write);
hook_register(bgp_inst_delete, bmp_bgp_del);
hook_register(frr_late_init, bgp_bmp_init);
+ hook_register(bgp_route_update, bmp_route_update);
+ hook_register(frr_early_fini, bgp_bmp_early_fini);
return 0;
}
diff --git a/bgpd/bgp_bmp.h b/bgpd/bgp_bmp.h
index ab7463f..dadd99e 100644
--- a/bgpd/bgp_bmp.h
+++ b/bgpd/bgp_bmp.h
@@ -124,6 +124,7 @@ struct bmp {
* ahead we need to make sure that refcount is decremented. Also, on
* disconnects we need to walk the queue and drop our reference.
*/
+ struct bmp_queue_entry *locrib_queuepos;
struct bmp_queue_entry *queuepos;
struct bmp_mirrorq *mirrorpos;
bool mirror_lost;
@@ -215,12 +216,14 @@ struct bmp_targets {
int stat_msec;
/* only supporting:
- * - IPv4 / unicast & multicast
- * - IPv6 / unicast & multicast
+ * - IPv4 / unicast & multicast & VPN
+ * - IPv6 / unicast & multicast & VPN
* - L2VPN / EVPN
*/
#define BMP_MON_PREPOLICY (1 << 0)
#define BMP_MON_POSTPOLICY (1 << 1)
+#define BMP_MON_LOC_RIB (1 << 2)
+
uint8_t afimon[AFI_MAX][SAFI_MAX];
bool mirror;
@@ -232,6 +235,9 @@ struct bmp_targets {
struct bmp_qhash_head updhash;
struct bmp_qlist_head updlist;
+ struct bmp_qhash_head locupdhash;
+ struct bmp_qlist_head locupdlist;
+
uint64_t cnt_accept, cnt_aclrefused;
QOBJ_FIELDS;
diff --git a/bgpd/bgp_btoa.c b/bgpd/bgp_btoa.c
index 8e27d97..1d5034e 100644
--- a/bgpd/bgp_btoa.c
+++ b/bgpd/bgp_btoa.c
@@ -4,6 +4,7 @@
*/
#include <zebra.h>
+#include <fcntl.h>
#include "zebra.h"
#include "stream.h"
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c
index e522307..8336d6f 100644
--- a/bgpd/bgp_clist.c
+++ b/bgpd/bgp_clist.c
@@ -128,6 +128,7 @@ static void community_entry_free(struct community_entry *entry)
XFREE(MTYPE_COMMUNITY_LIST_CONFIG, entry->config);
if (entry->reg)
bgp_regex_free(entry->reg);
+ break;
default:
break;
}
diff --git a/bgpd/bgp_conditional_adv.c b/bgpd/bgp_conditional_adv.c
index 6ed0dd7..2d96b44 100644
--- a/bgpd/bgp_conditional_adv.c
+++ b/bgpd/bgp_conditional_adv.c
@@ -122,8 +122,9 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi,
if (update_type == UPDATE_TYPE_ADVERTISE &&
subgroup_announce_check(dest, pi, subgrp, dest_p,
&attr, &advmap_attr)) {
- bgp_adj_out_set_subgroup(dest, subgrp, &attr,
- pi);
+ if (!bgp_adj_out_set_subgroup(dest, subgrp,
+ &attr, pi))
+ bgp_attr_flush(&attr);
} else {
/* If default originate is enabled for
* the peer, do not send explicit
diff --git a/bgpd/bgp_damp.h b/bgpd/bgp_damp.h
index 5708e6f..6033c34 100644
--- a/bgpd/bgp_damp.h
+++ b/bgpd/bgp_damp.h
@@ -65,7 +65,6 @@ struct bgp_damp_config {
/* Non-configurable parameters but fixed at implementation time.
* To change this values, init_bgp_damp() should be modified.
*/
- time_t tmax; /* Max time previous instability retained */
unsigned int reuse_list_size; /* Number of reuse lists */
unsigned int reuse_index_size; /* Size of reuse index array */
@@ -75,8 +74,8 @@ struct bgp_damp_config {
unsigned int ceiling; /* Max value a penalty can attain */
unsigned int decay_rate_per_tick; /* Calculated from half-life */
unsigned int decay_array_size; /* Calculated using config parameters */
- double scale_factor;
unsigned int reuse_scale_factor;
+ double scale_factor;
/* Decay array per-set based. */
double *decay_array;
@@ -87,6 +86,7 @@ struct bgp_damp_config {
/* Reuse list array per-set based. */
struct bgp_damp_info **reuse_list;
int reuse_offset;
+ safi_t safi;
/* All dampening information which is not on reuse list. */
struct bgp_damp_info *no_reuse_list;
@@ -95,7 +95,6 @@ struct bgp_damp_config {
struct event *t_reuse;
afi_t afi;
- safi_t safi;
};
#define BGP_DAMP_NONE 0
diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c
index 123a1ca..3ecdc0d 100644
--- a/bgpd/bgp_debug.c
+++ b/bgpd/bgp_debug.c
@@ -16,6 +16,7 @@
#include "memory.h"
#include "queue.h"
#include "filter.h"
+#include "hook.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_aspath.h"
@@ -37,6 +38,9 @@
#include "bgpd/bgp_debug_clippy.c"
+DEFINE_HOOK(bgp_hook_config_write_debug, (struct vty *vty, bool running),
+ (vty, running));
+
unsigned long conf_bgp_debug_as4;
unsigned long conf_bgp_debug_neighbor_events;
unsigned long conf_bgp_debug_events;
@@ -216,6 +220,7 @@ static void bgp_debug_list_free(struct list *list)
listnode_delete(list, filter);
prefix_free(&filter->p);
XFREE(MTYPE_BGP_DEBUG_STR, filter->host);
+ XFREE(MTYPE_BGP_DEBUG_STR, filter->plist_name);
XFREE(MTYPE_BGP_DEBUG_FILTER, filter);
}
}
@@ -233,15 +238,21 @@ static void bgp_debug_list_print(struct vty *vty, const char *desc,
vty_out(vty, "%s", desc);
if (list && !list_isempty(list)) {
- vty_out(vty, " for");
+ vty_out(vty, " for:\n");
for (ALL_LIST_ELEMENTS(list, node, nnode, filter)) {
if (filter->host)
- vty_out(vty, " %s", filter->host);
+ vty_out(vty, " %s", filter->host);
+
+ if (filter->plist_name)
+ vty_out(vty, " with prefix-list %s",
+ filter->plist_name);
if (filter->p && filter->p->family == AF_EVPN)
bgp_debug_print_evpn_prefix(vty, "", filter->p);
else if (filter->p)
vty_out(vty, " %pFX", filter->p);
+
+ vty_out(vty, "\n");
}
}
@@ -261,7 +272,11 @@ static int bgp_debug_list_conf_print(struct vty *vty, const char *desc,
if (list && !list_isempty(list)) {
for (ALL_LIST_ELEMENTS(list, node, nnode, filter)) {
- if (filter->host) {
+ if (filter->host && filter->plist_name) {
+ vty_out(vty, "%s %s prefix-list %s\n", desc,
+ filter->host, filter->plist_name);
+ write++;
+ } else if (filter->host) {
vty_out(vty, "%s %s\n", desc, filter->host);
write++;
}
@@ -286,7 +301,8 @@ static int bgp_debug_list_conf_print(struct vty *vty, const char *desc,
}
static void bgp_debug_list_add_entry(struct list *list, const char *host,
- const struct prefix *p)
+ const struct prefix *p,
+ const char *plist_name)
{
struct bgp_debug_filter *filter;
@@ -295,13 +311,27 @@ static void bgp_debug_list_add_entry(struct list *list, const char *host,
if (host) {
filter->host = XSTRDUP(MTYPE_BGP_DEBUG_STR, host);
+ filter->plist_name = NULL;
+ filter->plist_v4 = NULL;
+ filter->plist_v6 = NULL;
filter->p = NULL;
} else if (p) {
filter->host = NULL;
+ filter->plist_name = NULL;
+ filter->plist_v4 = NULL;
+ filter->plist_v6 = NULL;
filter->p = prefix_new();
prefix_copy(filter->p, p);
}
+ if (plist_name) {
+ filter->plist_name = XSTRDUP(MTYPE_BGP_DEBUG_STR, plist_name);
+ filter->plist_v4 = prefix_list_lookup(AFI_IP,
+ filter->plist_name);
+ filter->plist_v6 = prefix_list_lookup(AFI_IP6,
+ filter->plist_name);
+ }
+
listnode_add(list, filter);
}
@@ -315,6 +345,7 @@ static bool bgp_debug_list_remove_entry(struct list *list, const char *host,
if (host && strcmp(filter->host, host) == 0) {
listnode_delete(list, filter);
XFREE(MTYPE_BGP_DEBUG_STR, filter->host);
+ XFREE(MTYPE_BGP_DEBUG_STR, filter->plist_name);
XFREE(MTYPE_BGP_DEBUG_FILTER, filter);
return true;
} else if (p && filter->p->prefixlen == p->prefixlen
@@ -330,16 +361,20 @@ static bool bgp_debug_list_remove_entry(struct list *list, const char *host,
}
static bool bgp_debug_list_has_entry(struct list *list, const char *host,
- const struct prefix *p)
+ const struct prefix *p,
+ const char *plist_name)
{
struct bgp_debug_filter *filter;
struct listnode *node, *nnode;
for (ALL_LIST_ELEMENTS(list, node, nnode, filter)) {
- if (host) {
- if (strcmp(filter->host, host) == 0) {
+ if (host && plist_name) {
+ if (strmatch(filter->host, host) && filter->plist_name &&
+ strmatch(filter->plist_name, plist_name))
+ return true;
+ } else if (host) {
+ if (strmatch(filter->host, host))
return true;
- }
} else if (p) {
if (filter->p->prefixlen == p->prefixlen
&& prefix_match(filter->p, p)) {
@@ -353,7 +388,7 @@ static bool bgp_debug_list_has_entry(struct list *list, const char *host,
bool bgp_debug_peer_updout_enabled(char *host)
{
- return (bgp_debug_list_has_entry(bgp_debug_update_out_peers, host,
+ return (bgp_debug_list_has_entry(bgp_debug_update_out_peers, host, NULL,
NULL));
}
@@ -780,14 +815,15 @@ DEFUN (debug_bgp_neighbor_events_peer,
bgp_debug_neighbor_events_peers = list_new();
if (bgp_debug_list_has_entry(bgp_debug_neighbor_events_peers, host,
- NULL)) {
+ NULL, NULL)) {
vty_out(vty,
"BGP neighbor-events debugging is already enabled for %s\n",
host);
return CMD_SUCCESS;
}
- bgp_debug_list_add_entry(bgp_debug_neighbor_events_peers, host, NULL);
+ bgp_debug_list_add_entry(bgp_debug_neighbor_events_peers, host, NULL,
+ NULL);
if (vty->node == CONFIG_NODE)
DEBUG_ON(neighbor_events, NEIGHBOR_EVENTS);
@@ -927,14 +963,15 @@ DEFUN (debug_bgp_keepalive_peer,
if (!bgp_debug_keepalive_peers)
bgp_debug_keepalive_peers = list_new();
- if (bgp_debug_list_has_entry(bgp_debug_keepalive_peers, host, NULL)) {
+ if (bgp_debug_list_has_entry(bgp_debug_keepalive_peers, host, NULL,
+ NULL)) {
vty_out(vty,
"BGP keepalive debugging is already enabled for %s\n",
host);
return CMD_SUCCESS;
}
- bgp_debug_list_add_entry(bgp_debug_keepalive_peers, host, NULL);
+ bgp_debug_list_add_entry(bgp_debug_keepalive_peers, host, NULL, NULL);
if (vty->node == CONFIG_NODE)
DEBUG_ON(keepalive, KEEPALIVE);
@@ -1015,15 +1052,16 @@ DEFPY (debug_bgp_bestpath_prefix,
if (!bgp_debug_bestpath_prefixes)
bgp_debug_bestpath_prefixes = list_new();
- if (bgp_debug_list_has_entry(bgp_debug_bestpath_prefixes, NULL,
- prefix)) {
+ if (bgp_debug_list_has_entry(bgp_debug_bestpath_prefixes, NULL, prefix,
+ NULL)) {
vty_out(vty,
"BGP bestpath debugging is already enabled for %s\n",
prefix_str);
return CMD_SUCCESS;
}
- bgp_debug_list_add_entry(bgp_debug_bestpath_prefixes, NULL, prefix);
+ bgp_debug_list_add_entry(bgp_debug_bestpath_prefixes, NULL, prefix,
+ NULL);
if (vty->node == CONFIG_NODE) {
DEBUG_ON(bestpath, BESTPATH);
@@ -1116,6 +1154,31 @@ DEFUN (debug_bgp_update,
return CMD_SUCCESS;
}
+DEFPY (debug_bgp_update_detail,
+ debug_bgp_update_detail_cmd,
+ "[no] debug bgp updates detail",
+ NO_STR
+ DEBUG_STR
+ BGP_STR
+ "BGP updates\n"
+ "Show detailed information about updates\n")
+{
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ DEBUG_OFF(update, UPDATE_DETAIL);
+ else
+ DEBUG_ON(update, UPDATE_DETAIL);
+ } else {
+ if (no)
+ TERM_DEBUG_OFF(update, UPDATE_DETAIL);
+ else
+ TERM_DEBUG_ON(update, UPDATE_DETAIL);
+ vty_out(vty, "BGP updates detail debugging is on\n");
+ }
+
+ return CMD_SUCCESS;
+}
+
DEFUN (debug_bgp_update_direct,
debug_bgp_update_direct_cmd,
"debug bgp updates <in|out>",
@@ -1150,9 +1213,9 @@ DEFUN (debug_bgp_update_direct,
return CMD_SUCCESS;
}
-DEFUN (debug_bgp_update_direct_peer,
+DEFPY (debug_bgp_update_direct_peer,
debug_bgp_update_direct_peer_cmd,
- "debug bgp updates <in|out> <A.B.C.D|X:X::X:X|WORD>",
+ "debug bgp updates <in|out> <A.B.C.D|X:X::X:X|WORD> [prefix-list PREFIXLIST_NAME$plist]",
DEBUG_STR
BGP_STR
"BGP updates\n"
@@ -1160,7 +1223,9 @@ DEFUN (debug_bgp_update_direct_peer,
"Outbound updates\n"
"BGP neighbor IP address to debug\n"
"BGP IPv6 neighbor to debug\n"
- "BGP neighbor on interface to debug\n")
+ "BGP neighbor on interface to debug\n"
+ "Use prefix-list to filter prefixes to debug\n"
+ "Name of prefix-list\n")
{
int idx_in_out = 3;
int idx_peer = 4;
@@ -1180,7 +1245,7 @@ DEFUN (debug_bgp_update_direct_peer,
if (inbound) {
if (bgp_debug_list_has_entry(bgp_debug_update_in_peers, host,
- NULL)) {
+ NULL, plist)) {
vty_out(vty,
"BGP inbound update debugging is already enabled for %s\n",
host);
@@ -1190,7 +1255,7 @@ DEFUN (debug_bgp_update_direct_peer,
else {
if (bgp_debug_list_has_entry(bgp_debug_update_out_peers, host,
- NULL)) {
+ NULL, plist)) {
vty_out(vty,
"BGP outbound update debugging is already enabled for %s\n",
host);
@@ -1199,14 +1264,15 @@ DEFUN (debug_bgp_update_direct_peer,
}
if (inbound)
- bgp_debug_list_add_entry(bgp_debug_update_in_peers, host, NULL);
+ bgp_debug_list_add_entry(bgp_debug_update_in_peers, host, NULL,
+ plist);
else {
struct peer *peer;
struct peer_af *paf;
int afidx;
- bgp_debug_list_add_entry(bgp_debug_update_out_peers, host,
- NULL);
+ bgp_debug_list_add_entry(bgp_debug_update_out_peers, host, NULL,
+ plist);
peer = bgp_find_peer(vty, host);
if (peer) {
@@ -1283,7 +1349,7 @@ DEFUN (no_debug_bgp_update_direct,
DEFUN (no_debug_bgp_update_direct_peer,
no_debug_bgp_update_direct_peer_cmd,
- "no debug bgp updates <in|out> <A.B.C.D|X:X::X:X|WORD>",
+ "no debug bgp updates <in|out> <A.B.C.D|X:X::X:X|WORD> [prefix-list PREFIXLIST_NAME]",
NO_STR
DEBUG_STR
BGP_STR
@@ -1292,7 +1358,9 @@ DEFUN (no_debug_bgp_update_direct_peer,
"Outbound updates\n"
"BGP neighbor IP address to debug\n"
"BGP IPv6 neighbor to debug\n"
- "BGP neighbor on interface to debug\n")
+ "BGP neighbor on interface to debug\n"
+ "Use prefix-list to filter prefixes to debug\n"
+ "Name of prefix-list\n")
{
int idx_in_out = 4;
int idx_peer = 5;
@@ -1414,15 +1482,15 @@ DEFPY (debug_bgp_update_prefix_afi_safi,
if (!bgp_debug_update_prefixes)
bgp_debug_update_prefixes = list_new();
- if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL,
- &argv_p)) {
+ if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL, &argv_p,
+ NULL)) {
vty_out(vty,
"BGP updates debugging is already enabled for %pFX\n",
&argv_p);
return CMD_SUCCESS;
}
- bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, &argv_p);
+ bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, &argv_p, NULL);
if (vty->node == CONFIG_NODE) {
DEBUG_ON(update, UPDATE_PREFIX);
@@ -1510,14 +1578,15 @@ DEFPY (debug_bgp_update_prefix,
if (!bgp_debug_update_prefixes)
bgp_debug_update_prefixes = list_new();
- if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL, prefix)) {
+ if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL, prefix,
+ NULL)) {
vty_out(vty,
"BGP updates debugging is already enabled for %s\n",
prefix_str);
return CMD_SUCCESS;
}
- bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, prefix);
+ bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, prefix, NULL);
if (vty->node == CONFIG_NODE) {
DEBUG_ON(update, UPDATE_PREFIX);
@@ -1647,13 +1716,14 @@ DEFPY (debug_bgp_zebra_prefix,
if (!bgp_debug_zebra_prefixes)
bgp_debug_zebra_prefixes = list_new();
- if (bgp_debug_list_has_entry(bgp_debug_zebra_prefixes, NULL, prefix)) {
+ if (bgp_debug_list_has_entry(bgp_debug_zebra_prefixes, NULL, prefix,
+ NULL)) {
vty_out(vty, "BGP zebra debugging is already enabled for %s\n",
prefix_str);
return CMD_SUCCESS;
}
- bgp_debug_list_add_entry(bgp_debug_zebra_prefixes, NULL, prefix);
+ bgp_debug_list_add_entry(bgp_debug_zebra_prefixes, NULL, prefix, NULL);
if (vty->node == CONFIG_NODE)
DEBUG_ON(zebra, ZEBRA);
@@ -2206,6 +2276,8 @@ DEFUN_NOSH (show_debugging_bgp,
cmd_show_lib_debugs(vty);
+ hook_call(bgp_hook_config_write_debug, vty, false);
+
return CMD_SUCCESS;
}
@@ -2265,6 +2337,11 @@ static int bgp_config_write_debug(struct vty *vty)
bgp_debug_update_out_peers);
}
+ if (CONF_BGP_DEBUG(update, UPDATE_DETAIL)) {
+ vty_out(vty, "debug bgp updates detail\n");
+ write++;
+ }
+
if (CONF_BGP_DEBUG(zebra, ZEBRA)) {
if (!bgp_debug_zebra_prefixes
|| list_isempty(bgp_debug_zebra_prefixes)) {
@@ -2340,6 +2417,9 @@ static int bgp_config_write_debug(struct vty *vty)
write++;
}
+ if (hook_call(bgp_hook_config_write_debug, vty, true))
+ write++;
+
return write;
}
@@ -2370,6 +2450,8 @@ void bgp_debug_init(void)
install_element(CONFIG_NODE, &debug_bgp_keepalive_cmd);
install_element(ENABLE_NODE, &debug_bgp_update_cmd);
install_element(CONFIG_NODE, &debug_bgp_update_cmd);
+ install_element(ENABLE_NODE, &debug_bgp_update_detail_cmd);
+ install_element(CONFIG_NODE, &debug_bgp_update_detail_cmd);
install_element(ENABLE_NODE, &debug_bgp_zebra_cmd);
install_element(CONFIG_NODE, &debug_bgp_zebra_cmd);
install_element(ENABLE_NODE, &debug_bgp_update_groups_cmd);
@@ -2510,7 +2592,8 @@ static int bgp_debug_per_prefix(const struct prefix *p,
/* Return true if this peer is on the per_peer_list of peers to debug
* for BGP_DEBUG_TYPE
*/
-static bool bgp_debug_per_peer(char *host, unsigned long term_bgp_debug_type,
+static bool bgp_debug_per_peer(char *host, const struct prefix *p,
+ unsigned long term_bgp_debug_type,
unsigned int BGP_DEBUG_TYPE,
struct list *per_peer_list)
{
@@ -2522,17 +2605,28 @@ static bool bgp_debug_per_peer(char *host, unsigned long term_bgp_debug_type,
if (!per_peer_list || list_isempty(per_peer_list))
return true;
- else {
- if (!host)
- return false;
+ if (!host)
+ return false;
- for (ALL_LIST_ELEMENTS(per_peer_list, node, nnode,
- filter))
- if (strcmp(filter->host, host) == 0)
- return true;
+ for (ALL_LIST_ELEMENTS(per_peer_list, node, nnode, filter))
+ if (strmatch(filter->host, host) &&
+ filter->plist_name && p) {
+ struct prefix_list *plist;
+ afi_t afi = family2afi(p->family);
- return false;
- }
+ plist = (afi == AFI_IP) ? filter->plist_v4
+ : filter->plist_v6;
+
+ if (!plist)
+ continue;
+
+ return prefix_list_apply(plist, p) ==
+ PREFIX_PERMIT;
+ } else if (strmatch(filter->host, host)) {
+ return true;
+ }
+
+ return false;
}
return false;
@@ -2545,7 +2639,7 @@ bool bgp_debug_neighbor_events(const struct peer *peer)
if (peer)
host = peer->host;
- return bgp_debug_per_peer(host, term_bgp_debug_neighbor_events,
+ return bgp_debug_per_peer(host, NULL, term_bgp_debug_neighbor_events,
BGP_DEBUG_NEIGHBOR_EVENTS,
bgp_debug_neighbor_events_peers);
}
@@ -2557,7 +2651,7 @@ bool bgp_debug_keepalive(const struct peer *peer)
if (peer)
host = peer->host;
- return bgp_debug_per_peer(host, term_bgp_debug_keepalive,
+ return bgp_debug_per_peer(host, NULL, term_bgp_debug_keepalive,
BGP_DEBUG_KEEPALIVE,
bgp_debug_keepalive_peers);
}
@@ -2571,7 +2665,7 @@ bool bgp_debug_update(const struct peer *peer, const struct prefix *p,
host = peer->host;
if (inbound) {
- if (bgp_debug_per_peer(host, term_bgp_debug_update,
+ if (bgp_debug_per_peer(host, p, term_bgp_debug_update,
BGP_DEBUG_UPDATE_IN,
bgp_debug_update_in_peers))
return true;
@@ -2579,7 +2673,7 @@ bool bgp_debug_update(const struct peer *peer, const struct prefix *p,
/* outbound */
else {
- if (bgp_debug_per_peer(host, term_bgp_debug_update,
+ if (bgp_debug_per_peer(host, p, term_bgp_debug_update,
BGP_DEBUG_UPDATE_OUT,
bgp_debug_update_out_peers))
return true;
diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h
index 118325e..5b09501 100644
--- a/bgpd/bgp_debug.h
+++ b/bgpd/bgp_debug.h
@@ -6,9 +6,15 @@
#ifndef _QUAGGA_BGP_DEBUG_H
#define _QUAGGA_BGP_DEBUG_H
+#include "hook.h"
+#include "vty.h"
+
#include "bgp_attr.h"
#include "bgp_updgrp.h"
+DECLARE_HOOK(bgp_hook_config_write_debug, (struct vty *vty, bool running),
+ (vty, running));
+
/* sort of packet direction */
#define DUMP_ON 1
#define DUMP_SEND 2
@@ -96,6 +102,9 @@ extern struct list *bgp_debug_zebra_prefixes;
struct bgp_debug_filter {
char *host;
+ char *plist_name;
+ struct prefix_list *plist_v4;
+ struct prefix_list *plist_v6;
struct prefix *p;
};
@@ -109,6 +118,7 @@ struct bgp_debug_filter {
#define BGP_DEBUG_UPDATE_IN 0x01
#define BGP_DEBUG_UPDATE_OUT 0x02
#define BGP_DEBUG_UPDATE_PREFIX 0x04
+#define BGP_DEBUG_UPDATE_DETAIL 0x08
#define BGP_DEBUG_ZEBRA 0x01
#define BGP_DEBUG_ALLOW_MARTIANS 0x01
#define BGP_DEBUG_NHT 0x01
@@ -124,9 +134,6 @@ struct bgp_debug_filter {
#define BGP_DEBUG_EVPN_MH_ES 0x01
#define BGP_DEBUG_EVPN_MH_RT 0x02
-#define BGP_DEBUG_PACKET_SEND 0x01
-#define BGP_DEBUG_PACKET_SEND_DETAIL 0x02
-
#define BGP_DEBUG_GRACEFUL_RESTART 0x01
#define BGP_DEBUG_BFD_LIB 0x01
diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c
index 529713e..53b5212 100644
--- a/bgpd/bgp_dump.c
+++ b/bgpd/bgp_dump.c
@@ -4,6 +4,7 @@
*/
#include <zebra.h>
+#include <sys/stat.h>
#include "log.h"
#include "stream.h"
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index c408edb..a8ae177 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -1042,6 +1042,34 @@ static int ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt,
return len;
}
+bool ecommunity_has_route_target(struct ecommunity *ecom)
+{
+ uint32_t i;
+ uint8_t *pnt;
+ uint8_t type = 0;
+ uint8_t sub_type = 0;
+
+ if (!ecom)
+ return false;
+ for (i = 0; i < ecom->size; i++) {
+ /* Retrieve value field */
+ pnt = ecom->val + (i * ecom->unit_size);
+
+ /* High-order octet is the type */
+ type = *pnt++;
+
+ if (type == ECOMMUNITY_ENCODE_AS ||
+ type == ECOMMUNITY_ENCODE_IP ||
+ type == ECOMMUNITY_ENCODE_AS4) {
+ /* Low-order octet of type. */
+ sub_type = *pnt++;
+ if (sub_type == ECOMMUNITY_ROUTE_TARGET)
+ return true;
+ }
+ }
+ return false;
+}
+
/* Convert extended community attribute to string.
* Due to historical reason of industry standard implementation, there
* are three types of format:
@@ -1581,8 +1609,8 @@ int ecommunity_fill_pbr_action(struct ecommunity_val *ecom_eval,
* in the 'Network Address of Next- Hop'
* field of the associated MP_REACH_NLRI.
*/
- struct ecommunity_ip *ip_ecom = (struct ecommunity_ip *)
- ecom_eval + 2;
+ struct ecommunity_ip *ip_ecom =
+ (struct ecommunity_ip *)&ecom_eval->val[2];
api->u.zr.redirect_ip_v4 = ip_ecom->ip;
} else
diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h
index 7dc04d2..62e0430 100644
--- a/bgpd/bgp_ecommunity.h
+++ b/bgpd/bgp_ecommunity.h
@@ -117,6 +117,9 @@ struct ecommunity {
*/
uint8_t unit_size;
+ /* Disable IEEE floating-point encoding for extended community */
+ bool disable_ieee_floating;
+
/* Size of Extended Communities attribute. */
uint32_t size;
@@ -125,9 +128,6 @@ struct ecommunity {
/* Human readable format string. */
char *str;
-
- /* Disable IEEE floating-point encoding for extended community */
- bool disable_ieee_floating;
};
struct ecommunity_as {
@@ -341,6 +341,7 @@ extern struct ecommunity *ecommunity_str2com(const char *, int, int);
extern struct ecommunity *ecommunity_str2com_ipv6(const char *str, int type,
int keyword_included);
extern char *ecommunity_ecom2str(struct ecommunity *, int, int);
+extern bool ecommunity_has_route_target(struct ecommunity *ecom);
extern void ecommunity_strfree(char **s);
extern bool ecommunity_include(struct ecommunity *e1, struct ecommunity *e2);
extern bool ecommunity_match(const struct ecommunity *,
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index ad101f1..a846484 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -311,6 +311,49 @@ static int is_vni_present_in_irt_vnis(struct list *vnis, struct bgpevpn *vpn)
return 0;
}
+/* Flag if the route is injectable into EVPN.
+ * This would be following category:
+ * Non-imported route,
+ * Non-EVPN imported route,
+ */
+bool is_route_injectable_into_evpn_non_supp(struct bgp_path_info *pi)
+{
+ struct bgp_path_info *parent_pi;
+ struct bgp_table *table;
+ struct bgp_dest *dest;
+
+ if (pi->sub_type != BGP_ROUTE_IMPORTED || !pi->extra ||
+ !pi->extra->vrfleak || !pi->extra->vrfleak->parent)
+ return true;
+
+ parent_pi = (struct bgp_path_info *)pi->extra->vrfleak->parent;
+ dest = parent_pi->net;
+ if (!dest)
+ return true;
+ table = bgp_dest_table(dest);
+ if (table &&
+ table->afi == AFI_L2VPN &&
+ table->safi == SAFI_EVPN)
+ return false;
+
+ return true;
+}
+
+/* Flag if the route is injectable into EVPN.
+ * This would be following category:
+ * Non-imported route,
+ * Non-EVPN imported route,
+ * Non Aggregate suppressed route.
+ */
+bool is_route_injectable_into_evpn(struct bgp_path_info *pi)
+{
+ /* do not import aggr suppressed routes */
+ if (bgp_path_suppressed(pi))
+ return false;
+
+ return is_route_injectable_into_evpn_non_supp(pi);
+}
+
/*
* Compare Route Targets.
*/
@@ -881,7 +924,7 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
zclient_create_header(
s, add ? ZEBRA_REMOTE_MACIP_ADD : ZEBRA_REMOTE_MACIP_DEL,
bgp->vrf_id);
- stream_putl(s, vpn->vni);
+ stream_putl(s, vpn ? vpn->vni : 0);
if (mac) /* Mac Addr */
stream_put(s, &mac->octet, ETH_ALEN);
@@ -927,7 +970,7 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
snprintf(esi_buf, sizeof(esi_buf), "-");
zlog_debug(
"Tx %s MACIP, VNI %u MAC %pEA IP %pIA flags 0x%x seq %u remote VTEP %pI4 esi %s",
- add ? "ADD" : "DEL", vpn->vni,
+ add ? "ADD" : "DEL", (vpn ? vpn->vni : 0),
(mac ? mac : &p->prefix.macip_addr.mac),
&p->prefix.macip_addr.ip, flags, seq, &remote_vtep_ip,
esi_buf);
@@ -970,14 +1013,14 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
zclient_create_header(
s, add ? ZEBRA_REMOTE_VTEP_ADD : ZEBRA_REMOTE_VTEP_DEL,
bgp->vrf_id);
- stream_putl(s, vpn->vni);
+ stream_putl(s, vpn ? vpn->vni : 0);
if (is_evpn_prefix_ipaddr_v4(p))
stream_put_in_addr(s, &p->prefix.imet_addr.ip.ipaddr_v4);
else if (is_evpn_prefix_ipaddr_v6(p)) {
flog_err(
EC_BGP_VTEP_INVALID,
"Bad remote IP when trying to %s remote VTEP for VNI %u",
- add ? "ADD" : "DEL", vpn->vni);
+ add ? "ADD" : "DEL", (vpn ? vpn->vni : 0));
return -1;
}
stream_putl(s, flood_control);
@@ -986,7 +1029,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
if (bgp_debug_zebra(NULL))
zlog_debug("Tx %s Remote VTEP, VNI %u remote VTEP %pI4",
- add ? "ADD" : "DEL", vpn->vni,
+ add ? "ADD" : "DEL", (vpn ? vpn->vni : 0),
&p->prefix.imet_addr.ip.ipaddr_v4);
frrtrace(3, frr_bgp, evpn_bum_vtep_zsend, add, vpn, p);
@@ -1638,6 +1681,9 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp,
vrf_id_to_name(bgp_vrf->vrf_id), evp, &attr.rmac,
&attr.nexthop);
+ frrtrace(4, frr_bgp, evpn_advertise_type5, bgp_vrf->vrf_id, evp,
+ &attr.rmac, attr.nexthop);
+
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
if (src_afi == AFI_IP6 &&
@@ -2280,6 +2326,8 @@ static int delete_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp)
if (!dest)
return 0;
+ frrtrace(2, frr_bgp, evpn_withdraw_type5, bgp_vrf->vrf_id, evp);
+
delete_evpn_route_entry(bgp_evpn, afi, safi, dest, &pi);
if (pi)
bgp_process(bgp_evpn, dest, afi, safi);
@@ -3029,11 +3077,22 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
/* Process for route leaking. */
vpn_leak_from_vrf_update(bgp_get_default(), bgp_vrf, pi);
- if (bgp_debug_zebra(NULL))
- zlog_debug("... %s pi dest %p (l %d) pi %p (l %d, f 0x%x)",
- new_pi ? "new" : "update", dest,
+ if (bgp_debug_zebra(NULL)) {
+ struct ipaddr nhip = {};
+
+ if (pi->net->rn->p.family == AF_INET6) {
+ SET_IPADDR_V6(&nhip);
+ IPV6_ADDR_COPY(&nhip.ipaddr_v6, &pi->attr->mp_nexthop_global);
+ } else {
+ SET_IPADDR_V4(&nhip);
+ IPV4_ADDR_COPY(&nhip.ipaddr_v4, &pi->attr->nexthop);
+ }
+ zlog_debug("... %s pi %s dest %p (l %d) pi %p (l %d, f 0x%x) nh %pIA",
+ new_pi ? "new" : "update",
+ bgp_vrf->name_pretty, dest,
bgp_dest_get_lock_count(dest), pi, pi->lock,
- pi->flags);
+ pi->flags, &nhip);
+ }
bgp_dest_unlock_node(dest);
@@ -3342,10 +3401,22 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
return 0;
}
- if (bgp_debug_zebra(NULL))
- zlog_debug("... delete dest %p (l %d) pi %p (l %d, f 0x%x)",
- dest, bgp_dest_get_lock_count(dest), pi, pi->lock,
- pi->flags);
+ if (bgp_debug_zebra(NULL)) {
+ struct ipaddr nhip = {};
+
+ if (pi->net->rn->p.family == AF_INET6) {
+ SET_IPADDR_V6(&nhip);
+ IPV6_ADDR_COPY(&nhip.ipaddr_v6, &pi->attr->mp_nexthop_global);
+ } else {
+ SET_IPADDR_V4(&nhip);
+ IPV4_ADDR_COPY(&nhip.ipaddr_v4, &pi->attr->nexthop);
+ }
+
+ zlog_debug("... delete pi %s dest %p (l %d) pi %p (l %d, f 0x%x) nh %pIA",
+ bgp_vrf->name_pretty, dest,
+ bgp_dest_get_lock_count(dest), pi, pi->lock,
+ pi->flags, &nhip);
+ }
/* Process for route leaking. */
vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp_vrf, pi);
@@ -3590,7 +3661,7 @@ static bool bgp_evpn_route_matches_macvrf_soo(struct bgp_path_info *pi,
struct ecommunity *macvrf_soo;
bool ret = false;
- if (!bgp_evpn->evpn_info)
+ if (!bgp_evpn || !bgp_evpn->evpn_info)
return false;
/* We only stamp the mac-vrf soo on routes from our local L2VNI.
@@ -6097,7 +6168,7 @@ void bgp_evpn_derive_auto_rd(struct bgp *bgp, struct bgpevpn *vpn)
snprintfrr(buf, sizeof(buf), "%pI4:%hu", &bgp->router_id, vpn->rd_id);
(void)str2prefix_rd(buf, &vpn->prd);
if (vpn->prd_pretty)
- XFREE(MTYPE_BGP, vpn->prd_pretty);
+ XFREE(MTYPE_BGP_NAME, vpn->prd_pretty);
UNSET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
}
@@ -6203,7 +6274,7 @@ void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn)
hash_release(bgp->vni_svi_hash, vpn);
hash_release(bgp->vnihash, vpn);
if (vpn->prd_pretty)
- XFREE(MTYPE_BGP, vpn->prd_pretty);
+ XFREE(MTYPE_BGP_NAME, vpn->prd_pretty);
QOBJ_UNREG(vpn);
XFREE(MTYPE_BGP_EVPN, vpn);
}
@@ -7080,7 +7151,7 @@ void bgp_evpn_cleanup(struct bgp *bgp)
}
if (bgp->vrf_prd_pretty)
- XFREE(MTYPE_BGP, bgp->vrf_prd_pretty);
+ XFREE(MTYPE_BGP_NAME, bgp->vrf_prd_pretty);
}
/*
@@ -7650,3 +7721,64 @@ bool bgp_evpn_mpath_has_dvni(const struct bgp *bgp_vrf,
return false;
}
+
+/* Upon aggregate set trigger unimport suppressed routes
+ * from EVPN
+ */
+void bgp_aggr_supp_withdraw_from_evpn(struct bgp *bgp, afi_t afi, safi_t safi)
+{
+ struct bgp_dest *agg_dest, *dest, *top;
+ const struct prefix *aggr_p;
+ struct bgp_aggregate *bgp_aggregate;
+ struct bgp_table *table;
+ struct bgp_path_info *pi;
+
+ if (!bgp_get_evpn() && !advertise_type5_routes(bgp, afi))
+ return;
+
+ /* Aggregate-address table walk. */
+ table = bgp->rib[afi][safi];
+ for (agg_dest = bgp_table_top(bgp->aggregate[afi][safi]); agg_dest;
+ agg_dest = bgp_route_next(agg_dest)) {
+ bgp_aggregate = bgp_dest_get_bgp_aggregate_info(agg_dest);
+
+ if (bgp_aggregate == NULL)
+ continue;
+
+ aggr_p = bgp_dest_get_prefix(agg_dest);
+
+ /* Look all nodes below the aggregate prefix in
+ * global AFI/SAFI table (IPv4/IPv6).
+ * Trigger withdrawal (this will be Type-5 routes only)
+ * from EVPN Global table.
+ */
+ top = bgp_node_get(table, aggr_p);
+ for (dest = bgp_node_get(table, aggr_p); dest;
+ dest = bgp_route_next_until(dest, top)) {
+ const struct prefix *dest_p = bgp_dest_get_prefix(dest);
+
+ if (dest_p->prefixlen <= aggr_p->prefixlen)
+ continue;
+
+ for (pi = bgp_dest_get_bgp_path_info(dest); pi;
+ pi = pi->next) {
+ if (pi->sub_type == BGP_ROUTE_AGGREGATE)
+ continue;
+
+ /* Only Suppressed route remove from EVPN */
+ if (!bgp_path_suppressed(pi))
+ continue;
+
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s aggregated %pFX remove suppressed route %pFX",
+ __func__, aggr_p, dest_p);
+
+ if (!is_route_injectable_into_evpn_non_supp(pi))
+ continue;
+
+ bgp_evpn_withdraw_type5_route(bgp, dest_p, afi,
+ safi);
+ }
+ }
+ }
+}
diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h
index 5547446..c641a64 100644
--- a/bgpd/bgp_evpn.h
+++ b/bgpd/bgp_evpn.h
@@ -94,31 +94,6 @@ static inline bool is_pi_family_evpn(struct bgp_path_info *pi)
return is_pi_family_matching(pi, AFI_L2VPN, SAFI_EVPN);
}
-/* Flag if the route is injectable into EVPN. This would be either a
- * non-imported route or a non-EVPN imported route.
- */
-static inline bool is_route_injectable_into_evpn(struct bgp_path_info *pi)
-{
- struct bgp_path_info *parent_pi;
- struct bgp_table *table;
- struct bgp_dest *dest;
-
- if (pi->sub_type != BGP_ROUTE_IMPORTED || !pi->extra ||
- !pi->extra->vrfleak || !pi->extra->vrfleak->parent)
- return true;
-
- parent_pi = (struct bgp_path_info *)pi->extra->vrfleak->parent;
- dest = parent_pi->net;
- if (!dest)
- return true;
- table = bgp_dest_table(dest);
- if (table &&
- table->afi == AFI_L2VPN &&
- table->safi == SAFI_EVPN)
- return false;
- return true;
-}
-
static inline bool evpn_resolve_overlay_index(void)
{
struct bgp *bgp = NULL;
@@ -206,5 +181,9 @@ extern mpls_label_t *bgp_evpn_path_info_labels_get_l3vni(mpls_label_t *labels,
extern vni_t bgp_evpn_path_info_get_l3vni(const struct bgp_path_info *pi);
extern bool bgp_evpn_mpath_has_dvni(const struct bgp *bgp_vrf,
struct bgp_path_info *mpinfo);
+extern bool is_route_injectable_into_evpn(struct bgp_path_info *pi);
+extern bool is_route_injectable_into_evpn_non_supp(struct bgp_path_info *pi);
+extern void bgp_aggr_supp_withdraw_from_evpn(struct bgp *bgp, afi_t afi,
+ safi_t safi);
#endif /* _QUAGGA_BGP_EVPN_H */
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index ffb1b17..d88c52d 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -37,7 +37,7 @@
#include "bgpd/bgp_zebra.h"
#include "bgpd/bgp_addpath.h"
#include "bgpd/bgp_label.h"
-#include "bgpd/bgp_nht.h"
+#include "bgpd/bgp_nhg.h"
#include "bgpd/bgp_mpath.h"
#include "bgpd/bgp_trace.h"
@@ -441,6 +441,10 @@ int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
? "esr"
: (vpn ? "ead-evi" : "ead-es"),
&attr->mp_nexthop_global_in);
+
+ frrtrace(4, frr_bgp, evpn_mh_local_ead_es_evi_route_upd,
+ &es->esi, (vpn ? vpn->vni : 0), evp->prefix.route_type,
+ attr->mp_nexthop_global_in);
}
/* Return back the route entry. */
@@ -491,6 +495,8 @@ static int bgp_evpn_mh_route_delete(struct bgp *bgp, struct bgp_evpn_es *es,
: (vpn ? "ead-evi" : "ead-es"),
&es->originator_ip);
+ frrtrace(4, frr_bgp, evpn_mh_local_ead_es_evi_route_del, &es->esi,
+ (vpn ? vpn->vni : 0), p->prefix.route_type, es->originator_ip);
/* Next, locate route node in the global EVPN routing table.
* Note that this table is a 2-level tree (RD-level + Prefix-level)
*/
@@ -2999,8 +3005,8 @@ static struct bgp_evpn_es_vrf *bgp_evpn_es_vrf_create(struct bgp_evpn_es *es,
listnode_add(es->es_vrf_list, &es_vrf->es_listnode);
/* setup the L3 NHG id for the ES */
- es_vrf->nhg_id = bgp_l3nhg_id_alloc();
- es_vrf->v6_nhg_id = bgp_l3nhg_id_alloc();
+ es_vrf->nhg_id = bgp_nhg_id_alloc();
+ es_vrf->v6_nhg_id = bgp_nhg_id_alloc();
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
zlog_debug("es %s vrf %u nhg %u v6_nhg %d create", es->esi_str,
@@ -3028,10 +3034,10 @@ static void bgp_evpn_es_vrf_delete(struct bgp_evpn_es_vrf *es_vrf)
/* Remove the NHG resources */
bgp_evpn_l3nhg_deactivate(es_vrf);
if (es_vrf->nhg_id)
- bgp_l3nhg_id_free(es_vrf->nhg_id);
+ bgp_nhg_id_free(es_vrf->nhg_id);
es_vrf->nhg_id = 0;
if (es_vrf->v6_nhg_id)
- bgp_l3nhg_id_free(es_vrf->v6_nhg_id);
+ bgp_nhg_id_free(es_vrf->v6_nhg_id);
es_vrf->v6_nhg_id = 0;
/* remove from the ES's VRF list */
@@ -3460,6 +3466,10 @@ static void bgp_evpn_es_evi_vtep_add(struct bgp *bgp,
evi_vtep->es_evi->vpn->vni, &evi_vtep->vtep_ip,
ead_es ? "ead_es" : "ead_evi");
+ frrtrace(4, frr_bgp, evpn_mh_es_evi_vtep_add,
+ &evi_vtep->es_evi->es->esi, evi_vtep->es_evi->vpn->vni,
+ evi_vtep->vtep_ip, ead_es);
+
if (ead_es)
SET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_ES);
else
@@ -3484,6 +3494,10 @@ static void bgp_evpn_es_evi_vtep_del(struct bgp *bgp,
evi_vtep->es_evi->vpn->vni, &evi_vtep->vtep_ip,
ead_es ? "ead_es" : "ead_evi");
+ frrtrace(4, frr_bgp, evpn_mh_es_evi_vtep_del,
+ &evi_vtep->es_evi->es->esi, evi_vtep->es_evi->vpn->vni,
+ evi_vtep->vtep_ip, ead_es);
+
if (ead_es)
UNSET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_ES);
else
@@ -4443,13 +4457,13 @@ static void bgp_evpn_nh_zebra_update_send(struct bgp_evpn_nh *nh, bool add)
stream_putw_at(s, 0, stream_get_endp(s));
- if (BGP_DEBUG(evpn_mh, EVPN_MH_ES)) {
+ if (BGP_DEBUG(evpn_mh, EVPN_MH_ES) || bgp_debug_zebra(NULL)) {
if (add)
- zlog_debug("evpn vrf %s nh %s rmac %pEA add to zebra",
+ zlog_debug("evpn %s nh %s rmac %pEA add to zebra",
nh->bgp_vrf->name_pretty, nh->nh_str,
&nh->rmac);
- else if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
- zlog_debug("evpn vrf %s nh %s del to zebra",
+ else
+ zlog_debug("evpn %s nh %s del to zebra",
nh->bgp_vrf->name_pretty, nh->nh_str);
}
@@ -4632,7 +4646,7 @@ static void bgp_evpn_nh_update_ref_pi(struct bgp_evpn_nh *nh)
continue;
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
- zlog_debug("evpn vrf %s nh %s ref_pi update",
+ zlog_debug("evpn %s nh %s ref_pi update",
nh->bgp_vrf->name_pretty, nh->nh_str);
nh->ref_pi = pi;
/* If we have a new pi copy rmac from it and update
@@ -4710,11 +4724,12 @@ static void bgp_evpn_path_nh_unlink(struct bgp_path_evpn_nh_info *nh_info)
pi = nh_info->pi;
if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
- zlog_debug("path %s unlinked from nh %s %s",
+ zlog_debug("path %s unlinked from %s nh %s pathcount %u",
pi->net ? prefix2str(&pi->net->rn->p, prefix_buf,
sizeof(prefix_buf))
: "",
- nh->bgp_vrf->name_pretty, nh->nh_str);
+ nh->bgp_vrf->name_pretty, nh->nh_str,
+ listcount(nh->pi_list));
list_delete_node(nh->pi_list, &nh_info->nh_listnode);
@@ -4745,7 +4760,7 @@ static void bgp_evpn_path_nh_link(struct bgp *bgp_vrf, struct bgp_path_info *pi)
if (!bgp_vrf->evpn_nh_table) {
if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
- zlog_debug("path %pFX linked to vrf %s failed",
+ zlog_debug("path %pFX linked to %s failed",
&pi->net->rn->p, bgp_vrf->name_pretty);
return;
}
@@ -4793,8 +4808,9 @@ static void bgp_evpn_path_nh_link(struct bgp *bgp_vrf, struct bgp_path_info *pi)
bgp_evpn_path_nh_unlink(nh_info);
if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
- zlog_debug("path %pFX linked to nh %s %s", &pi->net->rn->p,
- nh->bgp_vrf->name_pretty, nh->nh_str);
+ zlog_debug("path %pFX linked to %s nh %s pathcount %u",
+ &pi->net->rn->p, nh->bgp_vrf->name_pretty,
+ nh->nh_str, listcount(nh->pi_list));
/* link mac-ip path to the new nh */
nh_info->nh = nh;
diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h
index ee1f749..cebabb9 100644
--- a/bgpd/bgp_evpn_mh.h
+++ b/bgpd/bgp_evpn_mh.h
@@ -388,11 +388,6 @@ static inline bool bgp_evpn_attr_is_local_es(struct attr *attr)
return attr ? !!(attr->es_flags & ATTR_ES_IS_LOCAL) : false;
}
-static inline uint32_t bgp_evpn_attr_get_df_pref(struct attr *attr)
-{
- return (attr) ? attr->df_pref : 0;
-}
-
static inline bool bgp_evpn_local_es_is_active(struct bgp_evpn_es *es)
{
return (es->flags & BGP_EVPNES_OPER_UP)
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index eb9f34e..846a82b 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -2294,11 +2294,11 @@ static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd,
bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
if (bgp_vrf->vrf_prd_pretty)
- XFREE(MTYPE_BGP, bgp_vrf->vrf_prd_pretty);
+ XFREE(MTYPE_BGP_NAME, bgp_vrf->vrf_prd_pretty);
/* update RD */
memcpy(&bgp_vrf->vrf_prd, rd, sizeof(struct prefix_rd));
- bgp_vrf->vrf_prd_pretty = XSTRDUP(MTYPE_BGP, rd_pretty);
+ bgp_vrf->vrf_prd_pretty = XSTRDUP(MTYPE_BGP_NAME, rd_pretty);
SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
/* We have a new RD for VRF.
@@ -2321,7 +2321,7 @@ static void evpn_unconfigure_vrf_rd(struct bgp *bgp_vrf)
bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf);
UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
if (bgp_vrf->vrf_prd_pretty)
- XFREE(MTYPE_BGP, bgp_vrf->vrf_prd_pretty);
+ XFREE(MTYPE_BGP_NAME, bgp_vrf->vrf_prd_pretty);
/* We have a new RD for VRF.
* Advertise all type-5 routes again with the new RD
*/
@@ -2343,7 +2343,7 @@ static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn,
/* update RD */
memcpy(&vpn->prd, rd, sizeof(struct prefix_rd));
- vpn->prd_pretty = XSTRDUP(MTYPE_BGP, rd_pretty);
+ vpn->prd_pretty = XSTRDUP(MTYPE_BGP_NAME, rd_pretty);
SET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
if (is_vni_live(vpn))
diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c
index ad541b6..a851179 100644
--- a/bgpd/bgp_filter.c
+++ b/bgpd/bgp_filter.c
@@ -205,8 +205,17 @@ static struct as_list *as_list_new(void)
static void as_list_free(struct as_list *aslist)
{
- XFREE(MTYPE_AS_STR, aslist->name);
- XFREE(MTYPE_AS_LIST, aslist);
+ struct aspath_exclude_list *cur_bp = aslist->exclude_list;
+ struct aspath_exclude_list *next_bp = NULL;
+
+ while (cur_bp) {
+ next_bp = cur_bp->next;
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, cur_bp);
+ cur_bp = next_bp;
+ }
+
+ XFREE (MTYPE_AS_STR, aslist->name);
+ XFREE (MTYPE_AS_LIST, aslist);
}
/* Insert new AS list to list of as_list. Each as_list is sorted by
@@ -290,6 +299,7 @@ static void as_list_delete(struct as_list *aslist)
{
struct as_list_list *list;
struct as_filter *filter, *next;
+ struct aspath_exclude_list *cur_bp;
for (filter = aslist->head; filter; filter = next) {
next = filter->next;
@@ -308,6 +318,12 @@ static void as_list_delete(struct as_list *aslist)
else
list->head = aslist->next;
+ cur_bp = aslist->exclude_list;
+ while (cur_bp) {
+ cur_bp->bp_as_excl->exclude_aspath_acl = NULL;
+ cur_bp = cur_bp->next;
+ }
+
as_list_free(aslist);
}
diff --git a/bgpd/bgp_filter.h b/bgpd/bgp_filter.h
index 1890fd3..2d9f07c 100644
--- a/bgpd/bgp_filter.h
+++ b/bgpd/bgp_filter.h
@@ -25,6 +25,11 @@ struct as_filter {
int64_t seq;
};
+struct aspath_exclude_list {
+ struct aspath_exclude_list *next;
+ struct aspath_exclude *bp_as_excl;
+};
+
/* AS path filter list. */
struct as_list {
char *name;
@@ -34,6 +39,7 @@ struct as_list {
struct as_filter *head;
struct as_filter *tail;
+ struct aspath_exclude_list *exclude_list;
};
diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c
index a295ec5..d4ccca8 100644
--- a/bgpd/bgp_flowspec_vty.c
+++ b/bgpd/bgp_flowspec_vty.c
@@ -547,7 +547,7 @@ static int bgp_fs_local_install_interface(struct bgp *bgp,
return CMD_SUCCESS;
pbr_if = XCALLOC(MTYPE_TMP,
sizeof(struct bgp_pbr_interface));
- strlcpy(pbr_if->name, ifname, INTERFACE_NAMSIZ);
+ strlcpy(pbr_if->name, ifname, IFNAMSIZ);
RB_INSERT(bgp_pbr_interface_head, head, pbr_if);
*bgp_pbr_interface_any = false;
} else {
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index eef3b64..234dbb0 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -445,7 +445,7 @@ void bgp_timer_set(struct peer_connection *connection)
EVENT_OFF(peer->connection->t_pmax_restart);
EVENT_OFF(peer->t_refresh_stalepath);
- /* fallthru */
+ fallthrough;
case Clearing:
EVENT_OFF(connection->t_start);
EVENT_OFF(connection->t_connect);
@@ -562,42 +562,45 @@ void bgp_delayopen_timer(struct event *thread)
}
/* BGP Peer Down Cause */
-const char *const peer_down_str[] = {"",
- "Router ID changed",
- "Remote AS changed",
- "Local AS change",
- "Cluster ID changed",
- "Confederation identifier changed",
- "Confederation peer changed",
- "RR client config change",
- "RS client config change",
- "Update source change",
- "Address family activated",
- "Admin. shutdown",
- "User reset",
- "BGP Notification received",
- "BGP Notification send",
- "Peer closed the session",
- "Neighbor deleted",
- "Peer-group add member",
- "Peer-group delete member",
- "Capability changed",
- "Passive config change",
- "Multihop config change",
- "NSF peer closed the session",
- "Intf peering v6only config change",
- "BFD down received",
- "Interface down",
- "Neighbor address lost",
- "No path to specified Neighbor",
- "Waiting for Peer IPv6 LLA",
- "Waiting for VRF to be initialized",
- "No AFI/SAFI activated for peer",
- "AS Set config change",
- "Waiting for peer OPEN",
- "Reached received prefix count",
- "Socket Error",
- "Admin. shutdown (RTT)"};
+const char *const peer_down_str[] = {
+ "",
+ "Router ID changed",
+ "Remote AS changed",
+ "Local AS change",
+ "Cluster ID changed",
+ "Confederation identifier changed",
+ "Confederation peer changed",
+ "RR client config change",
+ "RS client config change",
+ "Update source change",
+ "Address family activated",
+ "Admin. shutdown",
+ "User reset",
+ "BGP Notification received",
+ "BGP Notification send",
+ "Peer closed the session",
+ "Neighbor deleted",
+ "Peer-group add member",
+ "Peer-group delete member",
+ "Capability changed",
+ "Passive config change",
+ "Multihop config change",
+ "NSF peer closed the session",
+ "Intf peering v6only config change",
+ "BFD down received",
+ "Interface down",
+ "Neighbor address lost",
+ "No path to specified Neighbor",
+ "Waiting for Peer IPv6 LLA",
+ "Waiting for VRF to be initialized",
+ "No AFI/SAFI activated for peer",
+ "AS Set config change",
+ "Waiting for peer OPEN",
+ "Reached received prefix count",
+ "Socket Error",
+ "Admin. shutdown (RTT)",
+ "Suppress Fib Turned On or Off",
+};
static void bgp_graceful_restart_timer_off(struct peer_connection *connection,
struct peer *peer)
@@ -2384,6 +2387,7 @@ void bgp_fsm_nht_update(struct peer_connection *connection, struct peer *peer,
&& (peer->gtsm_hops == BGP_GTSM_HOPS_CONNECTED
|| peer->bgp->fast_convergence))
BGP_EVENT_ADD(connection, TCP_fatal_error);
+ break;
case Clearing:
case Deleted:
case BGP_STATUS_MAX:
@@ -2716,7 +2720,7 @@ int bgp_gr_lookup_n_update_all_peer(struct bgp *bgp,
return BGP_GR_SUCCESS;
}
-int bgp_gr_update_all(struct bgp *bgp, int global_gr_cmd)
+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;
@@ -2870,7 +2874,8 @@ enum peer_mode bgp_peer_gr_mode_get(struct peer *peer)
return peer->peer_gr_present_state;
}
-int bgp_neighbor_graceful_restart(struct peer *peer, int peer_gr_cmd)
+int bgp_neighbor_graceful_restart(struct peer *peer,
+ enum peer_gr_command peer_gr_cmd)
{
enum peer_mode peer_new_state = PEER_INVALID;
enum peer_mode peer_old_state = PEER_INVALID;
@@ -2929,8 +2934,8 @@ int bgp_neighbor_graceful_restart(struct peer *peer, int peer_gr_cmd)
return result;
}
-unsigned int bgp_peer_gr_action(struct peer *peer, int old_peer_state,
- int new_peer_state)
+unsigned int bgp_peer_gr_action(struct peer *peer, enum peer_mode old_peer_state,
+ enum peer_mode new_peer_state)
{
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
@@ -2938,7 +2943,7 @@ unsigned int bgp_peer_gr_action(struct peer *peer, int old_peer_state,
__func__, print_peer_gr_mode(old_peer_state),
print_peer_gr_mode(new_peer_state));
- int bgp_gr_global_mode = GLOBAL_INVALID;
+ enum global_mode bgp_gr_global_mode = GLOBAL_INVALID;
unsigned int ret = BGP_GR_FAILURE;
if (old_peer_state == new_peer_state) {
@@ -2970,10 +2975,10 @@ unsigned int bgp_peer_gr_action(struct peer *peer, int old_peer_state,
BGP_PEER_GR_GLOBAL_INHERIT_UNSET(peer);
- if (new_peer_state == 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 ((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.
*/
ret = BGP_GR_SUCCESS;
} else {
@@ -3000,8 +3005,7 @@ unsigned int bgp_peer_gr_action(struct peer *peer, int old_peer_state,
BGP_PEER_GR_GLOBAL_INHERIT_SET(peer);
- if (old_peer_state == bgp_gr_global_mode) {
-
+ 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.
diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h
index fd46b79..2e96ac4 100644
--- a/bgpd/bgp_fsm.h
+++ b/bgpd/bgp_fsm.h
@@ -143,10 +143,11 @@ extern void bgp_adjust_routeadv(struct peer *);
DECLARE_HOOK(peer_backward_transition, (struct peer *peer), (peer));
DECLARE_HOOK(peer_established, (struct peer *peer), (peer));
-int bgp_gr_update_all(struct bgp *bgp, int global_gr_cmd);
-int bgp_neighbor_graceful_restart(struct peer *peer, int peer_gr_cmd);
-unsigned int bgp_peer_gr_action(struct peer *peer,
- int old_peer_state, int new_peer_state);
+int bgp_gr_update_all(struct bgp *bgp, enum global_gr_command global_gr_cmd);
+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);
unsigned int bgp_peer_gr_helper_enable(struct peer *peer);
unsigned int bgp_peer_gr_enable(struct peer *peer);
diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c
index b8ce1ae..7327ab5 100644
--- a/bgpd/bgp_label.c
+++ b/bgpd/bgp_label.c
@@ -132,9 +132,8 @@ static void bgp_send_fec_register_label_msg(struct bgp_dest *dest, bool reg,
return;
if (BGP_DEBUG(labelpool, LABELPOOL))
- zlog_debug("%s: FEC %sregister %pRN label_index=%u label=%u",
- __func__, reg ? "" : "un", bgp_dest_to_rnode(dest),
- label_index, label);
+ zlog_debug("%s: FEC %sregister %pBD label_index=%u label=%u",
+ __func__, reg ? "" : "un", dest, label_index, label);
/* If the route node has a local_label assigned or the
* path node has an MPLS SR label index allowing zebra to
* derive the label, proceed with registration. */
@@ -199,8 +198,8 @@ int bgp_reg_for_label_callback(mpls_label_t new_label, void *labelid,
assert(dest);
if (BGP_DEBUG(labelpool, LABELPOOL))
- zlog_debug("%s: FEC %pRN label=%u, allocated=%d", __func__,
- bgp_dest_to_rnode(dest), new_label, allocated);
+ zlog_debug("%s: FEC %pBD label=%u, allocated=%d", __func__,
+ dest, new_label, allocated);
if (!allocated) {
/*
diff --git a/bgpd/bgp_labelpool.c b/bgpd/bgp_labelpool.c
index 8833386..23e0c19 100644
--- a/bgpd/bgp_labelpool.c
+++ b/bgpd/bgp_labelpool.c
@@ -36,6 +36,8 @@ static void lptest_init(void);
static void lptest_finish(void);
#endif
+static void bgp_sync_label_manager(struct event *e);
+
/*
* Remember where pool data are kept
*/
@@ -448,13 +450,16 @@ void bgp_lp_get(
if (lp_fifo_count(&lp->requests) > lp->pending_count) {
if (!bgp_zebra_request_label_range(MPLS_LABEL_BASE_ANY,
- lp->next_chunksize))
+ lp->next_chunksize, true))
return;
lp->pending_count += lp->next_chunksize;
if ((lp->next_chunksize << 1) <= LP_CHUNK_SIZE_MAX)
lp->next_chunksize <<= 1;
}
+
+ event_add_timer(bm->master, bgp_sync_label_manager, NULL, 1,
+ &bm->t_bgp_sync_label_manager);
}
void bgp_lp_release(
@@ -494,8 +499,18 @@ void bgp_lp_release(
bf_release_index(chunk->allocated_map, index);
chunk->nfree += 1;
deallocated = true;
+ break;
}
assert(deallocated);
+ if (deallocated &&
+ chunk->nfree == chunk->last - chunk->first + 1 &&
+ lp_fifo_count(&lp->requests) == 0) {
+ bgp_zebra_release_label_range(chunk->first,
+ chunk->last);
+ list_delete_node(lp->chunks, node);
+ lp_chunk_free(chunk);
+ lp->next_chunksize = LP_CHUNK_SIZE_MIN;
+ }
}
}
}
@@ -547,6 +562,10 @@ static void bgp_sync_label_manager(struct event *e)
zlog_debug("%s: out of labels, await more",
__func__);
}
+
+ lp_fifo_add_tail(&lp->requests, lf);
+ event_add_timer(bm->master, bgp_sync_label_manager,
+ NULL, 1, &bm->t_bgp_sync_label_manager);
break;
}
@@ -572,9 +591,6 @@ static void bgp_sync_label_manager(struct event *e)
finishedrequest:
XFREE(MTYPE_BGP_LABEL_FIFO, lf);
}
-
- event_add_timer(bm->master, bgp_sync_label_manager, NULL, 1,
- &bm->t_bgp_sync_label_manager);
}
void bgp_lp_event_chunk(uint32_t first, uint32_t last)
@@ -642,7 +658,7 @@ void bgp_lp_event_zebra_up(void)
}
/* round up */
- chunks_needed = (labels_needed / lp->next_chunksize) + 1;
+ chunks_needed = (labels_needed + lp->next_chunksize - 1) / lp->next_chunksize;
labels_needed = chunks_needed * lp->next_chunksize;
/*
@@ -650,10 +666,10 @@ void bgp_lp_event_zebra_up(void)
*/
list_delete_all_node(lp->chunks);
- if (!bgp_zebra_request_label_range(MPLS_LABEL_BASE_ANY, labels_needed))
+ if (labels_needed && !bgp_zebra_request_label_range(MPLS_LABEL_BASE_ANY,
+ labels_needed, true))
return;
-
- lp->pending_count = labels_needed;
+ lp->pending_count += labels_needed;
/*
* Invalidate any existing labels and requeue them as requests
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index 11917c6..851c488 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -47,14 +47,20 @@
#include "bgpd/bgp_errors.h"
#include "bgpd/bgp_script.h"
#include "bgpd/bgp_evpn_mh.h"
-#include "bgpd/bgp_nht.h"
+#include "bgpd/bgp_nhg.h"
#include "bgpd/bgp_routemap_nb.h"
#include "bgpd/bgp_community_alias.h"
+DEFINE_HOOK(bgp_hook_config_write_vrf, (struct vty *vty, struct vrf *vrf),
+ (vty, vrf));
+
#ifdef ENABLE_BGP_VNC
#include "bgpd/rfapi/rfapi_backend.h"
#endif
+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' },
@@ -199,7 +205,7 @@ static __attribute__((__noreturn__)) void bgp_exit(int status)
bgp_delete(bgp_default);
bgp_evpn_mh_finish();
- bgp_l3nhg_finish();
+ bgp_nhg_finish();
/* reverse bgp_dump_init */
bgp_dump_finish();
@@ -287,6 +293,7 @@ static int bgp_vrf_enable(struct vrf *vrf)
bgp_handle_socket(bgp, vrf, old_vrf_id, true);
bgp_instance_up(bgp);
+ hook_call(bgp_hook_vrf_update, vrf, true);
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);
@@ -333,15 +340,36 @@ static int bgp_vrf_disable(struct vrf *vrf)
* "down". */
bgp_instance_down(bgp);
bgp_vrf_unlink(bgp, vrf);
+ hook_call(bgp_hook_vrf_update, vrf, false);
}
/* Note: This is a callback, the VRF will be deleted by the caller. */
return 0;
}
+static int bgp_vrf_config_write(struct vty *vty)
+{
+ struct vrf *vrf;
+
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ if (vrf->vrf_id == VRF_DEFAULT) {
+ vty_out(vty, "!\n");
+ continue;
+ }
+ vty_out(vty, "vrf %s\n", vrf->name);
+
+ hook_call(bgp_hook_config_write_vrf, vty, vrf);
+
+ vty_out(vty, "exit-vrf\n!\n");
+ }
+
+ return 0;
+}
+
static void bgp_vrf_init(void)
{
vrf_init(bgp_vrf_new, bgp_vrf_enable, bgp_vrf_disable, bgp_vrf_delete);
+ vrf_cmd_init(bgp_vrf_config_write);
}
static void bgp_vrf_terminate(void)
@@ -357,15 +385,20 @@ static const struct frr_yang_module_info *const bgpd_yang_modules[] = {
&frr_bgp_route_map_info,
};
-FRR_DAEMON_INFO(bgpd, BGP, .vty_port = BGP_VTY_PORT,
+/* clang-format off */
+FRR_DAEMON_INFO(bgpd, BGP,
+ .vty_port = BGP_VTY_PORT,
+ .proghelp = "Implementation of the BGP routing protocol.",
- .proghelp = "Implementation of the BGP routing protocol.",
+ .signals = bgp_signals,
+ .n_signals = array_size(bgp_signals),
- .signals = bgp_signals, .n_signals = array_size(bgp_signals),
+ .privs = &bgpd_privs,
- .privs = &bgpd_privs, .yang_modules = bgpd_yang_modules,
- .n_yang_modules = array_size(bgpd_yang_modules),
+ .yang_modules = bgpd_yang_modules,
+ .n_yang_modules = array_size(bgpd_yang_modules),
);
+/* clang-format on */
#define DEPRECATED_OPTIONS ""
diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c
index 5c3067f..0764f1e 100644
--- a/bgpd/bgp_memory.c
+++ b/bgpd/bgp_memory.c
@@ -15,6 +15,7 @@
DEFINE_MGROUP(BGPD, "bgpd");
DEFINE_MTYPE(BGPD, BGP, "BGP instance");
+DEFINE_MTYPE(BGPD, BGP_NAME, "BGP Name data");
DEFINE_MTYPE(BGPD, BGP_LISTENER, "BGP listen socket details");
DEFINE_MTYPE(BGPD, BGP_PEER, "BGP peer");
DEFINE_MTYPE(BGPD, BGP_PEER_CONNECTION, "BGP peer connection");
@@ -41,6 +42,7 @@ DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA, "BGP ancillary route info");
DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA_EVPN, "BGP extra info for EVPN");
DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA_FS, "BGP extra info for flowspec");
DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA_VRFLEAK, "BGP extra info for vrf leaking");
+DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA_VNC, "BGP extra info for vnc");
DEFINE_MTYPE(BGPD, BGP_CONN, "BGP connected");
DEFINE_MTYPE(BGPD, BGP_STATIC, "BGP static");
DEFINE_MTYPE(BGPD, BGP_ADVERTISE_ATTR, "BGP adv attr");
diff --git a/bgpd/bgp_memory.h b/bgpd/bgp_memory.h
index 7acb41e..29584cd 100644
--- a/bgpd/bgp_memory.h
+++ b/bgpd/bgp_memory.h
@@ -11,6 +11,7 @@
DECLARE_MGROUP(BGPD);
DECLARE_MTYPE(BGP);
+DECLARE_MTYPE(BGP_NAME);
DECLARE_MTYPE(BGP_LISTENER);
DECLARE_MTYPE(BGP_PEER);
DECLARE_MTYPE(BGP_PEER_CONNECTION);
@@ -37,6 +38,7 @@ DECLARE_MTYPE(BGP_ROUTE_EXTRA);
DECLARE_MTYPE(BGP_ROUTE_EXTRA_EVPN);
DECLARE_MTYPE(BGP_ROUTE_EXTRA_FS);
DECLARE_MTYPE(BGP_ROUTE_EXTRA_VRFLEAK);
+DECLARE_MTYPE(BGP_ROUTE_EXTRA_VNC);
DECLARE_MTYPE(BGP_CONN);
DECLARE_MTYPE(BGP_STATIC);
DECLARE_MTYPE(BGP_ADVERTISE_ATTR);
diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c
index f2d1ee0..c773c21 100644
--- a/bgpd/bgp_mpath.c
+++ b/bgpd/bgp_mpath.c
@@ -554,12 +554,11 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
}
if (debug)
- zlog_debug(
- "%pRN(%s): starting mpath update, newbest %s num candidates %d old-mpath-count %d old-cum-bw %" PRIu64,
- bgp_dest_to_rnode(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,
+ dest, bgp->name_pretty,
+ new_best ? new_best->peer->host : "NONE",
+ mp_list ? listcount(mp_list) : 0, old_mpath_count,
+ old_cum_bw);
/*
* We perform an ordered walk through both lists in parallel.
@@ -590,11 +589,10 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
tmp_info = mp_node ? listgetdata(mp_node) : NULL;
if (debug)
- zlog_debug(
- "%pRN(%s): comparing candidate %s with existing mpath %s",
- bgp_dest_to_rnode(dest), bgp->name_pretty,
- tmp_info ? tmp_info->peer->host : "NONE",
- cur_mpath ? cur_mpath->peer->host : "NONE");
+ 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 equal, the path was a multipath and is still a multipath.
@@ -622,10 +620,8 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
bgp_path_info_path_with_addpath_rx_str(
cur_mpath, path_buf,
sizeof(path_buf));
- zlog_debug(
- "%pRN: %s is still multipath, cur count %d",
- bgp_dest_to_rnode(dest),
- path_buf, mpath_count);
+ zlog_debug("%pBD: %s is still multipath, cur count %d",
+ dest, path_buf, mpath_count);
}
} else {
mpath_changed = 1;
@@ -633,12 +629,10 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
bgp_path_info_path_with_addpath_rx_str(
cur_mpath, path_buf,
sizeof(path_buf));
- zlog_debug(
- "%pRN: remove mpath %s nexthop %pI4, cur count %d",
- bgp_dest_to_rnode(dest),
- path_buf,
- &cur_mpath->attr->nexthop,
- mpath_count);
+ 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;
@@ -663,10 +657,10 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
if (debug) {
bgp_path_info_path_with_addpath_rx_str(
cur_mpath, path_buf, sizeof(path_buf));
- zlog_debug(
- "%pRN: remove mpath %s nexthop %pI4, cur count %d",
- bgp_dest_to_rnode(dest), path_buf,
- &cur_mpath->attr->nexthop, mpath_count);
+ zlog_debug("%pBD: remove mpath %s nexthop %pI4, cur count %d",
+ dest, path_buf,
+ &cur_mpath->attr->nexthop,
+ mpath_count);
}
cur_mpath = next_mpath;
} else {
@@ -713,12 +707,10 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
bgp_path_info_path_with_addpath_rx_str(
new_mpath, path_buf,
sizeof(path_buf));
- zlog_debug(
- "%pRN: add mpath %s nexthop %pI4, cur count %d",
- bgp_dest_to_rnode(dest),
- path_buf,
- &new_mpath->attr->nexthop,
- mpath_count);
+ 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;
@@ -737,11 +729,10 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
all_paths_lb, cum_bw);
if (debug)
- zlog_debug(
- "%pRN(%s): New mpath count (incl newbest) %d mpath-change %s all_paths_lb %d cum_bw %" PRIu64,
- bgp_dest_to_rnode(dest), bgp->name_pretty,
- mpath_count, mpath_changed ? "YES" : "NO",
- all_paths_lb, cum_bw);
+ 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_changed
|| (bgp_path_info_mpath_count(new_best) != old_mpath_count))
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 18d9f64..af8990a 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -300,7 +300,7 @@ void vpn_leak_zebra_vrf_label_update(struct bgp *bgp, afi_t afi)
return;
}
- if (vpn_leak_to_vpn_active(bgp, afi, NULL)) {
+ if (vpn_leak_to_vpn_active(bgp, afi, NULL, false)) {
label = bgp->vpn_policy[afi].tovpn_label;
}
@@ -388,6 +388,9 @@ void vpn_leak_zebra_vrf_sid_update_per_af(struct bgp *bgp, afi_t afi)
tovpn_sid_ls = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
*tovpn_sid_ls = *tovpn_sid;
+ if (bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent)
+ 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 = tovpn_sid_ls;
}
@@ -435,6 +438,8 @@ void vpn_leak_zebra_vrf_sid_update_per_vrf(struct bgp *bgp)
tovpn_sid_ls = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
*tovpn_sid_ls = *tovpn_sid;
+ if (bgp->tovpn_zebra_vrf_sid_last_sent)
+ XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_zebra_vrf_sid_last_sent);
bgp->tovpn_zebra_vrf_sid_last_sent = tovpn_sid_ls;
}
@@ -482,6 +487,7 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi)
bgp->vrf_id, ZEBRA_SEG6_LOCAL_ACTION_UNSPEC, NULL);
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;
}
/*
@@ -508,6 +514,7 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp)
bgp->vrf_id, ZEBRA_SEG6_LOCAL_ACTION_UNSPEC,
NULL);
XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_zebra_vrf_sid_last_sent);
+ bgp->tovpn_zebra_vrf_sid_last_sent = NULL;
}
/*
@@ -596,6 +603,11 @@ static void sid_register(struct bgp *bgp, const struct in6_addr *sid,
listnode_add(bgp->srv6_functions, func);
}
+void srv6_function_free(struct bgp_srv6_function *func)
+{
+ XFREE(MTYPE_BGP_SRV6_FUNCTION, func);
+}
+
void sid_unregister(struct bgp *bgp, const struct in6_addr *sid)
{
struct listnode *node, *nnode;
@@ -604,7 +616,7 @@ void sid_unregister(struct bgp *bgp, const struct in6_addr *sid)
for (ALL_LIST_ELEMENTS(bgp->srv6_functions, node, nnode, func))
if (sid_same(&func->sid, sid)) {
listnode_delete(bgp->srv6_functions, func);
- XFREE(MTYPE_BGP_SRV6_FUNCTION, func);
+ srv6_function_free(func);
}
}
@@ -1006,9 +1018,11 @@ static bool leak_update_nexthop_valid(struct bgp *to_bgp, struct bgp_dest *bn,
{
struct bgp_path_info *bpi_ultimate;
struct bgp *bgp_nexthop;
+ struct bgp_table *table;
bool nh_valid;
bpi_ultimate = bgp_get_imported_bpi_ultimate(source_bpi);
+ table = bgp_dest_table(bpi_ultimate->net);
if (bpi->extra && bpi->extra->vrfleak && bpi->extra->vrfleak->bgp_orig)
bgp_nexthop = bpi->extra->vrfleak->bgp_orig;
@@ -1024,7 +1038,23 @@ static bool leak_update_nexthop_valid(struct bgp *to_bgp, struct bgp_dest *bn,
is_pi_family_evpn(bpi_ultimate) ||
CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_ACCEPT_OWN))
nh_valid = true;
- else
+ else if (bpi_ultimate->type == ZEBRA_ROUTE_BGP &&
+ bpi_ultimate->sub_type == BGP_ROUTE_STATIC && table &&
+ (table->safi == SAFI_UNICAST ||
+ table->safi == SAFI_LABELED_UNICAST)) {
+ /* the route is defined with the "network <prefix>" command */
+
+ if (CHECK_FLAG(bgp_nexthop->flags, BGP_FLAG_IMPORT_CHECK))
+ nh_valid = bgp_find_or_add_nexthop(to_bgp, bgp_nexthop,
+ afi, SAFI_UNICAST,
+ bpi_ultimate, NULL,
+ 0, p);
+ else
+ /* if "no bgp network import-check" is set,
+ * then mark the nexthop as valid.
+ */
+ nh_valid = true;
+ } else
/*
* TBD do we need to do anything about the
* 'connected' parameter?
@@ -1225,8 +1255,9 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
new->extra->vrfleak->parent = bgp_path_info_lock(parent);
bgp_dest_lock_node(
(struct bgp_dest *)parent->net);
- if (bgp_orig)
- new->extra->vrfleak->bgp_orig = bgp_lock(bgp_orig);
+
+ new->extra->vrfleak->bgp_orig = bgp_lock(bgp_orig);
+
if (nexthop_orig)
new->extra->vrfleak->nexthop_orig = *nexthop_orig;
@@ -1532,6 +1563,9 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */
struct bgp_dest *bn;
const char *debugmsg;
int nexthop_self_flag = 0;
+ struct ecommunity *old_ecom;
+ struct ecommunity *new_ecom = NULL;
+ struct ecommunity *rtlist_ecom;
if (debug)
zlog_debug("%s: from vrf %s", __func__, from_bgp->name_pretty);
@@ -1559,7 +1593,7 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */
if (!is_route_injectable_into_vpn(path_vrf))
return;
- if (!vpn_leak_to_vpn_active(from_bgp, afi, &debugmsg)) {
+ if (!vpn_leak_to_vpn_active(from_bgp, afi, &debugmsg, false)) {
if (debug)
zlog_debug("%s: %s skipping: %s", __func__,
from_bgp->name, debugmsg);
@@ -1569,32 +1603,6 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */
/* shallow copy */
static_attr = *path_vrf->attr;
- /*
- * route map handling
- */
- if (from_bgp->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN]) {
- struct bgp_path_info info;
- route_map_result_t ret;
-
- memset(&info, 0, sizeof(info));
- info.peer = to_bgp->peer_self;
- info.attr = &static_attr;
- ret = route_map_apply(from_bgp->vpn_policy[afi]
- .rmap[BGP_VPN_POLICY_DIR_TOVPN],
- p, &info);
- if (RMAP_DENYMATCH == ret) {
- bgp_attr_flush(&static_attr); /* free any added parts */
- if (debug)
- zlog_debug(
- "%s: vrf %s route map \"%s\" says DENY, returning",
- __func__, from_bgp->name_pretty,
- from_bgp->vpn_policy[afi]
- .rmap[BGP_VPN_POLICY_DIR_TOVPN]
- ->name);
- return;
- }
- }
-
if (debug && bgp_attr_get_ecommunity(&static_attr)) {
char *s = ecommunity_ecom2str(
bgp_attr_get_ecommunity(&static_attr),
@@ -1608,29 +1616,62 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */
/*
* Add the vpn-policy rt-list
*/
- struct ecommunity *old_ecom;
- struct ecommunity *new_ecom;
/* Export with the 'from' instance's export RTs. */
/* If doing VRF-to-VRF leaking, strip existing RTs first. */
old_ecom = bgp_attr_get_ecommunity(&static_attr);
+ rtlist_ecom = from_bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN];
if (old_ecom) {
new_ecom = ecommunity_dup(old_ecom);
if (CHECK_FLAG(from_bgp->af_flags[afi][SAFI_UNICAST],
BGP_CONFIG_VRF_TO_VRF_EXPORT))
ecommunity_strip_rts(new_ecom);
- new_ecom = ecommunity_merge(
- new_ecom, from_bgp->vpn_policy[afi]
- .rtlist[BGP_VPN_POLICY_DIR_TOVPN]);
+ if (rtlist_ecom)
+ new_ecom = ecommunity_merge(new_ecom, rtlist_ecom);
if (!old_ecom->refcnt)
ecommunity_free(&old_ecom);
+ } else if (rtlist_ecom) {
+ new_ecom = ecommunity_dup(rtlist_ecom);
} else {
- new_ecom = ecommunity_dup(
- from_bgp->vpn_policy[afi]
- .rtlist[BGP_VPN_POLICY_DIR_TOVPN]);
+ new_ecom = NULL;
}
+
bgp_attr_set_ecommunity(&static_attr, new_ecom);
+ /*
+ * route map handling
+ */
+ if (from_bgp->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN]) {
+ struct bgp_path_info info;
+ route_map_result_t ret;
+
+ memset(&info, 0, sizeof(info));
+ info.peer = to_bgp->peer_self;
+ info.attr = &static_attr;
+ ret = route_map_apply(from_bgp->vpn_policy[afi]
+ .rmap[BGP_VPN_POLICY_DIR_TOVPN],
+ p, &info);
+ if (RMAP_DENYMATCH == ret) {
+ bgp_attr_flush(&static_attr); /* free any added parts */
+ if (debug)
+ zlog_debug("%s: vrf %s route map \"%s\" says DENY, returning",
+ __func__, from_bgp->name_pretty,
+ from_bgp->vpn_policy[afi]
+ .rmap[BGP_VPN_POLICY_DIR_TOVPN]
+ ->name);
+ return;
+ }
+ }
+
+ new_ecom = bgp_attr_get_ecommunity(&static_attr);
+ if (!ecommunity_has_route_target(new_ecom)) {
+ ecommunity_free(&new_ecom);
+ if (debug)
+ zlog_debug("%s: %s skipping: waiting for a valid export rt list.",
+ __func__, from_bgp->name_pretty);
+ return;
+ }
+
if (debug && bgp_attr_get_ecommunity(&static_attr)) {
char *s = ecommunity_ecom2str(
bgp_attr_get_ecommunity(&static_attr),
@@ -1884,20 +1925,20 @@ void vpn_leak_from_vrf_withdraw(struct bgp *to_bgp, /* to */
if (!is_route_injectable_into_vpn(path_vrf))
return;
- if (!vpn_leak_to_vpn_active(from_bgp, afi, &debugmsg)) {
+ if (!vpn_leak_to_vpn_active(from_bgp, afi, &debugmsg, true)) {
if (debug)
zlog_debug("%s: skipping: %s", __func__, debugmsg);
return;
}
- if (debug)
- zlog_debug("%s: withdrawing (path_vrf=%p)", __func__, path_vrf);
-
- bn = bgp_afi_node_get(to_bgp->rib[afi][safi], afi, safi, p,
- &(from_bgp->vpn_policy[afi].tovpn_rd));
+ bn = bgp_safi_node_lookup(to_bgp->rib[afi][safi], safi, p,
+ &(from_bgp->vpn_policy[afi].tovpn_rd));
if (!bn)
return;
+ if (debug)
+ zlog_debug("%s: withdrawing (path_vrf=%p)", __func__, path_vrf);
+
/*
* vrf -> vpn
* match original bpi imported from
@@ -2056,6 +2097,7 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
uint32_t num_labels = 0;
int nexthop_self_flag = 1;
struct bgp_path_info *bpi_ultimate = NULL;
+ struct bgp_path_info *bpi;
int origin_local = 0;
struct bgp *src_vrf;
struct interface *ifp;
@@ -2145,6 +2187,20 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
community_strip_accept_own(&static_attr);
+ bn = bgp_afi_node_get(to_bgp->rib[afi][safi], afi, safi, p, NULL);
+
+ for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) {
+ if (bpi->extra && bpi->extra->vrfleak &&
+ bpi->extra->vrfleak->parent == path_vpn)
+ break;
+ }
+
+ if (bpi && leak_update_nexthop_valid(to_bgp, bn, &static_attr, afi, safi,
+ path_vpn, bpi, src_vrf, p, debug))
+ SET_FLAG(static_attr.nh_flags, BGP_ATTR_NH_VALID);
+ else
+ UNSET_FLAG(static_attr.nh_flags, BGP_ATTR_NH_VALID);
+
/*
* Nexthop: stash and clear
*
@@ -2160,12 +2216,22 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
/* If the path has accept-own community and the source VRF
* is valid, reset next-hop to self, to allow importing own
* routes between different VRFs on the same node.
- * Set the nh ifindex to VRF's interface, not the real interface.
+ */
+
+ if (src_bgp)
+ subgroup_announce_reset_nhop(nhfamily, &static_attr);
+
+ bpi_ultimate = bgp_get_imported_bpi_ultimate(path_vpn);
+
+ /* The nh ifindex may not be defined (when the route is
+ * imported from the network statement => BGP_ROUTE_STATIC)
+ * or to the real interface.
+ * Rewrite the nh ifindex to VRF's interface.
* Let the kernel to decide with double lookup the real next-hop
* interface when installing the route.
*/
- if (src_bgp) {
- subgroup_announce_reset_nhop(nhfamily, &static_attr);
+ if (src_bgp || bpi_ultimate->sub_type == BGP_ROUTE_STATIC ||
+ bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE) {
ifp = if_get_vrf_loopback(src_vrf->vrf_id);
if (ifp)
static_attr.nh_ifindex = ifp->ifindex;
@@ -2237,8 +2303,6 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
new_attr = bgp_attr_intern(&static_attr);
bgp_attr_flush(&static_attr);
- bn = bgp_afi_node_get(to_bgp->rib[afi][safi], afi, safi, p, NULL);
-
/*
* ensure labels are copied
*
@@ -2253,9 +2317,6 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
*/
if (!CHECK_FLAG(to_bgp->af_flags[afi][safi],
BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
- /* work back to original route */
- bpi_ultimate = bgp_get_imported_bpi_ultimate(path_vpn);
-
/*
* if original route was unicast,
* then it did not arrive over vpn
@@ -2665,7 +2726,7 @@ void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw,
edir = BGP_VPN_POLICY_DIR_TOVPN;
for (afi = 0; afi < AFI_MAX; ++afi) {
- if (!vpn_leak_to_vpn_active(bgp, afi, NULL))
+ if (!vpn_leak_to_vpn_active(bgp, afi, NULL, false))
continue;
if (withdraw) {
diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h
index 19b6f4e..cd25899 100644
--- a/bgpd/bgp_mplsvpn.h
+++ b/bgpd/bgp_mplsvpn.h
@@ -13,6 +13,7 @@
#include "bgpd/bgp_rd.h"
#include "bgpd/bgp_zebra.h"
#include "bgpd/bgp_vty.h"
+#include "bgpd/bgp_label.h"
#define MPLS_LABEL_IS_SPECIAL(label) ((label) <= MPLS_LABEL_EXTENSION)
#define MPLS_LABEL_IS_NULL(label) \
@@ -112,7 +113,8 @@ static inline bool is_bgp_vrf_mplsvpn(struct bgp *bgp)
}
static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi,
- const char **pmsg)
+ const char **pmsg,
+ bool ignore_export_rt_list)
{
if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF
&& bgp_vrf->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
@@ -132,8 +134,21 @@ static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi,
return 0;
}
- /* Is there an RT list set? */
- if (!bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN]) {
+ /* Before performing withdrawal, VPN activation is checked; however,
+ * when the route-map modifies the export route-target (RT) list, it
+ * becomes challenging to determine if VPN prefixes were previously
+ * present, or not. The 'ignore_export_rt_list' parameter will be
+ * used to force the withdraw operation by not checking the possible
+ * route-map changes.
+ * Of the 'ignore_export_rt_list' is set to false, check the following:
+ * - Is there an RT list set?
+ * - Is there a route-map that sets RT communities
+ */
+ if (!ignore_export_rt_list &&
+ !bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN] &&
+ (!bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN] ||
+ !bgp_route_map_has_extcommunity_rt(
+ bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN]))) {
if (pmsg)
*pmsg = "rtlist tovpn not defined";
return 0;
@@ -165,6 +180,25 @@ static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi,
return 0;
}
+ /* Is there a "manual" export label that isn't allocated yet? */
+ if (!CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_AUTO) &&
+ bgp_vrf->vpn_policy[afi].tovpn_label != BGP_PREVENT_VRF_2_VRF_LEAK &&
+ bgp_vrf->vpn_policy[afi].tovpn_label != MPLS_LABEL_NONE &&
+ (bgp_vrf->vpn_policy[afi].tovpn_label >= MPLS_LABEL_UNRESERVED_MIN &&
+ !CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_MANUAL_REG))) {
+ if (!bgp_zebra_request_label_range(bgp_vrf->vpn_policy[afi]
+ .tovpn_label,
+ 1, false)) {
+ if (pmsg)
+ *pmsg = "manual label could not be allocated";
+ return 0;
+ }
+ SET_FLAG(bgp_vrf->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_MANUAL_REG);
+ }
+
return 1;
}
@@ -226,8 +260,7 @@ static inline void vpn_leak_prechange(enum vpn_policy_direction direction,
vpn_leak_to_vrf_withdraw_all(bgp_vrf, afi);
}
if ((direction == BGP_VPN_POLICY_DIR_TOVPN) &&
- vpn_leak_to_vpn_active(bgp_vrf, afi, NULL)) {
-
+ vpn_leak_to_vpn_active(bgp_vrf, afi, NULL, true)) {
vpn_leak_from_vrf_withdraw_all(bgp_vpn, bgp_vrf, afi);
}
}
diff --git a/bgpd/bgp_mplsvpn_snmp.c b/bgpd/bgp_mplsvpn_snmp.c
index 0208a6f..3344e9e 100644
--- a/bgpd/bgp_mplsvpn_snmp.c
+++ b/bgpd/bgp_mplsvpn_snmp.c
@@ -511,8 +511,8 @@ static int bgp_init_snmp_stats(struct bgp *bgp)
{
if (is_bgp_vrf_mplsvpn(bgp)) {
if (bgp->snmp_stats == NULL) {
- bgp->snmp_stats = XCALLOC(
- MTYPE_BGP, sizeof(struct bgp_snmp_stats));
+ bgp->snmp_stats = XCALLOC(MTYPE_BGP_NAME,
+ sizeof(struct bgp_snmp_stats));
/* fix up added routes */
if (bgp->snmp_stats) {
bgp->snmp_stats->routes_added =
@@ -523,7 +523,7 @@ static int bgp_init_snmp_stats(struct bgp *bgp)
}
} else {
if (bgp->snmp_stats) {
- XFREE(MTYPE_BGP, bgp->snmp_stats);
+ XFREE(MTYPE_BGP_NAME, bgp->snmp_stats);
bgp->snmp_stats = NULL;
}
}
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index d831c6a..dbb34b0 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -484,10 +484,23 @@ static void bgp_accept(struct event *thread)
/* Dynamic neighbor has been created, let it proceed */
connection1->fd = bgp_sock;
+ if (bgp_set_socket_ttl(connection1) < 0) {
+ peer1->last_reset = PEER_DOWN_SOCKET_ERROR;
+ zlog_err("%s: Unable to set min/max TTL on peer %s (dynamic), error received: %s(%d)",
+ __func__, peer1->host,
+ safe_strerror(errno), errno);
+ return;
+ }
+
/* Set the user configured MSS to TCP socket */
if (CHECK_FLAG(peer1->flags, PEER_FLAG_TCP_MSS))
sockopt_tcp_mss_set(bgp_sock, peer1->tcp_mss);
+ frr_with_privs (&bgpd_privs) {
+ vrf_bind(peer1->bgp->vrf_id, bgp_sock,
+ bgp_get_bound_name(connection1));
+ }
+ bgp_peer_reg_with_nht(peer1);
bgp_fsm_change_status(connection1, Active);
EVENT_OFF(connection1->t_start);
@@ -693,7 +706,6 @@ int bgp_update_address(struct interface *ifp, const union sockunion *dst,
{
struct prefix *p, *sel, d;
struct connected *connected;
- struct listnode *node;
int common;
if (!sockunion2hostprefix(dst, &d))
@@ -702,7 +714,7 @@ int bgp_update_address(struct interface *ifp, const union sockunion *dst,
sel = NULL;
common = -1;
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
p = connected->address;
if (p->family != d.family)
continue;
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h
index 49cbbaf..8308838 100644
--- a/bgpd/bgp_nexthop.h
+++ b/bgpd/bgp_nexthop.h
@@ -26,6 +26,8 @@ PREDECL_RBTREE_UNIQ(bgp_nexthop_cache);
/* BGP nexthop cache value structure. */
struct bgp_nexthop_cache {
+ afi_t afi;
+
/* The ifindex of the outgoing interface *if* it's a v6 LL */
ifindex_t ifindex_ipv6_ll;
@@ -37,6 +39,18 @@ struct bgp_nexthop_cache {
/* Nexthop number and nexthop linked list.*/
uint8_t nexthop_num;
+
+ /* This flag is set to TRUE for a bnc that is gateway IP overlay index
+ * nexthop.
+ */
+ bool is_evpn_gwip_nexthop;
+
+ uint16_t change_flags;
+#define BGP_NEXTHOP_CHANGED (1 << 0)
+#define BGP_NEXTHOP_METRIC_CHANGED (1 << 1)
+#define BGP_NEXTHOP_CONNECTED_CHANGED (1 << 2)
+#define BGP_NEXTHOP_MACIP_CHANGED (1 << 3)
+
struct nexthop *nexthop;
time_t last_update;
uint16_t flags;
@@ -70,27 +84,16 @@ struct bgp_nexthop_cache {
*/
#define BGP_NEXTHOP_EVPN_INCOMPLETE (1 << 7)
- uint16_t change_flags;
-
-#define BGP_NEXTHOP_CHANGED (1 << 0)
-#define BGP_NEXTHOP_METRIC_CHANGED (1 << 1)
-#define BGP_NEXTHOP_CONNECTED_CHANGED (1 << 2)
-#define BGP_NEXTHOP_MACIP_CHANGED (1 << 3)
+ uint32_t srte_color;
/* Back pointer to the cache tree this entry belongs to. */
struct bgp_nexthop_cache_head *tree;
- uint32_t srte_color;
struct prefix prefix;
void *nht_info; /* In BGP, peer session */
LIST_HEAD(path_list, bgp_path_info) paths;
unsigned int path_count;
struct bgp *bgp;
-
- /* This flag is set to TRUE for a bnc that is gateway IP overlay index
- * nexthop.
- */
- bool is_evpn_gwip_nexthop;
};
extern int bgp_nexthop_cache_compare(const struct bgp_nexthop_cache *a,
diff --git a/bgpd/bgp_nhg.c b/bgpd/bgp_nhg.c
new file mode 100644
index 0000000..bf0ba77
--- /dev/null
+++ b/bgpd/bgp_nhg.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* BGP Nexthop Group Support
+ * Copyright (C) 2023 NVIDIA Corporation
+ * Copyright (C) 2023 6WIND
+ */
+
+#include <zebra.h>
+
+#include <bgpd/bgpd.h>
+#include <bgpd/bgp_debug.h>
+#include <bgpd/bgp_nhg.h>
+
+
+/****************************************************************************
+ * L3 NHGs are used for fast failover of nexthops in the dplane. These are
+ * the APIs for allocating L3 NHG ids. Management of the L3 NHG itself is
+ * left to the application using it.
+ * PS: Currently EVPN host routes is the only app using L3 NHG for fast
+ * failover of remote ES links.
+ ***************************************************************************/
+static bitfield_t bgp_nh_id_bitmap;
+static uint32_t bgp_nhg_start;
+
+/* XXX - currently we do nothing on the callbacks */
+static void bgp_nhg_add_cb(const char *name)
+{
+}
+
+static void bgp_nhg_modify_cb(const struct nexthop_group_cmd *nhgc)
+{
+}
+
+static void bgp_nhg_add_nexthop_cb(const struct nexthop_group_cmd *nhgc,
+ const struct nexthop *nhop)
+{
+}
+
+static void bgp_nhg_del_nexthop_cb(const struct nexthop_group_cmd *nhgc,
+ const struct nexthop *nhop)
+{
+}
+
+static void bgp_nhg_del_cb(const char *name)
+{
+}
+
+static void bgp_nhg_zebra_init(void)
+{
+ static bool bgp_nhg_zebra_inited;
+
+ if (bgp_nhg_zebra_inited)
+ return;
+
+ bgp_nhg_zebra_inited = true;
+ bgp_nhg_start = zclient_get_nhg_start(ZEBRA_ROUTE_BGP);
+ nexthop_group_init(bgp_nhg_add_cb, bgp_nhg_modify_cb,
+ bgp_nhg_add_nexthop_cb, bgp_nhg_del_nexthop_cb,
+ bgp_nhg_del_cb);
+}
+
+void bgp_nhg_init(void)
+{
+ uint32_t id_max;
+
+ id_max = MIN(ZEBRA_NHG_PROTO_SPACING - 1, 16 * 1024);
+ bf_init(bgp_nh_id_bitmap, id_max);
+ bf_assign_zero_index(bgp_nh_id_bitmap);
+
+ if (BGP_DEBUG(nht, NHT) || BGP_DEBUG(evpn_mh, EVPN_MH_ES))
+ zlog_debug("bgp nhg range %u - %u", bgp_nhg_start + 1,
+ bgp_nhg_start + id_max);
+}
+
+void bgp_nhg_finish(void)
+{
+ bf_free(bgp_nh_id_bitmap);
+}
+
+uint32_t bgp_nhg_id_alloc(void)
+{
+ uint32_t nhg_id = 0;
+
+ bgp_nhg_zebra_init();
+ bf_assign_index(bgp_nh_id_bitmap, nhg_id);
+ if (nhg_id)
+ nhg_id += bgp_nhg_start;
+
+ return nhg_id;
+}
+
+void bgp_nhg_id_free(uint32_t nhg_id)
+{
+ if (!nhg_id || (nhg_id <= bgp_nhg_start))
+ return;
+
+ nhg_id -= bgp_nhg_start;
+
+ bf_release_index(bgp_nh_id_bitmap, nhg_id);
+}
diff --git a/bgpd/bgp_nhg.h b/bgpd/bgp_nhg.h
new file mode 100644
index 0000000..370e8ab
--- /dev/null
+++ b/bgpd/bgp_nhg.h
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* BGP Nexthop Group Support
+ * Copyright (C) 2023 NVIDIA Corporation
+ * Copyright (C) 2023 6WIND
+ */
+
+#ifndef _BGP_NHG_H
+#define _BGP_NHG_H
+
+#include "nexthop_group.h"
+
+/* APIs for setting up and allocating L3 nexthop group ids */
+extern uint32_t bgp_nhg_id_alloc(void);
+extern void bgp_nhg_id_free(uint32_t nhg_id);
+extern void bgp_nhg_init(void);
+void bgp_nhg_finish(void);
+
+#endif /* _BGP_NHG_H */
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index 60d6f74..e2c103b 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -386,6 +386,7 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
bnc = bnc_find(tree, &p, srte_color, ifindex);
if (!bnc) {
bnc = bnc_new(tree, &p, srte_color, ifindex);
+ bnc->afi = afi;
bnc->bgp = bgp_nexthop;
if (BGP_DEBUG(nht, NHT))
zlog_debug("Allocated bnc %pFX(%d)(%u)(%s) peer %p",
@@ -405,7 +406,7 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
if (pi && is_route_parent_evpn(pi))
bnc->is_evpn_gwip_nexthop = true;
- if (is_bgp_static_route) {
+ if (is_bgp_static_route && !CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE)) {
SET_FLAG(bnc->flags, BGP_STATIC_ROUTE);
/* If we're toggling the type, re-register */
@@ -897,52 +898,60 @@ void bgp_nht_interface_events(struct peer *peer)
bnc->ifindex_ipv6_ll, NULL);
}
-void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
+void bgp_nexthop_update(struct vrf *vrf, struct prefix *match,
+ struct zapi_route *nhr)
{
struct bgp_nexthop_cache_head *tree = NULL;
struct bgp_nexthop_cache *bnc_nhc, *bnc_import;
- struct bgp *bgp;
- struct prefix match;
- struct zapi_route nhr;
+ struct bgp *bgp, *bgp_default;
+ struct bgp_path_info *pi;
+ struct bgp_dest *dest;
+ safi_t safi;
afi_t afi;
- bgp = bgp_lookup_by_vrf_id(vrf_id);
- if (!bgp) {
- flog_err(
- EC_BGP_NH_UPD,
- "parse nexthop update: instance not found for vrf_id %u",
- vrf_id);
- return;
- }
-
- if (!zapi_nexthop_update_decode(zclient->ibuf, &match, &nhr)) {
- zlog_err("%s[%s]: Failure to decode nexthop update", __func__,
- bgp->name_pretty);
+ if (!vrf->info) {
+ flog_err(EC_BGP_NH_UPD,
+ "parse nexthop update: instance not found for vrf_id %u",
+ vrf->vrf_id);
return;
}
- afi = family2afi(match.family);
+ bgp = (struct bgp *)vrf->info;
+ afi = family2afi(match->family);
tree = &bgp->nexthop_cache_table[afi];
- bnc_nhc = bnc_find(tree, &match, nhr.srte_color, 0);
- if (!bnc_nhc) {
- if (BGP_DEBUG(nht, NHT))
- zlog_debug(
- "parse nexthop update %pFX(%u)(%s): bnc info not found for nexthop cache",
- &nhr.prefix, nhr.srte_color, bgp->name_pretty);
- } else
- bgp_process_nexthop_update(bnc_nhc, &nhr, false);
+ bnc_nhc = bnc_find(tree, match, nhr->srte_color, 0);
+ if (bnc_nhc)
+ bgp_process_nexthop_update(bnc_nhc, nhr, false);
+ else if (BGP_DEBUG(nht, NHT))
+ zlog_debug("parse nexthop update %pFX(%u)(%s): bnc info not found for nexthop cache",
+ &nhr->prefix, nhr->srte_color,
+ bgp->name_pretty);
tree = &bgp->import_check_table[afi];
- bnc_import = bnc_find(tree, &match, nhr.srte_color, 0);
- if (!bnc_import) {
- if (BGP_DEBUG(nht, NHT))
- zlog_debug(
- "parse nexthop update %pFX(%u)(%s): bnc info not found for import check",
- &nhr.prefix, nhr.srte_color, bgp->name_pretty);
- } else
- bgp_process_nexthop_update(bnc_import, &nhr, true);
+ bnc_import = bnc_find(tree, match, nhr->srte_color, 0);
+ if (bnc_import) {
+ bgp_process_nexthop_update(bnc_import, nhr, true);
+
+ bgp_default = bgp_get_default();
+ safi = nhr->safi;
+ if (bgp != bgp_default && bgp->rib[afi][safi]) {
+ dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
+ match, NULL);
+
+ for (pi = bgp_dest_get_bgp_path_info(dest); pi;
+ pi = pi->next)
+ if (pi->peer == bgp->peer_self &&
+ pi->type == ZEBRA_ROUTE_BGP &&
+ pi->sub_type == BGP_ROUTE_STATIC)
+ vpn_leak_from_vrf_update(bgp_default,
+ bgp, pi);
+ }
+ } else if (BGP_DEBUG(nht, NHT))
+ zlog_debug("parse nexthop update %pFX(%u)(%s): bnc info not found for import check",
+ &nhr->prefix, nhr->srte_color,
+ bgp->name_pretty);
/*
* HACK: if any BGP route is dependant on an SR-policy that doesn't
@@ -955,7 +964,7 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
* which should provide a better infrastructure to solve this issue in
* a more efficient and elegant way.
*/
- if (nhr.srte_color == 0 && bnc_nhc) {
+ if (nhr->srte_color == 0 && bnc_nhc) {
struct bgp_nexthop_cache *bnc_iter;
frr_each (bgp_nexthop_cache, &bgp->nexthop_cache_table[afi],
@@ -965,7 +974,7 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
CHECK_FLAG(bnc_iter->flags, BGP_NEXTHOP_VALID))
continue;
- bgp_process_nexthop_update(bnc_iter, &nhr, false);
+ bgp_process_nexthop_update(bnc_iter, nhr, false);
}
}
}
@@ -1170,6 +1179,11 @@ static void register_zebra_rnh(struct bgp_nexthop_cache *bnc)
*/
static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc)
{
+ struct bgp_nexthop_cache *import;
+ struct bgp_nexthop_cache *nexthop;
+
+ struct bgp *bgp = bnc->bgp;
+
/* Check if we have already registered */
if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
return;
@@ -1179,6 +1193,19 @@ static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc)
return;
}
+ import = bnc_find(&bgp->import_check_table[bnc->afi], &bnc->prefix, 0,
+ 0);
+ nexthop = bnc_find(&bgp->nexthop_cache_table[bnc->afi], &bnc->prefix, 0,
+ 0);
+
+ /*
+ * If this entry has both a import and a nexthop entry
+ * then let's not send the unregister quite as of yet
+ * wait until we only have 1 left
+ */
+ if (import && nexthop)
+ return;
+
sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER);
}
@@ -1558,90 +1585,3 @@ void bgp_nht_dereg_enhe_cap_intfs(struct peer *peer)
0);
}
}
-
-/****************************************************************************
- * L3 NHGs are used for fast failover of nexthops in the dplane. These are
- * the APIs for allocating L3 NHG ids. Management of the L3 NHG itself is
- * left to the application using it.
- * PS: Currently EVPN host routes is the only app using L3 NHG for fast
- * failover of remote ES links.
- ***************************************************************************/
-static bitfield_t bgp_nh_id_bitmap;
-static uint32_t bgp_l3nhg_start;
-
-/* XXX - currently we do nothing on the callbacks */
-static void bgp_l3nhg_add_cb(const char *name)
-{
-}
-
-static void bgp_l3nhg_modify_cb(const struct nexthop_group_cmd *nhgc)
-{
-}
-
-static void bgp_l3nhg_add_nexthop_cb(const struct nexthop_group_cmd *nhgc,
- const struct nexthop *nhop)
-{
-}
-
-static void bgp_l3nhg_del_nexthop_cb(const struct nexthop_group_cmd *nhgc,
- const struct nexthop *nhop)
-{
-}
-
-static void bgp_l3nhg_del_cb(const char *name)
-{
-}
-
-static void bgp_l3nhg_zebra_init(void)
-{
- static bool bgp_l3nhg_zebra_inited;
- if (bgp_l3nhg_zebra_inited)
- return;
-
- bgp_l3nhg_zebra_inited = true;
- bgp_l3nhg_start = zclient_get_nhg_start(ZEBRA_ROUTE_BGP);
- nexthop_group_init(bgp_l3nhg_add_cb, bgp_l3nhg_modify_cb,
- bgp_l3nhg_add_nexthop_cb, bgp_l3nhg_del_nexthop_cb,
- bgp_l3nhg_del_cb);
-}
-
-
-void bgp_l3nhg_init(void)
-{
- uint32_t id_max;
-
- id_max = MIN(ZEBRA_NHG_PROTO_SPACING - 1, 16 * 1024);
- bf_init(bgp_nh_id_bitmap, id_max);
- bf_assign_zero_index(bgp_nh_id_bitmap);
-
- if (BGP_DEBUG(nht, NHT) || BGP_DEBUG(evpn_mh, EVPN_MH_ES))
- zlog_debug("bgp l3_nhg range %u - %u", bgp_l3nhg_start + 1,
- bgp_l3nhg_start + id_max);
-}
-
-void bgp_l3nhg_finish(void)
-{
- bf_free(bgp_nh_id_bitmap);
-}
-
-uint32_t bgp_l3nhg_id_alloc(void)
-{
- uint32_t nhg_id = 0;
-
- bgp_l3nhg_zebra_init();
- bf_assign_index(bgp_nh_id_bitmap, nhg_id);
- if (nhg_id)
- nhg_id += bgp_l3nhg_start;
-
- return nhg_id;
-}
-
-void bgp_l3nhg_id_free(uint32_t nhg_id)
-{
- if (!nhg_id || (nhg_id <= bgp_l3nhg_start))
- return;
-
- nhg_id -= bgp_l3nhg_start;
-
- bf_release_index(bgp_nh_id_bitmap, nhg_id);
-}
diff --git a/bgpd/bgp_nht.h b/bgpd/bgp_nht.h
index 0758a0c..e7c6fdc 100644
--- a/bgpd/bgp_nht.h
+++ b/bgpd/bgp_nht.h
@@ -7,9 +7,10 @@
#define _BGP_NHT_H
/**
- * bgp_parse_nexthop_update() - parse a nexthop update message from Zebra.
+ * bgp_nexthop_update() - process a nexthop update message from Zebra.
*/
-extern void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id);
+extern void bgp_nexthop_update(struct vrf *vrf, struct prefix *match,
+ struct zapi_route *nhr);
/**
* bgp_find_or_add_nexthop() - lookup the nexthop cache table for the bnc
@@ -78,12 +79,6 @@ extern void bgp_nht_reg_enhe_cap_intfs(struct peer *peer);
extern void bgp_nht_dereg_enhe_cap_intfs(struct peer *peer);
extern void evaluate_paths(struct bgp_nexthop_cache *bnc);
-/* APIs for setting up and allocating L3 nexthop group ids */
-extern uint32_t bgp_l3nhg_id_alloc(void);
-extern void bgp_l3nhg_id_free(uint32_t nhg_id);
-extern void bgp_l3nhg_init(void);
-void bgp_l3nhg_finish(void);
-
extern void bgp_nht_ifp_up(struct interface *ifp);
extern void bgp_nht_ifp_down(struct interface *ifp);
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index b030c45..6447586 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -340,15 +340,14 @@ static void bgp_capability_orf_not_support(struct peer *peer, iana_afi_t afi,
peer->host, afi, safi, type, mode);
}
-static const struct message orf_type_str[] = {
- {ORF_TYPE_RESERVED, "Reserved"},
- {ORF_TYPE_PREFIX, "Prefixlist"},
- {0}};
+const struct message orf_type_str[] = { { ORF_TYPE_RESERVED, "Reserved" },
+ { ORF_TYPE_PREFIX, "Prefixlist" },
+ { 0 } };
-static const struct message orf_mode_str[] = {{ORF_MODE_RECEIVE, "Receive"},
- {ORF_MODE_SEND, "Send"},
- {ORF_MODE_BOTH, "Both"},
- {0}};
+const struct message orf_mode_str[] = { { ORF_MODE_RECEIVE, "Receive" },
+ { ORF_MODE_SEND, "Send" },
+ { ORF_MODE_BOTH, "Both" },
+ { 0 } };
static int bgp_capability_orf_entry(struct peer *peer,
struct capability_header *hdr)
@@ -623,17 +622,17 @@ static int bgp_capability_llgr(struct peer *peer,
/* Unlike other capability parsing routines, this one returns 0 on error */
static as_t bgp_capability_as4(struct peer *peer, struct capability_header *hdr)
{
- SET_FLAG(peer->cap, PEER_CAP_AS4_RCV);
-
if (hdr->length != CAPABILITY_CODE_AS4_LEN) {
flog_err(EC_BGP_PKT_OPEN,
"%s AS4 capability has incorrect data length %d",
peer->host, hdr->length);
- return 0;
+ return -1;
}
as_t as4 = stream_getl(BGP_INPUT(peer));
+ SET_FLAG(peer->cap, PEER_CAP_AS4_RCV);
+
if (BGP_DEBUG(as4, AS4))
zlog_debug(
"%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
@@ -663,10 +662,8 @@ static int bgp_capability_addpath(struct peer *peer,
struct stream *s = BGP_INPUT(peer);
size_t end = stream_get_getp(s) + hdr->length;
- SET_FLAG(peer->cap, PEER_CAP_ADDPATH_RCV);
-
/* Verify length is a multiple of 4 */
- if (hdr->length % 4) {
+ if (hdr->length % CAPABILITY_CODE_ADDPATH_LEN) {
flog_warn(
EC_BGP_CAPABILITY_INVALID_LENGTH,
"Add Path: Received invalid length %d, non-multiple of 4",
@@ -674,23 +671,38 @@ static int bgp_capability_addpath(struct peer *peer,
return -1;
}
- while (stream_get_getp(s) + 4 <= end) {
+ SET_FLAG(peer->cap, PEER_CAP_ADDPATH_RCV);
+
+ while (stream_get_getp(s) + CAPABILITY_CODE_ADDPATH_LEN <= end) {
afi_t afi;
safi_t safi;
iana_afi_t pkt_afi = stream_getw(s);
iana_safi_t pkt_safi = stream_getc(s);
uint8_t send_receive = stream_getc(s);
+ /* If any other value (other than 1-3) is received, then
+ * the capability SHOULD be treated as not understood
+ * and ignored.
+ */
+ if (!send_receive || send_receive > 3) {
+ flog_warn(EC_BGP_CAPABILITY_INVALID_DATA,
+ "Add Path: Received invalid send/receive value %u in Add Path capability",
+ send_receive);
+ continue;
+ }
+
if (bgp_debug_neighbor_events(peer))
- zlog_debug(
- "%s OPEN has %s capability for afi/safi: %s/%s%s%s",
- peer->host,
- lookup_msg(capcode_str, hdr->code, NULL),
- iana_afi2str(pkt_afi), iana_safi2str(pkt_safi),
- (send_receive & BGP_ADDPATH_RX) ? ", receive"
- : "",
- (send_receive & BGP_ADDPATH_TX) ? ", transmit"
- : "");
+ zlog_debug("%s OPEN has %s capability for afi/safi: %s/%s%s%s",
+ peer->host,
+ lookup_msg(capcode_str, hdr->code, NULL),
+ iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi),
+ CHECK_FLAG(send_receive, BGP_ADDPATH_RX)
+ ? ", receive"
+ : "",
+ CHECK_FLAG(send_receive, BGP_ADDPATH_TX)
+ ? ", transmit"
+ : "");
/* Convert AFI, SAFI to internal values, check. */
if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
@@ -709,13 +721,19 @@ static int bgp_capability_addpath(struct peer *peer,
continue;
}
- if (send_receive & BGP_ADDPATH_RX)
+ if (CHECK_FLAG(send_receive, BGP_ADDPATH_RX))
SET_FLAG(peer->af_cap[afi][safi],
PEER_CAP_ADDPATH_AF_RX_RCV);
+ else
+ UNSET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_RX_RCV);
- if (send_receive & BGP_ADDPATH_TX)
+ if (CHECK_FLAG(send_receive, BGP_ADDPATH_TX))
SET_FLAG(peer->af_cap[afi][safi],
PEER_CAP_ADDPATH_AF_TX_RCV);
+ else
+ UNSET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_TX_RCV);
}
return 0;
@@ -800,8 +818,6 @@ static int bgp_capability_hostname(struct peer *peer,
size_t end = stream_get_getp(s) + hdr->length;
uint8_t len;
- SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_RCV);
-
len = stream_getc(s);
if (stream_get_getp(s) + len > end) {
flog_warn(
@@ -859,6 +875,8 @@ static int bgp_capability_hostname(struct peer *peer,
peer->domainname = XSTRDUP(MTYPE_BGP_PEER_HOST, str);
}
+ SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_RCV);
+
if (bgp_debug_neighbor_events(peer)) {
zlog_debug("%s received hostname %s, domainname %s", peer->host,
peer->hostname, peer->domainname);
@@ -869,14 +887,16 @@ static int bgp_capability_hostname(struct peer *peer,
static int bgp_capability_role(struct peer *peer, struct capability_header *hdr)
{
- SET_FLAG(peer->cap, PEER_CAP_ROLE_RCV);
if (hdr->length != CAPABILITY_CODE_ROLE_LEN) {
flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH,
"Role: Received invalid length %d", hdr->length);
return -1;
}
+
uint8_t role = stream_getc(BGP_INPUT(peer));
+ SET_FLAG(peer->cap, PEER_CAP_ROLE_RCV);
+
peer->remote_role = role;
return 0;
}
@@ -1020,6 +1040,7 @@ static int bgp_capability_parse(struct peer *peer, size_t length,
BGP_NOTIFY_OPEN_MALFORMED_ATTR);
return -1;
}
+ break;
/* we deliberately ignore unknown codes, see below */
default:
break;
@@ -1876,8 +1897,9 @@ uint16_t bgp_open_capability(struct stream *s, struct peer *peer,
stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN);
}
- /* Hostname capability */
- if (cmd_hostname_get()) {
+ /* FQDN capability */
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_FQDN)
+ && cmd_hostname_get()) {
SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV);
stream_putc(s, BGP_OPEN_OPT_CAP);
rcapp = stream_get_endp(s); /* Ptr to length placeholder */
@@ -1929,8 +1951,7 @@ uint16_t bgp_open_capability(struct stream *s, struct peer *peer,
* or disable its use, and that switch MUST be off by default.
*/
if (peergroup_flag_check(peer, PEER_FLAG_CAPABILITY_SOFT_VERSION) ||
- CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SOFT_VERSION_CAPABILITY) ||
- peer->sort == BGP_PEER_IBGP) {
+ peer->sort == BGP_PEER_IBGP || peer->sub_sort == BGP_PEER_EBGP_OAD) {
SET_FLAG(peer->cap, PEER_CAP_SOFT_VERSION_ADV);
stream_putc(s, BGP_OPEN_OPT_CAP);
rcapp = stream_get_endp(s);
diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h
index a92c56d..34f4b76 100644
--- a/bgpd/bgp_open.h
+++ b/bgpd/bgp_open.h
@@ -108,5 +108,7 @@ extern void bgp_capability_vty_out(struct vty *vty, struct peer *peer,
bool use_json, json_object *json_neigh);
extern as_t peek_for_as4_capability(struct peer *peer, uint16_t length);
extern const struct message capcode_str[];
+extern const struct message orf_type_str[];
+extern const struct message orf_mode_str[];
#endif /* _QUAGGA_BGP_OPEN_H */
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index cae82cb..1f808ee 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -24,6 +24,7 @@
#include "lib_errors.h"
#include "bgpd/bgpd.h"
+#include "bgpd/bgp_addpath.h"
#include "bgpd/bgp_table.h"
#include "bgpd/bgp_dump.h"
#include "bgpd/bgp_bmp.h"
@@ -1211,8 +1212,14 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
unsigned long cap_len;
uint16_t len;
uint32_t gr_restart_time;
+ uint8_t addpath_afi_safi_count = 0;
+ bool adv_addpath_tx = false;
+ unsigned long number_of_orfs_p;
+ uint8_t number_of_orfs = 0;
const char *capability = lookup_msg(capcode_str, capability_code,
"Unknown");
+ const char *hostname = cmd_hostname_get();
+ const char *domainname = cmd_domainname_get();
if (!peer_established(peer->connection))
return;
@@ -1232,7 +1239,6 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
/* Encode MP_EXT capability. */
switch (capability_code) {
case CAPABILITY_CODE_SOFT_VERSION:
- SET_FLAG(peer->cap, PEER_CAP_SOFT_VERSION_ADV);
stream_putc(s, action);
stream_putc(s, CAPABILITY_CODE_SOFT_VERSION);
cap_len = stream_get_endp(s);
@@ -1263,6 +1269,9 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
: "Removing",
capability, iana_afi2str(pkt_afi),
iana_safi2str(pkt_safi));
+
+ COND_FLAG(peer->cap, PEER_CAP_SOFT_VERSION_ADV,
+ action == CAPABILITY_ACTION_SET);
break;
case CAPABILITY_CODE_MP:
stream_putc(s, action);
@@ -1282,11 +1291,6 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
iana_safi2str(pkt_safi));
break;
case CAPABILITY_CODE_RESTART:
- if (!CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART) &&
- !CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART_HELPER))
- return;
-
- SET_FLAG(peer->cap, PEER_CAP_RESTART_ADV);
stream_putc(s, action);
stream_putc(s, CAPABILITY_CODE_RESTART);
cap_len = stream_get_endp(s);
@@ -1335,13 +1339,10 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
capability, iana_afi2str(pkt_afi),
iana_safi2str(pkt_safi));
+ COND_FLAG(peer->cap, PEER_CAP_RESTART_ADV,
+ action == CAPABILITY_ACTION_SET);
break;
case CAPABILITY_CODE_LLGR:
- if (!CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV))
- return;
-
- SET_FLAG(peer->cap, PEER_CAP_LLGR_ADV);
-
stream_putc(s, action);
stream_putc(s, CAPABILITY_CODE_LLGR);
cap_len = stream_get_endp(s);
@@ -1373,25 +1374,214 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
: "Removing",
capability, iana_afi2str(pkt_afi),
iana_safi2str(pkt_safi));
+
+ COND_FLAG(peer->cap, PEER_CAP_LLGR_ADV,
+ action == CAPABILITY_ACTION_SET);
+ break;
+ case CAPABILITY_CODE_ADDPATH:
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (peer->afc[afi][safi]) {
+ addpath_afi_safi_count++;
+
+ /* Only advertise addpath TX if a feature that
+ * will use it is
+ * configured */
+ if (peer->addpath_type[afi][safi] !=
+ BGP_ADDPATH_NONE)
+ adv_addpath_tx = true;
+
+ /* If we have enabled labeled unicast, we MUST check
+ * against unicast SAFI because addpath IDs are
+ * allocated under unicast SAFI, the same as the RIB
+ * is managed in unicast SAFI.
+ */
+ if (safi == SAFI_LABELED_UNICAST)
+ if (peer->addpath_type[afi][SAFI_UNICAST] !=
+ BGP_ADDPATH_NONE)
+ adv_addpath_tx = true;
+ }
+ }
+
+ stream_putc(s, action);
+ stream_putc(s, CAPABILITY_CODE_ADDPATH);
+ stream_putc(s, CAPABILITY_CODE_ADDPATH_LEN *
+ addpath_afi_safi_count);
+
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (peer->afc[afi][safi]) {
+ bool adv_addpath_rx =
+ !CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_DISABLE_ADDPATH_RX);
+ uint8_t flags = 0;
+
+ /* Convert AFI, SAFI to values for packet. */
+ bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi,
+ &pkt_safi);
+
+ stream_putw(s, pkt_afi);
+ stream_putc(s, pkt_safi);
+
+ if (adv_addpath_rx) {
+ SET_FLAG(flags, BGP_ADDPATH_RX);
+ SET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_RX_ADV);
+ } else {
+ UNSET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_RX_ADV);
+ }
+
+ if (adv_addpath_tx) {
+ SET_FLAG(flags, BGP_ADDPATH_TX);
+ SET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_TX_ADV);
+ if (safi == SAFI_LABELED_UNICAST)
+ SET_FLAG(peer->af_cap[afi]
+ [SAFI_UNICAST],
+ PEER_CAP_ADDPATH_AF_TX_ADV);
+ } else {
+ UNSET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_TX_ADV);
+ }
+
+ stream_putc(s, flags);
+ }
+ }
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%pBP sending CAPABILITY has %s %s for afi/safi: %s/%s",
+ peer,
+ action == CAPABILITY_ACTION_SET
+ ? "Advertising"
+ : "Removing",
+ capability, iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+
+ COND_FLAG(peer->cap, PEER_CAP_ADDPATH_ADV,
+ action == CAPABILITY_ACTION_SET);
break;
- case CAPABILITY_CODE_REFRESH:
case CAPABILITY_CODE_ORF:
+ /* Convert AFI, SAFI to values for packet. */
+ bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
+
+ stream_putc(s, action);
+ stream_putc(s, CAPABILITY_CODE_ORF);
+ cap_len = stream_get_endp(s);
+ stream_putc(s, 0);
+
+ stream_putw(s, pkt_afi); /* Address Family Identifier */
+ stream_putc(s, 0); /* Reserved */
+ stream_putc(s,
+ pkt_safi); /* Subsequent Address Family Identifier */
+
+ number_of_orfs_p =
+ stream_get_endp(s); /* Number of ORFs pointer */
+ stream_putc(s, 0); /* Number of ORFs */
+
+ /* Address Prefix ORF */
+ if (CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_ORF_PREFIX_SM) ||
+ CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_ORF_PREFIX_RM)) {
+ stream_putc(s, ORF_TYPE_PREFIX);
+
+ if (CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_ORF_PREFIX_SM) &&
+ CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_ORF_PREFIX_RM)) {
+ SET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_ADV);
+ SET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_ADV);
+ stream_putc(s, ORF_MODE_BOTH);
+ } else if (CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_ORF_PREFIX_SM)) {
+ SET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_ADV);
+ UNSET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_ADV);
+ stream_putc(s, ORF_MODE_SEND);
+ } else {
+ SET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_ADV);
+ UNSET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_ADV);
+ stream_putc(s, ORF_MODE_RECEIVE);
+ }
+ number_of_orfs++;
+ } else {
+ UNSET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_ADV);
+ UNSET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_ADV);
+ }
+
+ /* Total Number of ORFs. */
+ stream_putc_at(s, number_of_orfs_p, number_of_orfs);
+
+ len = stream_get_endp(s) - cap_len - 1;
+ stream_putc_at(s, cap_len, len);
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%pBP sending CAPABILITY has %s %s for afi/safi: %s/%s",
+ peer,
+ action == CAPABILITY_ACTION_SET
+ ? "Advertising"
+ : "Removing",
+ capability, iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+ break;
+ case CAPABILITY_CODE_FQDN:
+ stream_putc(s, action);
+ stream_putc(s, CAPABILITY_CODE_FQDN);
+ cap_len = stream_get_endp(s);
+ stream_putc(s, 0); /* Capability Length */
+
+ len = strlen(hostname);
+ if (len > BGP_MAX_HOSTNAME)
+ len = BGP_MAX_HOSTNAME;
+
+ stream_putc(s, len);
+ stream_put(s, hostname, len);
+
+ if (domainname) {
+ len = strlen(domainname);
+ if (len > BGP_MAX_HOSTNAME)
+ len = BGP_MAX_HOSTNAME;
+
+ stream_putc(s, len);
+ stream_put(s, domainname, len);
+ } else
+ stream_putc(s, 0);
+
+ len = stream_get_endp(s) - cap_len - 1;
+ stream_putc_at(s, cap_len, len);
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%pBP sending CAPABILITY has %s %s for afi/safi: %s/%s",
+ peer,
+ action == CAPABILITY_ACTION_SET
+ ? "Advertising"
+ : "Removing",
+ capability, iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+
+ COND_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV,
+ action == CAPABILITY_ACTION_SET);
+ break;
+ case CAPABILITY_CODE_REFRESH:
case CAPABILITY_CODE_AS4:
case CAPABILITY_CODE_DYNAMIC:
- case CAPABILITY_CODE_ADDPATH:
case CAPABILITY_CODE_ENHANCED_RR:
- case CAPABILITY_CODE_FQDN:
case CAPABILITY_CODE_ENHE:
case CAPABILITY_CODE_EXT_MESSAGE:
break;
case CAPABILITY_CODE_ROLE:
- if (peer->local_role != ROLE_UNDEFINED) {
- SET_FLAG(peer->cap, PEER_CAP_ROLE_ADV);
- stream_putc(s, action);
- stream_putc(s, CAPABILITY_CODE_ROLE);
- stream_putc(s, CAPABILITY_CODE_ROLE_LEN);
- stream_putc(s, peer->local_role);
- }
+ stream_putc(s, action);
+ stream_putc(s, CAPABILITY_CODE_ROLE);
+ stream_putc(s, CAPABILITY_CODE_ROLE_LEN);
+ stream_putc(s, peer->local_role);
+ COND_FLAG(peer->cap, PEER_CAP_ROLE_ADV,
+ action == CAPABILITY_ACTION_SET);
break;
default:
break;
@@ -2155,7 +2345,8 @@ static int bgp_update_receive(struct peer_connection *connection,
"%pBP rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
peer);
- if (ret && bgp_debug_update(peer, NULL, NULL, 1)) {
+ if (ret && bgp_debug_update(peer, NULL, NULL, 1) &&
+ BGP_DEBUG(update, UPDATE_DETAIL)) {
zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
peer->rcvd_attr_str);
peer->rcvd_attr_printed = 1;
@@ -2190,7 +2381,7 @@ static int bgp_update_receive(struct peer_connection *connection,
}
}
- if (BGP_DEBUG(update, UPDATE_IN))
+ if (BGP_DEBUG(update, UPDATE_IN) && BGP_DEBUG(update, UPDATE_DETAIL))
zlog_debug("%pBP rcvd UPDATE wlen %d attrlen %d alen %d", peer,
withdraw_len, attribute_len, update_len);
@@ -2872,6 +3063,304 @@ static int bgp_route_refresh_receive(struct peer_connection *connection,
return BGP_PACKET_NOOP;
}
+static void bgp_dynamic_capability_addpath(uint8_t *pnt, int action,
+ struct capability_header *hdr,
+ struct peer *peer)
+{
+ uint8_t *data = pnt + 3;
+ uint8_t *end = data + hdr->length;
+ size_t len = end - data;
+ afi_t afi;
+ safi_t safi;
+
+ if (action == CAPABILITY_ACTION_SET) {
+ if (len % CAPABILITY_CODE_ADDPATH_LEN) {
+ flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH,
+ "Add Path: Received invalid length %zu, non-multiple of 4",
+ len);
+ return;
+ }
+
+ SET_FLAG(peer->cap, PEER_CAP_ADDPATH_RCV);
+
+ while (data + CAPABILITY_CODE_ADDPATH_LEN <= end) {
+ afi_t afi;
+ safi_t safi;
+ iana_afi_t pkt_afi;
+ iana_safi_t pkt_safi;
+ struct bgp_addpath_capability bac;
+
+ memcpy(&bac, data, sizeof(bac));
+ pkt_afi = ntohs(bac.afi);
+ pkt_safi = safi_int2iana(bac.safi);
+
+ /* If any other value (other than 1-3) is received,
+ * then the capability SHOULD be treated as not
+ * understood and ignored.
+ */
+ if (!bac.flags || bac.flags > 3) {
+ flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH,
+ "Add Path: Received invalid send/receive value %u in Add Path capability",
+ bac.flags);
+ goto ignore;
+ }
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s OPEN has %s capability for afi/safi: %s/%s%s%s",
+ peer->host,
+ lookup_msg(capcode_str, hdr->code,
+ NULL),
+ iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi),
+ (bac.flags & BGP_ADDPATH_RX)
+ ? ", receive"
+ : "",
+ (bac.flags & BGP_ADDPATH_TX)
+ ? ", transmit"
+ : "");
+
+ if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi,
+ &safi)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s Addr-family %s/%s(afi/safi) not supported. Ignore the Addpath Attribute for this AFI/SAFI",
+ peer->host,
+ iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+ goto ignore;
+ } else if (!peer->afc[afi][safi]) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s Addr-family %s/%s(afi/safi) not enabled. Ignore the AddPath capability for this AFI/SAFI",
+ peer->host,
+ iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+ goto ignore;
+ }
+
+ if (CHECK_FLAG(bac.flags, BGP_ADDPATH_RX))
+ SET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_RX_RCV);
+ else
+ UNSET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_RX_RCV);
+
+ if (CHECK_FLAG(bac.flags, BGP_ADDPATH_TX))
+ SET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_TX_RCV);
+ else
+ UNSET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_TX_RCV);
+
+ignore:
+ data += CAPABILITY_CODE_ADDPATH_LEN;
+ }
+ } else {
+ FOREACH_AFI_SAFI (afi, safi) {
+ UNSET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_RX_RCV);
+ UNSET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_TX_RCV);
+ }
+
+ UNSET_FLAG(peer->cap, PEER_CAP_ADDPATH_RCV);
+ }
+}
+
+static void bgp_dynamic_capability_orf(uint8_t *pnt, int action,
+ struct capability_header *hdr,
+ struct peer *peer)
+{
+ uint8_t *data = pnt + 3;
+ uint8_t *end = data + hdr->length;
+ size_t len = end - data;
+
+ struct capability_mp_data mpc;
+ uint8_t num;
+ iana_afi_t pkt_afi;
+ afi_t afi;
+ iana_safi_t pkt_safi;
+ safi_t safi;
+ uint8_t type;
+ uint8_t mode;
+ uint16_t sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
+ uint16_t rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
+ int i;
+
+ if (data + CAPABILITY_CODE_ORF_LEN > end) {
+ flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH,
+ "ORF: Received invalid length %zu, less than %d", len,
+ CAPABILITY_CODE_ORF_LEN);
+ return;
+ }
+
+ /* ORF Entry header */
+ memcpy(&mpc, data, sizeof(mpc));
+ data += sizeof(mpc);
+ num = *data++;
+ pkt_afi = ntohs(mpc.afi);
+ pkt_safi = mpc.safi;
+
+ /* Convert AFI, SAFI to internal values, check. */
+ if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
+ zlog_info("%pBP Addr-family %d/%d not supported. Ignoring the ORF capability",
+ peer, pkt_afi, pkt_safi);
+ return;
+ }
+
+ /* validate number field */
+ if (CAPABILITY_CODE_ORF_LEN + (num * 2) > hdr->length) {
+ zlog_info("%pBP ORF Capability entry length error, Cap length %u, num %u",
+ peer, hdr->length, num);
+ return;
+ }
+
+ if (action == CAPABILITY_ACTION_UNSET) {
+ UNSET_FLAG(peer->af_cap[afi][safi], sm_cap);
+ UNSET_FLAG(peer->af_cap[afi][safi], rm_cap);
+ return;
+ }
+
+ for (i = 0; i < num; i++) {
+ if (data + 1 > end) {
+ flog_err(EC_BGP_CAPABILITY_INVALID_LENGTH,
+ "%pBP ORF Capability entry length (type) error, Cap length %u, num %u",
+ peer, hdr->length, num);
+ return;
+ }
+ type = *data++;
+
+ if (data + 1 > end) {
+ flog_err(EC_BGP_CAPABILITY_INVALID_LENGTH,
+ "%pBP ORF Capability entry length (mode) error, Cap length %u, num %u",
+ peer, hdr->length, num);
+ return;
+ }
+ mode = *data++;
+
+ /* ORF Mode error check */
+ switch (mode) {
+ case ORF_MODE_BOTH:
+ case ORF_MODE_SEND:
+ case ORF_MODE_RECEIVE:
+ break;
+ default:
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%pBP Addr-family %d/%d has ORF type/mode %d/%d not supported",
+ peer, afi, safi, type, mode);
+ continue;
+ }
+
+ if (!((afi == AFI_IP && safi == SAFI_UNICAST) ||
+ (afi == AFI_IP && safi == SAFI_MULTICAST) ||
+ (afi == AFI_IP6 && safi == SAFI_UNICAST))) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%pBP Addr-family %d/%d unsupported AFI/SAFI received",
+ peer, afi, safi);
+ continue;
+ }
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%pBP OPEN has %s ORF capability as %s for afi/safi: %s/%s",
+ peer, lookup_msg(orf_type_str, type, NULL),
+ lookup_msg(orf_mode_str, mode, NULL),
+ iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+
+ switch (mode) {
+ case ORF_MODE_BOTH:
+ SET_FLAG(peer->af_cap[afi][safi], sm_cap);
+ SET_FLAG(peer->af_cap[afi][safi], rm_cap);
+ break;
+ case ORF_MODE_SEND:
+ SET_FLAG(peer->af_cap[afi][safi], sm_cap);
+ UNSET_FLAG(peer->af_cap[afi][safi], rm_cap);
+ break;
+ case ORF_MODE_RECEIVE:
+ SET_FLAG(peer->af_cap[afi][safi], rm_cap);
+ UNSET_FLAG(peer->af_cap[afi][safi], sm_cap);
+ break;
+ }
+ }
+}
+
+static void bgp_dynamic_capability_fqdn(uint8_t *pnt, int action,
+ struct capability_header *hdr,
+ struct peer *peer)
+{
+ uint8_t *data = pnt + 3;
+ uint8_t *end = data + hdr->length;
+ char str[BGP_MAX_HOSTNAME + 1] = {};
+ uint8_t len;
+
+ if (action == CAPABILITY_ACTION_SET) {
+ /* hostname */
+ if (data + 1 > end) {
+ zlog_err("%pBP: Received invalid FQDN capability (host name length)",
+ peer);
+ return;
+ }
+
+ len = *data;
+ if (data + len > end) {
+ zlog_err("%pBP: Received invalid FQDN capability length (host name) %d",
+ peer, hdr->length);
+ return;
+ }
+ data++;
+
+ if (len > BGP_MAX_HOSTNAME) {
+ memcpy(&str, data, BGP_MAX_HOSTNAME);
+ str[BGP_MAX_HOSTNAME] = '\0';
+ } else if (len) {
+ memcpy(&str, data, len);
+ str[len] = '\0';
+ }
+ data += len;
+
+ if (len) {
+ XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
+ XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
+
+ peer->hostname = XSTRDUP(MTYPE_BGP_PEER_HOST, str);
+ }
+
+ if (data + 1 > end) {
+ zlog_err("%pBP: Received invalid FQDN capability (domain name length)",
+ peer);
+ return;
+ }
+
+ /* domainname */
+ len = *data;
+ if (data + len > end) {
+ zlog_err("%pBP: Received invalid FQDN capability length (domain name) %d",
+ peer, len);
+ return;
+ }
+ data++;
+
+ if (len > BGP_MAX_HOSTNAME) {
+ memcpy(&str, data, BGP_MAX_HOSTNAME);
+ str[BGP_MAX_HOSTNAME] = '\0';
+ } else if (len) {
+ memcpy(&str, data, len);
+ str[len] = '\0';
+ }
+ /* data += len; In case new code is ever added */
+
+ if (len) {
+ XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
+
+ peer->domainname = XSTRDUP(MTYPE_BGP_PEER_HOST, str);
+ }
+
+ SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_RCV);
+ } else {
+ UNSET_FLAG(peer->cap, PEER_CAP_HOSTNAME_RCV);
+ XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
+ XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
+ }
+}
+
static void bgp_dynamic_capability_llgr(uint8_t *pnt, int action,
struct capability_header *hdr,
struct peer *peer)
@@ -3121,6 +3610,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
zlog_err("%pBP: Capability length error", peer);
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_SUBCODE_UNSPECIFIC);
+ pnt += length;
return BGP_Stop;
}
action = *pnt;
@@ -3133,7 +3623,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
action);
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_SUBCODE_UNSPECIFIC);
- return BGP_Stop;
+ goto done;
}
if (bgp_debug_neighbor_events(peer))
@@ -3145,12 +3635,13 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
zlog_err("%pBP: Capability length error", peer);
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_SUBCODE_UNSPECIFIC);
+ pnt += length;
return BGP_Stop;
}
/* Ignore capability when override-capability is set. */
if (CHECK_FLAG(peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
- continue;
+ goto done;
capability = lookup_msg(capcode_str, hdr->code, "Unknown");
@@ -3165,7 +3656,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
peer, capability,
sizeof(struct capability_mp_data),
hdr->length);
- return BGP_Stop;
+ goto done;
}
memcpy(&mpc, pnt + 3, sizeof(struct capability_mp_data));
@@ -3180,7 +3671,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
peer, capability,
iana_afi2str(pkt_afi),
iana_safi2str(pkt_safi));
- continue;
+ goto done;
}
/* Address family check. */
@@ -3207,7 +3698,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
if (peer_active_nego(peer))
bgp_clear_route(peer, afi, safi);
else
- return BGP_Stop;
+ goto done;
}
break;
case CAPABILITY_CODE_RESTART:
@@ -3217,7 +3708,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
bgp_notify_send(peer->connection,
BGP_NOTIFY_CEASE,
BGP_NOTIFY_SUBCODE_UNSPECIFIC);
- return BGP_Stop;
+ goto done;
}
bgp_dynamic_capability_graceful_restart(pnt, action,
@@ -3226,13 +3717,19 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
case CAPABILITY_CODE_LLGR:
bgp_dynamic_capability_llgr(pnt, action, hdr, peer);
break;
- case CAPABILITY_CODE_REFRESH:
+ case CAPABILITY_CODE_ADDPATH:
+ bgp_dynamic_capability_addpath(pnt, action, hdr, peer);
+ break;
case CAPABILITY_CODE_ORF:
+ bgp_dynamic_capability_orf(pnt, action, hdr, peer);
+ break;
+ case CAPABILITY_CODE_FQDN:
+ bgp_dynamic_capability_fqdn(pnt, action, hdr, peer);
+ break;
+ case CAPABILITY_CODE_REFRESH:
case CAPABILITY_CODE_AS4:
case CAPABILITY_CODE_DYNAMIC:
- case CAPABILITY_CODE_ADDPATH:
case CAPABILITY_CODE_ENHANCED_RR:
- case CAPABILITY_CODE_FQDN:
case CAPABILITY_CODE_ENHE:
case CAPABILITY_CODE_EXT_MESSAGE:
break;
@@ -3243,7 +3740,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
bgp_notify_send(peer->connection,
BGP_NOTIFY_CEASE,
BGP_NOTIFY_SUBCODE_UNSPECIFIC);
- return BGP_Stop;
+ goto done;
}
uint8_t role;
@@ -3265,6 +3762,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
break;
}
+done:
pnt += hdr->length + 3;
}
diff --git a/bgpd/bgp_pbr.h b/bgpd/bgp_pbr.h
index ed143d9..cb16c4d 100644
--- a/bgpd/bgp_pbr.h
+++ b/bgpd/bgp_pbr.h
@@ -134,7 +134,7 @@ struct bgp_pbr_entry_main {
struct bgp_pbr_interface {
RB_ENTRY(bgp_pbr_interface) id_entry;
- char name[INTERFACE_NAMSIZ];
+ char name[IFNAMSIZ];
};
RB_HEAD(bgp_pbr_interface_head, bgp_pbr_interface);
diff --git a/bgpd/bgp_rd.h b/bgpd/bgp_rd.h
index e38c2fa..93dda17 100644
--- a/bgpd/bgp_rd.h
+++ b/bgpd/bgp_rd.h
@@ -41,8 +41,8 @@ struct rd_as {
struct rd_ip {
uint16_t type;
- struct in_addr ip;
uint16_t val;
+ struct in_addr ip;
};
#ifdef ENABLE_BGP_VNC
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 3a850a4..38983e2 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -28,6 +28,8 @@
#include "lib/json.h"
#include "lib_errors.h"
#include "zclient.h"
+#include "frrdistance.h"
+
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
#include "bgpd/bgp_route.h"
@@ -85,6 +87,11 @@ DEFINE_HOOK(bgp_rpki_prefix_status,
const struct prefix *prefix),
(peer, attr, prefix));
+DEFINE_HOOK(bgp_route_update,
+ (struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
+ struct bgp_path_info *old_route, struct bgp_path_info *new_route),
+ (bgp, afi, safi, bn, old_route, new_route));
+
/* Extern from bgp_dump.c */
extern const char *bgp_origin_str[];
extern const char *bgp_origin_long_str[];
@@ -113,7 +120,7 @@ DEFINE_HOOK(bgp_process,
(bgp, afi, safi, bn, peer, withdraw));
/** Test if path is suppressed. */
-static bool bgp_path_suppressed(struct bgp_path_info *pi)
+bool bgp_path_suppressed(struct bgp_path_info *pi)
{
if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
return false;
@@ -256,6 +263,10 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
XFREE(MTYPE_BGP_ROUTE_EXTRA_FS, e->flowspec);
if (e->vrfleak)
XFREE(MTYPE_BGP_ROUTE_EXTRA_VRFLEAK, e->vrfleak);
+#ifdef ENABLE_BGP_VNC
+ if (e->vnc)
+ XFREE(MTYPE_BGP_ROUTE_EXTRA_VNC, e->vnc);
+#endif
XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
}
@@ -606,6 +617,8 @@ int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
struct attr *newattr, *existattr;
enum bgp_peer_sort new_sort;
enum bgp_peer_sort exist_sort;
+ enum bgp_peer_sub_sort new_sub_sort;
+ enum bgp_peer_sub_sort exist_sub_sort;
uint32_t new_pref;
uint32_t exist_pref;
uint32_t new_med;
@@ -1140,26 +1153,34 @@ int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
/* 7. Peer type check. */
new_sort = peer_new->sort;
exist_sort = peer_exist->sort;
+ new_sub_sort = peer_new->sub_sort;
+ exist_sub_sort = peer_exist->sub_sort;
- if (new_sort == BGP_PEER_EBGP
- && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
+ if (new_sort == BGP_PEER_EBGP &&
+ (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED ||
+ exist_sub_sort == BGP_PEER_EBGP_OAD)) {
*reason = bgp_path_selection_peer;
if (debug)
- zlog_debug(
- "%s: %s wins over %s due to eBGP peer > iBGP peer",
- pfx_buf, new_buf, exist_buf);
+ zlog_debug("%s: %s wins over %s due to eBGP peer > %s peer",
+ pfx_buf, new_buf, exist_buf,
+ (exist_sub_sort == BGP_PEER_EBGP_OAD)
+ ? "eBGP-OAD"
+ : "iBGP");
if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
return 1;
peer_sort_ret = 1;
}
- if (exist_sort == BGP_PEER_EBGP
- && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
+ if (exist_sort == BGP_PEER_EBGP &&
+ (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED ||
+ new_sub_sort == BGP_PEER_EBGP_OAD)) {
*reason = bgp_path_selection_peer;
if (debug)
- zlog_debug(
- "%s: %s loses to %s due to iBGP peer < eBGP peer",
- pfx_buf, new_buf, exist_buf);
+ zlog_debug("%s: %s loses to %s due to %s peer < eBGP peer",
+ pfx_buf, new_buf, exist_buf,
+ (exist_sub_sort == BGP_PEER_EBGP_OAD)
+ ? "eBGP-OAD"
+ : "iBGP");
if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
return 0;
peer_sort_ret = 0;
@@ -2162,9 +2183,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
* configured for default-originate */
if (CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_DEFAULT_ORIGINATE)) {
- if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
- return false;
- else if (p->family == AF_INET6 && p->prefixlen == 0)
+ if ((p->family == AF_INET || p->family == AF_INET6) && p->prefixlen == 0)
return false;
}
@@ -2299,8 +2318,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
/* Remove MED if its an EBGP peer - will get overwritten by route-maps
*/
- if (peer->sort == BGP_PEER_EBGP
- && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
+ if (peer->sort == BGP_PEER_EBGP && peer->sub_sort != BGP_PEER_EBGP_OAD &&
+ attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
if (from != bgp->peer_self && !transparent
&& !CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_MED_UNCHANGED))
@@ -2514,8 +2533,9 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
return false;
if (bgp_in_graceful_shutdown(bgp)) {
- if (peer->sort == BGP_PEER_IBGP
- || peer->sort == BGP_PEER_CONFED) {
+ if (peer->sort == BGP_PEER_IBGP ||
+ peer->sort == BGP_PEER_CONFED ||
+ peer->sub_sort == BGP_PEER_EBGP_OAD) {
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
attr->local_pref = BGP_GSHUT_LOCAL_PREF;
} else {
@@ -2645,17 +2665,25 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
/* If this is an iBGP, send Origin Validation State (OVS)
* extended community (rfc8097).
+ * draft-uttaro-idr-bgp-oad states:
+ * For example, the Origin Validation State Extended Community,
+ * defined as non-transitive in [RFC8097], can be advertised to
+ * peers in the same OAD.
*/
- if (peer->sort == BGP_PEER_IBGP) {
+ if ((peer->sort == BGP_PEER_IBGP ||
+ peer->sub_sort == BGP_PEER_EBGP_OAD) &&
+ peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_SEND_EXT_COMMUNITY_RPKI)) {
enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
rpki_state = hook_call(bgp_rpki_prefix_status, peer, attr, p);
if (rpki_state != RPKI_NOT_BEING_USED)
- bgp_attr_set_ecommunity(
- attr, ecommunity_add_origin_validation_state(
- rpki_state,
- bgp_attr_get_ecommunity(attr)));
+ bgp_attr_set_ecommunity(attr,
+ ecommunity_add_origin_validation_state(
+ rpki_state,
+ bgp_attr_get_ecommunity(
+ attr)));
}
/*
@@ -2816,18 +2844,18 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
/* reap REMOVED routes, if needs be
* selected route must stay for a while longer though
*/
- if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED) &&
- (pi != old_select)) {
- dest = bgp_path_info_reap(dest, pi);
- assert(dest);
- }
-
if (debug)
zlog_debug(
"%s: %pBD(%s) pi from %s in holddown",
__func__, dest, bgp->name_pretty,
pi->peer->host);
+ if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED) &&
+ (pi != old_select)) {
+ dest = bgp_path_info_reap(dest, pi);
+ assert(dest);
+ }
+
continue;
}
@@ -2958,7 +2986,7 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp,
{
const struct prefix *p;
struct peer *onlypeer;
- struct attr attr;
+ struct attr attr = { 0 }, *pattr = &attr;
struct bgp *bgp;
bool advertise;
@@ -2986,26 +3014,30 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp,
advertise = bgp_check_advertise(bgp, dest, safi);
if (selected) {
- if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
+ if (subgroup_announce_check(dest, selected, subgrp, p, pattr,
NULL)) {
/* Route is selected, if the route is already installed
* in FIB, then it is advertised
*/
if (advertise) {
if (!bgp_check_withdrawal(bgp, dest, safi)) {
- struct attr *adv_attr =
- bgp_attr_intern(&attr);
-
- bgp_adj_out_set_subgroup(dest, subgrp,
- adv_attr,
- selected);
- } else
+ if (!bgp_adj_out_set_subgroup(dest,
+ subgrp,
+ pattr,
+ selected))
+ bgp_attr_flush(pattr);
+ } else {
bgp_adj_out_unset_subgroup(
dest, subgrp, 1, addpath_tx_id);
- }
- } else
+ bgp_attr_flush(pattr);
+ }
+ } else
+ bgp_attr_flush(pattr);
+ } else {
bgp_adj_out_unset_subgroup(dest, subgrp, 1,
addpath_tx_id);
+ bgp_attr_flush(pattr);
+ }
}
/* If selected is NULL we must withdraw the path using addpath_tx_id */
@@ -3434,6 +3466,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
&bgp->t_rmap_def_originate_eval);
}
+ /* TODO BMP insert rib update hook */
if (old_select)
bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
if (new_select) {
@@ -3446,6 +3479,15 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
}
+ /* call bmp hook for loc-rib route update / withdraw after flags were
+ * set
+ */
+ if (old_select || new_select) {
+ hook_call(bgp_route_update, bgp, afi, safi, dest, old_select,
+ new_select);
+ }
+
+
#ifdef ENABLE_BGP_VNC
if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
if (old_select != new_select) {
@@ -3463,14 +3505,6 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
}
#endif
- group_announce_route(bgp, afi, safi, dest, new_select);
-
- /* unicast routes must also be annouced to labeled-unicast update-groups
- */
- if (safi == SAFI_UNICAST)
- group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
- new_select);
-
/* FIB update. */
if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
&& !bgp_option_check(BGP_OPT_NO_FIB)) {
@@ -3486,7 +3520,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
*/
if (old_select &&
is_route_parent_evpn(old_select))
- bgp_zebra_withdraw(p, old_select, bgp, safi);
+ bgp_zebra_withdraw(p, old_select, bgp, afi,
+ safi);
bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
} else {
@@ -3496,10 +3531,20 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
|| old_select->sub_type == BGP_ROUTE_AGGREGATE
|| old_select->sub_type == BGP_ROUTE_IMPORTED))
- bgp_zebra_withdraw(p, old_select, bgp, safi);
+ bgp_zebra_withdraw(p, old_select, bgp, afi,
+ safi);
}
}
+ group_announce_route(bgp, afi, safi, dest, new_select);
+
+ /* unicast routes must also be annouced to labeled-unicast update-groups
+ */
+ if (safi == SAFI_UNICAST)
+ group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
+ new_select);
+
+
bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
old_select);
@@ -4151,7 +4196,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
int aspath_loop_count = 0;
struct bgp_dest *dest;
struct bgp *bgp;
- struct attr new_attr;
+ struct attr new_attr = {};
struct attr *attr_new;
struct bgp_path_info *pi;
struct bgp_path_info *new = NULL;
@@ -4184,10 +4229,6 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (orig_safi == SAFI_LABELED_UNICAST)
safi = SAFI_UNICAST;
- memset(&new_attr, 0, sizeof(new_attr));
- new_attr.label_index = BGP_INVALID_LABEL_INDEX;
- new_attr.label = MPLS_INVALID_LABEL;
-
bgp = peer->bgp;
dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
/* TODO: Check to see if we can get rid of "is_valid_label" */
@@ -4397,7 +4438,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
/* remove from RIB previous entry */
- bgp_zebra_withdraw(p, pi, bgp, safi);
+ bgp_zebra_withdraw(p, pi, bgp, afi, safi);
}
if (peer->sort == BGP_PEER_EBGP) {
@@ -4490,12 +4531,12 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
/* Same attribute comes in. */
- if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
- && same_attr
- && (!has_valid_label
- || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
- num_labels * sizeof(mpls_label_t))
- == 0)) {
+ if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED) && same_attr &&
+ (!has_valid_label ||
+ (bgp_path_info_extra_get(pi) &&
+ bgp_labels_same((const mpls_label_t *)pi->extra->label,
+ pi->extra->num_labels, label,
+ num_labels)))) {
if (CHECK_FLAG(bgp->af_flags[afi][safi],
BGP_CONFIG_DAMPENING)
&& peer->sort == BGP_PEER_EBGP
@@ -4680,7 +4721,9 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
/* Update MPLS label */
if (has_valid_label) {
extra = bgp_path_info_extra_get(pi);
- if (extra->label != label) {
+ if (!bgp_labels_same((const mpls_label_t *)extra->label,
+ extra->num_labels, label,
+ num_labels)) {
memcpy(&extra->label, label,
num_labels * sizeof(mpls_label_t));
extra->num_labels = num_labels;
@@ -4761,9 +4804,10 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
BGP_PATH_VALID);
} else {
if (BGP_DEBUG(nht, NHT)) {
- zlog_debug("%s(%pI4): NH unresolved",
+ zlog_debug("%s(%pI4): NH unresolved for existing %pFX pi %p flags 0x%x",
__func__,
- (in_addr_t *)&attr_new->nexthop);
+ (in_addr_t *)&attr_new->nexthop,
+ p, pi, pi->flags);
}
bgp_path_info_unset_flag(dest, pi,
BGP_PATH_VALID);
@@ -4808,10 +4852,23 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
* updating
* the attributes for the route in the VNI(s).
*/
- if (safi == SAFI_EVPN &&
- (!same_attr || force_evpn_import) &&
- CHECK_FLAG(pi->flags, BGP_PATH_VALID))
- bgp_evpn_import_route(bgp, afi, safi, p, pi);
+ if (safi == SAFI_EVPN) {
+ if ((!same_attr || force_evpn_import) &&
+ CHECK_FLAG(pi->flags, BGP_PATH_VALID))
+ bgp_evpn_import_route(bgp, afi, safi, p, pi);
+
+ /* If existing path is marked invalid then unimport the
+ * path from EVPN prefix. This will ensure EVPN route
+ * has only valid paths and path refcount maintained in
+ * EVPN nexthop is decremented appropriately.
+ */
+ else if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)) {
+ if (BGP_DEBUG(nht, NHT))
+ zlog_debug("%s unimport EVPN %pFX as pi %p is not VALID",
+ __func__, p, pi);
+ bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
+ }
+ }
/* Process change. */
bgp_aggregate_increment(bgp, p, pi, afi, safi);
@@ -4865,7 +4922,8 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
/* Update MPLS label */
if (has_valid_label) {
extra = bgp_path_info_extra_get(new);
- if (extra->label != label) {
+ if (!bgp_labels_same((const mpls_label_t *)extra->label,
+ extra->num_labels, label, num_labels)) {
memcpy(&extra->label, label,
num_labels * sizeof(mpls_label_t));
extra->num_labels = num_labels;
@@ -5146,7 +5204,7 @@ void bgp_withdraw(struct peer *peer, const struct prefix *p,
}
void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
- int withdraw)
+ bool withdraw)
{
struct update_subgroup *subgrp;
subgrp = peer_subgroup(peer, afi, safi);
@@ -5960,10 +6018,10 @@ bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
if (peer->sort == BGP_PEER_IBGP)
return true;
- if (peer->sort == BGP_PEER_EBGP
- && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
- || FILTER_LIST_OUT_NAME(filter)
- || DISTRIBUTE_OUT_NAME(filter)))
+ if (peer->sort == BGP_PEER_EBGP &&
+ (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter) ||
+ FILTER_LIST_OUT_NAME(filter) || DISTRIBUTE_OUT_NAME(filter) ||
+ UNSUPPRESS_MAP_NAME(filter)))
return true;
return false;
}
@@ -5982,7 +6040,7 @@ bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
}
static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
- safi_t safi)
+ afi_t afi, safi_t safi)
{
struct bgp_dest *dest;
struct bgp_path_info *pi;
@@ -6006,7 +6064,8 @@ static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
|| pi->sub_type == BGP_ROUTE_IMPORTED)) {
if (bgp_fibupd_safi(safi))
- bgp_zebra_withdraw(p, pi, bgp, safi);
+ bgp_zebra_withdraw(p, pi, bgp, afi,
+ safi);
}
dest = bgp_path_info_reap(dest, pi);
@@ -6024,7 +6083,7 @@ void bgp_cleanup_routes(struct bgp *bgp)
for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
if (afi == AFI_L2VPN)
continue;
- bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
+ bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST], afi,
SAFI_UNICAST);
/*
* VPN and ENCAP and EVPN tables are two-level (RD is top level)
@@ -6036,7 +6095,7 @@ void bgp_cleanup_routes(struct bgp *bgp)
dest = bgp_route_next(dest)) {
table = bgp_dest_get_bgp_table_info(dest);
if (table != NULL) {
- bgp_cleanup_table(bgp, table, safi);
+ 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);
@@ -6049,7 +6108,7 @@ void bgp_cleanup_routes(struct bgp *bgp)
dest = bgp_route_next(dest)) {
table = bgp_dest_get_bgp_table_info(dest);
if (table != NULL) {
- bgp_cleanup_table(bgp, table, safi);
+ 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);
@@ -6063,7 +6122,7 @@ void bgp_cleanup_routes(struct bgp *bgp)
dest = bgp_route_next(dest)) {
table = bgp_dest_get_bgp_table_info(dest);
if (table != NULL) {
- bgp_cleanup_table(bgp, table, SAFI_EVPN);
+ bgp_cleanup_table(bgp, table, afi, SAFI_EVPN);
bgp_table_finish(&table);
bgp_dest_set_bgp_table_info(dest, NULL);
dest = bgp_dest_unlock_node(dest);
@@ -6239,13 +6298,14 @@ static void bgp_nexthop_reachability_check(afi_t afi, safi_t safi,
struct bgp_path_info *bpi,
const struct prefix *p,
struct bgp_dest *dest,
- struct bgp *bgp)
+ struct bgp *bgp,
+ struct bgp *bgp_nexthop)
{
/* Nexthop reachability check. */
if (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST) {
if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)) {
- if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, bpi,
- NULL, 0, p))
+ if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, afi, safi,
+ bpi, NULL, 0, p))
bgp_path_info_set_flag(dest, bpi,
BGP_PATH_VALID);
else {
@@ -6283,7 +6343,7 @@ static void bgp_static_free(struct bgp_static *bgp_static)
route_map_counter_decrement(bgp_static->rmap.map);
if (bgp_static->prd_pretty)
- XFREE(MTYPE_BGP, bgp_static->prd_pretty);
+ XFREE(MTYPE_BGP_NAME, bgp_static->prd_pretty);
XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
XFREE(MTYPE_BGP_STATIC, bgp_static);
}
@@ -6303,6 +6363,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
mpls_label_t label = 0;
#endif
uint32_t num_labels = 0;
+ struct bgp *bgp_nexthop = bgp;
assert(bgp_static);
@@ -6457,9 +6518,11 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
&pi->extra->label[0]);
}
#endif
+ if (pi->extra && pi->extra->vrfleak->bgp_orig)
+ bgp_nexthop = pi->extra->vrfleak->bgp_orig;
bgp_nexthop_reachability_check(afi, safi, pi, p, dest,
- bgp);
+ bgp, bgp_nexthop);
/* Process change. */
bgp_aggregate_increment(bgp, p, pi, afi, safi);
@@ -6509,7 +6572,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
#endif
}
- bgp_nexthop_reachability_check(afi, safi, new, p, dest, bgp);
+ bgp_nexthop_reachability_check(afi, safi, new, p, dest, bgp, bgp);
/* Aggregate address increment. */
bgp_aggregate_increment(bgp, p, new, afi, safi);
@@ -7322,8 +7385,9 @@ static void bgp_aggregate_install(
* If the aggregate information has not changed
* no need to re-install it again.
*/
- if (pi && bgp_aggregate_info_same(pi, origin, aspath, community,
- ecommunity, lcommunity)) {
+ if (pi && (!aggregate->rmap.changed &&
+ bgp_aggregate_info_same(pi, origin, aspath, community,
+ ecommunity, lcommunity))) {
bgp_dest_unlock_node(dest);
if (aspath)
@@ -7577,7 +7641,6 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
*/
aggregate->count = 0;
aggregate->incomplete_origin_count = 0;
- aggregate->incomplete_origin_count = 0;
aggregate->egp_origin_count = 0;
/* ORIGIN attribute: If at least one route among routes that are
@@ -7752,6 +7815,9 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
lcommunity = lcommunity_dup(aggregate->lcommunity);
}
+ /* Unimport suppressed routes from EVPN */
+ bgp_aggr_supp_withdraw_from_evpn(bgp, afi, safi);
+
bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
ecommunity, lcommunity, atomic_aggregate,
aggregate);
@@ -8331,6 +8397,7 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
aggregate->rmap.name =
XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
aggregate->rmap.map = route_map_lookup_by_name(rmap);
+ aggregate->rmap.changed = true;
route_map_counter_increment(aggregate->rmap.map);
}
@@ -9465,14 +9532,12 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
const struct prefix *p, struct attr *attr, safi_t safi,
bool use_json, json_object *json_ar, bool wide)
{
- json_object *json_status = NULL;
json_object *json_net = NULL;
int len;
char buff[BUFSIZ];
/* Route status display. */
if (use_json) {
- json_status = json_object_new_object();
json_net = json_object_new_object();
} else {
vty_out(vty, " *");
@@ -9539,11 +9604,6 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
attr->aspath->str);
/* Print origin */
-#if CONFDATE > 20231208
-CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
-#endif
- json_object_string_add(json_net, "bgpOriginCode",
- bgp_origin_str[attr->origin]);
json_object_string_add(
json_net, "origin",
bgp_origin_long_str[attr->origin]);
@@ -9599,20 +9659,11 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
if (use_json) {
struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(dest);
-#if CONFDATE > 20231208
-CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
-#endif
- json_object_boolean_true_add(json_status, "*");
- json_object_boolean_true_add(json_status, ">");
json_object_boolean_true_add(json_net, "valid");
json_object_boolean_true_add(json_net, "best");
- if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_MULTIPATH)) {
- json_object_boolean_true_add(json_status, "=");
+ if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_MULTIPATH))
json_object_boolean_true_add(json_net, "multipath");
- }
- json_object_object_add(json_net, "appliedStatusSymbols",
- json_status);
json_object_object_addf(json_ar, json_net, "%pFX", p);
} else
vty_out(vty, "\n");
@@ -10661,9 +10712,17 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
} else {
if (json_paths)
json_object_string_add(
- json_peer, "type", "external");
+ json_peer, "type",
+ (path->peer->sub_sort ==
+ BGP_PEER_EBGP_OAD)
+ ? "external (oad)"
+ : "external");
else
- vty_out(vty, ", external");
+ vty_out(vty, ", %s",
+ (path->peer->sub_sort ==
+ BGP_PEER_EBGP_OAD)
+ ? "external (oad)"
+ : "external");
}
}
} else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
@@ -11599,7 +11658,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t sa
total_count);
} else
vty_out(vty,
- "\nDisplayed %ld routes and %ld total paths\n",
+ "\nDisplayed %ld routes and %ld total paths\n",
output_count, total_count);
}
}
@@ -11650,7 +11709,7 @@ int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
total_cum);
else
vty_out(vty,
- "\nDisplayed %ld routes and %ld total paths\n",
+ "\nDisplayed %ld routes and %ld total paths\n",
output_cum, total_cum);
} else {
if (use_json && output_cum == 0 && json_header_depth == 0)
@@ -13925,9 +13984,7 @@ DEFUN (show_bgp_l2vpn_evpn_route_prefix,
static void show_adj_route_header(struct vty *vty, struct peer *peer,
struct bgp_table *table, int *header1,
- int *header2, json_object *json,
- json_object *json_scode,
- json_object *json_ocode, bool wide,
+ int *header2, json_object *json, bool wide,
bool detail)
{
uint64_t version = table ? table->version : 0;
@@ -13943,10 +14000,6 @@ static void show_adj_route_header(struct vty *vty, struct peer *peer,
peer->change_local_as
? peer->change_local_as
: peer->local_as);
- json_object_object_add(json, "bgpStatusCodes",
- json_scode);
- json_object_object_add(json, "bgpOriginCodes",
- json_ocode);
} else {
vty_out(vty,
"BGP table version is %" PRIu64
@@ -13983,7 +14036,6 @@ static void
show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
const char *rmap_name, json_object *json, json_object *json_ar,
- json_object *json_scode, json_object *json_ocode,
uint16_t show_flags, int *header1, int *header2, char *rd_str,
const struct prefix *match, unsigned long *output_count,
unsigned long *filtered_count)
@@ -14078,8 +14130,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
if (ret != RMAP_DENY) {
show_adj_route_header(vty, peer, table, header1,
- header2, json, json_scode,
- json_ocode, wide, detail);
+ header2, json, wide, detail);
if (use_json)
json_net = json_object_new_object();
@@ -14116,10 +14167,6 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
peer->change_local_as
? peer->change_local_as
: peer->local_as);
- json_object_object_add(json, "bgpStatusCodes",
- json_scode);
- json_object_object_add(json, "bgpOriginCodes",
- json_ocode);
json_object_string_add(
json, "bgpOriginatingDefaultNetwork",
(afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
@@ -14159,8 +14206,8 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
if (ain->peer != peer)
continue;
show_adj_route_header(vty, peer, table, header1,
- header2, json, json_scode,
- json_ocode, wide, detail);
+ header2, json, wide,
+ detail);
if ((safi == SAFI_MPLS_VPN)
|| (safi == SAFI_ENCAP)
@@ -14244,10 +14291,10 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
if (paf->peer != peer || !adj->attr)
continue;
- show_adj_route_header(
- vty, peer, table, header1,
- header2, json, json_scode,
- json_ocode, wide, detail);
+ show_adj_route_header(vty, peer, table,
+ header1, header2,
+ json, wide,
+ detail);
const struct prefix *rn_p =
bgp_dest_get_prefix(dest);
@@ -14311,8 +14358,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
struct bgp_path_info *pi;
show_adj_route_header(vty, peer, table, header1,
- header2, json, json_scode,
- json_ocode, wide, detail);
+ header2, json, wide, detail);
const struct prefix *rn_p = bgp_dest_get_prefix(dest);
@@ -14355,8 +14401,6 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
struct bgp *bgp;
struct bgp_table *table;
json_object *json = NULL;
- json_object *json_scode = NULL;
- json_object *json_ocode = NULL;
json_object *json_ar = NULL;
bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
@@ -14385,28 +14429,6 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
if (use_json) {
json = json_object_new_object();
json_ar = json_object_new_object();
- json_scode = json_object_new_object();
- json_ocode = json_object_new_object();
-#if CONFDATE > 20231208
-CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
-#endif
- json_object_string_add(json_scode, "suppressed", "s");
- json_object_string_add(json_scode, "damped", "d");
- json_object_string_add(json_scode, "history", "h");
- json_object_string_add(json_scode, "valid", "*");
- json_object_string_add(json_scode, "best", ">");
- json_object_string_add(json_scode, "multipath", "=");
- json_object_string_add(json_scode, "internal", "i");
- json_object_string_add(json_scode, "ribFailure", "r");
- json_object_string_add(json_scode, "stale", "S");
- json_object_string_add(json_scode, "removed", "R");
-
-#if CONFDATE > 20231208
-CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
-#endif
- json_object_string_add(json_ocode, "igp", "i");
- json_object_string_add(json_ocode, "egp", "e");
- json_object_string_add(json_ocode, "incomplete", "?");
}
if (!peer || !peer->afc[afi][safi]) {
@@ -14417,8 +14439,6 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
vty_out(vty, "%s\n", json_object_to_json_string(json));
json_object_free(json);
json_object_free(json_ar);
- json_object_free(json_scode);
- json_object_free(json_ocode);
} else
vty_out(vty, "%% No such neighbor or address family\n");
@@ -14436,8 +14456,6 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
vty_out(vty, "%s\n", json_object_to_json_string(json));
json_object_free(json);
json_object_free(json_ar);
- json_object_free(json_scode);
- json_object_free(json_ocode);
} else
vty_out(vty,
"%% Inbound soft reconfiguration not enabled\n");
@@ -14477,11 +14495,11 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
prefix_rd2str(prd, rd_str, sizeof(rd_str),
bgp->asnotation);
- show_adj_route(
- vty, peer, table, afi, safi, type, rmap_name,
- json, json_routes, json_scode, json_ocode,
- show_flags, &header1, &header2, rd_str, match,
- &output_count_per_rd, &filtered_count_per_rd);
+ show_adj_route(vty, peer, table, afi, safi, type,
+ rmap_name, json, json_routes, show_flags,
+ &header1, &header2, rd_str, match,
+ &output_count_per_rd,
+ &filtered_count_per_rd);
/* Don't include an empty RD in the output! */
if (json_routes && (output_count_per_rd > 0))
@@ -14493,9 +14511,8 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
}
} else
show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
- json, json_ar, json_scode, json_ocode,
- show_flags, &header1, &header2, rd_str, match,
- &output_count, &filtered_count);
+ json, json_ar, show_flags, &header1, &header2,
+ rd_str, match, &output_count, &filtered_count);
if (use_json) {
if (type == bgp_show_adj_route_advertised)
@@ -14507,16 +14524,6 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
json_object_int_add(json, "filteredPrefixCounter",
filtered_count);
- /*
- * These fields only give up ownership to `json` when `header1`
- * is used (set to zero). See code in `show_adj_route` and
- * `show_adj_route_header`.
- */
- if (header1 == 1) {
- json_object_free(json_scode);
- json_object_free(json_ocode);
- }
-
/*
* This is an extremely expensive operation at scale
* and non-pretty reduces memory footprint significantly.
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index e9f48ea..2d82f0f 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -193,30 +193,9 @@ struct bgp_path_info_extra_vrfleak {
struct prefix nexthop_orig;
};
-/* Ancillary information to struct bgp_path_info,
- * used for uncommonly used data (aggregation, MPLS, etc.)
- * and lazily allocated to save memory.
- */
-struct bgp_path_info_extra {
- /* Pointer to dampening structure. */
- struct bgp_damp_info *damp_info;
-
- /** List of aggregations that suppress this path. */
- struct list *aggr_suppressors;
-
- /* Nexthop reachability check. */
- uint32_t igpmetric;
-
- /* MPLS label(s) - VNI(s) for EVPN-VxLAN */
- mpls_label_t label[BGP_MAX_LABELS];
- uint32_t num_labels;
-
- /*For EVPN*/
- struct bgp_path_info_extra_evpn *evpn;
-
#ifdef ENABLE_BGP_VNC
+struct bgp_path_info_extra_vnc {
union {
-
struct {
void *rfapi_handle; /* export: NVE advertising this
route */
@@ -239,8 +218,36 @@ struct bgp_path_info_extra {
struct prefix aux_prefix; /* AFI_L2VPN: the IP addr,
if family set */
} import;
-
} vnc;
+};
+#endif
+
+/* Ancillary information to struct bgp_path_info,
+ * used for uncommonly used data (aggregation, MPLS, etc.)
+ * and lazily allocated to save memory.
+ */
+struct bgp_path_info_extra {
+ /* Pointer to dampening structure. */
+ struct bgp_damp_info *damp_info;
+
+ /** List of aggregations that suppress this path. */
+ struct list *aggr_suppressors;
+
+ /* Nexthop reachability check. */
+ uint32_t igpmetric;
+
+ /* MPLS label(s) - VNI(s) for EVPN-VxLAN */
+ mpls_label_t label[BGP_MAX_LABELS];
+ uint32_t num_labels;
+
+ /* timestamp of the rib installation */
+ time_t bgp_rib_uptime;
+
+ /*For EVPN*/
+ struct bgp_path_info_extra_evpn *evpn;
+
+#ifdef ENABLE_BGP_VNC
+ struct bgp_path_info_extra_vnc *vnc;
#endif
/* For flowspec*/
@@ -366,6 +373,8 @@ struct bgp_static {
/* Import check status. */
uint8_t valid;
+ uint16_t encap_tunneltype;
+
/* IGP metric. */
uint32_t igpmetric;
@@ -391,7 +400,6 @@ struct bgp_static {
/* EVPN */
esi_t *eth_s_id;
struct ethaddr *router_mac;
- uint16_t encap_tunneltype;
struct prefix gatewayIp;
};
@@ -412,10 +420,22 @@ struct bgp_aggregate {
/* AS set generation. */
uint8_t as_set;
+ /* Optional modify flag to override ORIGIN */
+ uint8_t origin;
+
+ /** Are there MED mismatches? */
+ bool med_mismatched;
+ /* MED matching state. */
+ /** Did we get the first MED value? */
+ bool med_initialized;
+ /** Match only equal MED. */
+ bool match_med;
+
/* Route-map for aggregated route. */
struct {
char *name;
struct route_map *map;
+ bool changed;
} rmap;
/* Suppress-count. */
@@ -427,9 +447,6 @@ struct bgp_aggregate {
/* Count of routes of origin type egp under this aggregate. */
unsigned long egp_origin_count;
- /* Optional modify flag to override ORIGIN */
- uint8_t origin;
-
/* Hash containing the communities of all the
* routes under this aggregate.
*/
@@ -465,13 +482,6 @@ struct bgp_aggregate {
/* SAFI configuration. */
safi_t safi;
- /** Match only equal MED. */
- bool match_med;
- /* MED matching state. */
- /** Did we get the first MED value? */
- bool med_initialized;
- /** Are there MED mismatches? */
- bool med_mismatched;
/** MED value found in current group. */
uint32_t med_matched_value;
@@ -674,6 +684,12 @@ DECLARE_HOOK(bgp_process,
struct peer *peer, bool withdraw),
(bgp, afi, safi, bn, peer, withdraw));
+/* called when a route is updated in the rib */
+DECLARE_HOOK(bgp_route_update,
+ (struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
+ struct bgp_path_info *old_route, struct bgp_path_info *new_route),
+ (bgp, afi, safi, bn, old_route, new_route));
+
/* BGP show options */
#define BGP_SHOW_OPT_JSON (1 << 0)
#define BGP_SHOW_OPT_WIDE (1 << 1)
@@ -698,7 +714,8 @@ extern void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi,
bool force);
extern void bgp_stop_announce_route_timer(struct peer_af *paf);
extern void bgp_announce_route_all(struct peer *);
-extern void bgp_default_originate(struct peer *, afi_t, safi_t, int);
+extern void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
+ bool withdraw);
extern void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
const struct bgp_table *table,
const struct peer *peer);
@@ -905,6 +922,7 @@ extern void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
extern void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr);
const char *
bgp_path_selection_reason2str(enum bgp_path_selection_reason reason);
+extern bool bgp_path_suppressed(struct bgp_path_info *pi);
extern bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi);
extern const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
safi_t safi);
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index e0db43f..d604a7a 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -2323,17 +2323,10 @@ static const struct route_map_rule_cmd route_set_aspath_prepend_cmd = {
route_set_aspath_prepend_free,
};
-/* `set as-path exclude ASn' */
-struct aspath_exclude {
- struct aspath *aspath;
- bool exclude_all;
- char *exclude_aspath_acl_name;
- struct as_list *exclude_aspath_acl;
-};
-
static void *route_aspath_exclude_compile(const char *arg)
{
struct aspath_exclude *ase;
+ struct aspath_exclude_list *ael;
const char *str = arg;
static const char asp_acl[] = "as-path-access-list";
@@ -2348,16 +2341,41 @@ static void *route_aspath_exclude_compile(const char *arg)
ase->exclude_aspath_acl = as_list_lookup(str);
} else
ase->aspath = aspath_str2aspath(str, bgp_get_asnotation(NULL));
+
+ if (ase->exclude_aspath_acl) {
+ ael = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
+ sizeof(struct aspath_exclude_list));
+ ael->bp_as_excl = ase;
+ ael->next = ase->exclude_aspath_acl->exclude_list;
+ ase->exclude_aspath_acl->exclude_list = ael;
+ }
+
return ase;
}
static void route_aspath_exclude_free(void *rule)
{
struct aspath_exclude *ase = rule;
+ struct aspath_exclude_list *cur_ael = NULL;
+ struct aspath_exclude_list *prev_ael = NULL;
aspath_free(ase->aspath);
if (ase->exclude_aspath_acl_name)
XFREE(MTYPE_TMP, ase->exclude_aspath_acl_name);
+ if (ase->exclude_aspath_acl)
+ cur_ael = ase->exclude_aspath_acl->exclude_list;
+ while (cur_ael) {
+ if (cur_ael->bp_as_excl == ase) {
+ if (prev_ael)
+ prev_ael->next = cur_ael->next;
+ else
+ ase->exclude_aspath_acl->exclude_list = NULL;
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, cur_ael);
+ break;
+ }
+ prev_ael = cur_ael;
+ cur_ael = cur_ael->next;
+ }
XFREE(MTYPE_ROUTE_MAP_COMPILED, ase);
}
@@ -4442,6 +4460,13 @@ static void bgp_route_map_update_peer_group(const char *rmap_name,
filter->map[direct].name)
== 0))
filter->map[direct].map = map;
+
+ if (group->conf->default_rmap[afi][safi].name &&
+ strmatch(group->conf->default_rmap[afi][safi]
+ .name,
+ rmap_name))
+ group->conf->default_rmap[afi][safi].map =
+ map;
}
if (filter->usmap.name
@@ -4596,6 +4621,7 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
route_map_counter_increment(map);
aggregate->rmap.map = map;
+ aggregate->rmap.changed = true;
matched = true;
}
@@ -4743,6 +4769,24 @@ static void bgp_route_map_delete(const char *rmap_name)
route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
}
+bool bgp_route_map_has_extcommunity_rt(const struct route_map *map)
+{
+ struct route_map_index *index = NULL;
+ struct route_map_rule *set = NULL;
+
+ assert(map);
+
+ for (index = map->head; index; index = index->next) {
+ for (set = index->set_list.head; set; set = set->next) {
+ if (set->cmd && set->cmd->str &&
+ (strmatch(set->cmd->str, "extcommunity rt") ||
+ strmatch(set->cmd->str, "extended-comm-list")))
+ return true;
+ }
+ }
+ return false;
+}
+
static void bgp_route_map_event(const char *rmap_name)
{
if (route_map_mark_updated(rmap_name) == 0)
diff --git a/bgpd/bgp_routemap_nb.c b/bgpd/bgp_routemap_nb.c
index abebfe5..096502a 100644
--- a/bgpd/bgp_routemap_nb.c
+++ b/bgpd/bgp_routemap_nb.c
@@ -147,6 +147,8 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
{
.xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:comm-list",
.cbs = {
+ .create = lib_route_map_entry_match_condition_rmap_match_condition_comm_list_create,
+ .destroy = lib_route_map_entry_match_condition_rmap_match_condition_comm_list_destroy,
.apply_finish = lib_route_map_entry_match_condition_rmap_match_condition_comm_list_finish,
}
},
@@ -154,7 +156,6 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
.xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
.cbs = {
.modify = lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_name_modify,
- .destroy = lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_name_destroy,
}
},
{
@@ -356,6 +357,8 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
{
.xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:aggregator",
.cbs = {
+ .create = lib_route_map_entry_set_action_rmap_set_action_aggregator_create,
+ .destroy = lib_route_map_entry_set_action_rmap_set_action_aggregator_destroy,
.apply_finish = lib_route_map_entry_set_action_rmap_set_action_aggregator_finish,
}
},
@@ -363,14 +366,12 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
.xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-asn",
.cbs = {
.modify = lib_route_map_entry_set_action_rmap_set_action_aggregator_aggregator_asn_modify,
- .destroy = lib_route_map_entry_set_action_rmap_set_action_aggregator_aggregator_asn_destroy,
}
},
{
.xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-address",
.cbs = {
.modify = lib_route_map_entry_set_action_rmap_set_action_aggregator_aggregator_address_modify,
- .destroy = lib_route_map_entry_set_action_rmap_set_action_aggregator_aggregator_address_destroy,
}
},
{
@@ -390,6 +391,8 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
{
.xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:extcommunity-lb",
.cbs = {
+ .create = lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_create,
+ .destroy = lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_destroy,
.apply_finish = lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish,
}
},
@@ -397,7 +400,6 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
.xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:extcommunity-lb/lb-type",
.cbs = {
.modify = lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_lb_type_modify,
- .destroy = lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_lb_type_destroy,
}
},
{
@@ -418,7 +420,6 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
.xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:extcommunity-lb/two-octet-as-specific",
.cbs = {
.modify = lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_two_octet_as_specific_modify,
- .destroy = lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_two_octet_as_specific_destroy,
}
},
{
diff --git a/bgpd/bgp_routemap_nb.h b/bgpd/bgp_routemap_nb.h
index 28e4188..d7f0cea 100644
--- a/bgpd/bgp_routemap_nb.h
+++ b/bgpd/bgp_routemap_nb.h
@@ -60,9 +60,12 @@ int lib_route_map_entry_match_condition_rmap_match_condition_evpn_route_type_mod
int lib_route_map_entry_match_condition_rmap_match_condition_evpn_route_type_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_route_distinguisher_modify(struct nb_cb_modify_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_route_distinguisher_destroy(struct nb_cb_destroy_args *args);
+int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_create(
+ struct nb_cb_create_args *args);
+int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_destroy(
+ struct nb_cb_destroy_args *args);
void lib_route_map_entry_match_condition_rmap_match_condition_comm_list_finish(struct nb_cb_apply_finish_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_name_modify(struct nb_cb_modify_args *args);
-int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_name_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_name_exact_match_modify(struct nb_cb_modify_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_name_exact_match_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_name_any_modify(
@@ -127,24 +130,28 @@ int lib_route_map_entry_set_action_rmap_set_action_large_community_none_modify(s
int lib_route_map_entry_set_action_rmap_set_action_large_community_none_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_set_action_rmap_set_action_large_community_string_modify(struct nb_cb_modify_args *args);
int lib_route_map_entry_set_action_rmap_set_action_large_community_string_destroy(struct nb_cb_destroy_args *args);
+int lib_route_map_entry_set_action_rmap_set_action_aggregator_create(
+ struct nb_cb_create_args *args);
+int lib_route_map_entry_set_action_rmap_set_action_aggregator_destroy(
+ struct nb_cb_destroy_args *args);
void lib_route_map_entry_set_action_rmap_set_action_aggregator_finish(struct nb_cb_apply_finish_args *args);
int lib_route_map_entry_set_action_rmap_set_action_aggregator_aggregator_asn_modify(struct nb_cb_modify_args *args);
-int lib_route_map_entry_set_action_rmap_set_action_aggregator_aggregator_asn_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_set_action_rmap_set_action_aggregator_aggregator_address_modify(struct nb_cb_modify_args *args);
-int lib_route_map_entry_set_action_rmap_set_action_aggregator_aggregator_address_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_set_action_rmap_set_action_comm_list_num_modify(struct nb_cb_modify_args *args);
int lib_route_map_entry_set_action_rmap_set_action_comm_list_num_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_set_action_rmap_set_action_comm_list_num_extended_modify(struct nb_cb_modify_args *args);
int lib_route_map_entry_set_action_rmap_set_action_comm_list_num_extended_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_set_action_rmap_set_action_comm_list_name_modify(struct nb_cb_modify_args *args);
int lib_route_map_entry_set_action_rmap_set_action_comm_list_name_destroy(struct nb_cb_destroy_args *args);
+int lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_create(
+ struct nb_cb_create_args *args);
+int lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_destroy(
+ struct nb_cb_destroy_args *args);
void lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish(struct nb_cb_apply_finish_args *args);
int lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_lb_type_modify(struct nb_cb_modify_args *args);
-int lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_lb_type_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_bandwidth_modify(struct nb_cb_modify_args *args);
int lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_bandwidth_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_two_octet_as_specific_modify(struct nb_cb_modify_args *args);
-int lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_two_octet_as_specific_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_set_action_rmap_set_action_extcommunity_none_modify(
struct nb_cb_modify_args *args);
int lib_route_map_entry_set_action_rmap_set_action_extcommunity_none_destroy(
diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c
index 370295b..c1d6ee1 100644
--- a/bgpd/bgp_routemap_nb_config.c
+++ b/bgpd/bgp_routemap_nb_config.c
@@ -522,6 +522,7 @@ lib_route_map_entry_match_condition_rmap_match_condition_probability_destroy(
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
+ break;
case NB_EV_APPLY:
return lib_route_map_entry_match_destroy(args);
}
@@ -1120,6 +1121,27 @@ lib_route_map_entry_match_condition_rmap_match_condition_route_distinguisher_des
/*
* XPath = /frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:comm-list
*/
+int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_create(
+ struct nb_cb_create_args *args)
+{
+ return NB_OK;
+}
+
+int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ return lib_route_map_entry_match_destroy(args);
+ }
+
+ return NB_OK;
+}
+
void
lib_route_map_entry_match_condition_rmap_match_condition_comm_list_finish(
struct nb_cb_apply_finish_args *args)
@@ -1135,14 +1157,14 @@ lib_route_map_entry_match_condition_rmap_match_condition_comm_list_finish(
/* Add configuration. */
rhc = nb_running_get_entry(args->dnode, NULL, true);
- value = yang_dnode_get_string(args->dnode, "./comm-list-name");
+ value = yang_dnode_get_string(args->dnode, "comm-list-name");
- if (yang_dnode_exists(args->dnode, "./comm-list-name-exact-match"))
+ if (yang_dnode_exists(args->dnode, "comm-list-name-exact-match"))
exact_match = yang_dnode_get_bool(
args->dnode, "./comm-list-name-exact-match");
- if (yang_dnode_exists(args->dnode, "./comm-list-name-any"))
- any = yang_dnode_get_bool(args->dnode, "./comm-list-name-any");
+ if (yang_dnode_exists(args->dnode, "comm-list-name-any"))
+ any = yang_dnode_get_bool(args->dnode, "comm-list-name-any");
if (exact_match) {
argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
@@ -1210,23 +1232,6 @@ lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_nam
return NB_OK;
}
-int
-lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_name_destroy(
- struct nb_cb_destroy_args *args)
-{
- switch (args->event) {
- case NB_EV_VALIDATE:
- case NB_EV_PREPARE:
- case NB_EV_ABORT:
- break;
- case NB_EV_APPLY:
- return lib_route_map_entry_match_destroy(args);
- }
-
- return NB_OK;
-
-}
-
/*
* XPath:
* /frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-any
@@ -1252,9 +1257,8 @@ int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
- break;
case NB_EV_APPLY:
- return lib_route_map_entry_match_destroy(args);
+ break;
}
return NB_OK;
@@ -1286,9 +1290,8 @@ lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_nam
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
- break;
case NB_EV_APPLY:
- return lib_route_map_entry_match_destroy(args);
+ break;
}
return NB_OK;
@@ -1450,7 +1453,7 @@ int lib_route_map_entry_set_action_rmap_set_action_distance_destroy(
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
- return lib_route_map_entry_match_destroy(args);
+ return lib_route_map_entry_set_destroy(args);
}
return NB_OK;
@@ -1504,7 +1507,7 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_rt_destroy(
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
- return lib_route_map_entry_match_destroy(args);
+ return lib_route_map_entry_set_destroy(args);
}
return NB_OK;
@@ -1556,7 +1559,7 @@ int lib_route_map_entry_set_action_rmap_set_action_extcommunity_nt_destroy(
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
- return lib_route_map_entry_match_destroy(args);
+ return lib_route_map_entry_set_destroy(args);
}
return NB_OK;
@@ -1611,7 +1614,7 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_soo_destroy(
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
- return lib_route_map_entry_match_destroy(args);
+ return lib_route_map_entry_set_destroy(args);
}
return NB_OK;
@@ -1747,7 +1750,7 @@ int lib_route_map_entry_set_action_rmap_set_action_ipv6_address_modify(
|| IN6_IS_ADDR_LINKLOCAL(&i6a))
return NB_ERR_VALIDATION;
}
- /* FALLTHROUGH */
+ return NB_OK;
case NB_EV_PREPARE:
case NB_EV_ABORT:
return NB_OK;
@@ -2734,6 +2737,27 @@ lib_route_map_entry_set_action_rmap_set_action_large_community_string_destroy(
* xpath =
* /frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:aggregator
*/
+int lib_route_map_entry_set_action_rmap_set_action_aggregator_create(
+ struct nb_cb_create_args *args)
+{
+ return NB_OK;
+}
+
+int lib_route_map_entry_set_action_rmap_set_action_aggregator_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ return lib_route_map_entry_set_destroy(args);
+ }
+
+ return NB_OK;
+}
+
void lib_route_map_entry_set_action_rmap_set_action_aggregator_finish(
struct nb_cb_apply_finish_args *args)
{
@@ -2745,8 +2769,8 @@ void lib_route_map_entry_set_action_rmap_set_action_aggregator_finish(
/* Add configuration. */
rhc = nb_running_get_entry(args->dnode, NULL, true);
- asn = yang_dnode_get_string(args->dnode, "./aggregator-asn");
- addr = yang_dnode_get_string(args->dnode, "./aggregator-address");
+ asn = yang_dnode_get_string(args->dnode, "aggregator-asn");
+ addr = yang_dnode_get_string(args->dnode, "aggregator-address");
argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
strlen(asn) + strlen(addr) + 2);
@@ -2798,22 +2822,6 @@ lib_route_map_entry_set_action_rmap_set_action_aggregator_aggregator_asn_modify(
return NB_OK;
}
-int
-lib_route_map_entry_set_action_rmap_set_action_aggregator_aggregator_asn_destroy(
- struct nb_cb_destroy_args *args)
-{
- switch (args->event) {
- case NB_EV_VALIDATE:
- case NB_EV_PREPARE:
- case NB_EV_ABORT:
- break;
- case NB_EV_APPLY:
- return lib_route_map_entry_set_destroy(args);
- }
-
- return NB_OK;
-}
-
/*
* XPath:
* /frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-address
@@ -2833,22 +2841,6 @@ lib_route_map_entry_set_action_rmap_set_action_aggregator_aggregator_address_mod
return NB_OK;
}
-int
-lib_route_map_entry_set_action_rmap_set_action_aggregator_aggregator_address_destroy(
- struct nb_cb_destroy_args *args)
-{
- switch (args->event) {
- case NB_EV_VALIDATE:
- case NB_EV_PREPARE:
- case NB_EV_ABORT:
- break;
- case NB_EV_APPLY:
- return lib_route_map_entry_set_destroy(args);
- }
-
- return NB_OK;
-}
-
/*
* XPath:
* /frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:comm-list-name
@@ -2917,6 +2909,27 @@ lib_route_map_entry_set_action_rmap_set_action_comm_list_name_destroy(
* XPath:
* /frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:extcommunity-lb
*/
+int lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_create(
+ struct nb_cb_create_args *args)
+{
+ return NB_OK;
+}
+
+int lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ return lib_route_map_entry_set_destroy(args);
+ }
+
+ return NB_OK;
+}
+
void
lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish(
struct nb_cb_apply_finish_args *args)
@@ -2929,7 +2942,7 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish(
/* Add configuration. */
rhc = nb_running_get_entry(args->dnode, NULL, true);
- lb_type = yang_dnode_get_enum(args->dnode, "./lb-type");
+ lb_type = yang_dnode_get_enum(args->dnode, "lb-type");
/* Set destroy information. */
rhc->rhc_shook = generic_set_delete;
@@ -2938,7 +2951,7 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish(
switch (lb_type) {
case EXPLICIT_BANDWIDTH:
- bandwidth = yang_dnode_get_uint16(args->dnode, "./bandwidth");
+ bandwidth = yang_dnode_get_uint16(args->dnode, "bandwidth");
snprintf(str, sizeof(str), "%d", bandwidth);
break;
case CUMULATIVE_BANDWIDTH:
@@ -2948,7 +2961,7 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish(
snprintf(str, sizeof(str), "%s", "num-multipaths");
}
- if (yang_dnode_get_bool(args->dnode, "./two-octet-as-specific"))
+ if (yang_dnode_get_bool(args->dnode, "two-octet-as-specific"))
strlcat(str, " non-transitive", sizeof(str));
ret = generic_set_add(rhc->rhc_rmi, "extcommunity bandwidth", str,
@@ -2972,13 +2985,6 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_lb_type_modify(
return NB_OK;
}
-int
-lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_lb_type_destroy(
- struct nb_cb_destroy_args *args)
-{
- return lib_route_map_entry_set_destroy(args);
-}
-
/*
* XPath:
* /frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:extcommunity-lb/bandwidth
@@ -2994,7 +3000,7 @@ int
lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_bandwidth_destroy(
struct nb_cb_destroy_args *args)
{
- return lib_route_map_entry_set_destroy(args);
+ return NB_OK;
}
/*
@@ -3043,7 +3049,7 @@ int lib_route_map_entry_set_action_rmap_set_action_extcommunity_color_destroy(
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
- return lib_route_map_entry_match_destroy(args);
+ return lib_route_map_entry_set_destroy(args);
}
return NB_OK;
@@ -3060,13 +3066,6 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_two_octet_as_spec
return NB_OK;
}
-int
-lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_two_octet_as_specific_destroy(
- struct nb_cb_destroy_args *args)
-{
- return lib_route_map_entry_set_destroy(args);
-}
-
/*
* XPath:
* /frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:extcommunity-none
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index f0b2ffd..22f78fb 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -25,6 +25,7 @@
#include "memory.h"
#include "frrevent.h"
#include "filter.h"
+#include "lib_errors.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
#include "bgp_advertise.h"
@@ -33,6 +34,7 @@
#include "bgpd/bgp_aspath.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_rpki.h"
+#include "bgpd/bgp_debug.h"
#include "northbound_cli.h"
#include "lib/network.h"
@@ -43,27 +45,33 @@
#include "bgpd/bgp_rpki_clippy.c"
+DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_TEMP, "BGP RPKI Intermediate Buffer");
DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_CACHE, "BGP RPKI Cache server");
DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_CACHE_GROUP, "BGP RPKI Cache server group");
DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_RTRLIB, "BGP RPKI RTRLib");
DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_REVALIDATE, "BGP RPKI Revalidation");
+#define STR_SEPARATOR 10
+
#define POLLING_PERIOD_DEFAULT 3600
#define EXPIRE_INTERVAL_DEFAULT 7200
#define RETRY_INTERVAL_DEFAULT 600
#define BGP_RPKI_CACHE_SERVER_SYNC_RETRY_TIMEOUT 3
-static struct event *t_rpki_sync;
-
#define RPKI_DEBUG(...) \
- if (rpki_debug) { \
+ if (rpki_debug_conf || rpki_debug_term) { \
zlog_debug("RPKI: " __VA_ARGS__); \
}
#define RPKI_OUTPUT_STRING "Control rpki specific settings\n"
struct cache {
- enum { TCP, SSH } type;
+ enum {
+ TCP,
+#if defined(FOUND_SSH)
+ SSH
+#endif
+ } type;
struct tr_socket *tr_socket;
union {
struct tr_tcp_config *tcp_config;
@@ -71,6 +79,7 @@ struct cache {
} tr_config;
struct rtr_socket *rtr_socket;
uint8_t preference;
+ struct rpki_vrf *rpki_vrf;
};
enum return_values { SUCCESS = 0, ERROR = -1 };
@@ -83,32 +92,61 @@ struct rpki_for_each_record_arg {
enum asnotation_mode asnotation;
};
-static int start(void);
-static void stop(void);
-static int reset(bool force);
-static struct rtr_mgr_group *get_connected_group(void);
-static void print_prefix_table(struct vty *vty, json_object *json);
+struct rpki_vrf {
+ struct rtr_mgr_config *rtr_config;
+ struct list *cache_list;
+ bool rtr_is_running;
+ bool rtr_is_stopping;
+ bool rtr_is_synced;
+ _Atomic int rtr_update_overflow;
+ unsigned int polling_period;
+ unsigned int expire_interval;
+ unsigned int retry_interval;
+ int rpki_sync_socket_rtr;
+ int rpki_sync_socket_bgpd;
+ char *vrfname;
+ struct event *t_rpki_sync;
+
+ QOBJ_FIELDS;
+};
+
+static pthread_key_t rpki_pthread;
+
+static struct rpki_vrf *find_rpki_vrf(const char *vrfname);
+static int bgp_rpki_vrf_update(struct vrf *vrf, bool enabled);
+static int bgp_rpki_write_vrf(struct vty *vty, struct vrf *vrf);
+static int bgp_rpki_hook_write_vrf(struct vty *vty, struct vrf *vrf);
+static int bgp_rpki_write_debug(struct vty *vty, bool running);
+static int start(struct rpki_vrf *rpki_vrf);
+static void stop(struct rpki_vrf *rpki_vrf);
+static int reset(bool force, struct rpki_vrf *rpki_vrf);
+static struct rtr_mgr_group *get_connected_group(struct rpki_vrf *rpki_vrf);
+static void print_prefix_table(struct vty *vty, struct rpki_vrf *rpki_vrf,
+ json_object *json, bool count_only);
static void install_cli_commands(void);
static int config_write(struct vty *vty);
static int config_on_exit(struct vty *vty);
static void free_cache(struct cache *cache);
-static struct rtr_mgr_group *get_groups(void);
+static struct rtr_mgr_group *get_groups(struct list *cache_list);
#if defined(FOUND_SSH)
-static int add_ssh_cache(const char *host, const unsigned int port,
- const char *username, const char *client_privkey_path,
+static int add_ssh_cache(struct rpki_vrf *rpki_vrf, const char *host,
+ const unsigned int port, const char *username,
+ const char *client_privkey_path,
const char *server_pubkey_path,
const uint8_t preference, const char *bindaddr);
#endif
static struct rtr_socket *create_rtr_socket(struct tr_socket *tr_socket);
-static struct cache *find_cache(const uint8_t preference);
-static void rpki_delete_all_cache_nodes(void);
-static int add_tcp_cache(const char *host, const char *port,
- const uint8_t preference, const char *bindaddr);
+static struct cache *find_cache(const uint8_t preference,
+ struct list *cache_list);
+static void rpki_delete_all_cache_nodes(struct rpki_vrf *rpki_vrf);
+static int add_tcp_cache(struct rpki_vrf *rpki_vrf, const char *host,
+ const char *port, const uint8_t preference,
+ const char *bindaddr);
static void print_record(const struct pfx_record *record, struct vty *vty,
json_object *json, enum asnotation_mode asnotation);
-static bool is_synchronized(void);
-static bool is_running(void);
-static bool is_stopping(void);
+static bool is_synchronized(struct rpki_vrf *rpki_vrf);
+static bool is_running(struct rpki_vrf *rpki_vrf);
+static bool is_stopping(struct rpki_vrf *rpki_vrf);
static void route_match_free(void *rule);
static enum route_map_cmd_result_t route_match(void *rule,
const struct prefix *prefix,
@@ -116,20 +154,14 @@ static enum route_map_cmd_result_t route_match(void *rule,
void *object);
static void *route_match_compile(const char *arg);
static void revalidate_bgp_node(struct bgp_dest *dest, afi_t afi, safi_t safi);
-static void revalidate_all_routes(void);
-
-static struct rtr_mgr_config *rtr_config;
-static struct list *cache_list;
-static bool rtr_is_running;
-static bool rtr_is_stopping;
-static bool rtr_is_synced;
-static _Atomic int rtr_update_overflow;
-static bool rpki_debug;
-static unsigned int polling_period;
-static unsigned int expire_interval;
-static unsigned int retry_interval;
-static int rpki_sync_socket_rtr;
-static int rpki_sync_socket_bgpd;
+static void revalidate_all_routes(struct rpki_vrf *rpki_vrf);
+
+static bool rpki_debug_conf, rpki_debug_term;
+
+DECLARE_QOBJ_TYPE(rpki_vrf);
+DEFINE_QOBJ_TYPE(rpki_vrf);
+
+struct list *rpki_vrf_list;
static struct cmd_node rpki_node = {
.name = "rpki",
@@ -139,6 +171,16 @@ static struct cmd_node rpki_node = {
.config_write = config_write,
.node_exit = config_on_exit,
};
+
+static struct cmd_node rpki_vrf_node = {
+ .name = "rpki",
+ .node = RPKI_VRF_NODE,
+ .parent_node = VRF_NODE,
+ .prompt = "%s(config-vrf-rpki)# ",
+ .config_write = NULL,
+ .node_exit = config_on_exit,
+};
+
static const struct route_map_rule_cmd route_match_rpki_cmd = {
"rpki", route_match, route_match_compile, route_match_free};
@@ -246,10 +288,141 @@ static struct rtr_socket *create_rtr_socket(struct tr_socket *tr_socket)
return rtr_socket;
}
-static struct cache *find_cache(const uint8_t preference)
+static int bgp_rpki_vrf_update(struct vrf *vrf, bool enabled)
+{
+ struct rpki_vrf *rpki;
+
+ if (vrf->vrf_id == VRF_DEFAULT)
+ rpki = find_rpki_vrf(NULL);
+ else
+ rpki = find_rpki_vrf(vrf->name);
+ if (!rpki)
+ return 0;
+
+ if (enabled)
+ start(rpki);
+ else
+ stop(rpki);
+ return 1;
+}
+
+/* tcp identifier : <HOST>:<PORT>
+ * ssh identifier : <user>@<HOST>:<PORT>
+ */
+static struct rpki_vrf *find_rpki_vrf_from_ident(const char *ident)
{
+#if defined(FOUND_SSH)
+ struct tr_ssh_config *ssh_config;
+#endif
+ struct tr_tcp_config *tcp_config;
+ struct listnode *rpki_vrf_nnode;
+ unsigned int cache_port, port;
struct listnode *cache_node;
+ struct rpki_vrf *rpki_vrf;
struct cache *cache;
+ bool is_tcp = true;
+ size_t host_len;
+ char *endptr;
+ char *host;
+ char *ptr;
+ char *buf;
+
+ /* extract the <SOCKET> */
+ ptr = strrchr(ident, ':');
+ if (!ptr)
+ return NULL;
+
+ ptr++;
+ /* extract port */
+ port = atoi(ptr);
+ if (port == 0)
+ /* not ours */
+ return NULL;
+
+ /* extract host */
+ ptr--;
+ host_len = (size_t)(ptr - ident);
+ buf = XCALLOC(MTYPE_BGP_RPKI_TEMP, host_len + 1);
+ memcpy(buf, ident, host_len);
+ buf[host_len] = '\0';
+ endptr = strrchr(buf, '@');
+
+ /* ssh session */
+ if (endptr) {
+ host = XCALLOC(MTYPE_BGP_RPKI_TEMP,
+ (size_t)(buf + host_len - endptr) + 1);
+ memcpy(host, endptr + 1, (size_t)(buf + host_len - endptr) + 1);
+ is_tcp = false;
+ } else {
+ host = buf;
+ buf = NULL;
+ }
+
+ for (ALL_LIST_ELEMENTS_RO(rpki_vrf_list, rpki_vrf_nnode, rpki_vrf)) {
+ for (ALL_LIST_ELEMENTS_RO(rpki_vrf->cache_list, cache_node,
+ cache)) {
+ if ((cache->type == TCP && !is_tcp)
+#if defined(FOUND_SSH)
+ || (cache->type == SSH && is_tcp)
+#endif
+ )
+ continue;
+
+ if (is_tcp) {
+ tcp_config = cache->tr_config.tcp_config;
+ cache_port = atoi(tcp_config->port);
+ if (cache_port != port)
+ continue;
+ if (strlen(tcp_config->host) != strlen(host))
+ continue;
+ if (memcmp(tcp_config->host, host, host_len) ==
+ 0)
+ break;
+ }
+#if defined(FOUND_SSH)
+ else {
+ ssh_config = cache->tr_config.ssh_config;
+ if (port != ssh_config->port)
+ continue;
+ if (strmatch(ssh_config->host, host))
+ break;
+ }
+#endif
+ }
+ if (cache)
+ break;
+ }
+ if (host)
+ XFREE(MTYPE_BGP_RPKI_TEMP, host);
+ if (buf)
+ XFREE(MTYPE_BGP_RPKI_TEMP, buf);
+ return rpki_vrf;
+}
+
+static struct rpki_vrf *find_rpki_vrf(const char *vrfname)
+{
+ struct listnode *rpki_vrf_nnode;
+ struct rpki_vrf *rpki_vrf;
+
+ for (ALL_LIST_ELEMENTS_RO(rpki_vrf_list, rpki_vrf_nnode, rpki_vrf)) {
+ if (!vrfname && !rpki_vrf->vrfname)
+ /* rpki_vrf struct of the default VRF */
+ return rpki_vrf;
+ if (vrfname && rpki_vrf->vrfname &&
+ strmatch(vrfname, rpki_vrf->vrfname))
+ return rpki_vrf;
+ }
+ return NULL;
+}
+
+static struct cache *find_cache(const uint8_t preference,
+ struct list *cache_list)
+{
+ struct listnode *cache_node;
+ struct cache *cache;
+
+ if (!cache_list)
+ return NULL;
for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
if (cache->preference == preference)
@@ -258,14 +431,15 @@ static struct cache *find_cache(const uint8_t preference)
return NULL;
}
-static void rpki_delete_all_cache_nodes(void)
+static void rpki_delete_all_cache_nodes(struct rpki_vrf *rpki_vrf)
{
struct listnode *cache_node, *cache_next;
struct cache *cache;
- for (ALL_LIST_ELEMENTS(cache_list, cache_node, cache_next, cache)) {
- rtr_mgr_remove_group(rtr_config, cache->preference);
- listnode_delete(cache_list, cache);
+ for (ALL_LIST_ELEMENTS(rpki_vrf->cache_list, cache_node, cache_next,
+ cache)) {
+ rtr_mgr_remove_group(rpki_vrf->rtr_config, cache->preference);
+ listnode_delete(rpki_vrf->cache_list, cache);
}
}
@@ -315,7 +489,14 @@ static void print_record_cb(const struct pfx_record *record, void *data)
print_record(record, vty, arg->json, arg->asnotation);
}
-static struct rtr_mgr_group *get_groups(void)
+static void count_record_cb(const struct pfx_record *record, void *data)
+{
+ struct rpki_for_each_record_arg *arg = data;
+
+ (*arg->prefix_amount)++;
+}
+
+static struct rtr_mgr_group *get_groups(struct list *cache_list)
{
struct listnode *cache_node;
struct rtr_mgr_group *rtr_mgr_groups;
@@ -344,19 +525,19 @@ static struct rtr_mgr_group *get_groups(void)
return rtr_mgr_groups;
}
-inline bool is_synchronized(void)
+inline bool is_synchronized(struct rpki_vrf *rpki_vrf)
{
- return rtr_is_synced;
+ return rpki_vrf->rtr_is_synced;
}
-inline bool is_running(void)
+inline bool is_running(struct rpki_vrf *rpki_vrf)
{
- return rtr_is_running;
+ return rpki_vrf->rtr_is_running;
}
-inline bool is_stopping(void)
+inline bool is_stopping(struct rpki_vrf *rpki_vrf)
{
- return rtr_is_stopping;
+ return rpki_vrf->rtr_is_stopping;
}
static void pfx_record_to_prefix(struct pfx_record *record,
@@ -408,23 +589,26 @@ static void bgpd_sync_callback(struct event *thread)
struct listnode *node;
struct prefix prefix;
struct pfx_record rec;
+ struct rpki_vrf *rpki_vrf = EVENT_ARG(thread);
+ struct vrf *vrf = NULL;
- event_add_read(bm->master, bgpd_sync_callback, NULL,
- rpki_sync_socket_bgpd, NULL);
+ event_add_read(bm->master, bgpd_sync_callback, rpki_vrf,
+ rpki_vrf->rpki_sync_socket_bgpd, NULL);
- if (atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst)) {
- while (read(rpki_sync_socket_bgpd, &rec,
+ if (atomic_load_explicit(&rpki_vrf->rtr_update_overflow,
+ memory_order_seq_cst)) {
+ while (read(rpki_vrf->rpki_sync_socket_bgpd, &rec,
sizeof(struct pfx_record)) != -1)
;
- atomic_store_explicit(&rtr_update_overflow, 0,
+ atomic_store_explicit(&rpki_vrf->rtr_update_overflow, 0,
memory_order_seq_cst);
- revalidate_all_routes();
+ revalidate_all_routes(rpki_vrf);
return;
}
- int retval =
- read(rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record));
+ int retval = read(rpki_vrf->rpki_sync_socket_bgpd, &rec,
+ sizeof(struct pfx_record));
if (retval != sizeof(struct pfx_record)) {
RPKI_DEBUG("Could not read from rpki_sync_socket_bgpd");
return;
@@ -433,9 +617,23 @@ static void bgpd_sync_callback(struct event *thread)
afi_t afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6;
+ if (rpki_vrf->vrfname) {
+ vrf = vrf_lookup_by_name(rpki_vrf->vrfname);
+ if (!vrf) {
+ zlog_err("%s(): vrf for rpki %s not found", __func__,
+ rpki_vrf->vrfname);
+ return;
+ }
+ }
+
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
safi_t safi;
+ if (!vrf && bgp->vrf_id != VRF_DEFAULT)
+ continue;
+ if (vrf && bgp->vrf_id != vrf->vrf_id)
+ continue;
+
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
struct bgp_table *table = bgp->rib[afi][safi];
struct rpki_revalidate_prefix *rrp;
@@ -501,15 +699,30 @@ static void bgp_rpki_revalidate_peer(struct event *thread)
XFREE(MTYPE_BGP_RPKI_REVALIDATE, rvp);
}
-static void revalidate_all_routes(void)
+static void revalidate_all_routes(struct rpki_vrf *rpki_vrf)
{
struct bgp *bgp;
struct listnode *node;
+ struct vrf *vrf = NULL;
+
+ if (rpki_vrf->vrfname) {
+ vrf = vrf_lookup_by_name(rpki_vrf->vrfname);
+ if (!vrf) {
+ zlog_err("%s(): vrf for rpki %s not found", __func__,
+ rpki_vrf->vrfname);
+ return;
+ }
+ }
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
struct peer *peer;
struct listnode *peer_listnode;
+ if (!vrf && bgp->vrf_id != VRF_DEFAULT)
+ continue;
+ if (vrf && bgp->vrf_id != vrf->vrf_id)
+ continue;
+
for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) {
afi_t afi;
safi_t safi;
@@ -542,21 +755,49 @@ static void rpki_update_cb_sync_rtr(struct pfx_table *p __attribute__((unused)),
const struct pfx_record rec,
const bool added __attribute__((unused)))
{
- if (is_stopping() ||
- atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst))
+ struct rpki_vrf *rpki_vrf;
+ const char *msg;
+ const struct rtr_socket *rtr = rec.socket;
+ const char *ident;
+
+ if (!rtr) {
+ msg = "could not find rtr_socket from cb_sync_rtr";
+ goto err;
+ }
+ if (!rtr->tr_socket) {
+ msg = "could not find tr_socket from cb_sync_rtr";
+ goto err;
+ }
+ ident = rtr->tr_socket->ident_fp(rtr->tr_socket->socket);
+ if (!ident) {
+ msg = "could not find ident from cb_sync_rtr";
+ goto err;
+ }
+ rpki_vrf = find_rpki_vrf_from_ident(ident);
+ if (!rpki_vrf) {
+ msg = "could not find rpki_vrf";
+ goto err;
+ }
+
+ if (is_stopping(rpki_vrf) ||
+ atomic_load_explicit(&rpki_vrf->rtr_update_overflow,
+ memory_order_seq_cst))
return;
- int retval =
- write(rpki_sync_socket_rtr, &rec, sizeof(struct pfx_record));
+ int retval = write(rpki_vrf->rpki_sync_socket_rtr, &rec,
+ sizeof(struct pfx_record));
if (retval == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
- atomic_store_explicit(&rtr_update_overflow, 1,
+ atomic_store_explicit(&rpki_vrf->rtr_update_overflow, 1,
memory_order_seq_cst);
else if (retval != sizeof(struct pfx_record))
RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
+ return;
+err:
+ zlog_err("RPKI: %s", msg);
}
-static void rpki_init_sync_socket(void)
+static void rpki_init_sync_socket(struct rpki_vrf *rpki_vrf)
{
int fds[2];
const char *msg;
@@ -566,22 +807,22 @@ static void rpki_init_sync_socket(void)
msg = "could not open rpki sync socketpair";
goto err;
}
- rpki_sync_socket_rtr = fds[0];
- rpki_sync_socket_bgpd = fds[1];
+ rpki_vrf->rpki_sync_socket_rtr = fds[0];
+ rpki_vrf->rpki_sync_socket_bgpd = fds[1];
- if (set_nonblocking(rpki_sync_socket_rtr) != 0) {
+ if (set_nonblocking(rpki_vrf->rpki_sync_socket_rtr) != 0) {
msg = "could not set rpki_sync_socket_rtr to non blocking";
goto err;
}
- if (set_nonblocking(rpki_sync_socket_bgpd) != 0) {
+ if (set_nonblocking(rpki_vrf->rpki_sync_socket_bgpd) != 0) {
msg = "could not set rpki_sync_socket_bgpd to non blocking";
goto err;
}
- event_add_read(bm->master, bgpd_sync_callback, NULL,
- rpki_sync_socket_bgpd, NULL);
+ event_add_read(bm->master, bgpd_sync_callback, rpki_vrf,
+ rpki_vrf->rpki_sync_socket_bgpd, NULL);
return;
@@ -591,139 +832,195 @@ err:
}
+static struct rpki_vrf *bgp_rpki_allocate(const char *vrfname)
+{
+ struct rpki_vrf *rpki_vrf;
+
+ /* initialise default vrf cache list */
+ rpki_vrf = XCALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct rpki_vrf));
+
+ rpki_vrf->cache_list = list_new();
+ rpki_vrf->cache_list->del = (void (*)(void *)) & free_cache;
+ rpki_vrf->polling_period = POLLING_PERIOD_DEFAULT;
+ rpki_vrf->expire_interval = EXPIRE_INTERVAL_DEFAULT;
+ rpki_vrf->retry_interval = RETRY_INTERVAL_DEFAULT;
+
+ if (vrfname && !strmatch(vrfname, VRF_DEFAULT_NAME))
+ rpki_vrf->vrfname = XSTRDUP(MTYPE_BGP_RPKI_CACHE, vrfname);
+ QOBJ_REG(rpki_vrf, rpki_vrf);
+ listnode_add(rpki_vrf_list, rpki_vrf);
+
+ return rpki_vrf;
+}
+
static int bgp_rpki_init(struct event_loop *master)
{
- rpki_debug = false;
- rtr_is_running = false;
- rtr_is_stopping = false;
- rtr_is_synced = false;
+ rpki_debug_conf = false;
+ rpki_debug_term = false;
- cache_list = list_new();
- cache_list->del = (void (*)(void *)) & free_cache;
+ rpki_vrf_list = list_new();
- polling_period = POLLING_PERIOD_DEFAULT;
- expire_interval = EXPIRE_INTERVAL_DEFAULT;
- retry_interval = RETRY_INTERVAL_DEFAULT;
install_cli_commands();
- rpki_init_sync_socket();
+
return 0;
}
static int bgp_rpki_fini(void)
{
- stop();
- list_delete(&cache_list);
+ struct listnode *node, *nnode;
+ struct rpki_vrf *rpki_vrf;
+
+ for (ALL_LIST_ELEMENTS(rpki_vrf_list, node, nnode, rpki_vrf)) {
+ stop(rpki_vrf);
+ list_delete(&rpki_vrf->cache_list);
- close(rpki_sync_socket_rtr);
- close(rpki_sync_socket_bgpd);
+ close(rpki_vrf->rpki_sync_socket_rtr);
+ close(rpki_vrf->rpki_sync_socket_bgpd);
+
+ listnode_delete(rpki_vrf_list, rpki_vrf);
+ QOBJ_UNREG(rpki_vrf);
+ if (rpki_vrf->vrfname)
+ XFREE(MTYPE_BGP_RPKI_CACHE, rpki_vrf->vrfname);
+ XFREE(MTYPE_BGP_RPKI_CACHE, rpki_vrf);
+ }
return 0;
}
static int bgp_rpki_module_init(void)
{
+ pthread_key_create(&rpki_pthread, NULL);
+
lrtr_set_alloc_functions(malloc_wrapper, realloc_wrapper, free_wrapper);
hook_register(bgp_rpki_prefix_status, rpki_validate_prefix);
hook_register(frr_late_init, bgp_rpki_init);
hook_register(frr_early_fini, bgp_rpki_fini);
+ hook_register(bgp_hook_config_write_debug, &bgp_rpki_write_debug);
+ hook_register(bgp_hook_vrf_update, &bgp_rpki_vrf_update);
+ hook_register(bgp_hook_config_write_vrf, &bgp_rpki_hook_write_vrf);
return 0;
}
static void sync_expired(struct event *thread)
{
- if (!rtr_mgr_conf_in_sync(rtr_config)) {
+ struct rpki_vrf *rpki_vrf = EVENT_ARG(thread);
+
+ if (!rtr_mgr_conf_in_sync(rpki_vrf->rtr_config)) {
RPKI_DEBUG("rtr_mgr is not synced, retrying.");
- event_add_timer(bm->master, sync_expired, NULL,
+ event_add_timer(bm->master, sync_expired, rpki_vrf,
BGP_RPKI_CACHE_SERVER_SYNC_RETRY_TIMEOUT,
- &t_rpki_sync);
+ &rpki_vrf->t_rpki_sync);
return;
}
RPKI_DEBUG("rtr_mgr sync is done.");
- rtr_is_synced = true;
+ rpki_vrf->rtr_is_synced = true;
}
-static int start(void)
+static int start(struct rpki_vrf *rpki_vrf)
{
+ struct list *cache_list = NULL;
+ struct vrf *vrf;
int ret;
- rtr_is_stopping = false;
- rtr_is_synced = false;
- rtr_update_overflow = 0;
+ rpki_vrf->rtr_is_stopping = false;
+ rpki_vrf->rtr_is_synced = false;
+ rpki_vrf->rtr_update_overflow = 0;
+ cache_list = rpki_vrf->cache_list;
+ rpki_vrf->rtr_update_overflow = 0;
- if (list_isempty(cache_list)) {
+ if (!cache_list || list_isempty(cache_list)) {
RPKI_DEBUG(
"No caches were found in config. Prefix validation is off.");
return ERROR;
}
- RPKI_DEBUG("Init rtr_mgr.");
+
+ if (rpki_vrf->vrfname)
+ vrf = vrf_lookup_by_name(rpki_vrf->vrfname);
+ else
+ vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ if (!vrf || !CHECK_FLAG(vrf->status, VRF_ACTIVE)) {
+ RPKI_DEBUG("VRF %s not present or disabled", rpki_vrf->vrfname);
+ return ERROR;
+ }
+
+ RPKI_DEBUG("Init rtr_mgr (%s).", vrf->name);
int groups_len = listcount(cache_list);
- struct rtr_mgr_group *groups = get_groups();
+ struct rtr_mgr_group *groups = get_groups(rpki_vrf->cache_list);
- RPKI_DEBUG("Polling period: %d", polling_period);
- ret = rtr_mgr_init(&rtr_config, groups, groups_len, polling_period,
- expire_interval, retry_interval,
- rpki_update_cb_sync_rtr, NULL, NULL, NULL);
+ RPKI_DEBUG("Polling period: %d", rpki_vrf->polling_period);
+ ret = rtr_mgr_init(&rpki_vrf->rtr_config, groups, groups_len,
+ rpki_vrf->polling_period, rpki_vrf->expire_interval,
+ rpki_vrf->retry_interval, rpki_update_cb_sync_rtr,
+ NULL, NULL, NULL);
if (ret == RTR_ERROR) {
- RPKI_DEBUG("Init rtr_mgr failed.");
+ RPKI_DEBUG("Init rtr_mgr failed (%s).", vrf->name);
return ERROR;
}
- RPKI_DEBUG("Starting rtr_mgr.");
- ret = rtr_mgr_start(rtr_config);
+ RPKI_DEBUG("Starting rtr_mgr (%s).", vrf->name);
+ ret = rtr_mgr_start(rpki_vrf->rtr_config);
if (ret == RTR_ERROR) {
- RPKI_DEBUG("Starting rtr_mgr failed.");
- rtr_mgr_free(rtr_config);
+ RPKI_DEBUG("Starting rtr_mgr failed (%s).", vrf->name);
+ rtr_mgr_free(rpki_vrf->rtr_config);
return ERROR;
}
- event_add_timer(bm->master, sync_expired, NULL, 0, &t_rpki_sync);
+ event_add_timer(bm->master, sync_expired, rpki_vrf, 0,
+ &rpki_vrf->t_rpki_sync);
XFREE(MTYPE_BGP_RPKI_CACHE_GROUP, groups);
- rtr_is_running = true;
+ rpki_vrf->rtr_is_running = true;
return SUCCESS;
}
-static void stop(void)
+static void stop(struct rpki_vrf *rpki_vrf)
{
- rtr_is_stopping = true;
- if (is_running()) {
- EVENT_OFF(t_rpki_sync);
- rtr_mgr_stop(rtr_config);
- rtr_mgr_free(rtr_config);
- rtr_is_running = false;
+ rpki_vrf->rtr_is_stopping = true;
+ if (is_running(rpki_vrf)) {
+ EVENT_OFF(rpki_vrf->t_rpki_sync);
+ rtr_mgr_stop(rpki_vrf->rtr_config);
+ rtr_mgr_free(rpki_vrf->rtr_config);
+ rpki_vrf->rtr_is_running = false;
}
}
-static int reset(bool force)
+static int reset(bool force, struct rpki_vrf *rpki_vrf)
{
- if (is_running() && !force)
+ if (is_running(rpki_vrf) && !force)
return SUCCESS;
RPKI_DEBUG("Resetting RPKI Session");
- stop();
- return start();
+ stop(rpki_vrf);
+ return start(rpki_vrf);
}
-static struct rtr_mgr_group *get_connected_group(void)
+static struct rtr_mgr_group *get_connected_group(struct rpki_vrf *rpki_vrf)
{
+ struct list *cache_list;
+
+ if (!rpki_vrf)
+ return NULL;
+
+ cache_list = rpki_vrf->cache_list;
if (!cache_list || list_isempty(cache_list))
return NULL;
- return rtr_mgr_get_first_group(rtr_config);
+ return rtr_mgr_get_first_group(rpki_vrf->rtr_config);
}
static void print_prefix_table_by_asn(struct vty *vty, as_t as,
+ struct rpki_vrf *rpki_vrf,
json_object *json)
{
unsigned int number_of_ipv4_prefixes = 0;
unsigned int number_of_ipv6_prefixes = 0;
- struct rtr_mgr_group *group = get_connected_group();
+ struct rtr_mgr_group *group = get_connected_group(rpki_vrf);
struct rpki_for_each_record_arg arg;
json_object *json_records = NULL;
@@ -732,8 +1029,14 @@ static void print_prefix_table_by_asn(struct vty *vty, as_t as,
arg.json = NULL;
arg.asnotation = bgp_get_asnotation(bgp_lookup_by_vrf_id(VRF_DEFAULT));
+ if (!rpki_vrf)
+ return;
+
if (!group) {
- if (!json)
+ if (json) {
+ json_object_string_add(json, "error", "Cannot find a connected group.");
+ vty_json(vty, json);
+ } else
vty_out(vty, "Cannot find a connected group.\n");
return;
}
@@ -772,42 +1075,58 @@ static void print_prefix_table_by_asn(struct vty *vty, as_t as,
vty_json(vty, json);
}
-static void print_prefix_table(struct vty *vty, json_object *json)
+static void print_prefix_table(struct vty *vty, struct rpki_vrf *rpki_vrf,
+ json_object *json, bool count_only)
{
struct rpki_for_each_record_arg arg;
unsigned int number_of_ipv4_prefixes = 0;
unsigned int number_of_ipv6_prefixes = 0;
- struct rtr_mgr_group *group = get_connected_group();
+ struct rtr_mgr_group *group = get_connected_group(rpki_vrf);
json_object *json_records = NULL;
+ if (!rpki_vrf)
+ return;
+
+ group = get_connected_group(rpki_vrf);
arg.vty = vty;
arg.json = NULL;
arg.asnotation = bgp_get_asnotation(bgp_lookup_by_vrf_id(VRF_DEFAULT));
if (!group) {
- if (!json)
+ if (json) {
+ json_object_string_add(json, "error", "Cannot find a connected group.");
+ vty_json(vty, json);
+ } else
vty_out(vty, "Cannot find a connected group.\n");
return;
}
struct pfx_table *pfx_table = group->sockets[0]->pfx_table;
- if (!json) {
- vty_out(vty, "RPKI/RTR prefix table\n");
- vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length",
- "Origin-AS");
- } else {
- json_records = json_object_new_array();
- json_object_object_add(json, "prefixes", json_records);
- arg.json = json_records;
+ if (!count_only) {
+ if (!json) {
+ vty_out(vty, "RPKI/RTR prefix table\n");
+ vty_out(vty, "%-40s %s %s\n", "Prefix",
+ "Prefix Length", "Origin-AS");
+ } else {
+ json_records = json_object_new_array();
+ json_object_object_add(json, "prefixes", json_records);
+ arg.json = json_records;
+ }
}
arg.prefix_amount = &number_of_ipv4_prefixes;
- pfx_table_for_each_ipv4_record(pfx_table, print_record_cb, &arg);
+ if (count_only)
+ pfx_table_for_each_ipv4_record(pfx_table, count_record_cb, &arg);
+ else
+ pfx_table_for_each_ipv4_record(pfx_table, print_record_cb, &arg);
arg.prefix_amount = &number_of_ipv6_prefixes;
- pfx_table_for_each_ipv6_record(pfx_table, print_record_cb, &arg);
+ if (count_only)
+ pfx_table_for_each_ipv6_record(pfx_table, count_record_cb, &arg);
+ else
+ pfx_table_for_each_ipv6_record(pfx_table, print_record_cb, &arg);
if (!json) {
vty_out(vty, "Number of IPv4 Prefixes: %u\n",
@@ -832,8 +1151,25 @@ static int rpki_validate_prefix(struct peer *peer, struct attr *attr,
as_t as_number = 0;
struct lrtr_ip_addr ip_addr_prefix;
enum pfxv_state result;
+ struct bgp *bgp = peer->bgp;
+ struct vrf *vrf;
+ struct rpki_vrf *rpki_vrf;
+
+ if (!bgp)
+ return 0;
+
+ vrf = vrf_lookup_by_id(bgp->vrf_id);
+ if (!vrf)
+ return 0;
+
+ if (vrf->vrf_id == VRF_DEFAULT)
+ rpki_vrf = find_rpki_vrf(NULL);
+ else
+ rpki_vrf = find_rpki_vrf(vrf->name);
+ if (!rpki_vrf || !is_synchronized(rpki_vrf))
+ return 0;
- if (!is_synchronized())
+ if (!is_synchronized(rpki_vrf))
return RPKI_NOT_BEING_USED;
// No aspath means route comes from iBGP
@@ -878,7 +1214,7 @@ static int rpki_validate_prefix(struct peer *peer, struct attr *attr,
}
// Do the actual validation
- rtr_mgr_validate(rtr_config, as_number, &ip_addr_prefix,
+ rtr_mgr_validate(rpki_vrf->rtr_config, as_number, &ip_addr_prefix,
prefix->prefixlen, &result);
// Print Debug output
@@ -911,15 +1247,26 @@ static int add_cache(struct cache *cache)
{
uint8_t preference = cache->preference;
struct rtr_mgr_group group;
+ struct list *cache_list;
+ struct rpki_vrf *rpki_vrf;
+
+ rpki_vrf = cache->rpki_vrf;
+ if (!rpki_vrf)
+ return ERROR;
group.preference = preference;
group.sockets_len = 1;
group.sockets = &cache->rtr_socket;
- if (is_running()) {
+ cache_list = rpki_vrf->cache_list;
+ if (!cache_list)
+ return ERROR;
+
+ if (is_running(rpki_vrf)) {
init_tr_socket(cache);
- if (rtr_mgr_add_group(rtr_config, &group) != RTR_SUCCESS) {
+ if (rtr_mgr_add_group(rpki_vrf->rtr_config, &group) !=
+ RTR_SUCCESS) {
free_tr_socket(cache);
return ERROR;
}
@@ -930,8 +1277,165 @@ static int add_cache(struct cache *cache)
return SUCCESS;
}
-static int add_tcp_cache(const char *host, const char *port,
- const uint8_t preference, const char *bindaddr)
+static int rpki_create_socket(void *_cache)
+{
+ struct timeval prev_snd_tmout, prev_rcv_tmout, timeout;
+ struct cache *cache = (struct cache *)_cache;
+ struct rpki_vrf *rpki_vrf;
+ struct tr_tcp_config *tcp_config;
+ struct addrinfo *res = NULL;
+ struct addrinfo hints = {};
+ socklen_t optlen;
+ char *host, *port;
+ struct vrf *vrf;
+ int cancel_state;
+ int socket;
+ int ret;
+#if defined(FOUND_SSH)
+ struct tr_ssh_config *ssh_config;
+ char s_port[10];
+#endif
+
+ if (!cache)
+ return -1;
+
+ rpki_vrf = cache->rpki_vrf;
+
+ /*
+ * the rpki infrastructure can call this function
+ * multiple times per pthread. Why? I have absolutely
+ * no idea, and I am not sure I care a whole bunch.
+ * Why does this matter? Well when we attempt to
+ * hook this pthread into the rcu structure multiple
+ * times the rcu code asserts on shutdown. Clearly
+ * upset that you have rcu data associated with a pthread
+ * that has not been cleaned up. And frankly this is rightly so.
+ *
+ * At this point we know that this function is not
+ * called a million bajillion times so let's just
+ * add a bit of insurance by looking to see if
+ * some thread specific code has been set for this
+ * pthread. If not, hook into the rcu code and
+ * make things happy.
+ *
+ * IF YOU PUT A ZLOG_XXXX prior to the call into
+ * frr_pthread_non_controlled_startup in this function
+ * BGP WILL CRASH. You have been warned.
+ */
+ if (!pthread_getspecific(rpki_pthread) &&
+ frr_pthread_non_controlled_startup(cache->rtr_socket->thread_id,
+ "RPKI RTRLIB socket",
+ "rpki_create_socket") < 0)
+ return -1;
+
+ pthread_setspecific(rpki_pthread, &rpki_pthread);
+
+ if (rpki_vrf->vrfname == NULL)
+ vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ else
+ vrf = vrf_lookup_by_name(rpki_vrf->vrfname);
+ if (!vrf)
+ return -1;
+
+ if (!CHECK_FLAG(vrf->status, VRF_ACTIVE) || vrf->vrf_id == VRF_UNKNOWN)
+ return -1;
+
+ if (cache->type == TCP) {
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_ADDRCONFIG;
+
+ tcp_config = cache->tr_config.tcp_config;
+ host = tcp_config->host;
+ port = tcp_config->port;
+ }
+#if defined(FOUND_SSH)
+ else {
+ ssh_config = cache->tr_config.ssh_config;
+ host = ssh_config->host;
+ snprintf(s_port, sizeof(s_port), "%u", ssh_config->port);
+ port = s_port;
+
+ hints.ai_flags |= AI_NUMERICHOST;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ }
+#endif
+
+ frr_with_privs (&bgpd_privs) {
+ ret = vrf_getaddrinfo(host, port, &hints, &res, vrf->vrf_id);
+ }
+ if (ret != 0) {
+ flog_err_sys(EC_LIB_SOCKET, "getaddrinfo: %s",
+ gai_strerror(ret));
+ return -1;
+ }
+
+ frr_with_privs (&bgpd_privs) {
+ socket = vrf_socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol, vrf->vrf_id, NULL);
+ }
+ if (socket < 0) {
+ freeaddrinfo(res);
+ return -1;
+ }
+
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &cancel_state);
+ timeout.tv_sec = 30;
+ timeout.tv_usec = 0;
+
+ optlen = sizeof(prev_rcv_tmout);
+ ret = getsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &prev_rcv_tmout,
+ &optlen);
+ if (ret < 0)
+ zlog_warn("%s: failed to getsockopt SO_RCVTIMEO for socket %d",
+ __func__, socket);
+ ret = getsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &prev_snd_tmout,
+ &optlen);
+ if (ret < 0)
+ zlog_warn("%s: failed to getsockopt SO_SNDTIMEO for socket %d",
+ __func__, socket);
+ ret = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &timeout,
+ sizeof(timeout));
+ if (ret < 0)
+ zlog_warn("%s: failed to setsockopt SO_RCVTIMEO for socket %d",
+ __func__, socket);
+
+ ret = setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &timeout,
+ sizeof(timeout));
+ if (ret < 0)
+ zlog_warn("%s: failed to setsockopt SO_SNDTIMEO for socket %d",
+ __func__, socket);
+
+ if (connect(socket, res->ai_addr, res->ai_addrlen) == -1) {
+ freeaddrinfo(res);
+ close(socket);
+ pthread_setcancelstate(cancel_state, NULL);
+ return -1;
+ }
+
+ freeaddrinfo(res);
+ pthread_setcancelstate(cancel_state, NULL);
+
+ ret = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &prev_rcv_tmout,
+ sizeof(prev_rcv_tmout));
+ if (ret < 0)
+ zlog_warn("%s: failed to setsockopt SO_RCVTIMEO for socket %d",
+ __func__, socket);
+
+ ret = setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &prev_snd_tmout,
+ sizeof(prev_snd_tmout));
+ if (ret < 0)
+ zlog_warn("%s: failed to setsockopt SO_SNDTIMEO for socket %d",
+ __func__, socket);
+
+ return socket;
+}
+
+static int add_tcp_cache(struct rpki_vrf *rpki_vrf, const char *host,
+ const char *port, const uint8_t preference,
+ const char *bindaddr)
{
struct rtr_socket *rtr_socket;
struct tr_tcp_config *tcp_config =
@@ -948,8 +1452,11 @@ static int add_tcp_cache(const char *host, const char *port,
else
tcp_config->bindaddr = NULL;
+ tcp_config->data = cache;
+ tcp_config->new_socket = rpki_create_socket;
rtr_socket = create_rtr_socket(tr_socket);
+ cache->rpki_vrf = rpki_vrf;
cache->type = TCP;
cache->tr_socket = tr_socket;
cache->tr_config.tcp_config = tcp_config;
@@ -958,15 +1465,16 @@ static int add_tcp_cache(const char *host, const char *port,
int ret = add_cache(cache);
if (ret != SUCCESS) {
+ tcp_config->data = NULL;
free_cache(cache);
}
-
return ret;
}
#if defined(FOUND_SSH)
-static int add_ssh_cache(const char *host, const unsigned int port,
- const char *username, const char *client_privkey_path,
+static int add_ssh_cache(struct rpki_vrf *rpki_vrf, const char *host,
+ const unsigned int port, const char *username,
+ const char *client_privkey_path,
const char *server_pubkey_path,
const uint8_t preference, const char *bindaddr)
{
@@ -984,6 +1492,8 @@ static int add_ssh_cache(const char *host, const unsigned int port,
ssh_config->bindaddr = XSTRDUP(MTYPE_BGP_RPKI_CACHE, bindaddr);
else
ssh_config->bindaddr = NULL;
+ ssh_config->data = cache;
+ ssh_config->new_socket = rpki_create_socket;
ssh_config->username = XSTRDUP(MTYPE_BGP_RPKI_CACHE, username);
ssh_config->client_privkey_path =
@@ -993,6 +1503,7 @@ static int add_ssh_cache(const char *host, const unsigned int port,
rtr_socket = create_rtr_socket(tr_socket);
+ cache->rpki_vrf = rpki_vrf;
cache->type = SSH;
cache->tr_socket = tr_socket;
cache->tr_config.ssh_config = ssh_config;
@@ -1001,6 +1512,7 @@ static int add_ssh_cache(const char *host, const unsigned int port,
int ret = add_cache(cache);
if (ret != SUCCESS) {
+ ssh_config->data = NULL;
free_cache(cache);
}
@@ -1036,25 +1548,72 @@ static void free_cache(struct cache *cache)
XFREE(MTYPE_BGP_RPKI_CACHE, cache);
}
-static int config_write(struct vty *vty)
+static int bgp_rpki_write_debug(struct vty *vty, bool running)
{
- struct listnode *cache_node;
- struct cache *cache;
-
- if (rpki_debug)
+ if (rpki_debug_conf && running) {
vty_out(vty, "debug rpki\n");
+ return 1;
+ }
+ if ((rpki_debug_conf || rpki_debug_term) && !running) {
+ vty_out(vty, " BGP RPKI debugging is on\n");
+ return 1;
+ }
+ return 0;
+}
- vty_out(vty, "!\n");
- vty_out(vty, "rpki\n");
+static int bgp_rpki_hook_write_vrf(struct vty *vty, struct vrf *vrf)
+{
+ int ret;
- if (polling_period != POLLING_PERIOD_DEFAULT)
- vty_out(vty, " rpki polling_period %d\n", polling_period);
- if (retry_interval != RETRY_INTERVAL_DEFAULT)
- vty_out(vty, " rpki retry_interval %d\n", retry_interval);
- if (expire_interval != EXPIRE_INTERVAL_DEFAULT)
- vty_out(vty, " rpki expire_interval %d\n", expire_interval);
+ ret = bgp_rpki_write_vrf(vty, vrf);
+ if (ret == ERROR)
+ return 0;
+ return ret;
+}
- for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
+static int bgp_rpki_write_vrf(struct vty *vty, struct vrf *vrf)
+{
+ struct listnode *cache_node;
+ struct cache *cache;
+ struct rpki_vrf *rpki_vrf = NULL;
+ char sep[STR_SEPARATOR];
+ vrf_id_t vrf_id = VRF_DEFAULT;
+
+ if (!vrf) {
+ rpki_vrf = find_rpki_vrf(NULL);
+ snprintf(sep, sizeof(sep), "%s", "");
+ } else if (vrf->vrf_id != VRF_DEFAULT) {
+ rpki_vrf = find_rpki_vrf(vrf->name);
+ snprintf(sep, sizeof(sep), "%s", " ");
+ vrf_id = vrf->vrf_id;
+ } else
+ return ERROR;
+
+ if (!rpki_vrf)
+ return ERROR;
+
+ if (rpki_vrf->cache_list && list_isempty(rpki_vrf->cache_list) &&
+ rpki_vrf->polling_period == POLLING_PERIOD_DEFAULT &&
+ rpki_vrf->retry_interval == RETRY_INTERVAL_DEFAULT &&
+ rpki_vrf->expire_interval == EXPIRE_INTERVAL_DEFAULT)
+ /* do not display the default config values */
+ return 0;
+
+ if (vrf_id == VRF_DEFAULT)
+ vty_out(vty, "%s!\n", sep);
+ vty_out(vty, "%srpki\n", sep);
+
+ if (rpki_vrf->polling_period != POLLING_PERIOD_DEFAULT)
+ vty_out(vty, "%s rpki polling_period %d\n", sep,
+ rpki_vrf->polling_period);
+ if (rpki_vrf->retry_interval != RETRY_INTERVAL_DEFAULT)
+ vty_out(vty, "%s rpki retry_interval %d\n", sep,
+ rpki_vrf->retry_interval);
+ if (rpki_vrf->expire_interval != EXPIRE_INTERVAL_DEFAULT)
+ vty_out(vty, "%s rpki expire_interval %d\n", sep,
+ rpki_vrf->expire_interval);
+
+ for (ALL_LIST_ELEMENTS_RO(rpki_vrf->cache_list, cache_node, cache)) {
switch (cache->type) {
struct tr_tcp_config *tcp_config;
#if defined(FOUND_SSH)
@@ -1062,8 +1621,8 @@ static int config_write(struct vty *vty)
#endif
case TCP:
tcp_config = cache->tr_config.tcp_config;
- vty_out(vty, " rpki cache %s %s ", tcp_config->host,
- tcp_config->port);
+ vty_out(vty, "%s rpki cache %s %s ", sep,
+ tcp_config->host, tcp_config->port);
if (tcp_config->bindaddr)
vty_out(vty, "source %s ",
tcp_config->bindaddr);
@@ -1071,13 +1630,13 @@ static int config_write(struct vty *vty)
#if defined(FOUND_SSH)
case SSH:
ssh_config = cache->tr_config.ssh_config;
- vty_out(vty, " rpki cache %s %u %s %s %s ",
+ vty_out(vty, "%s rpki cache %s %u %s %s %s ", sep,
ssh_config->host, ssh_config->port,
ssh_config->username,
ssh_config->client_privkey_path,
ssh_config->server_hostkey_path != NULL
? ssh_config->server_hostkey_path
- : " ");
+ : "");
if (ssh_config->bindaddr)
vty_out(vty, "source %s ",
ssh_config->bindaddr);
@@ -1089,17 +1648,66 @@ static int config_write(struct vty *vty)
vty_out(vty, "preference %hhu\n", cache->preference);
}
- vty_out(vty, "exit\n");
+
+ vty_out(vty, "%sexit\n%s", sep, vrf_id == VRF_DEFAULT ? "!\n" : "");
return 1;
}
+static int config_write(struct vty *vty)
+{
+ return bgp_rpki_write_vrf(vty, NULL);
+}
+
+static struct rpki_vrf *get_rpki_vrf(const char *vrfname)
+{
+ struct rpki_vrf *rpki_vrf = NULL;
+ struct vrf *vrf = NULL;
+
+ if (vrfname && !strmatch(vrfname, VRF_DEFAULT_NAME)) {
+ vrf = vrf_lookup_by_name(vrfname);
+ if (!vrf)
+ return NULL;
+ rpki_vrf = find_rpki_vrf(vrf->name);
+ } else
+ /* default VRF */
+ rpki_vrf = find_rpki_vrf(NULL);
+
+ return rpki_vrf;
+}
+
DEFUN_NOSH (rpki,
rpki_cmd,
"rpki",
"Enable rpki and enter rpki configuration mode\n")
{
- vty->node = RPKI_NODE;
+ struct rpki_vrf *rpki_vrf;
+ char *vrfname = NULL;
+ struct vrf *vrf;
+
+ if (vty->node == CONFIG_NODE)
+ vty->node = RPKI_NODE;
+ else {
+ vrf = VTY_GET_CONTEXT(vrf);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ vty->node = RPKI_VRF_NODE;
+ if (vrf->vrf_id != VRF_DEFAULT)
+ vrfname = vrf->name;
+ }
+
+ rpki_vrf = find_rpki_vrf(vrfname);
+ if (!rpki_vrf) {
+ rpki_vrf = bgp_rpki_allocate(vrfname);
+
+ rpki_init_sync_socket(rpki_vrf);
+ }
+ if (vty->node == RPKI_VRF_NODE)
+ VTY_PUSH_CONTEXT_SUB(vty->node, rpki_vrf);
+ else
+ VTY_PUSH_CONTEXT(vty->node, rpki_vrf);
return CMD_SUCCESS;
}
@@ -1109,23 +1717,49 @@ DEFPY (no_rpki,
NO_STR
"Enable rpki and enter rpki configuration mode\n")
{
- rpki_delete_all_cache_nodes();
- stop();
+ struct rpki_vrf *rpki_vrf;
+ char *vrfname = NULL;
+
+ if (vty->node == VRF_NODE) {
+ VTY_DECLVAR_CONTEXT(vrf, vrf);
+
+ if (vrf->vrf_id != VRF_DEFAULT)
+ vrfname = vrf->name;
+ }
+
+ rpki_vrf = find_rpki_vrf(vrfname);
+
+ rpki_delete_all_cache_nodes(rpki_vrf);
+ stop(rpki_vrf);
+ rpki_vrf->polling_period = POLLING_PERIOD_DEFAULT;
+ rpki_vrf->expire_interval = EXPIRE_INTERVAL_DEFAULT;
+ rpki_vrf->retry_interval = RETRY_INTERVAL_DEFAULT;
+
return CMD_SUCCESS;
}
-DEFUN (bgp_rpki_start,
+DEFPY (bgp_rpki_start,
bgp_rpki_start_cmd,
- "rpki start",
+ "rpki start [vrf NAME$vrfname]",
RPKI_OUTPUT_STRING
- "start rpki support\n")
+ "start rpki support\n"
+ VRF_CMD_HELP_STR)
{
- if (listcount(cache_list) == 0)
+ struct list *cache_list = NULL;
+ struct rpki_vrf *rpki_vrf;
+
+ rpki_vrf = get_rpki_vrf(vrfname);
+
+ if (!rpki_vrf)
+ return CMD_WARNING;
+
+ cache_list = rpki_vrf->cache_list;
+ if (!cache_list || listcount(cache_list) == 0)
vty_out(vty,
"Could not start rpki because no caches are configured\n");
- if (!is_running()) {
- if (start() == ERROR) {
+ if (!is_running(rpki_vrf)) {
+ if (start(rpki_vrf) == ERROR) {
RPKI_DEBUG("RPKI failed to start");
return CMD_WARNING;
}
@@ -1133,14 +1767,19 @@ DEFUN (bgp_rpki_start,
return CMD_SUCCESS;
}
-DEFUN (bgp_rpki_stop,
+DEFPY (bgp_rpki_stop,
bgp_rpki_stop_cmd,
- "rpki stop",
+ "rpki stop [vrf NAME$vrfname]",
RPKI_OUTPUT_STRING
- "start rpki support\n")
+ "start rpki support\n"
+ VRF_CMD_HELP_STR)
{
- if (is_running())
- stop();
+ struct rpki_vrf *rpki_vrf;
+
+ rpki_vrf = get_rpki_vrf(vrfname);
+
+ if (rpki_vrf && is_running(rpki_vrf))
+ stop(rpki_vrf);
return CMD_SUCCESS;
}
@@ -1152,7 +1791,17 @@ DEFPY (rpki_polling_period,
"Set polling period\n"
"Polling period value\n")
{
- polling_period = pp;
+ struct rpki_vrf *rpki_vrf;
+
+ 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;
+
+ rpki_vrf->polling_period = pp;
return CMD_SUCCESS;
}
@@ -1164,7 +1813,17 @@ DEFUN (no_rpki_polling_period,
"Set polling period back to default\n"
"Polling period value\n")
{
- polling_period = POLLING_PERIOD_DEFAULT;
+ struct rpki_vrf *rpki_vrf;
+
+ 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;
+
+ rpki_vrf->polling_period = POLLING_PERIOD_DEFAULT;
return CMD_SUCCESS;
}
@@ -1175,8 +1834,18 @@ DEFPY (rpki_expire_interval,
"Set expire interval\n"
"Expire interval value\n")
{
- if ((unsigned int)tmp >= polling_period) {
- expire_interval = tmp;
+ struct rpki_vrf *rpki_vrf;
+
+ 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 ((unsigned int)tmp >= rpki_vrf->polling_period) {
+ rpki_vrf->expire_interval = tmp;
return CMD_SUCCESS;
}
@@ -1192,7 +1861,17 @@ DEFUN (no_rpki_expire_interval,
"Set expire interval back to default\n"
"Expire interval value\n")
{
- expire_interval = polling_period * 2;
+ struct rpki_vrf *rpki_vrf;
+
+ 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;
+
+ rpki_vrf->expire_interval = rpki_vrf->polling_period * 2;
return CMD_SUCCESS;
}
@@ -1203,7 +1882,17 @@ DEFPY (rpki_retry_interval,
"Set retry interval\n"
"retry interval value\n")
{
- retry_interval = tmp;
+ struct rpki_vrf *rpki_vrf;
+
+ 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;
+
+ rpki_vrf->retry_interval = tmp;
return CMD_SUCCESS;
}
@@ -1215,7 +1904,17 @@ DEFUN (no_rpki_retry_interval,
"Set retry interval back to default\n"
"retry interval value\n")
{
- retry_interval = RETRY_INTERVAL_DEFAULT;
+ struct rpki_vrf *rpki_vrf;
+
+ 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;
+
+ rpki_vrf->retry_interval = RETRY_INTERVAL_DEFAULT;
return CMD_SUCCESS;
}
@@ -1238,8 +1937,24 @@ DEFPY(rpki_cache, rpki_cache_cmd,
int return_value;
struct listnode *cache_node;
struct cache *current_cache;
+ struct rpki_vrf *rpki_vrf;
+ bool init;
- for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, current_cache)) {
+ 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",
@@ -1248,21 +1963,20 @@ DEFPY(rpki_cache, rpki_cache_cmd,
}
}
-
// use ssh connection
if (ssh_uname) {
#if defined(FOUND_SSH)
- return_value =
- add_ssh_cache(cache, sshport, ssh_uname, ssh_privkey,
- server_pubkey, preference, bindaddr_str);
+ return_value = add_ssh_cache(rpki_vrf, cache, sshport, ssh_uname,
+ ssh_privkey, server_pubkey,
+ 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(cache, tcpport, preference, bindaddr_str);
+ return_value = add_tcp_cache(rpki_vrf, cache, tcpport,
+ preference, bindaddr_str);
}
if (return_value == ERROR) {
@@ -1270,6 +1984,9 @@ DEFPY(rpki_cache, rpki_cache_cmd,
return CMD_WARNING;
}
+ if (init)
+ start(rpki_vrf);
+
return CMD_SUCCESS;
}
@@ -1291,18 +2008,31 @@ DEFPY (no_rpki_cache,
"Preference of the cache server\n"
"Preference value\n")
{
- struct cache *cache_p = find_cache(preference);
+ struct cache *cache_p;
+ struct list *cache_list = NULL;
+ struct rpki_vrf *rpki_vrf;
+
+ if (vty->node == RPKI_VRF_NODE)
+ rpki_vrf = VTY_GET_CONTEXT_SUB(rpki_vrf);
+ else
+ rpki_vrf = VTY_GET_CONTEXT(rpki_vrf);
- if (!cache_p) {
+ if (!rpki_vrf)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ cache_list = rpki_vrf->cache_list;
+ cache_p = find_cache(preference, cache_list);
+ if (!rpki_vrf || !cache_p) {
vty_out(vty, "Could not find cache with preference %ld\n",
preference);
return CMD_WARNING;
}
- if (is_running() && listcount(cache_list) == 1) {
- stop();
- } else if (is_running()) {
- if (rtr_mgr_remove_group(rtr_config, preference) == RTR_ERROR) {
+ if (is_running(rpki_vrf) && listcount(cache_list) == 1) {
+ stop(rpki_vrf);
+ } else if (is_running(rpki_vrf)) {
+ if (rtr_mgr_remove_group(rpki_vrf->rtr_config, preference) ==
+ RTR_ERROR) {
vty_out(vty,
"Could not remove cache with preference %ld\n",
preference);
@@ -1318,68 +2048,107 @@ DEFPY (no_rpki_cache,
DEFPY (show_rpki_prefix_table,
show_rpki_prefix_table_cmd,
- "show rpki prefix-table [json$uj]",
+ "show rpki <prefix-table|prefix-count>$prefixkind [vrf NAME$vrfname] [json$uj]",
SHOW_STR
RPKI_OUTPUT_STRING
"Show validated prefixes which were received from RPKI Cache\n"
+ "Show prefixes count which were received from RPKI Cache\n"
+ VRF_CMD_HELP_STR
JSON_STR)
{
struct json_object *json = NULL;
+ struct rpki_vrf *rpki_vrf;
+
+ if (uj)
+ json = json_object_new_object();
+
+ rpki_vrf = get_rpki_vrf(vrfname);
+ if (!rpki_vrf) {
+ if (uj)
+ vty_json(vty, json);
+ return CMD_SUCCESS;
+ }
- if (!is_synchronized()) {
- if (!uj)
+ if (is_synchronized(rpki_vrf)) {
+ if (strmatch(prefixkind, "prefix-count"))
+ print_prefix_table(vty, rpki_vrf, json, true);
+ else
+ print_prefix_table(vty, rpki_vrf, json, false);
+ } else {
+ if (json) {
+ json_object_string_add(json, "error", "No Connection to RPKI cache server.");
+ vty_json(vty, json);
+ } else
vty_out(vty, "No connection to RPKI cache server.\n");
return CMD_WARNING;
}
- if (uj)
- json = json_object_new_object();
-
- print_prefix_table(vty, json);
return CMD_SUCCESS;
}
DEFPY (show_rpki_as_number,
show_rpki_as_number_cmd,
- "show rpki as-number ASNUM$by_asn [json$uj]",
+ "show rpki as-number ASNUM$by_asn [vrf NAME$vrfname] [json$uj]",
SHOW_STR
RPKI_OUTPUT_STRING
"Lookup by ASN in prefix table\n"
"AS Number\n"
+ VRF_CMD_HELP_STR
JSON_STR)
{
struct json_object *json = NULL;
+ struct rpki_vrf *rpki_vrf;
+
+ if (uj)
+ json = json_object_new_object();
+
+ rpki_vrf = get_rpki_vrf(vrfname);
+ if (!rpki_vrf) {
+ if (uj)
+ vty_json(vty, json);
+ return CMD_SUCCESS;
+ }
- if (!is_synchronized()) {
- if (!uj)
+ if (!is_synchronized(rpki_vrf)) {
+ if (json) {
+ json_object_string_add(json, "error", "No Connection to RPKI cache server.");
+ vty_json(vty, json);
+ } else
vty_out(vty, "No Connection to RPKI cache server.\n");
return CMD_WARNING;
}
- if (uj)
- json = json_object_new_object();
-
- print_prefix_table_by_asn(vty, by_asn, json);
+ print_prefix_table_by_asn(vty, by_asn, rpki_vrf, json);
return CMD_SUCCESS;
}
DEFPY (show_rpki_prefix,
show_rpki_prefix_cmd,
- "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [ASNUM$asn] [json$uj]",
+ "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [ASNUM$asn] [vrf NAME$vrfname] [json$uj]",
SHOW_STR
RPKI_OUTPUT_STRING
"Lookup IP prefix and optionally ASN in prefix table\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
"AS Number\n"
+ VRF_CMD_HELP_STR
JSON_STR)
{
json_object *json = NULL;
json_object *json_records = NULL;
enum asnotation_mode asnotation;
+ struct rpki_vrf *rpki_vrf;
- if (!is_synchronized()) {
- if (!uj)
+ if (uj)
+ json = json_object_new_object();
+
+ rpki_vrf = get_rpki_vrf(vrfname);
+
+ if (!rpki_vrf || !is_synchronized(rpki_vrf)) {
+ if (json) {
+ json_object_string_add(json, "error", "No Connection to RPKI cache server.");
+ vty_json(vty, json);
+ } else
vty_out(vty, "No Connection to RPKI cache server.\n");
return CMD_WARNING;
}
@@ -1392,7 +2161,10 @@ DEFPY (show_rpki_prefix,
memcpy(addr_str, prefix_str, addr_len);
if (lrtr_ip_str_to_addr(addr_str, &addr) != 0) {
- if (!json)
+ if (json) {
+ json_object_string_add(json, "error", "Invalid IP prefix.");
+ vty_json(vty, json);
+ } else
vty_out(vty, "Invalid IP prefix\n");
return CMD_WARNING;
}
@@ -1401,16 +2173,17 @@ DEFPY (show_rpki_prefix,
unsigned int match_count = 0;
enum pfxv_state result;
- if (pfx_table_validate_r(rtr_config->pfx_table, &matches, &match_count,
- asn, &addr, prefix->prefixlen,
+ if (pfx_table_validate_r(rpki_vrf->rtr_config->pfx_table, &matches,
+ &match_count, asn, &addr, prefix->prefixlen,
&result) != PFX_SUCCESS) {
- if (!json)
+ if (json) {
+ json_object_string_add(json, "error", "Prefix lookup failed.");
+ vty_json(vty, json);
+ } else
vty_out(vty, "Prefix lookup failed\n");
return CMD_WARNING;
}
- if (uj)
- json = json_object_new_object();
if (!json) {
vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length",
@@ -1439,10 +2212,11 @@ DEFPY (show_rpki_prefix,
DEFPY (show_rpki_cache_server,
show_rpki_cache_server_cmd,
- "show rpki cache-server [json$uj]",
+ "show rpki cache-server [vrf NAME$vrfname] [json$uj]",
SHOW_STR
RPKI_OUTPUT_STRING
"Show configured cache server\n"
+ VRF_CMD_HELP_STR
JSON_STR)
{
struct json_object *json = NULL;
@@ -1450,6 +2224,7 @@ DEFPY (show_rpki_cache_server,
struct json_object *json_servers = NULL;
struct listnode *cache_node;
struct cache *cache;
+ struct rpki_vrf *rpki_vrf;
if (uj) {
json = json_object_new_object();
@@ -1457,7 +2232,14 @@ DEFPY (show_rpki_cache_server,
json_object_object_add(json, "servers", json_servers);
}
- for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
+ rpki_vrf = get_rpki_vrf(vrfname);
+ if (!rpki_vrf) {
+ if (json)
+ vty_json(vty, json);
+ return CMD_SUCCESS;
+ }
+
+ for (ALL_LIST_ELEMENTS_RO(rpki_vrf->cache_list, cache_node, cache)) {
if (cache->type == TCP) {
if (!json) {
vty_out(vty,
@@ -1532,10 +2314,11 @@ DEFPY (show_rpki_cache_server,
DEFPY (show_rpki_cache_connection,
show_rpki_cache_connection_cmd,
- "show rpki cache-connection [json$uj]",
+ "show rpki cache-connection [vrf NAME$vrfname] [json$uj]",
SHOW_STR
RPKI_OUTPUT_STRING
"Show to which RPKI Cache Servers we have a connection\n"
+ VRF_CMD_HELP_STR
JSON_STR)
{
struct json_object *json = NULL;
@@ -1544,25 +2327,35 @@ DEFPY (show_rpki_cache_connection,
struct listnode *cache_node;
struct cache *cache;
struct rtr_mgr_group *group;
+ struct rpki_vrf *rpki_vrf;
if (uj)
json = json_object_new_object();
- if (!is_synchronized()) {
- if (!json)
- vty_out(vty, "No connection to RPKI cache server.\n");
- else
+ rpki_vrf = get_rpki_vrf(vrfname);
+ if (!rpki_vrf) {
+ if (json)
vty_json(vty, json);
+ return CMD_SUCCESS;
+ }
+
+ if (!is_synchronized(rpki_vrf)) {
+ if (json) {
+ json_object_string_add(json, "error", "No connection to RPKI cache server.");
+ vty_json(vty, json);
+ } else
+ vty_out(vty, "No connection to RPKI cache server.\n");
return CMD_SUCCESS;
}
- group = get_connected_group();
+ group = get_connected_group(rpki_vrf);
if (!group) {
- if (!json)
- vty_out(vty, "Cannot find a connected group.\n");
- else
+ if (json) {
+ json_object_string_add(json, "error", "Cannot find a connected group.");
vty_json(vty, json);
+ } else
+ vty_out(vty, "Cannot find a connected group.\n");
return CMD_SUCCESS;
}
@@ -1575,7 +2368,7 @@ DEFPY (show_rpki_cache_connection,
json_object_object_add(json, "connections", json_conns);
}
- for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
+ for (ALL_LIST_ELEMENTS_RO(rpki_vrf->cache_list, cache_node, cache)) {
struct tr_tcp_config *tcp_config;
#if defined(FOUND_SSH)
struct tr_ssh_config *ssh_config;
@@ -1656,19 +2449,110 @@ DEFPY (show_rpki_cache_connection,
return CMD_SUCCESS;
}
+DEFPY(show_rpki_configuration, show_rpki_configuration_cmd,
+ "show rpki configuration [vrf NAME$vrfname] [json$uj]",
+ SHOW_STR RPKI_OUTPUT_STRING
+ "Show RPKI configuration\n"
+ VRF_CMD_HELP_STR
+ JSON_STR)
+{
+ struct json_object *json = NULL;
+ struct rpki_vrf *rpki_vrf;
+
+ if (uj)
+ json = json_object_new_object();
+
+ rpki_vrf = find_rpki_vrf(vrfname);
+ if (!rpki_vrf) {
+ if (uj)
+ vty_json(vty, json);
+ return CMD_SUCCESS;
+ }
+
+ if (uj) {
+ json_object_boolean_add(json, "enabled",
+ !!listcount(rpki_vrf->cache_list));
+ json_object_int_add(json, "serversCount",
+ listcount(rpki_vrf->cache_list));
+ json_object_int_add(json, "pollingPeriodSeconds",
+ rpki_vrf->polling_period);
+ json_object_int_add(json, "retryIntervalSeconds",
+ rpki_vrf->retry_interval);
+ json_object_int_add(json, "expireIntervalSeconds",
+ rpki_vrf->expire_interval);
+
+ vty_json(vty, json);
+
+ return CMD_SUCCESS;
+ }
+
+ vty_out(vty, "rpki is %s",
+ listcount(rpki_vrf->cache_list) ? "Enabled" : "Disabled");
+
+ if (list_isempty(rpki_vrf->cache_list)) {
+ vty_out(vty, "\n");
+ return CMD_SUCCESS;
+ }
+
+ vty_out(vty, " (%d cache servers configured)",
+ listcount(rpki_vrf->cache_list));
+ vty_out(vty, "\n");
+ vty_out(vty, "\tpolling period %d\n", rpki_vrf->polling_period);
+ vty_out(vty, "\tretry interval %d\n", rpki_vrf->retry_interval);
+ vty_out(vty, "\texpire interval %d\n", rpki_vrf->expire_interval);
+
+ return CMD_SUCCESS;
+}
+
static int config_on_exit(struct vty *vty)
{
- reset(false);
+ struct rpki_vrf *rpki_vrf;
+
+ 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;
+
+ reset(false, rpki_vrf);
return 1;
}
-DEFUN (rpki_reset,
+DEFPY(rpki_reset,
rpki_reset_cmd,
+ "rpki reset [vrf NAME$vrfname]",
+ RPKI_OUTPUT_STRING
+ "reset rpki\n"
+ VRF_CMD_HELP_STR)
+{
+ struct rpki_vrf *rpki_vrf;
+
+ rpki_vrf = find_rpki_vrf(vrfname);
+ if (!rpki_vrf)
+ return CMD_WARNING;
+
+ return reset(true, rpki_vrf) == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
+}
+
+DEFPY (rpki_reset_config_mode,
+ rpki_reset_config_mode_cmd,
"rpki reset",
RPKI_OUTPUT_STRING
"reset rpki\n")
{
- return reset(true) == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
+ struct rpki_vrf *rpki_vrf;
+
+ 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;
+
+ return reset(true, rpki_vrf) == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
}
DEFUN (debug_rpki,
@@ -1677,7 +2561,10 @@ DEFUN (debug_rpki,
DEBUG_STR
"Enable debugging for rpki\n")
{
- rpki_debug = true;
+ if (vty->node == CONFIG_NODE)
+ rpki_debug_conf = true;
+ else
+ rpki_debug_term = true;
return CMD_SUCCESS;
}
@@ -1688,7 +2575,10 @@ DEFUN (no_debug_rpki,
DEBUG_STR
"Disable debugging for rpki\n")
{
- rpki_debug = false;
+ if (vty->node == CONFIG_NODE)
+ rpki_debug_conf = false;
+ else
+ rpki_debug_term = false;
return CMD_SUCCESS;
}
@@ -1735,8 +2625,9 @@ static void install_cli_commands(void)
// TODO: make config write work
install_node(&rpki_node);
install_default(RPKI_NODE);
+ install_node(&rpki_vrf_node);
+ install_default(RPKI_VRF_NODE);
install_element(CONFIG_NODE, &rpki_cmd);
- install_element(ENABLE_NODE, &rpki_cmd);
install_element(CONFIG_NODE, &no_rpki_cmd);
@@ -1745,7 +2636,7 @@ static void install_cli_commands(void)
/* Install rpki reset command */
install_element(ENABLE_NODE, &rpki_reset_cmd);
- install_element(RPKI_NODE, &rpki_reset_cmd);
+ install_element(RPKI_NODE, &rpki_reset_config_mode_cmd);
/* Install rpki polling period commands */
install_element(RPKI_NODE, &rpki_polling_period_cmd);
@@ -1763,12 +2654,35 @@ static void install_cli_commands(void)
install_element(RPKI_NODE, &rpki_cache_cmd);
install_element(RPKI_NODE, &no_rpki_cache_cmd);
+ /* RPKI_VRF_NODE commands */
+ install_element(VRF_NODE, &rpki_cmd);
+ install_element(VRF_NODE, &no_rpki_cmd);
+ /* Install rpki reset command */
+ install_element(RPKI_VRF_NODE, &rpki_reset_config_mode_cmd);
+
+ /* Install rpki polling period commands */
+ install_element(RPKI_VRF_NODE, &rpki_polling_period_cmd);
+ install_element(RPKI_VRF_NODE, &no_rpki_polling_period_cmd);
+
+ /* Install rpki expire interval commands */
+ install_element(RPKI_VRF_NODE, &rpki_expire_interval_cmd);
+ install_element(RPKI_VRF_NODE, &no_rpki_expire_interval_cmd);
+
+ /* Install rpki retry interval commands */
+ install_element(RPKI_VRF_NODE, &rpki_retry_interval_cmd);
+ install_element(RPKI_VRF_NODE, &no_rpki_retry_interval_cmd);
+
+ /* Install rpki cache commands */
+ install_element(RPKI_VRF_NODE, &rpki_cache_cmd);
+ install_element(RPKI_VRF_NODE, &no_rpki_cache_cmd);
+
/* Install show commands */
install_element(VIEW_NODE, &show_rpki_prefix_table_cmd);
install_element(VIEW_NODE, &show_rpki_cache_connection_cmd);
install_element(VIEW_NODE, &show_rpki_cache_server_cmd);
install_element(VIEW_NODE, &show_rpki_prefix_cmd);
install_element(VIEW_NODE, &show_rpki_as_number_cmd);
+ install_element(VIEW_NODE, &show_rpki_configuration_cmd);
/* Install debug commands */
install_element(CONFIG_NODE, &debug_rpki_cmd);
diff --git a/bgpd/bgp_rpki.h b/bgpd/bgp_rpki.h
index de28715..4f2f87d 100644
--- a/bgpd/bgp_rpki.h
+++ b/bgpd/bgp_rpki.h
@@ -8,6 +8,8 @@
#ifndef __BGP_RPKI_H__
#define __BGP_RPKI_H__
+extern struct zebra_privs_t bgpd_privs;
+
enum rpki_states {
RPKI_NOT_BEING_USED,
RPKI_VALID,
diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c
index ce9442c..065ea76 100644
--- a/bgpd/bgp_snmp.c
+++ b/bgpd/bgp_snmp.c
@@ -29,10 +29,93 @@
#include "bgpd/bgp_snmp_bgp4.h"
#include "bgpd/bgp_snmp_bgp4v2.h"
#include "bgpd/bgp_mplsvpn_snmp.h"
+#include "bgpd/bgp_snmp_clippy.c"
+
+
+
+static int bgp_cli_snmp_traps_config_write(struct vty *vty);
+
+DEFPY(bgp_snmp_traps_rfc4273, bgp_snmp_traps_rfc4273_cmd,
+ "[no$no] bgp snmp traps rfc4273",
+ NO_STR BGP_STR
+ "Configure BGP SNMP\n"
+ "Configure SNMP traps for BGP\n"
+ "Configure use of rfc4273 SNMP traps for BGP\n")
+{
+ if (no) {
+ UNSET_FLAG(bm->options, BGP_OPT_TRAPS_RFC4273);
+ return CMD_SUCCESS;
+ }
+ SET_FLAG(bm->options, BGP_OPT_TRAPS_RFC4273);
+ 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
+ "Configure BGP SNMP\n"
+ "Configure SNMP traps for BGP\n"
+ "Configure use of BGP4-MIBv2 SNMP traps for BGP\n")
+{
+ if (no) {
+ UNSET_FLAG(bm->options, BGP_OPT_TRAPS_BGP4MIBV2);
+ return CMD_SUCCESS;
+ }
+ SET_FLAG(bm->options, BGP_OPT_TRAPS_BGP4MIBV2);
+ return CMD_SUCCESS;
+}
+
+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);
+
+ SET_FLAG(bm->options, BGP_OPT_TRAPS_RFC4273);
+ /* BGP4MIBv2 traps are disabled by default */
+}
+
+int bgp_cli_snmp_traps_config_write(struct vty *vty)
+{
+ int write = 0;
+
+ if (!CHECK_FLAG(bm->options, BGP_OPT_TRAPS_RFC4273)) {
+ vty_out(vty, "no bgp snmp traps rfc4273\n");
+ write++;
+ }
+ if (CHECK_FLAG(bm->options, BGP_OPT_TRAPS_BGP4MIBV2)) {
+ vty_out(vty, "bgp snmp traps bgp4-mibv2\n");
+ write++;
+ }
+
+ return write;
+}
+
+int bgpTrapEstablished(struct peer *peer)
+{
+ if (CHECK_FLAG(bm->options, BGP_OPT_TRAPS_RFC4273))
+ bgp4TrapEstablished(peer);
+
+ if (CHECK_FLAG(bm->options, BGP_OPT_TRAPS_BGP4MIBV2))
+ bgpv2TrapEstablished(peer);
+
+ return 0;
+}
+
+int bgpTrapBackwardTransition(struct peer *peer)
+{
+ if (CHECK_FLAG(bm->options, BGP_OPT_TRAPS_RFC4273))
+ bgp4TrapBackwardTransition(peer);
+
+ if (CHECK_FLAG(bm->options, BGP_OPT_TRAPS_BGP4MIBV2))
+ bgpv2TrapBackwardTransition(peer);
+
+ return 0;
+}
static int bgp_snmp_init(struct event_loop *tm)
{
smux_init(tm);
+ bgp_snmp_traps_init();
bgp_snmp_bgp4_init(tm);
bgp_snmp_bgp4v2_init(tm);
bgp_mpls_l3vpn_module_init();
@@ -44,6 +127,8 @@ static int bgp_snmp_module_init(void)
hook_register(peer_status_changed, bgpTrapEstablished);
hook_register(peer_backward_transition, bgpTrapBackwardTransition);
hook_register(frr_late_init, bgp_snmp_init);
+ hook_register(bgp_snmp_traps_config_write,
+ bgp_cli_snmp_traps_config_write);
return 0;
}
diff --git a/bgpd/bgp_snmp.h b/bgpd/bgp_snmp.h
index d324782..12ec652 100644
--- a/bgpd/bgp_snmp.h
+++ b/bgpd/bgp_snmp.h
@@ -15,4 +15,7 @@
#define IPADDRESS ASN_IPADDRESS
#define GAUGE32 ASN_UNSIGNED
+extern int bgpTrapEstablished(struct peer *peer);
+extern int bgpTrapBackwardTransition(struct peer *peer);
+
#endif /* _FRR_BGP_SNMP_H_ */
diff --git a/bgpd/bgp_snmp_bgp4.c b/bgpd/bgp_snmp_bgp4.c
index 692e232..3d04dc2 100644
--- a/bgpd/bgp_snmp_bgp4.c
+++ b/bgpd/bgp_snmp_bgp4.c
@@ -757,7 +757,7 @@ static struct variable bgp_variables[] = {
{6, 1, 14}},
};
-int bgpTrapEstablished(struct peer *peer)
+int bgp4TrapEstablished(struct peer *peer)
{
int ret;
struct in_addr addr;
@@ -782,7 +782,7 @@ int bgpTrapEstablished(struct peer *peer)
return 0;
}
-int bgpTrapBackwardTransition(struct peer *peer)
+int bgp4TrapBackwardTransition(struct peer *peer)
{
int ret;
struct in_addr addr;
diff --git a/bgpd/bgp_snmp_bgp4.h b/bgpd/bgp_snmp_bgp4.h
index ccf00d6..67f7cc6 100644
--- a/bgpd/bgp_snmp_bgp4.h
+++ b/bgpd/bgp_snmp_bgp4.h
@@ -69,8 +69,8 @@
#define BGP4PATHATTRBEST 13
#define BGP4PATHATTRUNKNOWN 14
-extern int bgpTrapEstablished(struct peer *peer);
-extern int bgpTrapBackwardTransition(struct peer *peer);
+extern int bgp4TrapEstablished(struct peer *peer);
+extern int bgp4TrapBackwardTransition(struct peer *peer);
extern int bgp_snmp_bgp4_init(struct event_loop *tm);
#endif /* _FRR_BGP_SNMP_BGP4_H_ */
diff --git a/bgpd/bgp_snmp_bgp4v2.c b/bgpd/bgp_snmp_bgp4v2.c
index f022284..0c8ed33 100644
--- a/bgpd/bgp_snmp_bgp4v2.c
+++ b/bgpd/bgp_snmp_bgp4v2.c
@@ -32,6 +32,7 @@
SNMP_LOCAL_VARIABLES
static oid bgpv2_oid[] = {BGP4V2MIB};
+static oid bgpv2_trap_oid[] = { BGP4V2MIB, 0 };
static struct in_addr bgp_empty_addr = {};
static struct peer *peer_lookup_all_vrf(struct ipaddr *addr)
@@ -435,7 +436,6 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
struct bgp_path_info *path, *min;
struct bgp_dest *dest;
union sockunion su;
- unsigned int len;
struct ipaddr paddr = {};
size_t namelen = v ? v->namelen : BGP4V2_NLRI_ENTRY_OFFSET;
sa_family_t family;
@@ -445,20 +445,28 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
size_t afi_len;
long prefix_type = 0;
long peer_addr_type = 0;
+ long nrli_index = 1;
+ long cur_index = 0;
/* Bgp4V2AddressFamilyIdentifierTC limited to IPv6 */
if (name[namelen - 1] > IANA_AFI_IPV6)
return NULL;
afi = afi_iana2int(name[namelen - 1]);
afi_len = afi == AFI_IP ? IN_ADDR_SIZE : IN6_ADDR_SIZE;
+ assert(IS_VALID_AFI(afi));
#define BGP_NLRI_ENTRY_OFFSET namelen
+#define BGP4V2_NLRI_V4_V4_OFFSET IN_ADDR_SIZE + IN_ADDR_SIZE + 5
+#define BGP4V2_NLRI_V4_V6_OFFSET IN_ADDR_SIZE + IN6_ADDR_SIZE + 5
+#define BGP4V2_NLRI_V6_V6_OFFSET IN6_ADDR_SIZE + IN6_ADDR_SIZE + 5
sockunion_init(&su);
if (exact) {
- if (*length - namelen != BGP_NLRI_ENTRY_OFFSET)
+ if (*length - namelen != BGP4V2_NLRI_V4_V4_OFFSET &&
+ *length - namelen != BGP4V2_NLRI_V4_V6_OFFSET &&
+ *length - namelen != BGP4V2_NLRI_V6_V6_OFFSET)
return NULL;
/* Set OID offset for prefix type */
@@ -502,12 +510,17 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
su.sin.sin_family = family;
/* get bgp4V2PeerRemoteAddr*/
- if (family == AF_INET)
+ if (family == AF_INET) {
oid2in_addr(offset, IN_ADDR_SIZE, &su.sin.sin_addr);
- else
+ offset += IN_ADDR_SIZE;
+ } else {
oid2in6_addr(offset, &su.sin6.sin6_addr);
+ offset += IN6_ADDR_SIZE;
+ }
- /* bgp4V2NlriIndex currently ignored */
+ /* bgp4V2NlriIndex */
+ nrli_index = *offset;
+ offset++;
/* Lookup node */
dest = bgp_node_lookup(bgp->rib[afi][safi], addr);
@@ -515,8 +528,11 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
for (path = bgp_dest_get_bgp_path_info(dest); path;
path = path->next)
if (sockunion_same(&path->peer->connection->su,
- &su))
- return path;
+ &su)) {
+ cur_index++;
+ if (cur_index == nrli_index)
+ return path;
+ }
bgp_dest_unlock_node(dest);
}
@@ -527,11 +543,9 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
/* Set OID offset for prefix type */
offset = name + namelen;
offsetlen = *length - namelen;
- len = offsetlen;
if (offsetlen == 0) {
dest = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]);
- safi = SAFI_UNICAST;
} else {
/* bgp4V2NlriAfi is already get */
@@ -571,18 +585,13 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
offsetlen--;
/* get node */
- dest = bgp_node_get(bgp->rib[afi][safi], addr);
+ dest = bgp_node_lookup(bgp->rib[afi][safi], addr);
}
if (!dest)
return NULL;
if (offsetlen > 0) {
- len = offsetlen;
- if (len > afi_len)
- len = afi_len;
-
-
/* get bgp4V2PeerRemoteAddrType */
peer_addr_type = *offset;
if (peer_addr_type == IANA_AFI_IPV4)
@@ -591,10 +600,17 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
family = AF_INET6;
offset++;
- if (family == AF_INET)
+ if (family == AF_INET) {
oid2in_addr(offset, IN_ADDR_SIZE, &paddr.ip._v4_addr);
- else
+ offset += IN_ADDR_SIZE;
+ } else {
oid2in6_addr(offset, &paddr.ip._v6_addr);
+ offset += IN6_ADDR_SIZE;
+ }
+ /* get bgp4V2NlriIndex */
+ nrli_index = *offset;
+ offset++;
+
} else {
/* default case start with ipv4*/
if (afi == AFI_IP)
@@ -602,11 +618,13 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
else
family = AF_INET6;
memset(&paddr.ip, 0, sizeof(paddr.ip));
+ nrli_index = 1;
}
do {
min = NULL;
min_family = 0;
+ cur_index = 0;
for (path = bgp_dest_get_bgp_path_info(dest); path;
path = path->next) {
@@ -616,19 +634,44 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
if (path_family < family)
continue;
- if (family == AF_INET
- && IPV4_ADDR_CMP(&paddr.ip._v4_addr,
- &path->peer->connection->su.sin.sin_addr)
- >= 0)
+ if (family == AF_INET &&
+ IPV4_ADDR_CMP(&paddr.ip._v4_addr,
+ &path->peer->connection->su.sin
+ .sin_addr) > 0)
+ continue;
+ else if (family == AF_INET6 &&
+ IPV6_ADDR_CMP(&paddr.ip._v6_addr,
+ &path->peer->connection->su.sin6
+ .sin6_addr) > 0)
+ continue;
+
+ if (family == AF_INET &&
+ IPV4_ADDR_CMP(&paddr.ip._v4_addr,
+ &path->peer->connection->su.sin
+ .sin_addr) == 0) {
+ if (cur_index == nrli_index) {
+ min = path;
+ min_family = family;
+ nrli_index++;
+ break;
+ }
+ cur_index++;
continue;
- else if (family == AF_INET6
- && IPV6_ADDR_CMP(
- &paddr.ip._v6_addr,
- &path->peer->connection->su.sin6.sin6_addr)
- >= 0)
+ } else if (family == AF_INET6 &&
+ IPV6_ADDR_CMP(&paddr.ip._v6_addr,
+ &path->peer->connection->su
+ .sin6.sin6_addr) == 0) {
+ if (cur_index == nrli_index) {
+ min = path;
+ min_family = family;
+ nrli_index++;
+ break;
+ }
+ cur_index++;
continue;
+ }
- /* first valid path its the min*/
+ /* first valid path its the min peer addr*/
if (!min) {
min = path;
min_family = path_family;
@@ -704,7 +747,7 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
/* Encode bgp4V2NlriIndex*/
- *offset = 1;
+ *offset = nrli_index;
offset++;
*length = offset - name;
@@ -718,6 +761,7 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
}
memset(&paddr.ip, 0, sizeof(paddr.ip));
+ nrli_index = 1;
} while ((dest = bgp_route_next(dest)));
@@ -896,6 +940,37 @@ static uint8_t *bgp4v2PathAttrTable(struct variable *v, oid name[],
return NULL;
}
+/* BGP V2 Traps. */
+static struct trap_object bgpv2TrapEstListv4[] = {
+ { 6, { 1, 2, 1, BGP4V2_PEER_STATE, 1, 1 } },
+ { 6, { 1, 2, 1, BGP4V2_PEER_LOCAL_PORT, 1, 1 } },
+ { 6, { 1, 2, 1, BGP4V2_PEER_REMOTE_PORT, 1, 1 } }
+};
+
+static struct trap_object bgpv2TrapEstListv6[] = {
+ { 6, { 1, 2, 1, BGP4V2_PEER_STATE, 1, 2 } },
+ { 6, { 1, 2, 1, BGP4V2_PEER_LOCAL_PORT, 1, 2 } },
+ { 6, { 1, 2, 1, BGP4V2_PEER_REMOTE_PORT, 1, 2 } }
+};
+
+static struct trap_object bgpv2TrapBackListv4[] = {
+ { 6, { 1, 2, 1, BGP4V2_PEER_STATE, 1, 1 } },
+ { 6, { 1, 2, 1, BGP4V2_PEER_LOCAL_PORT, 1, 1 } },
+ { 6, { 1, 2, 1, BGP4V2_PEER_REMOTE_PORT, 1, 1 } },
+ { 6, { 1, 3, 1, BGP4V2_PEER_LAST_ERROR_CODE_RECEIVED, 1, 1 } },
+ { 6, { 1, 3, 1, BGP4V2_PEER_LAST_ERROR_SUBCODE_RECEIVED, 1, 1 } },
+ { 6, { 1, 3, 1, BGP4V2_PEER_LAST_ERROR_RECEIVED_TEXT, 1, 1 } }
+};
+
+static struct trap_object bgpv2TrapBackListv6[] = {
+ { 6, { 1, 2, 1, BGP4V2_PEER_STATE, 1, 2 } },
+ { 6, { 1, 2, 1, BGP4V2_PEER_LOCAL_PORT, 1, 2 } },
+ { 6, { 1, 2, 1, BGP4V2_PEER_REMOTE_PORT, 1, 2 } },
+ { 6, { 1, 3, 1, BGP4V2_PEER_LAST_ERROR_CODE_RECEIVED, 1, 2 } },
+ { 6, { 1, 3, 1, BGP4V2_PEER_LAST_ERROR_SUBCODE_RECEIVED, 1, 2 } },
+ { 6, { 1, 3, 1, BGP4V2_PEER_LAST_ERROR_RECEIVED_TEXT, 1, 2 } }
+};
+
static struct variable bgpv2_variables[] = {
/* bgp4V2PeerEntry */
{BGP4V2_PEER_INSTANCE,
@@ -1515,6 +1590,79 @@ static struct variable bgpv2_variables[] = {
{1, 9, 1, BGP4V2_NLRI_PATH_ATTR_UNKNOWN, 1, 2}},
};
+int bgpv2TrapEstablished(struct peer *peer)
+{
+ oid index[sizeof(oid) * IN6_ADDR_SIZE];
+ size_t length;
+
+ if (!CHECK_FLAG(bm->options, BGP_OPT_TRAPS_BGP4MIBV2))
+ return 0;
+
+ /* Check if this peer just went to Established */
+ if ((peer->connection->ostatus != OpenConfirm) ||
+ !(peer_established(peer->connection)))
+ return 0;
+
+ switch (sockunion_family(&peer->connection->su)) {
+ case AF_INET:
+ oid_copy_in_addr(index, &peer->connection->su.sin.sin_addr);
+ length = IN_ADDR_SIZE;
+ smux_trap(bgpv2_variables, array_size(bgpv2_variables),
+ bgpv2_trap_oid, array_size(bgpv2_trap_oid), bgpv2_oid,
+ sizeof(bgpv2_oid) / sizeof(oid), index, length,
+ bgpv2TrapEstListv4, array_size(bgpv2TrapEstListv4),
+ BGP4V2ESTABLISHED);
+ break;
+ case AF_INET6:
+ oid_copy_in6_addr(index, &peer->connection->su.sin6.sin6_addr);
+ length = IN6_ADDR_SIZE;
+ smux_trap(bgpv2_variables, array_size(bgpv2_variables),
+ bgpv2_trap_oid, array_size(bgpv2_trap_oid), bgpv2_oid,
+ sizeof(bgpv2_oid) / sizeof(oid), index, length,
+ bgpv2TrapEstListv6, array_size(bgpv2TrapEstListv6),
+ BGP4V2ESTABLISHED);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int bgpv2TrapBackwardTransition(struct peer *peer)
+{
+ oid index[sizeof(oid) * IN6_ADDR_SIZE];
+ size_t length;
+
+ if (!CHECK_FLAG(bm->options, BGP_OPT_TRAPS_BGP4MIBV2))
+ return 0;
+
+ switch (sockunion_family(&peer->connection->su)) {
+ case AF_INET:
+ oid_copy_in_addr(index, &peer->connection->su.sin.sin_addr);
+ length = IN_ADDR_SIZE;
+ smux_trap(bgpv2_variables, array_size(bgpv2_variables),
+ bgpv2_trap_oid, array_size(bgpv2_trap_oid), bgpv2_oid,
+ sizeof(bgpv2_oid) / sizeof(oid), index, length,
+ bgpv2TrapBackListv4, array_size(bgpv2TrapBackListv4),
+ BGP4V2BACKWARDTRANSITION);
+ break;
+ case AF_INET6:
+ oid_copy_in6_addr(index, &peer->connection->su.sin6.sin6_addr);
+ length = IN6_ADDR_SIZE;
+ smux_trap(bgpv2_variables, array_size(bgpv2_variables),
+ bgpv2_trap_oid, array_size(bgpv2_trap_oid), bgpv2_oid,
+ sizeof(bgpv2_oid) / sizeof(oid), index, length,
+ bgpv2TrapBackListv6, array_size(bgpv2TrapBackListv6),
+ BGP4V2BACKWARDTRANSITION);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
int bgp_snmp_bgp4v2_init(struct event_loop *tm)
{
REGISTER_MIB("mibII/bgpv2", bgpv2_variables, variable, bgpv2_oid);
diff --git a/bgpd/bgp_snmp_bgp4v2.h b/bgpd/bgp_snmp_bgp4v2.h
index 6587a82..ca35533 100644
--- a/bgpd/bgp_snmp_bgp4v2.h
+++ b/bgpd/bgp_snmp_bgp4v2.h
@@ -16,6 +16,14 @@
* offset 1.3.6.1.3.5.1.1.2.1.x.(1|2).(4|16) = 13
* offset 1.3.6.1.4.1.7336.3.2.1.1.2.1.x.1.(1|2) = 16
*/
+
+
+/* bgpTraps */
+#define BGP4V2ESTABLISHED 1
+#define BGP4V2BACKWARDTRANSITION 2
+
+/* bgpPeerTable */
+
#define BGP4V2_PEER_ENTRY_OFFSET 13
#define BGP4V2_PEER_INSTANCE 1
#define BGP4V2_PEER_LOCAL_ADDR_TYPE 2
@@ -84,5 +92,7 @@
#define BGP4V2_BACKWARD_TRANSITION_NOTIFICATION 2
extern int bgp_snmp_bgp4v2_init(struct event_loop *tm);
+extern int bgpv2TrapEstablished(struct peer *peer);
+extern int bgpv2TrapBackwardTransition(struct peer *peer);
#endif /* _FRR_BGP_SNMP_BGP4V2_H_ */
diff --git a/bgpd/bgp_trace.h b/bgpd/bgp_trace.h
index 964393a..a77a25e 100644
--- a/bgpd/bgp_trace.h
+++ b/bgpd/bgp_trace.h
@@ -135,11 +135,12 @@ TRACEPOINT_LOGLEVEL(frr_bgp, bmp_mirror_packet, TRACE_INFO)
TRACEPOINT_EVENT(
frr_bgp,
bmp_eor,
- TP_ARGS(afi_t, afi, safi_t, safi, uint8_t, flags),
+ TP_ARGS(afi_t, afi, safi_t, safi, uint8_t, flags, uint8_t, peer_type_flag),
TP_FIELDS(
ctf_integer(afi_t, afi, afi)
ctf_integer(safi_t, safi, safi)
ctf_integer(uint8_t, flags, flags)
+ ctf_integer(uint8_t, peer_type_flag, peer_type_flag)
)
)
@@ -307,7 +308,8 @@ TRACEPOINT_EVENT(
struct in_addr, vtep, esi_t *, esi),
TP_FIELDS(
ctf_string(action, add ? "add" : "del")
- ctf_integer(vni_t, vni, vpn->vni)
+ ctf_integer(vni_t, vni, (vpn ? vpn->vni : 0))
+ ctf_integer(uint32_t, eth_tag, &pfx->prefix.macip_addr.eth_tag)
ctf_array(unsigned char, mac, &pfx->prefix.macip_addr.mac,
sizeof(struct ethaddr))
ctf_array(unsigned char, ip, &pfx->prefix.macip_addr.ip,
@@ -325,7 +327,7 @@ TRACEPOINT_EVENT(
const struct prefix_evpn *, pfx),
TP_FIELDS(
ctf_string(action, add ? "add" : "del")
- ctf_integer(vni_t, vni, vpn->vni)
+ ctf_integer(vni_t, vni, (vpn ? vpn->vni : 0))
ctf_integer_network_hex(unsigned int, vtep,
pfx->prefix.imet_addr.ip.ipaddr_v4.s_addr)
)
@@ -436,6 +438,64 @@ TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_local_es_evi_del_zrecv, TRACE_INFO)
TRACEPOINT_EVENT(
frr_bgp,
+ evpn_mh_es_evi_vtep_add,
+ TP_ARGS(esi_t *, esi, vni_t, vni, struct in_addr, vtep,
+ uint8_t, ead_es),
+ TP_FIELDS(
+ ctf_array(unsigned char, esi, esi, sizeof(esi_t))
+ ctf_integer(vni_t, vni, vni)
+ ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr)
+ ctf_integer(uint8_t, ead_es, ead_es)
+ )
+)
+TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_es_evi_vtep_add, TRACE_INFO)
+
+TRACEPOINT_EVENT(
+ frr_bgp,
+ evpn_mh_es_evi_vtep_del,
+ TP_ARGS(esi_t *, esi, vni_t, vni, struct in_addr, vtep,
+ uint8_t, ead_es),
+ TP_FIELDS(
+ ctf_array(unsigned char, esi, esi, sizeof(esi_t))
+ ctf_integer(vni_t, vni, vni)
+ ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr)
+ ctf_integer(uint8_t, ead_es, ead_es)
+ )
+)
+TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_es_evi_vtep_del, TRACE_INFO)
+
+TRACEPOINT_EVENT(
+ frr_bgp,
+ evpn_mh_local_ead_es_evi_route_upd,
+ TP_ARGS(esi_t *, esi, vni_t, vni,
+ uint8_t, route_type,
+ struct in_addr, vtep),
+ TP_FIELDS(
+ ctf_array(unsigned char, esi, esi, sizeof(esi_t))
+ ctf_integer(vni_t, vni, vni)
+ ctf_integer(uint8_t, route_type, route_type)
+ ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr)
+ )
+)
+TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_local_ead_es_evi_route_upd, TRACE_INFO)
+
+TRACEPOINT_EVENT(
+ frr_bgp,
+ evpn_mh_local_ead_es_evi_route_del,
+ TP_ARGS(esi_t *, esi, vni_t, vni,
+ uint8_t, route_type,
+ struct in_addr, vtep),
+ TP_FIELDS(
+ ctf_array(unsigned char, esi, esi, sizeof(esi_t))
+ ctf_integer(vni_t, vni, vni)
+ ctf_integer(uint8_t, route_type, route_type)
+ ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr)
+ )
+)
+TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_local_ead_es_evi_route_del, TRACE_INFO)
+
+TRACEPOINT_EVENT(
+ frr_bgp,
evpn_local_vni_add_zrecv,
TP_ARGS(vni_t, vni, struct in_addr, vtep, vrf_id_t, vrf,
struct in_addr, mc_grp),
@@ -496,6 +556,34 @@ TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_macip_del_zrecv, TRACE_INFO)
TRACEPOINT_EVENT(
frr_bgp,
+ evpn_advertise_type5,
+ TP_ARGS(vrf_id_t, vrf, const struct prefix_evpn *, pfx,
+ struct ethaddr *, rmac, struct in_addr, vtep),
+ TP_FIELDS(
+ ctf_integer(int, vrf_id, vrf)
+ ctf_array(unsigned char, ip, &pfx->prefix.prefix_addr.ip,
+ sizeof(struct ipaddr))
+ ctf_array(unsigned char, rmac, rmac,
+ sizeof(struct ethaddr))
+ ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr)
+ )
+)
+TRACEPOINT_LOGLEVEL(frr_bgp, evpn_advertise_type5, TRACE_INFO)
+
+TRACEPOINT_EVENT(
+ frr_bgp,
+ evpn_withdraw_type5,
+ TP_ARGS(vrf_id_t, vrf, const struct prefix_evpn *, pfx),
+ TP_FIELDS(
+ ctf_integer(int, vrf_id, vrf)
+ ctf_array(unsigned char, ip, &pfx->prefix.prefix_addr.ip,
+ sizeof(struct ipaddr))
+ )
+)
+TRACEPOINT_LOGLEVEL(frr_bgp, evpn_withdraw_type5, TRACE_INFO)
+
+TRACEPOINT_EVENT(
+ frr_bgp,
evpn_local_l3vni_add_zrecv,
TP_ARGS(vni_t, vni, vrf_id_t, vrf,
struct ethaddr *, svi_rmac,
diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c
index a2006c3..d13515a 100644
--- a/bgpd/bgp_updgrp.c
+++ b/bgpd/bgp_updgrp.c
@@ -128,6 +128,7 @@ static void conf_copy(struct peer *dst, struct peer *src, afi_t afi,
dst->bgp = src->bgp;
dst->sort = src->sort;
+ dst->sub_sort = src->sub_sort;
dst->as = src->as;
dst->v_routeadv = src->v_routeadv;
dst->flags = src->flags;
@@ -342,6 +343,7 @@ static unsigned int updgrp_hash_key_make(const void *p)
key = 0;
key = jhash_1word(peer->sort, key); /* EBGP or IBGP */
+ 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);
key = jhash_1word((uint32_t)peer->addpath_type[afi][safi], key);
@@ -447,19 +449,18 @@ static unsigned int updgrp_hash_key_make(const void *p)
* STATEMENT STAYS UP TO DATE
*/
if (bgp_debug_neighbor_events(peer)) {
- zlog_debug(
- "%pBP Update Group Hash: sort: %d UpdGrpFlags: %ju UpdGrpAFFlags: %ju",
- peer, peer->sort,
- (intmax_t)CHECK_FLAG(peer->flags, PEER_UPDGRP_FLAGS),
- (intmax_t)CHECK_FLAG(flags, PEER_UPDGRP_AF_FLAGS));
- zlog_debug(
- "%pBP Update Group Hash: addpath: %u UpdGrpCapFlag: %u UpdGrpCapAFFlag: %u route_adv: %u change local as: %u, as_path_loop_detection: %d",
- peer, (uint32_t)peer->addpath_type[afi][safi],
- CHECK_FLAG(peer->cap, PEER_UPDGRP_CAP_FLAGS),
- CHECK_FLAG(peer->af_cap[afi][safi],
- PEER_UPDGRP_AF_CAP_FLAGS),
- peer->v_routeadv, peer->change_local_as,
- peer->as_path_loop_detection);
+ zlog_debug("%pBP Update Group Hash: sort: %d sub_sort: %d UpdGrpFlags: %ju UpdGrpAFFlags: %ju",
+ peer, peer->sort, peer->sub_sort,
+ (intmax_t)CHECK_FLAG(peer->flags, PEER_UPDGRP_FLAGS),
+ (intmax_t)CHECK_FLAG(flags, PEER_UPDGRP_AF_FLAGS));
+ zlog_debug("%pBP Update Group Hash: addpath: %u UpdGrpCapFlag: %ju UpdGrpCapAFFlag: %u route_adv: %u change local as: %u, as_path_loop_detection: %d",
+ peer, (uint32_t)peer->addpath_type[afi][safi],
+ (intmax_t)CHECK_FLAG(peer->cap,
+ PEER_UPDGRP_CAP_FLAGS),
+ CHECK_FLAG(peer->af_cap[afi][safi],
+ PEER_UPDGRP_AF_CAP_FLAGS),
+ peer->v_routeadv, peer->change_local_as,
+ peer->as_path_loop_detection);
zlog_debug(
"%pBP Update Group Hash: max packet size: %u pmax_out: %u Peer Group: %s rmap out: %s",
peer, peer->max_packet_size, peer->pmax_out[afi][safi],
@@ -1698,14 +1699,14 @@ static int updgrp_policy_update_walkcb(struct update_group *updgrp, void *arg)
*/
UNSET_FLAG(subgrp->sflags,
SUBGRP_STATUS_DEFAULT_ORIGINATE);
- subgroup_default_originate(subgrp, 0);
+ subgroup_default_originate(subgrp, false);
} else {
/*
* This is a explicit withdraw, since the
* routemap is not present in routemap lib. need
- * to pass 1 for withdraw arg.
+ * to pass `true` for withdraw arg.
*/
- subgroup_default_originate(subgrp, 1);
+ subgroup_default_originate(subgrp, true);
}
}
update_subgroup_set_needs_refresh(subgrp, 0);
@@ -2101,7 +2102,7 @@ update_group_default_originate_route_map_walkcb(struct update_group *updgrp,
*/
UNSET_FLAG(subgrp->sflags,
SUBGRP_STATUS_DEFAULT_ORIGINATE);
- subgroup_default_originate(subgrp, 0);
+ subgroup_default_originate(subgrp, false);
}
}
diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h
index 0d866f3..5e8b537 100644
--- a/bgpd/bgp_updgrp.h
+++ b/bgpd/bgp_updgrp.h
@@ -40,17 +40,16 @@
(PEER_FLAG_LOCAL_AS_NO_PREPEND | PEER_FLAG_LOCAL_AS_REPLACE_AS)
#define PEER_UPDGRP_AF_FLAGS \
- (PEER_FLAG_SEND_COMMUNITY | PEER_FLAG_SEND_EXT_COMMUNITY \
- | PEER_FLAG_SEND_LARGE_COMMUNITY \
- | PEER_FLAG_DEFAULT_ORIGINATE | PEER_FLAG_REFLECTOR_CLIENT \
- | PEER_FLAG_RSERVER_CLIENT | PEER_FLAG_NEXTHOP_SELF \
- | PEER_FLAG_NEXTHOP_UNCHANGED | PEER_FLAG_FORCE_NEXTHOP_SELF \
- | PEER_FLAG_AS_PATH_UNCHANGED | PEER_FLAG_MED_UNCHANGED \
- | PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED | PEER_FLAG_REMOVE_PRIVATE_AS \
- | PEER_FLAG_REMOVE_PRIVATE_AS_ALL \
- | PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE \
- | PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE \
- | PEER_FLAG_AS_OVERRIDE)
+ (PEER_FLAG_SEND_COMMUNITY | PEER_FLAG_SEND_EXT_COMMUNITY | \
+ PEER_FLAG_SEND_EXT_COMMUNITY_RPKI | PEER_FLAG_SEND_LARGE_COMMUNITY | \
+ PEER_FLAG_DEFAULT_ORIGINATE | PEER_FLAG_REFLECTOR_CLIENT | \
+ PEER_FLAG_RSERVER_CLIENT | PEER_FLAG_NEXTHOP_SELF | \
+ PEER_FLAG_NEXTHOP_UNCHANGED | PEER_FLAG_FORCE_NEXTHOP_SELF | \
+ PEER_FLAG_AS_PATH_UNCHANGED | PEER_FLAG_MED_UNCHANGED | \
+ PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED | PEER_FLAG_REMOVE_PRIVATE_AS | \
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL | \
+ PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE | \
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE | PEER_FLAG_AS_OVERRIDE)
#define PEER_UPDGRP_CAP_FLAGS (PEER_CAP_AS4_RCV)
@@ -428,7 +427,7 @@ extern void subgroup_announce_route(struct update_subgroup *subgrp);
extern void subgroup_announce_all(struct update_subgroup *subgrp);
extern void subgroup_default_originate(struct update_subgroup *subgrp,
- int withdraw);
+ bool withdraw);
extern void group_announce_route(struct bgp *bgp, afi_t afi, safi_t safi,
struct bgp_dest *dest,
struct bgp_path_info *pi);
@@ -442,7 +441,7 @@ extern struct bgp_adj_out *bgp_adj_out_alloc(struct update_subgroup *subgrp,
extern void bgp_adj_out_remove_subgroup(struct bgp_dest *dest,
struct bgp_adj_out *adj,
struct update_subgroup *subgrp);
-extern void bgp_adj_out_set_subgroup(struct bgp_dest *dest,
+extern bool bgp_adj_out_set_subgroup(struct bgp_dest *dest,
struct update_subgroup *subgrp,
struct attr *attr,
struct bgp_path_info *path);
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index ccbb23e..267a756 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -198,9 +198,8 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)
addpath_capable = bgp_addpath_encode_tx(peer, afi, safi);
if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug("%s: afi=%s, safi=%s, p=%pRN", __func__,
- afi2str(afi), safi2str(safi),
- bgp_dest_to_rnode(ctx->dest));
+ zlog_debug("%s: afi=%s, safi=%s, p=%pBD", __func__,
+ afi2str(afi), safi2str(safi), ctx->dest);
UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) {
/*
@@ -479,7 +478,7 @@ bgp_advertise_clean_subgroup(struct update_subgroup *subgrp,
bgp_advertise_delete(baa, adv);
/* Fetch next advertise candidate. */
- next = baa->adv;
+ next = bgp_advertise_attr_fifo_first(&baa->fifo);
/* Unintern BGP advertise attribute. */
bgp_advertise_attr_unintern(subgrp->hash, baa);
@@ -497,7 +496,7 @@ bgp_advertise_clean_subgroup(struct update_subgroup *subgrp,
return next;
}
-void bgp_adj_out_set_subgroup(struct bgp_dest *dest,
+bool bgp_adj_out_set_subgroup(struct bgp_dest *dest,
struct update_subgroup *subgrp, struct attr *attr,
struct bgp_path_info *path)
{
@@ -517,7 +516,7 @@ void bgp_adj_out_set_subgroup(struct bgp_dest *dest,
bgp = SUBGRP_INST(subgrp);
if (DISABLE_BGP_ANNOUNCE)
- return;
+ return false;
/* Look for adjacency information. */
adj = adj_lookup(
@@ -533,7 +532,7 @@ void bgp_adj_out_set_subgroup(struct bgp_dest *dest,
bgp_addpath_id_for_peer(peer, afi, safi,
&path->tx_addpath));
if (!adj)
- return;
+ return false;
subgrp->pscount++;
}
@@ -572,7 +571,7 @@ void bgp_adj_out_set_subgroup(struct bgp_dest *dest,
* will never be able to coalesce the 3rd peer down
*/
subgrp->version = MAX(subgrp->version, dest->version);
- return;
+ return false;
}
if (adj->adv)
@@ -620,6 +619,8 @@ void bgp_adj_out_set_subgroup(struct bgp_dest *dest,
bgp_adv_fifo_add_tail(&subgrp->sync->update, adv);
subgrp->version = MAX(subgrp->version, dest->version);
+
+ return true;
}
/* The only time 'withdraw' will be false is if we are sending
@@ -734,7 +735,7 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN
&& CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_DEFAULT_ORIGINATE))
- subgroup_default_originate(subgrp, 0);
+ subgroup_default_originate(subgrp, false);
subgrp->pscount = 0;
SET_FLAG(subgrp->sflags, SUBGRP_STATUS_TABLE_REPARSING);
@@ -826,11 +827,12 @@ void subgroup_announce_route(struct update_subgroup *subgrp)
}
}
-void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
+void subgroup_default_originate(struct update_subgroup *subgrp, bool withdraw)
{
struct bgp *bgp;
- struct attr attr;
+ struct attr attr = { 0 };
struct attr *new_attr = &attr;
+ struct aspath *aspath;
struct prefix p;
struct peer *from;
struct bgp_dest *dest;
@@ -868,6 +870,7 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
/* make coverity happy */
assert(attr.aspath);
+ aspath = attr.aspath;
attr.med = 0;
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
@@ -915,8 +918,8 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
bgp_attr_flush(new_attr);
new_attr = bgp_attr_intern(
tmp_pi.attr);
- bgp_attr_flush(tmp_pi.attr);
}
+ bgp_attr_flush(tmp_pi.attr);
subgroup_announce_reset_nhop(
(peer_cap_enhe(peer, afi, safi)
? AF_INET6
@@ -941,7 +944,7 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
SUBGRP_STATUS_DEFAULT_ORIGINATE)))
SET_FLAG(subgrp->sflags,
SUBGRP_STATUS_DEFAULT_ORIGINATE);
- withdraw = 1;
+ withdraw = true;
}
}
@@ -968,18 +971,19 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
if (dest) {
for (pi = bgp_dest_get_bgp_path_info(dest); pi;
pi = pi->next) {
- if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
- if (subgroup_announce_check(
- dest, pi, subgrp,
- bgp_dest_get_prefix(dest),
- &attr, NULL)) {
- struct attr *default_attr =
- bgp_attr_intern(&attr);
-
- bgp_adj_out_set_subgroup(
- dest, subgrp,
- default_attr, pi);
- }
+ if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
+ continue;
+
+ if (subgroup_announce_check(dest, pi, subgrp,
+ bgp_dest_get_prefix(
+ dest),
+ &attr, NULL)) {
+ if (!bgp_adj_out_set_subgroup(dest,
+ subgrp,
+ &attr, pi))
+ bgp_attr_flush(&attr);
+ } else
+ bgp_attr_flush(&attr);
}
bgp_dest_unlock_node(dest);
}
@@ -1023,7 +1027,7 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
}
}
- aspath_unintern(&attr.aspath);
+ aspath_unintern(&aspath);
}
/*
diff --git a/bgpd/bgp_vpn.c b/bgpd/bgp_vpn.c
index 0ed1d04..8fe24eb 100644
--- a/bgpd/bgp_vpn.c
+++ b/bgpd/bgp_vpn.c
@@ -30,8 +30,6 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer,
int rd_header;
int header = 1;
json_object *json = NULL;
- json_object *json_scode = NULL;
- json_object *json_ocode = NULL;
json_object *json_adv = NULL;
json_object *json_routes = NULL;
char rd_str[BUFSIZ];
@@ -47,21 +45,8 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer,
}
if (use_json) {
- json_scode = json_object_new_object();
- json_ocode = json_object_new_object();
json = json_object_new_object();
json_adv = json_object_new_object();
-
- json_object_string_add(json_scode, "suppressed", "s");
- json_object_string_add(json_scode, "damped", "d");
- json_object_string_add(json_scode, "history", "h");
- json_object_string_add(json_scode, "valid", "*");
- json_object_string_add(json_scode, "best", ">");
- json_object_string_add(json_scode, "internal", "i");
-
- json_object_string_add(json_ocode, "igp", "i");
- json_object_string_add(json_ocode, "egp", "e");
- json_object_string_add(json_ocode, "incomplete", "?");
}
for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
@@ -117,12 +102,6 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer,
json_object_int_add(
json, "localAS",
bgp->as);
- json_object_object_add(json,
- "bgpStatusCodes",
- json_scode);
- json_object_object_add(json,
- "bgpOriginCodes",
- json_ocode);
} else {
vty_out(vty,
"BGP table version is 0, local router ID is %pI4\n",
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index e49baff..9530a66 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -5,6 +5,10 @@
#include <zebra.h>
+#ifdef GNU_LINUX
+#include <linux/rtnetlink.h> //RT_TABLE_XXX
+#endif
+
#include "command.h"
#include "lib/json.h"
#include "lib/sockopt.h"
@@ -122,12 +126,17 @@ FRR_CFG_DEFAULT_BOOL(BGP_SOFT_VERSION_CAPABILITY,
{ .val_bool = true, .match_profile = "datacenter", },
{ .val_bool = false },
);
+FRR_CFG_DEFAULT_BOOL(BGP_ENFORCE_FIRST_AS,
+ { .val_bool = false, .match_version = "< 9.1", },
+ { .val_bool = true },
+);
DEFINE_HOOK(bgp_inst_config_write,
(struct bgp *bgp, struct vty *vty),
(bgp, vty));
DEFINE_HOOK(bgp_snmp_update_last_changed, (struct bgp *bgp), (bgp));
DEFINE_HOOK(bgp_snmp_init_stats, (struct bgp *bgp), (bgp));
+DEFINE_HOOK(bgp_snmp_traps_config_write, (struct vty * vty), (vty));
static struct peer_group *listen_range_exists(struct bgp *bgp,
struct prefix *range, int exact);
@@ -310,7 +319,7 @@ static int bgp_srv6_locator_unset(struct bgp *bgp)
/* refresh functions */
for (ALL_LIST_ELEMENTS(bgp->srv6_functions, node, nnode, func)) {
listnode_delete(bgp->srv6_functions, func);
- XFREE(MTYPE_BGP_SRV6_FUNCTION, func);
+ srv6_function_free(func);
}
/* refresh tovpn_sid */
@@ -614,6 +623,8 @@ int bgp_get_vty(struct bgp **bgp, as_t *as, const char *name,
if (DFLT_BGP_SOFT_VERSION_CAPABILITY)
SET_FLAG((*bgp)->flags,
BGP_FLAG_SOFT_VERSION_CAPABILITY);
+ if (DFLT_BGP_ENFORCE_FIRST_AS)
+ SET_FLAG((*bgp)->flags, BGP_FLAG_ENFORCE_FIRST_AS);
ret = BGP_SUCCESS;
}
@@ -1591,8 +1602,9 @@ DEFUN_NOSH (router_bgp,
* - update asnotation if explicitly mentioned
*/
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO)) {
- XFREE(MTYPE_BGP, bgp->as_pretty);
- bgp->as_pretty = XSTRDUP(MTYPE_BGP, argv[idx_asn]->arg);
+ XFREE(MTYPE_BGP_NAME, bgp->as_pretty);
+ bgp->as_pretty = XSTRDUP(MTYPE_BGP_NAME,
+ argv[idx_asn]->arg);
if (!CHECK_FLAG(bgp->config, BGP_CONFIG_ASNOTATION) &&
asnotation != ASNOTATION_UNDEFINED) {
SET_FLAG(bgp->config, BGP_CONFIG_ASNOTATION);
@@ -2827,6 +2839,23 @@ DEFUN(no_bgp_ebgp_requires_policy, no_bgp_ebgp_requires_policy_cmd,
return CMD_SUCCESS;
}
+DEFPY(bgp_enforce_first_as,
+ bgp_enforce_first_as_cmd,
+ "[no] bgp enforce-first-as",
+ NO_STR
+ BGP_STR
+ "Enforce the first AS for EBGP routes\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ if (no)
+ UNSET_FLAG(bgp->flags, BGP_FLAG_ENFORCE_FIRST_AS);
+ else
+ SET_FLAG(bgp->flags, BGP_FLAG_ENFORCE_FIRST_AS);
+
+ return CMD_SUCCESS;
+}
+
DEFPY(bgp_lu_uses_explicit_null, bgp_lu_uses_explicit_null_cmd,
"[no] bgp labeled-unicast <explicit-null|ipv4-explicit-null|ipv6-explicit-null>$value",
NO_STR BGP_STR
@@ -3231,6 +3260,8 @@ DEFUN (bgp_graceful_restart_disable,
GR_DISABLE)
{
int ret = BGP_GR_FAILURE;
+ struct listnode *node, *nnode;
+ struct peer *peer;
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
@@ -3249,6 +3280,15 @@ DEFUN (bgp_graceful_restart_disable,
vty_out(vty,
"Graceful restart configuration changed, reset all peers to take effect\n");
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_RESTART,
+ CAPABILITY_ACTION_UNSET);
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_LLGR,
+ CAPABILITY_ACTION_UNSET);
+ }
+
return bgp_vty_return(vty, ret);
}
@@ -5706,6 +5746,37 @@ DEFUN (no_neighbor_dont_capability_negotiate,
PEER_FLAG_DONT_CAPABILITY);
}
+/* neighbor capability fqdn */
+DEFPY (neighbor_capability_fqdn,
+ neighbor_capability_fqdn_cmd,
+ "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor capability fqdn",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Advertise capability to the peer\n"
+ "Advertise fqdn capability to the peer\n")
+{
+ struct peer *peer;
+ int ret;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (no)
+ ret = peer_flag_unset_vty(vty, neighbor,
+ PEER_FLAG_CAPABILITY_FQDN);
+ else
+ ret = peer_flag_set_vty(vty, neighbor,
+ PEER_FLAG_CAPABILITY_FQDN);
+
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, CAPABILITY_CODE_FQDN,
+ no ? CAPABILITY_ACTION_UNSET
+ : CAPABILITY_ACTION_SET);
+
+ return ret;
+}
+
/* neighbor capability extended next hop encoding */
DEFUN (neighbor_capability_enhe,
neighbor_capability_enhe_cmd,
@@ -5831,24 +5902,37 @@ DEFUN (neighbor_capability_orf_prefix,
struct peer *peer;
afi_t afi = bgp_node_afi(vty);
safi_t safi = bgp_node_safi(vty);
+ int ret;
peer = peer_and_group_lookup_vty(vty, peer_str);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
- if (strmatch(argv[idx_send_recv]->text, "send"))
- return peer_af_flag_set_vty(vty, peer_str, afi, safi,
- PEER_FLAG_ORF_PREFIX_SM);
+ if (strmatch(argv[idx_send_recv]->text, "send")) {
+ ret = peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_ORF_PREFIX_SM);
+ bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_ORF,
+ CAPABILITY_ACTION_SET);
+ return ret;
+ }
- if (strmatch(argv[idx_send_recv]->text, "receive"))
- return peer_af_flag_set_vty(vty, peer_str, afi, safi,
- PEER_FLAG_ORF_PREFIX_RM);
+ if (strmatch(argv[idx_send_recv]->text, "receive")) {
+ ret = peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_ORF_PREFIX_RM);
+ bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_ORF,
+ CAPABILITY_ACTION_SET);
+ return ret;
+ }
- if (strmatch(argv[idx_send_recv]->text, "both"))
- return peer_af_flag_set_vty(vty, peer_str, afi, safi,
- PEER_FLAG_ORF_PREFIX_SM)
- | peer_af_flag_set_vty(vty, peer_str, afi, safi,
- PEER_FLAG_ORF_PREFIX_RM);
+ if (strmatch(argv[idx_send_recv]->text, "both")) {
+ ret = peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_ORF_PREFIX_SM) |
+ peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_ORF_PREFIX_RM);
+ bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_ORF,
+ CAPABILITY_ACTION_SET);
+ return ret;
+ }
return CMD_WARNING_CONFIG_FAILED;
}
@@ -5883,24 +5967,37 @@ DEFUN (no_neighbor_capability_orf_prefix,
struct peer *peer;
afi_t afi = bgp_node_afi(vty);
safi_t safi = bgp_node_safi(vty);
+ int ret;
peer = peer_and_group_lookup_vty(vty, peer_str);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
- if (strmatch(argv[idx_send_recv]->text, "send"))
- return peer_af_flag_unset_vty(vty, peer_str, afi, safi,
- PEER_FLAG_ORF_PREFIX_SM);
+ if (strmatch(argv[idx_send_recv]->text, "send")) {
+ ret = peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_ORF_PREFIX_SM);
+ bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_ORF,
+ CAPABILITY_ACTION_UNSET);
+ return ret;
+ }
- if (strmatch(argv[idx_send_recv]->text, "receive"))
- return peer_af_flag_unset_vty(vty, peer_str, afi, safi,
- PEER_FLAG_ORF_PREFIX_RM);
+ if (strmatch(argv[idx_send_recv]->text, "receive")) {
+ ret = peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_ORF_PREFIX_RM);
+ bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_ORF,
+ CAPABILITY_ACTION_UNSET);
+ return ret;
+ }
- if (strmatch(argv[idx_send_recv]->text, "both"))
- return peer_af_flag_unset_vty(vty, peer_str, afi, safi,
- PEER_FLAG_ORF_PREFIX_SM)
- | peer_af_flag_unset_vty(vty, peer_str, afi, safi,
- PEER_FLAG_ORF_PREFIX_RM);
+ if (strmatch(argv[idx_send_recv]->text, "both")) {
+ ret = peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_ORF_PREFIX_SM) |
+ peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_ORF_PREFIX_RM);
+ bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_ORF,
+ CAPABILITY_ACTION_UNSET);
+ return ret;
+ }
return CMD_WARNING_CONFIG_FAILED;
}
@@ -6387,6 +6484,32 @@ ALIAS_HIDDEN(
"Send Standard Community attributes\n"
"Send Large Community attributes\n")
+DEFPY (neighbor_ecommunity_rpki,
+ neighbor_ecommunity_rpki_cmd,
+ "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor send-community extended rpki",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Send Community attribute to this neighbor\n"
+ "Send Extended Community attributes\n"
+ "Send RPKI Extended Community attributes\n")
+{
+ struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (no)
+ return peer_af_flag_unset_vty(vty, neighbor, afi, safi,
+ PEER_FLAG_SEND_EXT_COMMUNITY_RPKI);
+ else
+ return peer_af_flag_set_vty(vty, neighbor, afi, safi,
+ PEER_FLAG_SEND_EXT_COMMUNITY_RPKI);
+}
+
/* neighbor soft-reconfig. */
DEFUN (neighbor_soft_reconfiguration,
neighbor_soft_reconfiguration_cmd,
@@ -6900,6 +7023,28 @@ DEFPY(no_neighbor_role,
return ret;
}
+DEFPY (neighbor_oad,
+ neighbor_oad_cmd,
+ "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor oad",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Set peering session type to EBGP-OAD\n")
+{
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (no)
+ peer->sub_sort = 0;
+ else if (peer->sort == BGP_PEER_EBGP)
+ peer->sub_sort = BGP_PEER_EBGP_OAD;
+
+ return CMD_SUCCESS;
+}
+
/* disable-connected-check */
DEFUN (neighbor_disable_connected_check,
neighbor_disable_connected_check_cmd,
@@ -8840,13 +8985,21 @@ DEFUN(neighbor_disable_addpath_rx,
struct peer *peer;
afi_t afi = bgp_node_afi(vty);
safi_t safi = bgp_node_safi(vty);
+ int ret;
+ int action;
peer = peer_and_group_lookup_vty(vty, peer_str);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
- return peer_af_flag_set_vty(vty, peer_str, afi, safi,
- PEER_FLAG_DISABLE_ADDPATH_RX);
+ action = bgp_addpath_capability_action(peer->addpath_type[afi][safi], 0);
+
+ ret = peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_DISABLE_ADDPATH_RX);
+
+ bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_ADDPATH, action);
+
+ return ret;
}
DEFUN(no_neighbor_disable_addpath_rx,
@@ -8861,13 +9014,21 @@ DEFUN(no_neighbor_disable_addpath_rx,
struct peer *peer;
afi_t afi = bgp_node_afi(vty);
safi_t safi = bgp_node_safi(vty);
+ int ret;
+ int action;
peer = peer_and_group_lookup_vty(vty, peer_str);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
- return peer_af_flag_unset_vty(vty, peer_str, afi, safi,
- PEER_FLAG_DISABLE_ADDPATH_RX);
+ action = bgp_addpath_capability_action(peer->addpath_type[afi][safi], 0);
+
+ ret = peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_DISABLE_ADDPATH_RX);
+
+ bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_ADDPATH, action);
+
+ return ret;
}
DEFUN (neighbor_addpath_tx_all_paths,
@@ -8879,13 +9040,15 @@ DEFUN (neighbor_addpath_tx_all_paths,
{
int idx_peer = 1;
struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
- bgp_addpath_set_peer_type(peer, bgp_node_afi(vty), bgp_node_safi(vty),
- BGP_ADDPATH_ALL, 0);
+ bgp_addpath_set_peer_type(peer, afi, safi, BGP_ADDPATH_ALL, 0);
+
return CMD_SUCCESS;
}
@@ -8905,20 +9068,20 @@ DEFUN (no_neighbor_addpath_tx_all_paths,
{
int idx_peer = 2;
struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
- if (peer->addpath_type[bgp_node_afi(vty)][bgp_node_safi(vty)]
- != BGP_ADDPATH_ALL) {
+ if (peer->addpath_type[afi][safi] != BGP_ADDPATH_ALL) {
vty_out(vty,
"%% Peer not currently configured to transmit all paths.");
return CMD_WARNING_CONFIG_FAILED;
}
- bgp_addpath_set_peer_type(peer, bgp_node_afi(vty), bgp_node_safi(vty),
- BGP_ADDPATH_NONE, 0);
+ bgp_addpath_set_peer_type(peer, afi, safi, BGP_ADDPATH_NONE, 0);
return CMD_SUCCESS;
}
@@ -9298,13 +9461,13 @@ DEFPY (af_rd_vpn_export,
bgp_get_default(), bgp);
if (yes) {
- bgp->vpn_policy[afi].tovpn_rd_pretty =
- XSTRDUP(MTYPE_BGP, rd_str);
+ bgp->vpn_policy[afi].tovpn_rd_pretty = XSTRDUP(MTYPE_BGP_NAME,
+ rd_str);
bgp->vpn_policy[afi].tovpn_rd = prd;
SET_FLAG(bgp->vpn_policy[afi].flags,
BGP_VPN_POLICY_TOVPN_RD_SET);
} else {
- XFREE(MTYPE_BGP, bgp->vpn_policy[afi].tovpn_rd_pretty);
+ XFREE(MTYPE_BGP_NAME, bgp->vpn_policy[afi].tovpn_rd_pretty);
UNSET_FLAG(bgp->vpn_policy[afi].flags,
BGP_VPN_POLICY_TOVPN_RD_SET);
}
@@ -9394,7 +9557,7 @@ DEFPY (af_label_vpn_export,
"Automatically assign a label\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
- mpls_label_t label = MPLS_LABEL_NONE;
+ mpls_label_t label = (mpls_label_t)label_val;
afi_t afi;
int idx = 0;
bool yes = true;
@@ -9402,24 +9565,28 @@ DEFPY (af_label_vpn_export,
if (argv_find(argv, argc, "no", &idx))
yes = false;
- /* If "no ...", squash trailing parameter */
- if (!yes)
- label_auto = NULL;
-
- if (yes) {
- if (!label_auto)
- label = label_val; /* parser should force unsigned */
- }
-
afi = vpn_policy_getafi(vty, bgp, false);
if (afi == AFI_MAX)
return CMD_WARNING_CONFIG_FAILED;
-
- if (label_auto && CHECK_FLAG(bgp->vpn_policy[afi].flags,
- BGP_VPN_POLICY_TOVPN_LABEL_AUTO))
- /* no change */
- return CMD_SUCCESS;
+ if (yes) {
+ if (label_auto && CHECK_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_AUTO))
+ /* no change */
+ return CMD_SUCCESS;
+ if (!label_auto && label == bgp->vpn_policy[afi].tovpn_label)
+ /* no change */
+ return CMD_SUCCESS;
+ } else {
+ if (label_auto && !CHECK_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_AUTO))
+ /* no match */
+ return CMD_WARNING_CONFIG_FAILED;
+ if (!label_auto && label_val &&
+ label != bgp->vpn_policy[afi].tovpn_label)
+ /* no change */
+ return CMD_WARNING_CONFIG_FAILED;
+ }
/*
* pre-change: un-export vpn routes (vpn->vrf routes unaffected)
@@ -9427,9 +9594,16 @@ DEFPY (af_label_vpn_export,
vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
bgp_get_default(), bgp);
- if (!label_auto && CHECK_FLAG(bgp->vpn_policy[afi].flags,
- BGP_VPN_POLICY_TOVPN_LABEL_AUTO)) {
+ if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_MANUAL_REG)) {
+ bgp_zebra_release_label_range(bgp->vpn_policy[afi].tovpn_label,
+ bgp->vpn_policy[afi].tovpn_label);
+ UNSET_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_MANUAL_REG);
+ } else if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_AUTO)) {
+ /* release any previous auto label */
if (bgp->vpn_policy[afi].tovpn_label != MPLS_LABEL_NONE) {
/*
@@ -9446,16 +9620,32 @@ DEFPY (af_label_vpn_export,
&bgp->vpn_policy[afi],
bgp->vpn_policy[afi].tovpn_label);
}
- UNSET_FLAG(bgp->vpn_policy[afi].flags,
- BGP_VPN_POLICY_TOVPN_LABEL_AUTO);
}
- bgp->vpn_policy[afi].tovpn_label = label;
- if (label_auto) {
- SET_FLAG(bgp->vpn_policy[afi].flags,
- BGP_VPN_POLICY_TOVPN_LABEL_AUTO);
- bgp_lp_get(LP_TYPE_VRF, &bgp->vpn_policy[afi],
- vpn_leak_label_callback);
+ if (yes) {
+ if (label_auto) {
+ SET_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_AUTO);
+ /* fetch a label */
+ bgp->vpn_policy[afi].tovpn_label = MPLS_LABEL_NONE;
+ bgp_lp_get(LP_TYPE_VRF, &bgp->vpn_policy[afi],
+ vpn_leak_label_callback);
+ } else {
+ bgp->vpn_policy[afi].tovpn_label = label;
+ UNSET_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_AUTO);
+ if (bgp->vpn_policy[afi].tovpn_label >=
+ MPLS_LABEL_UNRESERVED_MIN &&
+ bgp_zebra_request_label_range(bgp->vpn_policy[afi]
+ .tovpn_label,
+ 1, false))
+ SET_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_MANUAL_REG);
+ }
+ } else {
+ UNSET_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_AUTO);
+ bgp->vpn_policy[afi].tovpn_label = MPLS_LABEL_NONE;
}
/* post-change: re-export vpn routes */
@@ -10506,7 +10696,7 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name,
/* one clear bgp command to rule them all */
DEFUN (clear_ip_bgp_all,
clear_ip_bgp_all_cmd,
- "clear [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|l2vpn> [<unicast|multicast|vpn|labeled-unicast|flowspec|evpn>]] <*|A.B.C.D$neighbor|X:X::X:X$neighbor|WORD$neighbor|ASNUM|external|peer-group PGNAME> [<soft [<in|out>]|in [prefix-filter]|out|message-stats>]",
+ "clear [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|l2vpn> [<unicast|multicast|vpn|labeled-unicast|flowspec|evpn>]] <*|A.B.C.D$neighbor|X:X::X:X$neighbor|WORD$neighbor|ASNUM|external|peer-group PGNAME> [<soft [<in|out>]|in [prefix-filter]|out|message-stats|capabilities>]",
CLEAR_STR
IP_STR
BGP_STR
@@ -10529,7 +10719,8 @@ DEFUN (clear_ip_bgp_all,
BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n"
BGP_SOFT_OUT_STR
- "Reset message statistics\n")
+ "Reset message statistics\n"
+ "Resend capabilities\n")
{
char *vrf = NULL;
@@ -10586,7 +10777,7 @@ DEFUN (clear_ip_bgp_all,
clr_sort = clear_external;
}
- /* [<soft [<in|out>]|in [prefix-filter]|out|message-stats>] */
+ /* [<soft [<in|out>]|in [prefix-filter]|out|message-stats|capabilities>] */
if (argv_find(argv, argc, "soft", &idx)) {
if (argv_find(argv, argc, "in", &idx)
|| argv_find(argv, argc, "out", &idx))
@@ -10603,6 +10794,8 @@ DEFUN (clear_ip_bgp_all,
clr_type = BGP_CLEAR_SOFT_OUT;
} else if (argv_find(argv, argc, "message-stats", &idx)) {
clr_type = BGP_CLEAR_MESSAGE_STATS;
+ } else if (argv_find(argv, argc, "capabilities", &idx)) {
+ clr_type = BGP_CLEAR_CAPABILITIES;
} else
clr_type = BGP_CLEAR_SOFT_NONE;
@@ -11534,8 +11727,9 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
: bgp->name);
} else {
vty_out(vty,
- "BGP router identifier %pI4, local AS number %s vrf-id %d",
+ "BGP router identifier %pI4, local AS number %s %s vrf-id %d",
&bgp->router_id, bgp->as_pretty,
+ bgp->name_pretty,
bgp->vrf_id == VRF_UNKNOWN
? -1
: (int)bgp->vrf_id);
@@ -12152,12 +12346,10 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
safi,
true));
} else {
- vty_out(vty,
- "\n%s Summary (%s):\n",
+ vty_out(vty, "\n%s Summary:\n",
get_afi_safi_str(afi,
safi,
- false),
- bgp->name_pretty);
+ false));
}
}
bgp_show_summary(vty, bgp, afi, safi, fpeer,
@@ -16780,10 +16972,11 @@ ALIAS_HIDDEN(
DEFUN (bgp_redistribute_ipv4_ospf,
bgp_redistribute_ipv4_ospf_cmd,
- "redistribute <ospf|table> (1-65535)",
+ "redistribute <ospf|table|table-direct> (1-65535)",
"Redistribute information from another routing protocol\n"
"Open Shortest Path First (OSPFv2)\n"
"Non-main Kernel Routing Table\n"
+ "Non-main Kernel Routing Table - Direct\n"
"Instance ID/Table ID\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
@@ -16803,7 +16996,18 @@ DEFUN (bgp_redistribute_ipv4_ospf,
argv[idx_ospf_table]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
- protocol = ZEBRA_ROUTE_TABLE;
+ if (strncmp(argv[idx_ospf_table]->arg, "table-direct",
+ strlen("table-direct")) == 0) {
+ protocol = ZEBRA_ROUTE_TABLE_DIRECT;
+ if (instance == RT_TABLE_MAIN ||
+ instance == RT_TABLE_LOCAL) {
+ vty_out(vty,
+ "%% 'table-direct', can not use %u routing table\n",
+ instance);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ } else
+ protocol = ZEBRA_ROUTE_TABLE;
}
bgp_redist_add(bgp, AFI_IP, protocol, instance);
@@ -16811,18 +17015,20 @@ DEFUN (bgp_redistribute_ipv4_ospf,
}
ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf, bgp_redistribute_ipv4_ospf_hidden_cmd,
- "redistribute <ospf|table> (1-65535)",
+ "redistribute <ospf|table|table-direct> (1-65535)",
"Redistribute information from another routing protocol\n"
"Open Shortest Path First (OSPFv2)\n"
"Non-main Kernel Routing Table\n"
+ "Non-main Kernel Routing Table - Direct\n"
"Instance ID/Table ID\n")
DEFUN (bgp_redistribute_ipv4_ospf_rmap,
bgp_redistribute_ipv4_ospf_rmap_cmd,
- "redistribute <ospf|table> (1-65535) route-map RMAP_NAME",
+ "redistribute <ospf|table|table-direct> (1-65535) route-map RMAP_NAME",
"Redistribute information from another routing protocol\n"
"Open Shortest Path First (OSPFv2)\n"
"Non-main Kernel Routing Table\n"
+ "Non-main Kernel Routing Table - Direct\n"
"Instance ID/Table ID\n"
"Route map reference\n"
"Pointer to route-map entries\n")
@@ -16838,6 +17044,8 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap,
struct route_map *route_map =
route_map_lookup_warn_noexist(vty, argv[idx_word]->arg);
+ instance = strtoul(argv[idx_number]->arg, NULL, 10);
+
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
protocol = ZEBRA_ROUTE_OSPF;
else {
@@ -16847,10 +17055,20 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap,
argv[idx_ospf_table]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
- protocol = ZEBRA_ROUTE_TABLE;
+ if (strncmp(argv[idx_ospf_table]->arg, "table-direct",
+ strlen("table-direct")) == 0) {
+ protocol = ZEBRA_ROUTE_TABLE_DIRECT;
+ if (instance == RT_TABLE_MAIN ||
+ instance == RT_TABLE_LOCAL) {
+ vty_out(vty,
+ "%% 'table-direct', can not use %u routing table\n",
+ instance);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ } else
+ protocol = ZEBRA_ROUTE_TABLE;
}
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
changed =
bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map);
@@ -16859,20 +17077,22 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap,
ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf_rmap,
bgp_redistribute_ipv4_ospf_rmap_hidden_cmd,
- "redistribute <ospf|table> (1-65535) route-map RMAP_NAME",
+ "redistribute <ospf|table|table-direct> (1-65535) route-map RMAP_NAME",
"Redistribute information from another routing protocol\n"
"Open Shortest Path First (OSPFv2)\n"
"Non-main Kernel Routing Table\n"
+ "Non-main Kernel Routing Table - Direct\n"
"Instance ID/Table ID\n"
"Route map reference\n"
"Pointer to route-map entries\n")
DEFUN (bgp_redistribute_ipv4_ospf_metric,
bgp_redistribute_ipv4_ospf_metric_cmd,
- "redistribute <ospf|table> (1-65535) metric (0-4294967295)",
+ "redistribute <ospf|table|table-direct> (1-65535) metric (0-4294967295)",
"Redistribute information from another routing protocol\n"
"Open Shortest Path First (OSPFv2)\n"
"Non-main Kernel Routing Table\n"
+ "Non-main Kernel Routing Table - Direct\n"
"Instance ID/Table ID\n"
"Metric for redistributed routes\n"
"Default metric\n")
@@ -16887,6 +17107,8 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric,
int protocol;
bool changed;
+ instance = strtoul(argv[idx_number]->arg, NULL, 10);
+
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
protocol = ZEBRA_ROUTE_OSPF;
else {
@@ -16896,10 +17118,20 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric,
argv[idx_ospf_table]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
- protocol = ZEBRA_ROUTE_TABLE;
+ if (strncmp(argv[idx_ospf_table]->arg, "table-direct",
+ strlen("table-direct")) == 0) {
+ protocol = ZEBRA_ROUTE_TABLE_DIRECT;
+ if (instance == RT_TABLE_MAIN ||
+ instance == RT_TABLE_LOCAL) {
+ vty_out(vty,
+ "%% 'table-direct', can not use %u routing table\n",
+ instance);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ } else
+ protocol = ZEBRA_ROUTE_TABLE;
}
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
@@ -16910,20 +17142,22 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric,
ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf_metric,
bgp_redistribute_ipv4_ospf_metric_hidden_cmd,
- "redistribute <ospf|table> (1-65535) metric (0-4294967295)",
+ "redistribute <ospf|table|table-direct> (1-65535) metric (0-4294967295)",
"Redistribute information from another routing protocol\n"
"Open Shortest Path First (OSPFv2)\n"
"Non-main Kernel Routing Table\n"
+ "Non-main Kernel Routing Table - Direct\n"
"Instance ID/Table ID\n"
"Metric for redistributed routes\n"
"Default metric\n")
DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric,
bgp_redistribute_ipv4_ospf_rmap_metric_cmd,
- "redistribute <ospf|table> (1-65535) route-map RMAP_NAME metric (0-4294967295)",
+ "redistribute <ospf|table|table-direct> (1-65535) route-map RMAP_NAME metric (0-4294967295)",
"Redistribute information from another routing protocol\n"
"Open Shortest Path First (OSPFv2)\n"
"Non-main Kernel Routing Table\n"
+ "Non-main Kernel Routing Table - Direct\n"
"Instance ID/Table ID\n"
"Route map reference\n"
"Pointer to route-map entries\n"
@@ -16943,6 +17177,8 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric,
struct route_map *route_map =
route_map_lookup_warn_noexist(vty, argv[idx_word]->arg);
+ instance = strtoul(argv[idx_number]->arg, NULL, 10);
+
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
protocol = ZEBRA_ROUTE_OSPF;
else {
@@ -16952,10 +17188,20 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric,
argv[idx_ospf_table]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
- protocol = ZEBRA_ROUTE_TABLE;
+ if (strncmp(argv[idx_ospf_table]->arg, "table-direct",
+ strlen("table-direct")) == 0) {
+ protocol = ZEBRA_ROUTE_TABLE_DIRECT;
+ if (instance == RT_TABLE_MAIN ||
+ instance == RT_TABLE_LOCAL) {
+ vty_out(vty,
+ "%% 'table-direct', can not use %u routing table\n",
+ instance);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ } else
+ protocol = ZEBRA_ROUTE_TABLE;
}
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
@@ -16969,10 +17215,11 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric,
ALIAS_HIDDEN(
bgp_redistribute_ipv4_ospf_rmap_metric,
bgp_redistribute_ipv4_ospf_rmap_metric_hidden_cmd,
- "redistribute <ospf|table> (1-65535) route-map RMAP_NAME metric (0-4294967295)",
+ "redistribute <ospf|table|table-direct> (1-65535) route-map RMAP_NAME metric (0-4294967295)",
"Redistribute information from another routing protocol\n"
"Open Shortest Path First (OSPFv2)\n"
"Non-main Kernel Routing Table\n"
+ "Non-main Kernel Routing Table - Direct\n"
"Instance ID/Table ID\n"
"Route map reference\n"
"Pointer to route-map entries\n"
@@ -16981,10 +17228,11 @@ ALIAS_HIDDEN(
DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap,
bgp_redistribute_ipv4_ospf_metric_rmap_cmd,
- "redistribute <ospf|table> (1-65535) metric (0-4294967295) route-map RMAP_NAME",
+ "redistribute <ospf|table|table-direct> (1-65535) metric (0-4294967295) route-map RMAP_NAME",
"Redistribute information from another routing protocol\n"
"Open Shortest Path First (OSPFv2)\n"
"Non-main Kernel Routing Table\n"
+ "Non-main Kernel Routing Table - Direct\n"
"Instance ID/Table ID\n"
"Metric for redistributed routes\n"
"Default metric\n"
@@ -17004,6 +17252,8 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap,
struct route_map *route_map =
route_map_lookup_warn_noexist(vty, argv[idx_word]->arg);
+ instance = strtoul(argv[idx_number]->arg, NULL, 10);
+
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
protocol = ZEBRA_ROUTE_OSPF;
else {
@@ -17012,8 +17262,18 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap,
"%% Only default BGP instance can use '%s'\n",
argv[idx_ospf_table]->arg);
return CMD_WARNING_CONFIG_FAILED;
- }
- protocol = ZEBRA_ROUTE_TABLE;
+ } else if (strncmp(argv[idx_ospf_table]->arg, "table-direct",
+ strlen("table-direct")) == 0) {
+ protocol = ZEBRA_ROUTE_TABLE_DIRECT;
+ if (instance == RT_TABLE_MAIN ||
+ instance == RT_TABLE_LOCAL) {
+ vty_out(vty,
+ "%% 'table-direct', can not use %u routing table\n",
+ instance);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ } else
+ protocol = ZEBRA_ROUTE_TABLE;
}
instance = strtoul(argv[idx_number]->arg, NULL, 10);
@@ -17030,10 +17290,11 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap,
ALIAS_HIDDEN(
bgp_redistribute_ipv4_ospf_metric_rmap,
bgp_redistribute_ipv4_ospf_metric_rmap_hidden_cmd,
- "redistribute <ospf|table> (1-65535) metric (0-4294967295) route-map RMAP_NAME",
+ "redistribute <ospf|table|table-direct> (1-65535) metric (0-4294967295) route-map RMAP_NAME",
"Redistribute information from another routing protocol\n"
"Open Shortest Path First (OSPFv2)\n"
"Non-main Kernel Routing Table\n"
+ "Non-main Kernel Routing Table - Direct\n"
"Instance ID/Table ID\n"
"Metric for redistributed routes\n"
"Default metric\n"
@@ -17042,11 +17303,12 @@ ALIAS_HIDDEN(
DEFUN (no_bgp_redistribute_ipv4_ospf,
no_bgp_redistribute_ipv4_ospf_cmd,
- "no redistribute <ospf|table> (1-65535) [{metric (0-4294967295)|route-map RMAP_NAME}]",
+ "no redistribute <ospf|table|table-direct> (1-65535) [{metric (0-4294967295)|route-map RMAP_NAME}]",
NO_STR
"Redistribute information from another routing protocol\n"
"Open Shortest Path First (OSPFv2)\n"
"Non-main Kernel Routing Table\n"
+ "Non-main Kernel Routing Table - Direct\n"
"Instance ID/Table ID\n"
"Metric for redistributed routes\n"
"Default metric\n"
@@ -17059,6 +17321,8 @@ DEFUN (no_bgp_redistribute_ipv4_ospf,
unsigned short instance;
int protocol;
+ instance = strtoul(argv[idx_number]->arg, NULL, 10);
+
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
protocol = ZEBRA_ROUTE_OSPF;
else {
@@ -17068,21 +17332,32 @@ DEFUN (no_bgp_redistribute_ipv4_ospf,
argv[idx_ospf_table]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
- protocol = ZEBRA_ROUTE_TABLE;
+ if (strncmp(argv[idx_ospf_table]->arg, "table-direct",
+ strlen("table-direct")) == 0) {
+ protocol = ZEBRA_ROUTE_TABLE_DIRECT;
+ if (instance == RT_TABLE_MAIN ||
+ instance == RT_TABLE_LOCAL) {
+ vty_out(vty,
+ "%% 'table-direct', can not use %u routing table\n",
+ instance);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ } else
+ protocol = ZEBRA_ROUTE_TABLE;
}
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
bgp_redistribute_unset(bgp, AFI_IP, protocol, instance);
return CMD_SUCCESS;
}
ALIAS_HIDDEN(
no_bgp_redistribute_ipv4_ospf, no_bgp_redistribute_ipv4_ospf_hidden_cmd,
- "no redistribute <ospf|table> (1-65535) [{metric (0-4294967295)|route-map RMAP_NAME}]",
+ "no redistribute <ospf|table|table-direct> (1-65535) [{metric (0-4294967295)|route-map RMAP_NAME}]",
NO_STR
"Redistribute information from another routing protocol\n"
"Open Shortest Path First (OSPFv2)\n"
"Non-main Kernel Routing Table\n"
+ "Non-main Kernel Routing Table - Direct\n"
"Instance ID/Table ID\n"
"Metric for redistributed routes\n"
"Default metric\n"
@@ -17427,8 +17702,8 @@ bool peergroup_flag_check(struct peer *peer, uint64_t flag)
return !!CHECK_FLAG(peer->flags_override, flag);
}
-static bool peergroup_af_flag_check(struct peer *peer, afi_t afi, safi_t safi,
- uint64_t flag)
+bool peergroup_af_flag_check(struct peer *peer, afi_t afi, safi_t safi,
+ uint64_t flag)
{
if (!peer_group_active(peer)) {
if (CHECK_FLAG(peer->af_flags_invert[afi][safi], flag))
@@ -17876,6 +18151,9 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
? " strict-mode"
: "");
+ if (peer->sub_sort == BGP_PEER_EBGP_OAD)
+ vty_out(vty, " neighbor %s oad\n", addr);
+
/* ttl-security hops */
if (peer->gtsm_hops != BGP_GTSM_HOPS_DISABLED) {
if (!peer_group_active(peer)
@@ -17900,8 +18178,13 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
addr);
/* enforce-first-as */
- if (peergroup_flag_check(peer, PEER_FLAG_ENFORCE_FIRST_AS))
- vty_out(vty, " neighbor %s enforce-first-as\n", addr);
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_ENFORCE_FIRST_AS)) {
+ if (!peergroup_flag_check(peer, PEER_FLAG_ENFORCE_FIRST_AS))
+ vty_out(vty, " no neighbor %s enforce-first-as\n", addr);
+ } else {
+ if (peergroup_flag_check(peer, PEER_FLAG_ENFORCE_FIRST_AS))
+ vty_out(vty, " neighbor %s enforce-first-as\n", addr);
+ }
/* update-source */
if (peergroup_flag_check(peer, PEER_FLAG_UPDATE_SOURCE)) {
@@ -17966,14 +18249,30 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
}
/* capability software-version */
- if (peergroup_flag_check(peer, PEER_FLAG_CAPABILITY_SOFT_VERSION))
- vty_out(vty, " neighbor %s capability software-version\n",
- addr);
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_SOFT_VERSION_CAPABILITY)) {
+ if (!peergroup_flag_check(peer,
+ PEER_FLAG_CAPABILITY_SOFT_VERSION))
+ vty_out(vty,
+ " no neighbor %s capability software-version\n",
+ addr);
+ } else {
+ if (peergroup_flag_check(peer,
+ PEER_FLAG_CAPABILITY_SOFT_VERSION))
+ vty_out(vty,
+ " neighbor %s capability software-version\n",
+ addr);
+ }
/* dont-capability-negotiation */
if (peergroup_flag_check(peer, PEER_FLAG_DONT_CAPABILITY))
vty_out(vty, " neighbor %s dont-capability-negotiate\n", addr);
+ /* capability fqdn */
+ if (peergroup_flag_check(peer, PEER_FLAG_CAPABILITY_FQDN))
+ vty_out(vty,
+ " no neighbor %s capability fqdn\n",
+ addr);
+
/* override-capability */
if (peergroup_flag_check(peer, PEER_FLAG_OVERRIDE_CAPABILITY))
vty_out(vty, " neighbor %s override-capability\n", addr);
@@ -18190,6 +18489,12 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
if (flag_slcomm)
vty_out(vty, " no neighbor %s send-community large\n",
addr);
+
+ if (peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_SEND_EXT_COMMUNITY_RPKI))
+ vty_out(vty,
+ " no neighbor %s send-community extended rpki\n",
+ addr);
}
/* Default information */
@@ -18434,6 +18739,8 @@ int bgp_config_write(struct vty *vty)
safi_t safi;
uint32_t tovpn_sid_index = 0;
+ hook_call(bgp_snmp_traps_config_write, vty);
+
if (bm->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER)
vty_out(vty, "bgp route-map delay-timer %u\n",
bm->rmap_update_timer);
@@ -18524,6 +18831,15 @@ int bgp_config_write(struct vty *vty)
? ""
: "no ");
+ /* bgp enforce-first-as */
+ if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_ENFORCE_FIRST_AS) !=
+ SAVE_BGP_ENFORCE_FIRST_AS)
+ vty_out(vty, " %sbgp enforce-first-as\n",
+ CHECK_FLAG(bgp->flags,
+ BGP_FLAG_ENFORCE_FIRST_AS)
+ ? ""
+ : "no ");
+
if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_IPV4_EXPLICIT_NULL) &&
!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_IPV6_EXPLICIT_NULL))
vty_out(vty, " bgp labeled-unicast explicit-null\n");
@@ -19443,6 +19759,9 @@ void bgp_vty_init(void)
install_element(BGP_NODE, &neighbor_role_strict_cmd);
install_element(BGP_NODE, &no_neighbor_role_cmd);
+ /* "neighbor oad" commands. */
+ install_element(BGP_NODE, &neighbor_oad_cmd);
+
/* "neighbor aigp" commands. */
install_element(BGP_NODE, &neighbor_aigp_cmd);
@@ -19516,6 +19835,9 @@ void bgp_vty_init(void)
install_element(BGP_NODE, &bgp_ebgp_requires_policy_cmd);
install_element(BGP_NODE, &no_bgp_ebgp_requires_policy_cmd);
+ /* bgp enforce-first-as */
+ install_element(BGP_NODE, &bgp_enforce_first_as_cmd);
+
/* bgp labeled-unicast explicit-null */
install_element(BGP_NODE, &bgp_lu_uses_explicit_null_cmd);
@@ -20058,6 +20380,15 @@ void bgp_vty_init(void)
install_element(BGP_VPNV6_NODE, &neighbor_send_community_type_cmd);
install_element(BGP_VPNV6_NODE, &no_neighbor_send_community_cmd);
install_element(BGP_VPNV6_NODE, &no_neighbor_send_community_type_cmd);
+ install_element(BGP_NODE, &neighbor_ecommunity_rpki_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_ecommunity_rpki_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_ecommunity_rpki_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_ecommunity_rpki_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_ecommunity_rpki_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_ecommunity_rpki_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_ecommunity_rpki_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_ecommunity_rpki_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_ecommunity_rpki_cmd);
/* "neighbor route-reflector" commands.*/
install_element(BGP_NODE, &neighbor_route_reflector_client_hidden_cmd);
@@ -20293,6 +20624,9 @@ void bgp_vty_init(void)
install_element(BGP_NODE, &neighbor_dont_capability_negotiate_cmd);
install_element(BGP_NODE, &no_neighbor_dont_capability_negotiate_cmd);
+ /* "neighbor capability fqdn" command. */
+ install_element(BGP_NODE, &neighbor_capability_fqdn_cmd);
+
/* "neighbor ebgp-multihop" commands. */
install_element(BGP_NODE, &neighbor_ebgp_multihop_cmd);
install_element(BGP_NODE, &neighbor_ebgp_multihop_ttl_cmd);
diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h
index a105b6d..4955e4c 100644
--- a/bgpd/bgp_vty.h
+++ b/bgpd/bgp_vty.h
@@ -171,5 +171,7 @@ 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);
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);
#endif /* _QUAGGA_BGP_VTY_H */
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 5b69de0..87f2e55 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -24,6 +24,7 @@
#include "mpls.h"
#include "vxlan.h"
#include "pbr.h"
+#include "frrdistance.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_route.h"
@@ -72,9 +73,10 @@ static inline bool bgp_install_info_to_zebra(struct bgp *bgp)
return false;
if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
- zlog_debug(
- "%s: No zebra instance to talk to, not installing information",
- __func__);
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug(
+ "%s: No zebra instance to talk to, not installing information",
+ __func__);
return false;
}
@@ -98,13 +100,6 @@ static int bgp_router_id_update(ZAPI_CALLBACK_ARGS)
return 0;
}
-/* Nexthop update message from zebra. */
-static int bgp_read_nexthop_update(ZAPI_CALLBACK_ARGS)
-{
- bgp_parse_nexthop_update(cmd, vrf_id);
- return 0;
-}
-
/* Set or clear interface on which unnumbered neighbor is configured. This
* would in turn cause BGP to initiate or turn off IPv6 RAs on this
* interface.
@@ -151,7 +146,6 @@ static void bgp_start_interface_nbrs(struct bgp *bgp, struct interface *ifp)
static void bgp_nbr_connected_add(struct bgp *bgp, struct nbr_connected *ifc)
{
- struct listnode *node;
struct connected *connected;
struct interface *ifp;
struct prefix *p;
@@ -160,7 +154,7 @@ static void bgp_nbr_connected_add(struct bgp *bgp, struct nbr_connected *ifc)
* valid local address on the interface.
*/
ifp = ifc->ifp;
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
p = connected->address;
if (p->family == AF_INET6
&& IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6))
@@ -232,7 +226,7 @@ static int bgp_ifp_up(struct interface *ifp)
if (!bgp)
return 0;
- for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, c))
+ frr_each (if_connected, ifp->connected, c)
bgp_connected_add(bgp, c);
for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc))
@@ -263,7 +257,7 @@ static int bgp_ifp_down(struct interface *ifp)
if (!bgp)
return 0;
- for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, c))
+ frr_each (if_connected, ifp->connected, c)
bgp_connected_delete(bgp, c);
for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc))
@@ -564,7 +558,6 @@ static int zebra_read_route(ZAPI_CALLBACK_ARGS)
struct interface *if_lookup_by_ipv4(struct in_addr *addr, vrf_id_t vrf_id)
{
struct vrf *vrf;
- struct listnode *cnode;
struct interface *ifp;
struct connected *connected;
struct prefix_ipv4 p;
@@ -579,7 +572,7 @@ struct interface *if_lookup_by_ipv4(struct in_addr *addr, vrf_id_t vrf_id)
p.prefixlen = IPV4_MAX_BITLEN;
FOR_ALL_INTERFACES (vrf, ifp) {
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
cp = connected->address;
if (cp->family == AF_INET)
@@ -593,7 +586,6 @@ struct interface *if_lookup_by_ipv4(struct in_addr *addr, vrf_id_t vrf_id)
struct interface *if_lookup_by_ipv4_exact(struct in_addr *addr, vrf_id_t vrf_id)
{
struct vrf *vrf;
- struct listnode *cnode;
struct interface *ifp;
struct connected *connected;
struct prefix *cp;
@@ -603,7 +595,7 @@ struct interface *if_lookup_by_ipv4_exact(struct in_addr *addr, vrf_id_t vrf_id)
return NULL;
FOR_ALL_INTERFACES (vrf, ifp) {
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
cp = connected->address;
if (cp->family == AF_INET)
@@ -618,7 +610,6 @@ struct interface *if_lookup_by_ipv6(struct in6_addr *addr, ifindex_t ifindex,
vrf_id_t vrf_id)
{
struct vrf *vrf;
- struct listnode *cnode;
struct interface *ifp;
struct connected *connected;
struct prefix_ipv6 p;
@@ -633,7 +624,7 @@ struct interface *if_lookup_by_ipv6(struct in6_addr *addr, ifindex_t ifindex,
p.prefixlen = IPV6_MAX_BITLEN;
FOR_ALL_INTERFACES (vrf, ifp) {
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
cp = connected->address;
if (cp->family == AF_INET6)
@@ -654,7 +645,6 @@ struct interface *if_lookup_by_ipv6_exact(struct in6_addr *addr,
ifindex_t ifindex, vrf_id_t vrf_id)
{
struct vrf *vrf;
- struct listnode *cnode;
struct interface *ifp;
struct connected *connected;
struct prefix *cp;
@@ -664,7 +654,7 @@ struct interface *if_lookup_by_ipv6_exact(struct in6_addr *addr,
return NULL;
FOR_ALL_INTERFACES (vrf, ifp) {
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
cp = connected->address;
if (cp->family == AF_INET6)
@@ -683,11 +673,10 @@ struct interface *if_lookup_by_ipv6_exact(struct in6_addr *addr,
static int if_get_ipv6_global(struct interface *ifp, struct in6_addr *addr)
{
- struct listnode *cnode;
struct connected *connected;
struct prefix *cp;
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
cp = connected->address;
if (cp->family == AF_INET6)
@@ -701,11 +690,10 @@ static int if_get_ipv6_global(struct interface *ifp, struct in6_addr *addr)
static bool if_get_ipv6_local(struct interface *ifp, struct in6_addr *addr)
{
- struct listnode *cnode;
struct connected *connected;
struct prefix *cp;
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
cp = connected->address;
if (cp->family == AF_INET6)
@@ -719,11 +707,10 @@ static bool if_get_ipv6_local(struct interface *ifp, struct in6_addr *addr)
static int if_get_ipv4_address(struct interface *ifp, struct in_addr *addr)
{
- struct listnode *cnode;
struct connected *connected;
struct prefix *cp;
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
cp = connected->address;
if ((cp->family == AF_INET)
&& !ipv4_martian(&(cp->u.prefix4))) {
@@ -1207,83 +1194,49 @@ static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
}
static bool bgp_zebra_use_nhop_weighted(struct bgp *bgp, struct attr *attr,
- uint64_t tot_bw, uint32_t *nh_weight)
+ uint32_t *nh_weight)
{
- uint32_t bw;
- uint64_t tmp;
-
- bw = attr->link_bw;
/* zero link-bandwidth and link-bandwidth not present are treated
* as the same situation.
*/
- if (!bw) {
+ if (!attr->link_bw) {
/* the only situations should be if we're either told
* to skip or use default weight.
*/
if (bgp->lb_handling == BGP_LINK_BW_SKIP_MISSING)
return false;
*nh_weight = BGP_ZEBRA_DEFAULT_NHOP_WEIGHT;
- } else {
- tmp = (uint64_t)bw * 100;
- *nh_weight = ((uint32_t)(tmp / tot_bw));
- }
+ } else
+ *nh_weight = attr->link_bw;
return true;
}
-void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
- struct bgp_path_info *info, struct bgp *bgp, afi_t afi,
- safi_t safi)
+static void bgp_zebra_announce_parse_nexthop(
+ struct bgp_path_info *info, const struct prefix *p, struct bgp *bgp,
+ struct zapi_route *api, unsigned int *valid_nh_count, afi_t afi,
+ safi_t safi, uint32_t *nhg_id, uint32_t *metric, route_tag_t *tag,
+ bool *allow_recursion)
{
- struct zapi_route api = { 0 };
struct zapi_nexthop *api_nh;
int nh_family;
- unsigned int valid_nh_count = 0;
- bool allow_recursion = false;
- uint8_t distance;
- struct peer *peer;
struct bgp_path_info *mpinfo;
struct bgp *bgp_orig;
- uint32_t metric;
struct attr local_attr;
struct bgp_path_info local_info;
struct bgp_path_info *mpinfo_cp = &local_info;
- route_tag_t tag;
mpls_label_t *labels;
uint32_t num_labels = 0;
mpls_label_t nh_label;
int nh_othervrf = 0;
bool nh_updated = false;
bool do_wt_ecmp;
- uint64_t cum_bw = 0;
- uint32_t nhg_id = 0;
- bool is_add;
uint32_t ttl = 0;
uint32_t bos = 0;
uint32_t exp = 0;
- /*
- * BGP is installing this route and bgp has been configured
- * to suppress announcements until the route has been installed
- * let's set the fact that we expect this route to be installed
- */
- if (BGP_SUPPRESS_FIB_ENABLED(bgp))
- SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
-
- /* Don't try to install if we're not connected to Zebra or Zebra doesn't
- * know of this instance.
- */
- if (!bgp_install_info_to_zebra(bgp))
- return;
-
- if (bgp->main_zebra_update_hold)
- return;
-
- if (safi == SAFI_FLOWSPEC) {
- bgp_pbr_update_entry(bgp, bgp_dest_get_prefix(dest), info, afi,
- safi, true);
- return;
- }
+ /* Determine if we're doing weighted ECMP or not */
+ do_wt_ecmp = bgp_path_info_mpath_chkwtd(bgp, info);
/*
* vrf leaking support (will have only one nexthop)
@@ -1292,62 +1245,10 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
info->extra->vrfleak->bgp_orig)
nh_othervrf = 1;
- /* Make Zebra API structure. */
- api.vrf_id = bgp->vrf_id;
- api.type = ZEBRA_ROUTE_BGP;
- api.safi = safi;
- api.prefix = *p;
- SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
-
- peer = info->peer;
-
- if (info->type == ZEBRA_ROUTE_BGP
- && info->sub_type == BGP_ROUTE_IMPORTED) {
-
- /* Obtain peer from parent */
- if (info->extra && info->extra->vrfleak &&
- info->extra->vrfleak->parent)
- peer = ((struct bgp_path_info *)(info->extra->vrfleak
- ->parent))
- ->peer;
- }
-
- tag = info->attr->tag;
-
- if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED
- || info->sub_type == BGP_ROUTE_AGGREGATE) {
- SET_FLAG(api.flags, ZEBRA_FLAG_IBGP);
- SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
- }
-
- if ((peer->sort == BGP_PEER_EBGP && peer->ttl != BGP_DEFAULT_TTL)
- || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
- || CHECK_FLAG(bgp->flags, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
-
- allow_recursion = true;
-
- if (info->attr->rmap_table_id) {
- SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID);
- api.tableid = info->attr->rmap_table_id;
- }
-
- if (CHECK_FLAG(info->attr->flag, ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR)))
- SET_FLAG(api.message, ZAPI_MESSAGE_SRTE);
-
- /* Metric is currently based on the best-path only */
- metric = info->attr->med;
-
- /* Determine if we're doing weighted ECMP or not */
- do_wt_ecmp = bgp_path_info_mpath_chkwtd(bgp, info);
- if (do_wt_ecmp)
- cum_bw = bgp_path_info_mpath_cumbw(info);
-
/* EVPN MAC-IP routes are installed with a L3 NHG id */
- if (bgp_evpn_path_es_use_nhg(bgp, info, &nhg_id)) {
+ if (nhg_id && bgp_evpn_path_es_use_nhg(bgp, info, nhg_id)) {
mpinfo = NULL;
- api.nhgid = nhg_id;
- if (nhg_id)
- SET_FLAG(api.message, ZAPI_MESSAGE_NHG);
+ zapi_route_set_nhg_id(api, nhg_id);
} else {
mpinfo = info;
}
@@ -1359,7 +1260,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
bool is_evpn;
bool is_parent_evpn;
- if (valid_nh_count >= multipath_num)
+ if (*valid_nh_count >= multipath_num)
break;
*mpinfo_cp = *mpinfo;
@@ -1382,16 +1283,19 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
*/
if (do_wt_ecmp) {
if (!bgp_zebra_use_nhop_weighted(bgp, mpinfo->attr,
- cum_bw, &nh_weight))
+ &nh_weight))
continue;
}
- api_nh = &api.nexthops[valid_nh_count];
+ if (CHECK_FLAG(info->flags, BGP_PATH_SELECTED))
+ api_nh = &api->nexthops[*valid_nh_count];
+ else
+ api_nh = &api->backup_nexthops[*valid_nh_count];
if (CHECK_FLAG(info->attr->flag,
ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR)))
api_nh->srte_color = bgp_attr_get_color(info->attr);
- if (bgp_debug_zebra(&api.prefix)) {
+ if (bgp_debug_zebra(&api->prefix)) {
if (mpinfo->extra) {
zlog_debug("%s: p=%pFX, bgp_is_valid_label: %d",
__func__, p,
@@ -1416,8 +1320,10 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
/* metric/tag is only allowed to be
* overridden on 1st nexthop */
if (mpinfo == info) {
- metric = mpinfo_cp->attr->med;
- tag = mpinfo_cp->attr->tag;
+ if (metric)
+ *metric = mpinfo_cp->attr->med;
+ if (tag)
+ *tag = mpinfo_cp->attr->tag;
}
}
@@ -1458,11 +1364,11 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
/* Allow recursion if it is a multipath group with both
* eBGP and iBGP paths.
*/
- if (!allow_recursion
- && CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX)
- && (mpinfo->peer->sort == BGP_PEER_IBGP
- || mpinfo->peer->sort == BGP_PEER_CONFED))
- allow_recursion = true;
+ if (allow_recursion && !*allow_recursion &&
+ CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX) &&
+ (mpinfo->peer->sort == BGP_PEER_IBGP ||
+ mpinfo->peer->sort == BGP_PEER_CONFED))
+ *allow_recursion = true;
if (mpinfo->extra) {
labels = mpinfo->extra->label;
@@ -1515,7 +1421,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
&exp, &bos);
if (nh_label < MPLS_LABEL_UNRESERVED_MIN) {
- if (bgp_debug_zebra(&api.prefix))
+ if (bgp_debug_zebra(&api->prefix))
zlog_debug(
"skip invalid SRv6 routes: transposition scheme is used, but label is too small");
continue;
@@ -1532,8 +1438,156 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6);
}
- valid_nh_count++;
+ (*valid_nh_count)++;
+ }
+}
+
+static void bgp_debug_zebra_nh(struct zapi_route *api)
+{
+ int i;
+ int nh_family;
+ char nh_buf[INET6_ADDRSTRLEN];
+ char eth_buf[ETHER_ADDR_STRLEN + 7] = { '\0' };
+ char buf1[ETHER_ADDR_STRLEN];
+ char label_buf[20];
+ char sid_buf[20];
+ char segs_buf[256];
+ struct zapi_nexthop *api_nh;
+ int count;
+
+ count = api->nexthop_num;
+ for (i = 0; i < count; i++) {
+ api_nh = &api->nexthops[i];
+ switch (api_nh->type) {
+ case NEXTHOP_TYPE_IFINDEX:
+ nh_buf[0] = '\0';
+ break;
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ nh_family = AF_INET;
+ inet_ntop(nh_family, &api_nh->gate, nh_buf,
+ sizeof(nh_buf));
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ nh_family = AF_INET6;
+ inet_ntop(nh_family, &api_nh->gate, nh_buf,
+ sizeof(nh_buf));
+ break;
+ case NEXTHOP_TYPE_BLACKHOLE:
+ strlcpy(nh_buf, "blackhole", sizeof(nh_buf));
+ break;
+ default:
+ /* Note: add new nexthop case */
+ assert(0);
+ break;
+ }
+
+ label_buf[0] = '\0';
+ eth_buf[0] = '\0';
+ segs_buf[0] = '\0';
+ if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL) &&
+ !CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN))
+ snprintf(label_buf, sizeof(label_buf), "label %u",
+ api_nh->labels[0]);
+ if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6) &&
+ !CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN)) {
+ inet_ntop(AF_INET6, &api_nh->seg6_segs[0], sid_buf,
+ sizeof(sid_buf));
+ snprintf(segs_buf, sizeof(segs_buf), "segs %s", sid_buf);
+ }
+ if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN) &&
+ !is_zero_mac(&api_nh->rmac))
+ snprintf(eth_buf, sizeof(eth_buf), " RMAC %s",
+ prefix_mac2str(&api_nh->rmac, buf1,
+ sizeof(buf1)));
+ zlog_debug(" nhop [%d]: %s if %u VRF %u wt %u %s %s %s", i + 1,
+ nh_buf, api_nh->ifindex, api_nh->vrf_id,
+ api_nh->weight, label_buf, segs_buf, eth_buf);
}
+}
+
+void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
+ struct bgp_path_info *info, struct bgp *bgp, afi_t afi,
+ safi_t safi)
+{
+ struct bgp_path_info *bpi_ultimate;
+ struct zapi_route api = { 0 };
+ unsigned int valid_nh_count = 0;
+ bool allow_recursion = false;
+ uint8_t distance;
+ struct peer *peer;
+ uint32_t metric;
+ route_tag_t tag;
+ bool is_add;
+ uint32_t nhg_id = 0;
+ uint32_t recursion_flag = 0;
+
+ /*
+ * BGP is installing this route and bgp has been configured
+ * to suppress announcements until the route has been installed
+ * let's set the fact that we expect this route to be installed
+ */
+ if (BGP_SUPPRESS_FIB_ENABLED(bgp))
+ SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
+
+ /* Don't try to install if we're not connected to Zebra or Zebra doesn't
+ * know of this instance.
+ */
+ if (!bgp_install_info_to_zebra(bgp))
+ return;
+
+ if (bgp->main_zebra_update_hold)
+ return;
+
+ if (safi == SAFI_FLOWSPEC) {
+ bgp_pbr_update_entry(bgp, bgp_dest_get_prefix(dest), info, afi,
+ safi, true);
+ return;
+ }
+
+ /* Make Zebra API structure. */
+ api.vrf_id = bgp->vrf_id;
+ api.type = ZEBRA_ROUTE_BGP;
+ api.safi = safi;
+ api.prefix = *p;
+ SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+
+ peer = info->peer;
+
+ if (info->type == ZEBRA_ROUTE_BGP) {
+ bpi_ultimate = bgp_get_imported_bpi_ultimate(info);
+ peer = bpi_ultimate->peer;
+ }
+
+ tag = info->attr->tag;
+
+ if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED
+ || info->sub_type == BGP_ROUTE_AGGREGATE) {
+ SET_FLAG(api.flags, ZEBRA_FLAG_IBGP);
+ SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
+ }
+
+ if ((peer->sort == BGP_PEER_EBGP && peer->ttl != BGP_DEFAULT_TTL)
+ || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
+ || CHECK_FLAG(bgp->flags, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
+
+ allow_recursion = true;
+
+ if (info->attr->rmap_table_id) {
+ SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID);
+ api.tableid = info->attr->rmap_table_id;
+ }
+
+ if (CHECK_FLAG(info->attr->flag, ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR)))
+ SET_FLAG(api.message, ZAPI_MESSAGE_SRTE);
+
+ /* Metric is currently based on the best-path only */
+ metric = info->attr->med;
+
+ bgp_zebra_announce_parse_nexthop(info, p, bgp, &api, &valid_nh_count,
+ afi, safi, &nhg_id, &metric, &tag,
+ &allow_recursion);
is_add = (valid_nh_count || nhg_id) ? true : false;
@@ -1593,75 +1647,12 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
}
if (bgp_debug_zebra(p)) {
- char nh_buf[INET6_ADDRSTRLEN];
- char eth_buf[ETHER_ADDR_STRLEN + 7] = {'\0'};
- char buf1[ETHER_ADDR_STRLEN];
- char label_buf[20];
- char sid_buf[20];
- char segs_buf[256];
- int i;
-
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);
- for (i = 0; i < api.nexthop_num; i++) {
- api_nh = &api.nexthops[i];
-
- switch (api_nh->type) {
- case NEXTHOP_TYPE_IFINDEX:
- nh_buf[0] = '\0';
- break;
- case NEXTHOP_TYPE_IPV4:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- nh_family = AF_INET;
- inet_ntop(nh_family, &api_nh->gate, nh_buf,
- sizeof(nh_buf));
- break;
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- nh_family = AF_INET6;
- inet_ntop(nh_family, &api_nh->gate, nh_buf,
- sizeof(nh_buf));
- break;
- case NEXTHOP_TYPE_BLACKHOLE:
- strlcpy(nh_buf, "blackhole", sizeof(nh_buf));
- break;
- default:
- /* Note: add new nexthop case */
- assert(0);
- break;
- }
-
- label_buf[0] = '\0';
- eth_buf[0] = '\0';
- segs_buf[0] = '\0';
- if (CHECK_FLAG(api_nh->flags,
- ZAPI_NEXTHOP_FLAG_LABEL) &&
- !CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN))
- snprintf(label_buf, sizeof(label_buf),
- "label %u", api_nh->labels[0]);
- if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6) &&
- !CHECK_FLAG(api_nh->flags,
- ZAPI_NEXTHOP_FLAG_EVPN)) {
- inet_ntop(AF_INET6, &api_nh->seg6_segs[0],
- sid_buf, sizeof(sid_buf));
- snprintf(segs_buf, sizeof(segs_buf), "segs %s",
- sid_buf);
- }
- if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN) &&
- !is_zero_mac(&api_nh->rmac))
- snprintf(eth_buf, sizeof(eth_buf), " RMAC %s",
- prefix_mac2str(&api_nh->rmac,
- buf1, sizeof(buf1)));
- zlog_debug(" nhop [%d]: %s if %u VRF %u wt %u %s %s %s",
- i + 1, nh_buf, api_nh->ifindex,
- api_nh->vrf_id, api_nh->weight,
- label_buf, segs_buf, eth_buf);
- }
-
- int recursion_flag = 0;
+ bgp_debug_zebra_nh(&api);
if (CHECK_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION))
recursion_flag = 1;
@@ -1728,7 +1719,7 @@ void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi,
}
void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *info,
- struct bgp *bgp, safi_t safi)
+ struct bgp *bgp, afi_t afi, safi_t safi)
{
struct zapi_route api;
struct peer *peer;
@@ -1747,7 +1738,7 @@ void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *info,
if (safi == SAFI_FLOWSPEC) {
peer = info->peer;
- bgp_pbr_update_entry(peer->bgp, p, info, AFI_IP, safi, false);
+ bgp_pbr_update_entry(peer->bgp, p, info, afi, safi, false);
return;
}
@@ -1788,7 +1779,7 @@ void bgp_zebra_withdraw_table_all_subtypes(struct bgp *bgp, afi_t afi, safi_t sa
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
&& (pi->type == ZEBRA_ROUTE_BGP))
bgp_zebra_withdraw(bgp_dest_get_prefix(dest),
- pi, bgp, safi);
+ pi, bgp, afi, safi);
}
}
}
@@ -2060,7 +2051,8 @@ void bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type,
struct listnode *node, *nnode;
struct bgp_redist *red;
- if (type != ZEBRA_ROUTE_TABLE || instance != 0)
+ if ((type != ZEBRA_ROUTE_TABLE && type != ZEBRA_ROUTE_TABLE_DIRECT) ||
+ instance != 0)
return _bgp_redistribute_unset(bgp, afi, type, instance);
/* walk over instance */
@@ -2359,7 +2351,7 @@ static int rule_notify_owner(ZAPI_CALLBACK_ARGS)
enum zapi_rule_notify_owner note;
struct bgp_pbr_action *bgp_pbra;
struct bgp_pbr_rule *bgp_pbr = NULL;
- char ifname[INTERFACE_NAMSIZ + 1];
+ char ifname[IFNAMSIZ + 1];
if (!zapi_rule_notify_decode(zclient->ibuf, &seqno, &priority, &unique,
ifname, &note))
@@ -2605,8 +2597,12 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,
/* Find the bgp route node */
dest = bgp_safi_node_lookup(bgp->rib[afi][safi], safi, &p,
&bgp->vrf_prd);
- if (!dest)
+ if (!dest) {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: %pFX does not exist in the BGP table, nothing to do for %u",
+ __func__, &p, note);
return -1;
+ }
switch (note) {
case ZAPI_ROUTE_INSTALLED:
@@ -2615,7 +2611,7 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,
UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED);
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("route %pRN : INSTALLED", (void *)dest);
+ zlog_debug("route %pBD : INSTALLED", dest);
/* Find the best route */
for (pi = dest->info; pi; pi = pi->next) {
/* Process aggregate route */
@@ -2628,7 +2624,7 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,
group_announce_route(bgp, afi, safi, dest, new_select);
else {
flog_err(EC_BGP_INVALID_ROUTE,
- "selected route %pRN not found", (void *)dest);
+ "selected route %pBD not found", dest);
bgp_dest_unlock_node(dest);
return -1;
@@ -2641,13 +2637,13 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,
*/
UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED);
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("route %pRN: Removed from Fib", (void *)dest);
+ zlog_debug("route %pBD: Removed from Fib", dest);
break;
case ZAPI_ROUTE_FAIL_INSTALL:
new_select = NULL;
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("route: %pRN Failed to Install into Fib",
- (void *)dest);
+ zlog_debug("route: %pBD Failed to Install into Fib",
+ dest);
UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED);
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
@@ -2660,8 +2656,8 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,
break;
case ZAPI_ROUTE_BETTER_ADMIN_WON:
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("route: %pRN removed due to better admin won",
- (void *)dest);
+ zlog_debug("route: %pBD removed due to better admin won",
+ dest);
new_select = NULL;
UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED);
@@ -2675,8 +2671,7 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,
/* No action required */
break;
case ZAPI_ROUTE_REMOVE_FAIL:
- zlog_warn("%s: Route %pRN failure to remove",
- __func__, (void *)dest);
+ zlog_warn("%s: Route %pBD failure to remove", __func__, dest);
break;
}
@@ -2958,12 +2953,11 @@ static int bgp_zebra_process_local_l3vni(ZAPI_CALLBACK_ARGS)
is_anycast_mac = stream_getl(s);
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug(
- "Rx L3-VNI ADD VRF %s VNI %u Originator-IP %pI4 RMAC svi-mac %pEA vrr-mac %pEA filter %s svi-if %u",
- vrf_id_to_name(vrf_id), l3vni, &originator_ip,
- &svi_rmac, &vrr_rmac,
- filter ? "prefix-routes-only" : "none",
- svi_ifindex);
+ zlog_debug("Rx L3VNI ADD VRF %s VNI %u Originator-IP %pI4 RMAC svi-mac %pEA vrr-mac %pEA filter %s svi-if %u",
+ vrf_id_to_name(vrf_id), l3vni,
+ &originator_ip, &svi_rmac, &vrr_rmac,
+ filter ? "prefix-routes-only" : "none",
+ svi_ifindex);
frrtrace(8, frr_bgp, evpn_local_l3vni_add_zrecv, l3vni, vrf_id,
&svi_rmac, &vrr_rmac, filter, originator_ip,
@@ -2974,7 +2968,7 @@ static int bgp_zebra_process_local_l3vni(ZAPI_CALLBACK_ARGS)
is_anycast_mac);
} else {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Rx L3-VNI DEL VRF %s VNI %u",
+ zlog_debug("Rx L3VNI DEL VRF %s VNI %u",
vrf_id_to_name(vrf_id), l3vni);
frrtrace(2, frr_bgp, evpn_local_l3vni_del_zrecv, l3vni, vrf_id);
@@ -3235,7 +3229,7 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
if (prefix_match((struct prefix *)&loc.prefix,
(struct prefix *)&tmp_prefi)) {
listnode_delete(bgp->srv6_functions, func);
- XFREE(MTYPE_BGP_SRV6_FUNCTION, func);
+ srv6_function_free(func);
}
}
@@ -3339,7 +3333,6 @@ static zclient_handler *const bgp_handlers[] = {
[ZEBRA_INTERFACE_NBR_ADDRESS_DELETE] = bgp_interface_nbr_address_delete,
[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = zebra_read_route,
[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = zebra_read_route,
- [ZEBRA_NEXTHOP_UPDATE] = bgp_read_nexthop_update,
[ZEBRA_FEC_UPDATE] = bgp_read_fec_update,
[ZEBRA_LOCAL_ES_ADD] = bgp_zebra_process_local_es_add,
[ZEBRA_LOCAL_ES_DEL] = bgp_zebra_process_local_es_del,
@@ -3432,6 +3425,9 @@ static bool bgp_zebra_label_manager_connect(void)
/* tell label pool that zebra is connected */
bgp_lp_event_zebra_up();
+ /* tell BGP L3VPN that label manager is available */
+ if (bgp_get_default())
+ vpn_leak_postchange_all();
return true;
}
@@ -3442,13 +3438,12 @@ static void bgp_zebra_capabilities(struct zclient_capabilities *cap)
void bgp_zebra_init(struct event_loop *master, unsigned short instance)
{
- struct zclient_options options = zclient_options_default;
-
- options.synchronous = true;
zclient_num_connects = 0;
- if_zapi_callbacks(bgp_ifp_create, bgp_ifp_up,
- bgp_ifp_down, bgp_ifp_destroy);
+ hook_register_prio(if_real, 0, bgp_ifp_create);
+ hook_register_prio(if_up, 0, bgp_ifp_up);
+ hook_register_prio(if_down, 0, bgp_ifp_down);
+ hook_register_prio(if_unreal, 0, bgp_ifp_destroy);
/* Set default values. */
zclient = zclient_new(master, &zclient_options_default, bgp_handlers,
@@ -3456,10 +3451,11 @@ void bgp_zebra_init(struct event_loop *master, unsigned short instance)
zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs);
zclient->zebra_connected = bgp_zebra_connected;
zclient->zebra_capabilities = bgp_zebra_capabilities;
+ zclient->nexthop_update = bgp_nexthop_update;
zclient->instance = instance;
/* Initialize special zclient for synchronous message exchanges. */
- zclient_sync = zclient_new(master, &options, NULL, 0);
+ zclient_sync = zclient_new(master, &zclient_options_sync, NULL, 0);
zclient_sync->sock = -1;
zclient_sync->redist_default = ZEBRA_ROUTE_BGP;
zclient_sync->instance = instance;
@@ -3930,7 +3926,8 @@ void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
zebra_send_mpls_labels(zclient, cmd, &zl);
}
-bool bgp_zebra_request_label_range(uint32_t base, uint32_t chunk_size)
+bool bgp_zebra_request_label_range(uint32_t base, uint32_t chunk_size,
+ bool label_auto)
{
int ret;
uint32_t start, end;
@@ -3952,7 +3949,13 @@ bool bgp_zebra_request_label_range(uint32_t base, uint32_t chunk_size)
return false;
}
- bgp_lp_event_chunk(start, end);
+ if (label_auto)
+ /* label automatic is serviced by the bgp label pool
+ * manager, which allocates label chunks in
+ * pre-pools, and which needs to be notified about
+ * new chunks availability
+ */
+ bgp_lp_event_chunk(start, end);
return true;
}
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
index 0edae04..396c833 100644
--- a/bgpd/bgp_zebra.h
+++ b/bgpd/bgp_zebra.h
@@ -34,7 +34,7 @@ extern void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
extern void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi);
extern void bgp_zebra_withdraw(const struct prefix *p,
struct bgp_path_info *path, struct bgp *bgp,
- safi_t safi);
+ afi_t afi, safi_t safi);
/* Announce routes of any bgp subtype of a table to zebra */
extern void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi,
@@ -124,6 +124,7 @@ extern void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
enum lsp_types_t ltype,
struct prefix *p, uint32_t num_labels,
mpls_label_t out_labels[]);
-extern bool bgp_zebra_request_label_range(uint32_t base, uint32_t chunk_size);
+extern bool bgp_zebra_request_label_range(uint32_t base, uint32_t chunk_size,
+ bool label_auto);
extern void bgp_zebra_release_label_range(uint32_t start, uint32_t end);
#endif /* _QUAGGA_BGP_ZEBRA_H */
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 4b72798..1a03a06 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -63,6 +63,7 @@
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_mpath.h"
#include "bgpd/bgp_nht.h"
+#include "bgpd/bgp_nhg.h"
#include "bgpd/bgp_updgrp.h"
#include "bgpd/bgp_bfd.h"
#include "bgpd/bgp_memory.h"
@@ -186,7 +187,6 @@ int bgp_option_set(int flag)
int bgp_option_unset(int flag)
{
switch (flag) {
- /* Fall through. */
case BGP_OPT_NO_ZEBRA:
case BGP_OPT_NO_FIB:
UNSET_FLAG(bm->options, flag);
@@ -410,6 +410,9 @@ void bgp_router_id_static_set(struct bgp *bgp, struct in_addr id)
void bm_wait_for_fib_set(bool set)
{
bool send_msg = false;
+ struct bgp *bgp;
+ struct peer *peer;
+ struct listnode *next, *node;
if (bm->wait_for_fib == set)
return;
@@ -428,12 +431,32 @@ void bm_wait_for_fib_set(bool set)
if (send_msg && zclient)
zebra_route_notify_send(ZEBRA_ROUTE_NOTIFY_REQUEST,
zclient, set);
+
+ /*
+ * If this is configed at a time when peers are already set
+ * FRR needs to reset the connection(s) as that some installs
+ * may have already happened in some shape fashion or form
+ * let's just start over
+ */
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {
+ for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
+ 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);
+ }
+ }
}
/* Set the suppress fib pending for the bgp configuration */
void bgp_suppress_fib_pending_set(struct bgp *bgp, bool set)
{
bool send_msg = false;
+ struct peer *peer;
+ struct listnode *node;
if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
return;
@@ -465,6 +488,21 @@ void bgp_suppress_fib_pending_set(struct bgp *bgp, bool set)
zebra_route_notify_send(ZEBRA_ROUTE_NOTIFY_REQUEST,
zclient, set);
}
+
+ /*
+ * If this is configed at a time when peers are already set
+ * FRR needs to reset the connection as that some installs
+ * may have already happened in some shape fashion or form
+ * let's just start over
+ */
+ for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
+ 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);
+ }
}
/* BGP's cluster-id control. */
@@ -577,8 +615,8 @@ void bgp_confederation_id_set(struct bgp *bgp, as_t as, const char *as_str)
already_confed = bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION);
bgp->confed_id = as;
if (bgp->confed_id_pretty)
- XFREE(MTYPE_BGP, bgp->confed_id_pretty);
- bgp->confed_id_pretty = XSTRDUP(MTYPE_BGP, as_str);
+ XFREE(MTYPE_BGP_NAME, bgp->confed_id_pretty);
+ bgp->confed_id_pretty = XSTRDUP(MTYPE_BGP_NAME, as_str);
bgp_config_set(bgp, BGP_CONFIG_CONFEDERATION);
/* If we were doing confederation already, this is just an external
@@ -631,7 +669,7 @@ void bgp_confederation_id_unset(struct bgp *bgp)
struct listnode *node, *nnode;
bgp->confed_id = 0;
- XFREE(MTYPE_BGP, bgp->confed_id_pretty);
+ XFREE(MTYPE_BGP_NAME, bgp->confed_id_pretty);
bgp_config_unset(bgp, BGP_CONFIG_CONFEDERATION);
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
@@ -685,7 +723,7 @@ void bgp_confederation_peers_add(struct bgp *bgp, as_t as, const char *as_str)
bgp->confed_peers[bgp->confed_peers_cnt].as = as;
bgp->confed_peers[bgp->confed_peers_cnt].as_pretty =
- XSTRDUP(MTYPE_BGP, as_str);
+ XSTRDUP(MTYPE_BGP_NAME, as_str);
bgp->confed_peers_cnt++;
if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) {
@@ -723,7 +761,7 @@ void bgp_confederation_peers_remove(struct bgp *bgp, as_t as)
for (i = 0; i < bgp->confed_peers_cnt; i++)
if (bgp->confed_peers[i].as == as) {
- XFREE(MTYPE_BGP, bgp->confed_peers[i].as_pretty);
+ XFREE(MTYPE_BGP_NAME, bgp->confed_peers[i].as_pretty);
for (j = i + 1; j < bgp->confed_peers_cnt; j++) {
bgp->confed_peers[j - 1].as =
bgp->confed_peers[j].as;
@@ -1266,9 +1304,9 @@ static void peer_free(struct peer *peer)
bgp_addpath_set_peer_type(peer, afi, safi, BGP_ADDPATH_NONE, 0);
if (peer->change_local_as_pretty)
- XFREE(MTYPE_BGP, peer->change_local_as_pretty);
+ XFREE(MTYPE_BGP_NAME, peer->change_local_as_pretty);
if (peer->as_pretty)
- XFREE(MTYPE_BGP, peer->as_pretty);
+ XFREE(MTYPE_BGP_NAME, peer->as_pretty);
bgp_peer_connection_free(&peer->connection);
@@ -1428,7 +1466,9 @@ static void bgp_srv6_init(struct bgp *bgp)
bgp->srv6_enabled = false;
memset(bgp->srv6_locator_name, 0, sizeof(bgp->srv6_locator_name));
bgp->srv6_locator_chunks = list_new();
+ bgp->srv6_locator_chunks->del = srv6_locator_chunk_list_free;
bgp->srv6_functions = list_new();
+ bgp->srv6_functions->del = (void (*)(void *))srv6_function_free;
}
static void bgp_srv6_cleanup(struct bgp *bgp)
@@ -1473,6 +1513,8 @@ struct peer *peer_new(struct bgp *bgp)
SET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_SEND_EXT_COMMUNITY);
SET_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_SEND_EXT_COMMUNITY_RPKI);
+ SET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_SEND_LARGE_COMMUNITY);
SET_FLAG(peer->af_flags_invert[afi][safi],
@@ -1480,6 +1522,8 @@ struct peer *peer_new(struct bgp *bgp)
SET_FLAG(peer->af_flags_invert[afi][safi],
PEER_FLAG_SEND_EXT_COMMUNITY);
SET_FLAG(peer->af_flags_invert[afi][safi],
+ PEER_FLAG_SEND_EXT_COMMUNITY_RPKI);
+ SET_FLAG(peer->af_flags_invert[afi][safi],
PEER_FLAG_SEND_LARGE_COMMUNITY);
peer->addpath_type[afi][safi] = BGP_ADDPATH_NONE;
peer->addpath_best_selected[afi][safi] = 0;
@@ -1492,6 +1536,15 @@ struct peer *peer_new(struct bgp *bgp)
SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_ENFORCE_FIRST_AS))
+ SET_FLAG(peer->flags, PEER_FLAG_ENFORCE_FIRST_AS);
+
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_SOFT_VERSION_CAPABILITY))
+ SET_FLAG(peer->flags, PEER_FLAG_CAPABILITY_SOFT_VERSION);
+
+ SET_FLAG(peer->flags_invert, PEER_FLAG_CAPABILITY_FQDN);
+ SET_FLAG(peer->flags, PEER_FLAG_CAPABILITY_FQDN);
+
/* Initialize per peer bgp GR FSM */
bgp_peer_gr_init(peer);
@@ -1538,6 +1591,7 @@ void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src)
/* copy tcp_mss value */
peer_dst->tcp_mss = peer_src->tcp_mss;
(void)peer_sort(peer_dst);
+ peer_dst->sub_sort = peer_src->sub_sort;
peer_dst->rmap_type = peer_src->rmap_type;
peer_dst->local_role = peer_src->local_role;
@@ -1603,6 +1657,7 @@ void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src)
XSTRDUP(MTYPE_BGP_PEER_IFNAME, peer_src->ifname);
}
peer_dst->ttl = peer_src->ttl;
+ peer_dst->gtsm_hops = peer_src->gtsm_hops;
}
static int bgp_peer_conf_if_to_su_update_v4(struct peer_connection *connection,
@@ -1611,12 +1666,11 @@ static int bgp_peer_conf_if_to_su_update_v4(struct peer_connection *connection,
struct connected *ifc;
struct prefix p;
uint32_t addr;
- struct listnode *node;
/* If our IPv4 address on the interface is /30 or /31, we can derive the
* IPv4 address of the other end.
*/
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
+ frr_each (if_connected, ifp->connected, ifc) {
if (ifc->address && (ifc->address->family == AF_INET)) {
prefix_copy(&p, CONNECTED_PREFIX(ifc));
if (p.prefixlen == 30) {
@@ -1863,7 +1917,7 @@ struct peer *peer_create(union sockunion *su, const char *conf_if,
peer->as = remote_as;
/* internal and external values do not use as_pretty */
if (as_str && asn_str2asn(as_str, NULL))
- peer->as_pretty = XSTRDUP(MTYPE_BGP, as_str);
+ peer->as_pretty = XSTRDUP(MTYPE_BGP_NAME, as_str);
peer->as_type = as_type;
peer->local_id = bgp->router_id;
peer->v_holdtime = bgp->default_holdtime;
@@ -1985,10 +2039,10 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified,
peer->as = as;
if (as_specified == AS_SPECIFIED && as_str) {
if (peer->as_pretty)
- XFREE(MTYPE_BGP, peer->as_pretty);
- peer->as_pretty = XSTRDUP(MTYPE_BGP, as_str);
+ 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, peer->as_pretty);
+ XFREE(MTYPE_BGP_NAME, peer->as_pretty);
peer->as_type = as_specified;
if (bgp_config_check(peer->bgp, BGP_CONFIG_CONFEDERATION)
@@ -3147,6 +3201,7 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
peer->as_type = group->conf->as_type;
peer->as = group->conf->as;
peer->sort = group->conf->sort;
+ peer->sub_sort = group->conf->sub_sort;
}
ptype = peer_sort(peer);
@@ -3287,9 +3342,9 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp = XCALLOC(MTYPE_BGP, sizeof(struct bgp));
bgp->as = *as;
if (as_pretty)
- bgp->as_pretty = XSTRDUP(MTYPE_BGP, as_pretty);
+ bgp->as_pretty = XSTRDUP(MTYPE_BGP_NAME, as_pretty);
else
- bgp->as_pretty = XSTRDUP(MTYPE_BGP, asn_asn2asplain(*as));
+ bgp->as_pretty = XSTRDUP(MTYPE_BGP_NAME, asn_asn2asplain(*as));
if (asnotation != ASNOTATION_UNDEFINED) {
bgp->asnotation = asnotation;
@@ -3418,14 +3473,14 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp_mplsvpn_nh_label_bind_cache_init(&bgp->mplsvpn_nh_label_bind);
if (name)
- bgp->name = XSTRDUP(MTYPE_BGP, name);
+ bgp->name = XSTRDUP(MTYPE_BGP_NAME, name);
event_add_timer(bm->master, bgp_startup_timer_expire, bgp,
bgp->restart_time, &bgp->t_startup);
/* printable name we can use in debug messages */
if (inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
- bgp->name_pretty = XSTRDUP(MTYPE_BGP, "VRF default");
+ bgp->name_pretty = XSTRDUP(MTYPE_BGP_NAME, "VRF default");
} else {
const char *n;
int len;
@@ -3437,7 +3492,7 @@ static struct bgp *bgp_create(as_t *as, const char *name,
len = 4 + 1 + strlen(n) + 1; /* "view foo\0" */
- bgp->name_pretty = XCALLOC(MTYPE_BGP, len);
+ bgp->name_pretty = XCALLOC(MTYPE_BGP_NAME, len);
snprintf(bgp->name_pretty, len, "%s %s",
(bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
? "VRF"
@@ -4040,7 +4095,8 @@ void bgp_free(struct bgp *bgp)
if (bgp->vpn_policy[afi].rtlist[dir])
ecommunity_free(&bgp->vpn_policy[afi].rtlist[dir]);
if (bgp->vpn_policy[afi].tovpn_rd_pretty)
- XFREE(MTYPE_BGP, bgp->vpn_policy[afi].tovpn_rd_pretty);
+ XFREE(MTYPE_BGP_NAME,
+ bgp->vpn_policy[afi].tovpn_rd_pretty);
if (bgp->vpn_policy[afi].tovpn_sid_locator != NULL)
srv6_locator_chunk_free(
&bgp->vpn_policy[afi].tovpn_sid_locator);
@@ -4057,10 +4113,14 @@ void bgp_free(struct bgp *bgp)
bgp_srv6_cleanup(bgp);
bgp_confederation_id_unset(bgp);
- XFREE(MTYPE_BGP, bgp->as_pretty);
- XFREE(MTYPE_BGP, bgp->name);
- XFREE(MTYPE_BGP, bgp->name_pretty);
- XFREE(MTYPE_BGP, bgp->snmp_stats);
+ for (int i = 0; i < bgp->confed_peers_cnt; i++)
+ XFREE(MTYPE_BGP_NAME, bgp->confed_peers[i].as_pretty);
+
+ XFREE(MTYPE_BGP_NAME, bgp->as_pretty);
+ XFREE(MTYPE_BGP_NAME, bgp->name);
+ XFREE(MTYPE_BGP_NAME, bgp->name_pretty);
+ XFREE(MTYPE_BGP_NAME, bgp->snmp_stats);
+ XFREE(MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
XFREE(MTYPE_BGP, bgp);
}
@@ -4522,6 +4582,7 @@ static const struct peer_flag_action peer_flag_action_list[] = {
{PEER_FLAG_AIGP, 0, peer_change_none},
{PEER_FLAG_GRACEFUL_SHUTDOWN, 0, peer_change_none},
{PEER_FLAG_CAPABILITY_SOFT_VERSION, 0, peer_change_none},
+ {PEER_FLAG_CAPABILITY_FQDN, 0, peer_change_none},
{0, 0, 0}};
static const struct peer_flag_action peer_af_flag_action_list[] = {
@@ -4552,9 +4613,10 @@ static const struct peer_flag_action peer_af_flag_action_list[] = {
{PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out},
{PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE, 1, peer_change_reset_out},
{PEER_FLAG_WEIGHT, 0, peer_change_reset_in},
- {PEER_FLAG_DISABLE_ADDPATH_RX, 0, peer_change_reset},
+ {PEER_FLAG_DISABLE_ADDPATH_RX, 0, peer_change_none},
{PEER_FLAG_SOO, 0, peer_change_reset},
{PEER_FLAG_ACCEPT_OWN, 0, peer_change_reset},
+ {PEER_FLAG_SEND_EXT_COMMUNITY_RPKI, 1, peer_change_reset_out},
{0, 0, 0}};
/* Proper action set. */
@@ -4979,6 +5041,16 @@ static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
else if (flag == PEER_FLAG_ORF_PREFIX_RM)
peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
+ /* We should not reset the session if
+ * dynamic capability is enabled and we
+ * are changing the ORF prefix flags.
+ */
+ if ((CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV) &&
+ CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV)) &&
+ (flag == PEER_FLAG_ORF_PREFIX_RM ||
+ flag == PEER_FLAG_ORF_PREFIX_SM))
+ action.type = peer_change_none;
+
peer_change_action(peer, afi, safi, action.type);
}
}
@@ -5039,6 +5111,18 @@ static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
member->last_reset =
PEER_DOWN_CAPABILITY_CHANGE;
+ /* We should not reset the session if
+ * dynamic capability is enabled and we
+ * are changing the ORF prefix flags.
+ */
+ if ((CHECK_FLAG(peer->cap,
+ PEER_CAP_DYNAMIC_RCV) &&
+ CHECK_FLAG(peer->cap,
+ PEER_CAP_DYNAMIC_ADV)) &&
+ (flag == PEER_FLAG_ORF_PREFIX_RM ||
+ flag == PEER_FLAG_ORF_PREFIX_SM))
+ action.type = peer_change_none;
+
peer_change_action(member, afi, safi,
action.type);
}
@@ -5624,7 +5708,7 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
if (peer_established(peer->connection) &&
peer->afc_nego[afi][safi]) {
update_group_adjust_peer(peer_af_find(peer, afi, safi));
- bgp_default_originate(peer, afi, safi, 0);
+ bgp_default_originate(peer, afi, safi, false);
bgp_announce_route(peer, afi, safi, false);
}
@@ -5667,7 +5751,7 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
member->afc_nego[afi][safi]) {
update_group_adjust_peer(
peer_af_find(member, afi, safi));
- bgp_default_originate(member, afi, safi, 0);
+ bgp_default_originate(member, afi, safi, false);
bgp_announce_route(member, afi, safi, false);
}
}
@@ -5712,7 +5796,7 @@ int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi)
if (peer_established(peer->connection) &&
peer->afc_nego[afi][safi]) {
update_group_adjust_peer(peer_af_find(peer, afi, safi));
- bgp_default_originate(peer, afi, safi, 1);
+ bgp_default_originate(peer, afi, safi, true);
bgp_announce_route(peer, afi, safi, false);
}
@@ -5751,7 +5835,7 @@ int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi)
if (peer_established(member->connection) &&
member->afc_nego[afi][safi]) {
update_group_adjust_peer(peer_af_find(member, afi, safi));
- bgp_default_originate(member, afi, safi, 1);
+ bgp_default_originate(member, afi, safi, true);
bgp_announce_route(member, afi, safi, false);
}
}
@@ -6440,8 +6524,8 @@ int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend,
peer->change_local_as = as;
if (as_str) {
if (peer->change_local_as_pretty)
- XFREE(MTYPE_BGP, peer->change_local_as_pretty);
- peer->change_local_as_pretty = XSTRDUP(MTYPE_BGP, as_str);
+ XFREE(MTYPE_BGP_NAME, peer->change_local_as_pretty);
+ peer->change_local_as_pretty = XSTRDUP(MTYPE_BGP_NAME, as_str);
}
(void)peer_sort(peer);
@@ -6478,8 +6562,8 @@ int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend,
replace_as);
member->change_local_as = as;
if (as_str)
- member->change_local_as_pretty =
- XSTRDUP(MTYPE_BGP, as_str);
+ member->change_local_as_pretty = XSTRDUP(MTYPE_BGP_NAME,
+ as_str);
}
return 0;
@@ -6505,7 +6589,7 @@ int peer_local_as_unset(struct peer *peer)
peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);
peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS);
peer->change_local_as = 0;
- XFREE(MTYPE_BGP, peer->change_local_as_pretty);
+ XFREE(MTYPE_BGP_NAME, peer->change_local_as_pretty);
}
/* Check if handling a regular peer. */
@@ -6536,7 +6620,7 @@ int peer_local_as_unset(struct peer *peer)
UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
member->change_local_as = 0;
- XFREE(MTYPE_BGP, member->change_local_as_pretty);
+ XFREE(MTYPE_BGP_NAME, member->change_local_as_pretty);
/* Send notification or stop peer depending on state. */
if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) {
@@ -8024,6 +8108,16 @@ static void peer_reset_message_stats(struct peer *peer)
}
}
+/* Helper function to resend some BGP capabilities that are uncontrolled.
+ * For instance, FQDN capability, that can't be turned off, but let's say
+ * we changed the hostname, we need to resend it.
+ */
+static void peer_clear_capabilities(struct peer *peer, afi_t afi, safi_t safi)
+{
+ bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_FQDN,
+ CAPABILITY_ACTION_SET);
+}
+
/*
* If peer clear is invoked in a loop for all peers on the BGP instance,
* it may end up freeing the doppelganger, and if this was the next node
@@ -8132,6 +8226,9 @@ int peer_clear_soft(struct peer *peer, afi_t afi, safi_t safi,
if (stype == BGP_CLEAR_MESSAGE_STATS)
peer_reset_message_stats(peer);
+ if (stype == BGP_CLEAR_CAPABILITIES)
+ peer_clear_capabilities(peer, afi, safi);
+
return 0;
}
@@ -8220,7 +8317,7 @@ void bgp_master_init(struct event_loop *master, const int buffer_size,
/* mpls label dynamic allocation pool */
bgp_lp_init(bm->master, &bm->labelpool);
- bgp_l3nhg_init();
+ bgp_nhg_init();
bgp_evpn_mh_init();
QOBJ_REG(bm, bgp_master);
}
@@ -8240,10 +8337,9 @@ static void bgp_if_finish(struct bgp *bgp)
return;
FOR_ALL_INTERFACES (vrf, ifp) {
- struct listnode *c_node, *c_nnode;
struct connected *c;
- for (ALL_LIST_ELEMENTS(ifp->connected, c_node, c_nnode, c))
+ frr_each_safe (if_connected, ifp->connected, c)
bgp_connected_delete(bgp, c);
}
}
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index ca1411a..0f69095 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -34,6 +34,9 @@
#include "lib/bfd.h"
+DECLARE_HOOK(bgp_hook_config_write_vrf, (struct vty *vty, struct vrf *vrf),
+ (vty, vrf));
+
#define BGP_MAX_HOSTNAME 64 /* Linux max, is larger than most other sys */
#define BGP_PEER_MAX_HASH_SIZE 16384
@@ -121,6 +124,8 @@ struct bgp_master {
#define BGP_OPT_NO_FIB (1 << 0)
#define BGP_OPT_NO_LISTEN (1 << 1)
#define BGP_OPT_NO_ZEBRA (1 << 2)
+#define BGP_OPT_TRAPS_RFC4273 (1 << 3)
+#define BGP_OPT_TRAPS_BGP4MIBV2 (1 << 4)
uint64_t updgrp_idspace;
uint64_t subgrp_idspace;
@@ -217,6 +222,8 @@ struct vpn_policy {
#define BGP_VPN_POLICY_TOVPN_NEXTHOP_SET (1 << 2)
#define BGP_VPN_POLICY_TOVPN_SID_AUTO (1 << 3)
#define BGP_VPN_POLICY_TOVPN_LABEL_PER_NEXTHOP (1 << 4)
+/* Manual label is registered with zebra label manager */
+#define BGP_VPN_POLICY_TOVPN_LABEL_MANUAL_REG (1 << 5)
/*
* If we are importing another vrf into us keep a list of
@@ -514,6 +521,7 @@ struct bgp {
/* For BGP-LU, force IPv6 local prefixes to use ipv6-explicit-null label */
#define BGP_FLAG_LU_IPV6_EXPLICIT_NULL (1ULL << 34)
#define BGP_FLAG_SOFT_VERSION_CAPABILITY (1ULL << 35)
+#define BGP_FLAG_ENFORCE_FIRST_AS (1ULL << 36)
/* BGP default address-families.
* New peers inherit enabled afi/safis from bgp instance.
@@ -832,7 +840,10 @@ DECLARE_HOOK(bgp_inst_delete, (struct bgp *bgp), (bgp));
DECLARE_HOOK(bgp_inst_config_write,
(struct bgp *bgp, struct vty *vty),
(bgp, vty));
+DECLARE_HOOK(bgp_snmp_traps_config_write, (struct vty *vty), (vty));
DECLARE_HOOK(bgp_config_end, (struct bgp *bgp), (bgp));
+DECLARE_HOOK(bgp_hook_vrf_update, (struct vrf *vrf, bool enabled),
+ (vrf, enabled));
/* Thread callback information */
struct afi_safi_info {
@@ -877,10 +888,10 @@ struct peer_group {
struct bgp_notify {
uint8_t code;
uint8_t subcode;
- char *data;
bgp_size_t length;
- uint8_t *raw_data;
bool hard_reset;
+ char *data;
+ uint8_t *raw_data;
};
/* Next hop self address. */
@@ -971,6 +982,14 @@ enum bgp_peer_sort {
BGP_PEER_CONFED,
};
+/* BGP peering sub-types
+ * E.g.:
+ * EBGP-OAD - https://datatracker.ietf.org/doc/html/draft-uttaro-idr-bgp-oad
+ */
+enum bgp_peer_sub_sort {
+ BGP_PEER_EBGP_OAD = 1,
+};
+
/* BGP message header and packet size. */
#define BGP_MARKER_SIZE 16
#define BGP_HEADER_SIZE 19
@@ -1032,7 +1051,8 @@ enum peer_gr_command {
NO_PEER_HELPER_CMD
};
-typedef unsigned int (*bgp_peer_gr_action_ptr)(struct peer *, int, int);
+typedef unsigned int (*bgp_peer_gr_action_ptr)(struct peer *, enum peer_mode,
+ enum peer_mode);
struct bgp_peer_gr {
enum peer_mode next_state;
@@ -1129,6 +1149,11 @@ struct peer_connection {
int fd;
+ /* Thread flags */
+ _Atomic uint32_t thread_flags;
+#define PEER_THREAD_WRITES_ON (1U << 0)
+#define PEER_THREAD_READS_ON (1U << 1)
+
/* Packet receive and send buffer. */
pthread_mutex_t io_mtx; // guards ibuf, obuf
struct stream_fifo *ibuf; // packets waiting to be processed
@@ -1159,11 +1184,6 @@ struct peer_connection {
union sockunion su;
#define BGP_CONNECTION_SU_UNSPEC(connection) \
(connection->su.sa.sa_family == AF_UNSPEC)
-
- /* Thread flags */
- _Atomic uint32_t thread_flags;
-#define PEER_THREAD_WRITES_ON (1U << 0)
-#define PEER_THREAD_READS_ON (1U << 1)
};
extern struct peer_connection *bgp_peer_connection_new(struct peer *peer);
extern void bgp_peer_connection_free(struct peer_connection **connection);
@@ -1197,6 +1217,7 @@ struct peer {
as_t local_as;
enum bgp_peer_sort sort;
+ enum bgp_peer_sub_sort sub_sort;
/* Peer's Change local AS number. */
as_t change_local_as;
@@ -1279,39 +1300,39 @@ struct peer {
uint8_t afc_recv[AFI_MAX][SAFI_MAX];
/* Capability flags (reset in bgp_stop) */
- uint32_t cap;
-#define PEER_CAP_REFRESH_ADV (1U << 0) /* refresh advertised */
-#define PEER_CAP_REFRESH_RCV (1U << 2) /* refresh rfc received */
-#define PEER_CAP_DYNAMIC_ADV (1U << 3) /* dynamic advertised */
-#define PEER_CAP_DYNAMIC_RCV (1U << 4) /* dynamic received */
-#define PEER_CAP_RESTART_ADV (1U << 5) /* restart advertised */
-#define PEER_CAP_RESTART_RCV (1U << 6) /* restart received */
-#define PEER_CAP_AS4_ADV (1U << 7) /* as4 advertised */
-#define PEER_CAP_AS4_RCV (1U << 8) /* as4 received */
+ uint64_t cap;
+#define PEER_CAP_REFRESH_ADV (1ULL << 0) /* refresh advertised */
+#define PEER_CAP_REFRESH_RCV (1ULL << 2) /* refresh rfc received */
+#define PEER_CAP_DYNAMIC_ADV (1ULL << 3) /* dynamic advertised */
+#define PEER_CAP_DYNAMIC_RCV (1ULL << 4) /* dynamic received */
+#define PEER_CAP_RESTART_ADV (1ULL << 5) /* restart advertised */
+#define PEER_CAP_RESTART_RCV (1ULL << 6) /* restart received */
+#define PEER_CAP_AS4_ADV (1ULL << 7) /* as4 advertised */
+#define PEER_CAP_AS4_RCV (1ULL << 8) /* as4 received */
/* sent graceful-restart restart (R) bit */
-#define PEER_CAP_GRACEFUL_RESTART_R_BIT_ADV (1U << 9)
+#define PEER_CAP_GRACEFUL_RESTART_R_BIT_ADV (1ULL << 9)
/* received graceful-restart restart (R) bit */
-#define PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV (1U << 10)
-#define PEER_CAP_ADDPATH_ADV (1U << 11) /* addpath advertised */
-#define PEER_CAP_ADDPATH_RCV (1U << 12) /* addpath received */
-#define PEER_CAP_ENHE_ADV (1U << 13) /* Extended nexthop advertised */
-#define PEER_CAP_ENHE_RCV (1U << 14) /* Extended nexthop received */
-#define PEER_CAP_HOSTNAME_ADV (1U << 15) /* hostname advertised */
-#define PEER_CAP_HOSTNAME_RCV (1U << 16) /* hostname received */
-#define PEER_CAP_ENHANCED_RR_ADV (1U << 17) /* enhanced rr advertised */
-#define PEER_CAP_ENHANCED_RR_RCV (1U << 18) /* enhanced rr received */
-#define PEER_CAP_EXTENDED_MESSAGE_ADV (1U << 19)
-#define PEER_CAP_EXTENDED_MESSAGE_RCV (1U << 20)
-#define PEER_CAP_LLGR_ADV (1U << 21)
-#define PEER_CAP_LLGR_RCV (1U << 22)
+#define PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV (1ULL << 10)
+#define PEER_CAP_ADDPATH_ADV (1ULL << 11) /* addpath advertised */
+#define PEER_CAP_ADDPATH_RCV (1ULL << 12) /* addpath received */
+#define PEER_CAP_ENHE_ADV (1ULL << 13) /* Extended nexthop advertised */
+#define PEER_CAP_ENHE_RCV (1ULL << 14) /* Extended nexthop received */
+#define PEER_CAP_HOSTNAME_ADV (1ULL << 15) /* hostname advertised */
+#define PEER_CAP_HOSTNAME_RCV (1ULL << 16) /* hostname received */
+#define PEER_CAP_ENHANCED_RR_ADV (1ULL << 17) /* enhanced rr advertised */
+#define PEER_CAP_ENHANCED_RR_RCV (1ULL << 18) /* enhanced rr received */
+#define PEER_CAP_EXTENDED_MESSAGE_ADV (1ULL << 19)
+#define PEER_CAP_EXTENDED_MESSAGE_RCV (1ULL << 20)
+#define PEER_CAP_LLGR_ADV (1ULL << 21)
+#define PEER_CAP_LLGR_RCV (1ULL << 22)
/* sent graceful-restart notification (N) bit */
-#define PEER_CAP_GRACEFUL_RESTART_N_BIT_ADV (1U << 23)
+#define PEER_CAP_GRACEFUL_RESTART_N_BIT_ADV (1ULL << 23)
/* received graceful-restart notification (N) bit */
-#define PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV (1U << 24)
-#define PEER_CAP_ROLE_ADV (1U << 25) /* role advertised */
-#define PEER_CAP_ROLE_RCV (1U << 26) /* role received */
-#define PEER_CAP_SOFT_VERSION_ADV (1U << 27)
-#define PEER_CAP_SOFT_VERSION_RCV (1U << 28)
+#define PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV (1ULL << 24)
+#define PEER_CAP_ROLE_ADV (1ULL << 25) /* role advertised */
+#define PEER_CAP_ROLE_RCV (1ULL << 26) /* role received */
+#define PEER_CAP_SOFT_VERSION_ADV (1ULL << 27)
+#define PEER_CAP_SOFT_VERSION_RCV (1ULL << 28)
/* Capability flags (reset in bgp_stop) */
uint32_t af_cap[AFI_MAX][SAFI_MAX];
@@ -1439,6 +1460,7 @@ struct peer {
#define PEER_FLAG_AIGP (1ULL << 34)
#define PEER_FLAG_GRACEFUL_SHUTDOWN (1ULL << 35)
#define PEER_FLAG_CAPABILITY_SOFT_VERSION (1ULL << 36)
+#define PEER_FLAG_CAPABILITY_FQDN (1ULL << 37) /* fqdn capability */
/*
*GR-Disabled mode means unset PEER_FLAG_GRACEFUL_RESTART
@@ -1505,6 +1527,7 @@ struct peer {
#define PEER_FLAG_MAX_PREFIX_FORCE (1ULL << 26)
#define PEER_FLAG_DISABLE_ADDPATH_RX (1ULL << 27)
#define PEER_FLAG_SOO (1ULL << 28)
+#define PEER_FLAG_SEND_EXT_COMMUNITY_RPKI (1ULL << 29)
#define PEER_FLAG_ACCEPT_OWN (1ULL << 63)
enum bgp_addpath_strat addpath_type[AFI_MAX][SAFI_MAX];
@@ -1742,6 +1765,7 @@ struct peer {
#define PEER_DOWN_PFX_COUNT 33U /* Reached received prefix count */
#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 */
/*
* Remember to update peer_down_str in bgp_fsm.c when you add
* a new value to the last_reset reason
@@ -1868,11 +1892,11 @@ struct bgp_nlri {
/* SAFI. */
uint8_t safi; /* iana_safi_t */
- /* Pointer to NLRI byte stream. */
- uint8_t *nlri;
-
/* Length of whole NLRI. */
bgp_size_t length;
+
+ /* Pointer to NLRI byte stream. */
+ uint8_t *nlri;
};
/* BGP versions. */
@@ -2042,7 +2066,6 @@ struct bgp_nlri {
#define BGP_UPTIME_LEN 25
/* Default configuration settings for bgpd. */
-#define BGP_VTY_PORT 2605
#define BGP_DEFAULT_CONFIG "bgpd.conf"
/* BGP Dynamic Neighbors feature */
@@ -2064,7 +2087,8 @@ enum bgp_clear_type {
BGP_CLEAR_SOFT_IN,
BGP_CLEAR_SOFT_BOTH,
BGP_CLEAR_SOFT_IN_ORF_PREFIX,
- BGP_CLEAR_MESSAGE_STATS
+ BGP_CLEAR_MESSAGE_STATS,
+ BGP_CLEAR_CAPABILITIES,
};
/* Macros. */
@@ -2430,6 +2454,8 @@ extern enum asnotation_mode bgp_get_asnotation(struct bgp *bgp);
extern void bgp_route_map_terminate(void);
+extern bool bgp_route_map_has_extcommunity_rt(const struct route_map *map);
+
extern int peer_cmp(struct peer *p1, struct peer *p2);
extern int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, iana_safi_t pkt_safi,
@@ -2721,6 +2747,9 @@ extern bool bgp_path_attribute_discard(struct peer *peer, char *buf,
size_t size);
extern bool bgp_path_attribute_treat_as_withdraw(struct peer *peer, char *buf,
size_t size);
+
+extern void srv6_function_free(struct bgp_srv6_function *func);
+
#ifdef _FRR_ATTRIBUTE_PRINTFRR
/* clang-format off */
#pragma FRR printfrr_ext "%pBP" (struct peer *)
diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c
index 5b6961d..a452ebe 100644
--- a/bgpd/rfapi/bgp_rfapi_cfg.c
+++ b/bgpd/rfapi/bgp_rfapi_cfg.c
@@ -531,7 +531,7 @@ rfapi_group_new(struct bgp *bgp, rfapi_group_cfg_type_t type, const char *name)
rfg = XCALLOC(MTYPE_RFAPI_GROUP_CFG,
sizeof(struct rfapi_nve_group_cfg));
rfg->type = type;
- rfg->name = strdup(name);
+ rfg->name = XSTRDUP(MTYPE_RFAPI_GROUP_CFG, name);
/* add to tail of list */
listnode_add(bgp->rfapi_cfg->nve_groups_sequential, rfg);
rfg->label = MPLS_LABEL_NONE;
@@ -832,8 +832,8 @@ DEFUN (vnc_redistribute_protocol,
if (bgp->rfapi_cfg->redist_bgp_exterior_view_name) {
VNC_REDIST_DISABLE(bgp, afi,
type); /* disabled view implicitly */
- free(bgp->rfapi_cfg->redist_bgp_exterior_view_name);
- bgp->rfapi_cfg->redist_bgp_exterior_view_name = NULL;
+ XFREE(MTYPE_RFAPI_GROUP_CFG,
+ bgp->rfapi_cfg->redist_bgp_exterior_view_name);
}
bgp->rfapi_cfg->redist_bgp_exterior_view = bgp;
}
@@ -873,10 +873,8 @@ DEFUN (vnc_no_redistribute_protocol,
VNC_REDIST_DISABLE(bgp, afi, type);
if (type == ZEBRA_ROUTE_BGP_DIRECT_EXT) {
- if (bgp->rfapi_cfg->redist_bgp_exterior_view_name) {
- free(bgp->rfapi_cfg->redist_bgp_exterior_view_name);
- bgp->rfapi_cfg->redist_bgp_exterior_view_name = NULL;
- }
+ XFREE(MTYPE_RFAPI_GROUP_CFG,
+ bgp->rfapi_cfg->redist_bgp_exterior_view_name);
bgp->rfapi_cfg->redist_bgp_exterior_view = NULL;
}
@@ -905,9 +903,10 @@ DEFUN (vnc_redistribute_bgp_exterior,
return CMD_WARNING_CONFIG_FAILED;
}
- if (bgp->rfapi_cfg->redist_bgp_exterior_view_name)
- free(bgp->rfapi_cfg->redist_bgp_exterior_view_name);
- bgp->rfapi_cfg->redist_bgp_exterior_view_name = strdup(argv[5]->arg);
+ XFREE(MTYPE_RFAPI_GROUP_CFG,
+ bgp->rfapi_cfg->redist_bgp_exterior_view_name);
+ bgp->rfapi_cfg->redist_bgp_exterior_view_name =
+ XSTRDUP(MTYPE_RFAPI_GROUP_CFG, argv[5]->arg);
/* could be NULL if name is not defined yet */
bgp->rfapi_cfg->redist_bgp_exterior_view =
bgp_lookup_by_name(argv[5]->arg);
@@ -935,9 +934,9 @@ DEFUN (vnc_redistribute_nvegroup,
*/
bgp->rfapi_cfg->rfg_redist = bgp_rfapi_cfg_match_byname(
bgp, argv[3]->arg, RFAPI_GROUP_CFG_NVE);
- if (bgp->rfapi_cfg->rfg_redist_name)
- free(bgp->rfapi_cfg->rfg_redist_name);
- bgp->rfapi_cfg->rfg_redist_name = strdup(argv[3]->arg);
+ XFREE(MTYPE_RFAPI_GROUP_CFG, bgp->rfapi_cfg->rfg_redist_name);
+ bgp->rfapi_cfg->rfg_redist_name = XSTRDUP(MTYPE_RFAPI_GROUP_CFG,
+ argv[3]->arg);
vnc_redistribute_postchange(bgp);
@@ -959,9 +958,7 @@ DEFUN (vnc_redistribute_no_nvegroup,
vnc_redistribute_prechange(bgp);
bgp->rfapi_cfg->rfg_redist = NULL;
- if (bgp->rfapi_cfg->rfg_redist_name)
- free(bgp->rfapi_cfg->rfg_redist_name);
- bgp->rfapi_cfg->rfg_redist_name = NULL;
+ XFREE(MTYPE_RFAPI_GROUP_CFG, bgp->rfapi_cfg->rfg_redist_name);
vnc_redistribute_postchange(bgp);
@@ -1030,9 +1027,7 @@ DEFUN (vnc_redist_bgpdirect_no_prefixlist,
vnc_redistribute_prechange(bgp);
- if (hc->plist_redist_name[route_type][afi])
- free(hc->plist_redist_name[route_type][afi]);
- hc->plist_redist_name[route_type][afi] = NULL;
+ XFREE(MTYPE_RFAPI_GROUP_CFG, hc->plist_redist_name[route_type][afi]);
hc->plist_redist[route_type][afi] = NULL;
vnc_redistribute_postchange(bgp);
@@ -1074,9 +1069,9 @@ DEFUN (vnc_redist_bgpdirect_prefixlist,
vnc_redistribute_prechange(bgp);
- if (hc->plist_redist_name[route_type][afi])
- free(hc->plist_redist_name[route_type][afi]);
- hc->plist_redist_name[route_type][afi] = strdup(argv[5]->arg);
+ XFREE(MTYPE_RFAPI_GROUP_CFG, hc->plist_redist_name[route_type][afi]);
+ hc->plist_redist_name[route_type][afi] = XSTRDUP(MTYPE_RFAPI_GROUP_CFG,
+ argv[5]->arg);
hc->plist_redist[route_type][afi] =
prefix_list_lookup(afi, argv[5]->arg);
@@ -1110,9 +1105,7 @@ DEFUN (vnc_redist_bgpdirect_no_routemap,
vnc_redistribute_prechange(bgp);
- if (hc->routemap_redist_name[route_type])
- free(hc->routemap_redist_name[route_type]);
- hc->routemap_redist_name[route_type] = NULL;
+ XFREE(MTYPE_RFAPI_GROUP_CFG, hc->routemap_redist_name[route_type]);
hc->routemap_redist[route_type] = NULL;
vnc_redistribute_postchange(bgp);
@@ -1144,15 +1137,16 @@ DEFUN (vnc_redist_bgpdirect_routemap,
vnc_redistribute_prechange(bgp);
- if (hc->routemap_redist_name[route_type])
- free(hc->routemap_redist_name[route_type]);
+ XFREE(MTYPE_RFAPI_GROUP_CFG, hc->routemap_redist_name[route_type]);
/* If the old route map config overwrite with new
* route map config , old routemap counter have to be
* reduced.
*/
route_map_counter_decrement(hc->routemap_redist[route_type]);
- hc->routemap_redist_name[route_type] = strdup(argv[4]->arg);
+ hc->routemap_redist_name[route_type] = XSTRDUP(MTYPE_RFAPI_GROUP_CFG,
+ argv[4]->arg);
+
hc->routemap_redist[route_type] =
route_map_lookup_by_name(argv[4]->arg);
route_map_counter_increment(hc->routemap_redist[route_type]);
@@ -1197,9 +1191,8 @@ DEFUN (vnc_nve_group_redist_bgpdirect_no_prefixlist,
vnc_redistribute_prechange(bgp);
- if (rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi])
- free(rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]);
- rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi] = NULL;
+ XFREE(MTYPE_RFAPI_GROUP_CFG,
+ rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]);
rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi] = NULL;
vnc_redistribute_postchange(bgp);
@@ -1238,10 +1231,10 @@ DEFUN (vnc_nve_group_redist_bgpdirect_prefixlist,
vnc_redistribute_prechange(bgp);
- if (rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi])
- free(rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]);
+ XFREE(MTYPE_RFAPI_GROUP_CFG,
+ rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]);
rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi] =
- strdup(argv[4]->arg);
+ XSTRDUP(MTYPE_RFAPI_GROUP_CFG, argv[4]->arg);
rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi] =
prefix_list_lookup(afi, argv[4]->arg);
@@ -1272,11 +1265,10 @@ DEFUN (vnc_nve_group_redist_bgpdirect_no_routemap,
vnc_redistribute_prechange(bgp);
- if (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT])
- free(rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]);
+ XFREE(MTYPE_RFAPI_GROUP_CFG,
+ rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]);
route_map_counter_decrement(
rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT]);
- rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT] = NULL;
rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT] = NULL;
vnc_redistribute_postchange(bgp);
@@ -1305,12 +1297,12 @@ DEFUN (vnc_nve_group_redist_bgpdirect_routemap,
vnc_redistribute_prechange(bgp);
- if (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT])
- free(rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]);
+ XFREE(MTYPE_RFAPI_GROUP_CFG,
+ rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]);
route_map_counter_decrement(
rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT]);
rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT] =
- strdup(argv[3]->arg);
+ XSTRDUP(MTYPE_RFAPI_GROUP_CFG, argv[3]->arg);
rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT] =
route_map_lookup_by_name(argv[3]->arg);
route_map_counter_increment(
@@ -1451,7 +1443,7 @@ DEFUN (vnc_export_nvegroup,
}
rfgn = rfgn_new();
- rfgn->name = strdup(argv[5]->arg);
+ rfgn->name = XSTRDUP(MTYPE_RFAPI_GROUP_CFG, argv[5]->arg);
rfgn->rfg = rfg_new; /* OK if not set yet */
listnode_add(bgp->rfapi_cfg->rfg_export_direct_bgp_l, rfgn);
@@ -1487,7 +1479,7 @@ DEFUN (vnc_export_nvegroup,
}
rfgn = rfgn_new();
- rfgn->name = strdup(argv[5]->arg);
+ rfgn->name = XSTRDUP(MTYPE_RFAPI_GROUP_CFG, argv[5]->arg);
rfgn->rfg = rfg_new; /* OK if not set yet */
listnode_add(bgp->rfapi_cfg->rfg_export_zebra_l, rfgn);
@@ -1531,7 +1523,7 @@ DEFUN (vnc_no_export_nvegroup,
if (rfgn->rfg)
vnc_direct_bgp_del_group(bgp,
rfgn->rfg);
- free(rfgn->name);
+ XFREE(MTYPE_RFAPI_GROUP_CFG, rfgn->name);
list_delete_node(
bgp->rfapi_cfg->rfg_export_direct_bgp_l,
node);
@@ -1548,7 +1540,7 @@ DEFUN (vnc_no_export_nvegroup,
if (rfgn->name && !strcmp(rfgn->name, argv[6]->arg)) {
if (rfgn->rfg)
vnc_zebra_del_group(bgp, rfgn->rfg);
- free(rfgn->name);
+ XFREE(MTYPE_RFAPI_GROUP_CFG, rfgn->name);
list_delete_node(
bgp->rfapi_cfg->rfg_export_zebra_l,
node);
@@ -1612,9 +1604,8 @@ DEFUN (vnc_nve_group_export_no_prefixlist,
|| (rfg->plist_export_zebra_name[afi]
&& strmatch(argv[idx]->arg,
rfg->plist_export_zebra_name[afi]))) {
- if (rfg->plist_export_zebra_name[afi])
- free(rfg->plist_export_zebra_name[afi]);
- rfg->plist_export_zebra_name[afi] = NULL;
+ XFREE(MTYPE_RFAPI_GROUP_CFG,
+ rfg->plist_export_zebra_name[afi]);
rfg->plist_export_zebra[afi] = NULL;
vnc_zebra_reexport_group_afi(bgp, rfg, afi);
@@ -1667,18 +1658,18 @@ DEFUN (vnc_nve_group_export_prefixlist,
idx = argc - 1;
if (is_bgp) {
- if (rfg->plist_export_bgp_name[afi])
- free(rfg->plist_export_bgp_name[afi]);
- rfg->plist_export_bgp_name[afi] = strdup(argv[idx]->arg);
+ XFREE(MTYPE_RFAPI_GROUP_CFG, rfg->plist_export_bgp_name[afi]);
+ rfg->plist_export_bgp_name[afi] = XSTRDUP(MTYPE_RFAPI_GROUP_CFG,
+ argv[idx]->arg);
rfg->plist_export_bgp[afi] =
prefix_list_lookup(afi, argv[idx]->arg);
vnc_direct_bgp_reexport_group_afi(bgp, rfg, afi);
} else {
- if (rfg->plist_export_zebra_name[afi])
- free(rfg->plist_export_zebra_name[afi]);
- rfg->plist_export_zebra_name[afi] = strdup(argv[idx]->arg);
+ XFREE(MTYPE_RFAPI_GROUP_CFG, rfg->plist_export_zebra_name[afi]);
+ rfg->plist_export_zebra_name[afi] =
+ XSTRDUP(MTYPE_RFAPI_GROUP_CFG, argv[idx]->arg);
rfg->plist_export_zebra[afi] =
prefix_list_lookup(afi, argv[idx]->arg);
@@ -1720,7 +1711,8 @@ DEFUN (vnc_nve_group_export_no_routemap,
switch (argv[idx]->text[0]) {
case 'z':
is_bgp = 0;
- /* fall thru */
+ idx += 2;
+ break;
case 'b':
idx += 2;
break;
@@ -1734,10 +1726,9 @@ DEFUN (vnc_nve_group_export_no_routemap,
|| (rfg->routemap_export_bgp_name
&& strmatch(argv[idx]->arg,
rfg->routemap_export_bgp_name))) {
- if (rfg->routemap_export_bgp_name)
- free(rfg->routemap_export_bgp_name);
+ XFREE(MTYPE_RFAPI_GROUP_CFG,
+ rfg->routemap_export_bgp_name);
route_map_counter_decrement(rfg->routemap_export_bgp);
- rfg->routemap_export_bgp_name = NULL;
rfg->routemap_export_bgp = NULL;
vnc_direct_bgp_reexport_group_afi(bgp, rfg, AFI_IP);
@@ -1748,10 +1739,8 @@ DEFUN (vnc_nve_group_export_no_routemap,
|| (rfg->routemap_export_zebra_name
&& strmatch(argv[idx]->arg,
rfg->routemap_export_zebra_name))) {
- if (rfg->routemap_export_zebra_name)
- free(rfg->routemap_export_zebra_name);
+ XFREE(MTYPE_RFAPI_GROUP_CFG, rfg->routemap_export_zebra_name);
route_map_counter_decrement(rfg->routemap_export_zebra);
- rfg->routemap_export_zebra_name = NULL;
rfg->routemap_export_zebra = NULL;
vnc_zebra_reexport_group_afi(bgp, rfg, AFI_IP);
@@ -1795,20 +1784,20 @@ DEFUN (vnc_nve_group_export_routemap,
idx = argc - 1;
if (is_bgp) {
- if (rfg->routemap_export_bgp_name)
- free(rfg->routemap_export_bgp_name);
+ XFREE(MTYPE_RFAPI_GROUP_CFG, rfg->routemap_export_bgp_name);
route_map_counter_decrement(rfg->routemap_export_bgp);
- rfg->routemap_export_bgp_name = strdup(argv[idx]->arg);
+ rfg->routemap_export_bgp_name = XSTRDUP(MTYPE_RFAPI_GROUP_CFG,
+ argv[idx]->arg);
rfg->routemap_export_bgp =
route_map_lookup_by_name(argv[idx]->arg);
route_map_counter_increment(rfg->routemap_export_bgp);
vnc_direct_bgp_reexport_group_afi(bgp, rfg, AFI_IP);
vnc_direct_bgp_reexport_group_afi(bgp, rfg, AFI_IP6);
} else {
- if (rfg->routemap_export_zebra_name)
- free(rfg->routemap_export_zebra_name);
+ XFREE(MTYPE_RFAPI_GROUP_CFG, rfg->routemap_export_zebra_name);
route_map_counter_decrement(rfg->routemap_export_zebra);
- rfg->routemap_export_zebra_name = strdup(argv[idx]->arg);
+ rfg->routemap_export_zebra_name = XSTRDUP(MTYPE_RFAPI_GROUP_CFG,
+ argv[idx]->arg);
rfg->routemap_export_zebra =
route_map_lookup_by_name(argv[idx]->arg);
route_map_counter_increment(rfg->routemap_export_zebra);
@@ -1853,9 +1842,8 @@ DEFUN (vnc_nve_export_no_prefixlist,
if (((argc > 6) && hc->plist_export_bgp_name[afi]
&& strmatch(argv[6]->text, hc->plist_export_bgp_name[afi]))
|| (argc <= 6)) {
-
- free(hc->plist_export_bgp_name[afi]);
- hc->plist_export_bgp_name[afi] = NULL;
+ XFREE(MTYPE_RFAPI_GROUP_CFG,
+ hc->plist_export_bgp_name[afi]);
hc->plist_export_bgp[afi] = NULL;
vnc_direct_bgp_reexport(bgp, afi);
}
@@ -1864,9 +1852,8 @@ DEFUN (vnc_nve_export_no_prefixlist,
&& strmatch(argv[6]->text,
hc->plist_export_zebra_name[afi]))
|| (argc <= 6)) {
-
- free(hc->plist_export_zebra_name[afi]);
- hc->plist_export_zebra_name[afi] = NULL;
+ XFREE(MTYPE_RFAPI_GROUP_CFG,
+ hc->plist_export_zebra_name[afi]);
hc->plist_export_zebra[afi] = NULL;
/* TBD vnc_zebra_rh_reexport(bgp, afi); */
}
@@ -1899,16 +1886,16 @@ DEFUN (vnc_nve_export_prefixlist,
}
if (argv[2]->arg[0] == 'b') {
- if (hc->plist_export_bgp_name[afi])
- free(hc->plist_export_bgp_name[afi]);
- hc->plist_export_bgp_name[afi] = strdup(argv[5]->arg);
+ XFREE(MTYPE_RFAPI_GROUP_CFG, hc->plist_export_bgp_name[afi]);
+ hc->plist_export_bgp_name[afi] = XSTRDUP(MTYPE_RFAPI_GROUP_CFG,
+ argv[5]->arg);
hc->plist_export_bgp[afi] =
prefix_list_lookup(afi, argv[5]->arg);
vnc_direct_bgp_reexport(bgp, afi);
} else {
- if (hc->plist_export_zebra_name[afi])
- free(hc->plist_export_zebra_name[afi]);
- hc->plist_export_zebra_name[afi] = strdup(argv[5]->arg);
+ XFREE(MTYPE_RFAPI_GROUP_CFG, hc->plist_export_zebra_name[afi]);
+ hc->plist_export_zebra_name[afi] =
+ XSTRDUP(MTYPE_RFAPI_GROUP_CFG, argv[5]->arg);
hc->plist_export_zebra[afi] =
prefix_list_lookup(afi, argv[5]->arg);
/* TBD vnc_zebra_rh_reexport(bgp, afi); */
@@ -1936,10 +1923,9 @@ DEFUN (vnc_nve_export_no_routemap,
if (((argc > 5) && hc->routemap_export_bgp_name
&& strmatch(argv[5]->text, hc->routemap_export_bgp_name))
|| (argc <= 5)) {
-
- free(hc->routemap_export_bgp_name);
+ XFREE(MTYPE_RFAPI_GROUP_CFG,
+ hc->routemap_export_bgp_name);
route_map_counter_decrement(hc->routemap_export_bgp);
- hc->routemap_export_bgp_name = NULL;
hc->routemap_export_bgp = NULL;
vnc_direct_bgp_reexport(bgp, AFI_IP);
vnc_direct_bgp_reexport(bgp, AFI_IP6);
@@ -1949,9 +1935,8 @@ DEFUN (vnc_nve_export_no_routemap,
&& strmatch(argv[5]->text, hc->routemap_export_zebra_name))
|| (argc <= 5)) {
- free(hc->routemap_export_zebra_name);
+ XFREE(MTYPE_RFAPI_GROUP_CFG, hc->routemap_export_zebra_name);
route_map_counter_decrement(hc->routemap_export_zebra);
- hc->routemap_export_zebra_name = NULL;
hc->routemap_export_zebra = NULL;
/* TBD vnc_zebra_rh_reexport(bgp, AFI_IP); */
/* TBD vnc_zebra_rh_reexport(bgp, AFI_IP6); */
@@ -1976,20 +1961,20 @@ DEFUN (vnc_nve_export_routemap,
hc = bgp->rfapi_cfg;
if (argv[2]->arg[0] == 'b') {
- if (hc->routemap_export_bgp_name)
- free(hc->routemap_export_bgp_name);
+ XFREE(MTYPE_RFAPI_GROUP_CFG, hc->routemap_export_bgp_name);
route_map_counter_decrement(hc->routemap_export_bgp);
- hc->routemap_export_bgp_name = strdup(argv[4]->arg);
+ hc->routemap_export_bgp_name = XSTRDUP(MTYPE_RFAPI_GROUP_CFG,
+ argv[4]->arg);
hc->routemap_export_bgp =
route_map_lookup_by_name(argv[4]->arg);
route_map_counter_increment(hc->routemap_export_bgp);
vnc_direct_bgp_reexport(bgp, AFI_IP);
vnc_direct_bgp_reexport(bgp, AFI_IP6);
} else {
- if (hc->routemap_export_zebra_name)
- free(hc->routemap_export_zebra_name);
+ XFREE(MTYPE_RFAPI_GROUP_CFG, hc->routemap_export_zebra_name);
route_map_counter_decrement(hc->routemap_export_zebra);
- hc->routemap_export_zebra_name = strdup(argv[4]->arg);
+ hc->routemap_export_zebra_name = XSTRDUP(MTYPE_RFAPI_GROUP_CFG,
+ argv[4]->arg);
hc->routemap_export_zebra =
route_map_lookup_by_name(argv[4]->arg);
route_map_counter_increment(hc->routemap_export_zebra);
@@ -2319,7 +2304,7 @@ static void bgp_rfapi_delete_nve_group(struct vty *vty, /* NULL = no output */
}
/* delete it */
- free(rfg->name);
+ XFREE(MTYPE_RFAPI_GROUP_CFG, rfg->name);
if (rfg->rfapi_import_table)
rfapiImportTableRefDelByIt(bgp, rfg->rfapi_import_table);
if (rfg->rt_import_list)
@@ -3410,7 +3395,7 @@ DEFUN_NOSH (vnc_l2_group,
vty_out(vty, "Can't allocate memory for L2 group\n");
return CMD_WARNING_CONFIG_FAILED;
}
- rfg->name = strdup(argv[2]->arg);
+ rfg->name = XSTRDUP(MTYPE_RFAPI_GROUP_CFG, argv[2]->arg);
/* add to tail of list */
listnode_add(bgp->rfapi_cfg->l2_groups, rfg);
}
@@ -3428,7 +3413,7 @@ static void bgp_rfapi_delete_l2_group(struct vty *vty, /* NULL = no output */
struct rfapi_l2_group_cfg *rfg)
{
/* delete it */
- free(rfg->name);
+ XFREE(MTYPE_RFAPI_GROUP_CFG, rfg->name);
if (rfg->rt_import_list)
ecommunity_free(&rfg->rt_import_list);
if (rfg->rt_export_list)
@@ -3590,7 +3575,9 @@ DEFUN (vnc_l2_group_rt,
switch (argv[1]->arg[0]) {
case 'b':
- do_export = 1; /* fall through */
+ do_export = 1;
+ do_import = 1;
+ break;
case 'i':
do_import = 1;
break;
@@ -3840,7 +3827,8 @@ struct rfapi_cfg *bgp_rfapi_cfg_new(struct rfapi_rfp_cfg *cfg)
static void bgp_rfapi_rfgn_list_delete(void *data)
{
struct rfapi_rfg_name *rfgn = data;
- free(rfgn->name);
+
+ XFREE(MTYPE_RFAPI_GROUP_CFG, rfgn->name);
rfgn_free(rfgn);
}
diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c
index ff7137b..382af05 100644
--- a/bgpd/rfapi/rfapi.c
+++ b/bgpd/rfapi/rfapi.c
@@ -46,11 +46,6 @@
#include "bgpd/rfapi/rfapi_encap_tlv.h"
#include "bgpd/rfapi/vnc_debug.h"
-#ifdef HAVE_GLIBC_BACKTRACE
-/* for backtrace and friends */
-#include <execinfo.h>
-#endif /* HAVE_GLIBC_BACKTRACE */
-
#define DEBUG_CLEANUP 0
struct ethaddr rfapi_ethaddr0 = {{0}};
@@ -371,20 +366,19 @@ void del_vnc_route(struct rfapi_descriptor *rfd,
for (bpi = (bn ? bgp_dest_get_bgp_path_info(bn) : NULL); bpi;
bpi = bpi->next) {
-
vnc_zlog_debug_verbose(
"%s: trying bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p, local_pref=%" PRIu64,
__func__, bpi, bpi->peer, bpi->type, bpi->sub_type,
- (bpi->extra ? bpi->extra->vnc.export.rfapi_handle
+ (bpi->extra ? bpi->extra->vnc->vnc.export.rfapi_handle
: NULL),
CHECK_FLAG(bpi->attr->flag,
ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)
- ? bpi->attr->local_pref : 0));
-
- if (bpi->peer == peer && bpi->type == type
- && bpi->sub_type == sub_type && bpi->extra
- && bpi->extra->vnc.export.rfapi_handle == (void *)rfd) {
+ ? bpi->attr->local_pref
+ : 0));
+ if (bpi->peer == peer && bpi->type == type &&
+ bpi->sub_type == sub_type && bpi->extra &&
+ bpi->extra->vnc->vnc.export.rfapi_handle == (void *)rfd) {
vnc_zlog_debug_verbose("%s: matched it", __func__);
break;
@@ -397,8 +391,8 @@ void del_vnc_route(struct rfapi_descriptor *rfd,
* route. Leave the route itself in place.
* TBD add return code reporting of success/failure
*/
- if (!bpi || !bpi->extra
- || !bpi->extra->vnc.export.local_nexthops) {
+ if (!bpi || !bpi->extra ||
+ !bpi->extra->vnc->vnc.export.local_nexthops) {
/*
* no local nexthops
*/
@@ -414,16 +408,16 @@ void del_vnc_route(struct rfapi_descriptor *rfd,
struct listnode *node;
struct rfapi_nexthop *pLnh = NULL;
- for (ALL_LIST_ELEMENTS_RO(bpi->extra->vnc.export.local_nexthops,
+ for (ALL_LIST_ELEMENTS_RO(bpi->extra->vnc->vnc.export
+ .local_nexthops,
node, pLnh)) {
-
if (prefix_same(&pLnh->addr, &lnh->addr)) {
break;
}
}
if (pLnh) {
- listnode_delete(bpi->extra->vnc.export.local_nexthops,
+ listnode_delete(bpi->extra->vnc->vnc.export.local_nexthops,
pLnh);
/* silly rabbit, listnode_delete doesn't invoke
@@ -464,8 +458,8 @@ void del_vnc_route(struct rfapi_descriptor *rfd,
/*
* Delete local_nexthops list
*/
- if (bpi->extra && bpi->extra->vnc.export.local_nexthops)
- list_delete(&bpi->extra->vnc.export.local_nexthops);
+ if (bpi->extra && bpi->extra->vnc->vnc.export.local_nexthops)
+ list_delete(&bpi->extra->vnc->vnc.export.local_nexthops);
bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
bgp_path_info_delete(bn, bpi);
@@ -907,11 +901,10 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
*/
for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) {
/* probably only need to check
- * bpi->extra->vnc.export.rfapi_handle */
- if (bpi->peer == rfd->peer && bpi->type == type
- && bpi->sub_type == sub_type && bpi->extra
- && bpi->extra->vnc.export.rfapi_handle == (void *)rfd) {
-
+ * bpi->extra->vnc->vnc.export.rfapi_handle */
+ if (bpi->peer == rfd->peer && bpi->type == type &&
+ bpi->sub_type == sub_type && bpi->extra &&
+ bpi->extra->vnc->vnc.export.rfapi_handle == (void *)rfd) {
break;
}
}
@@ -923,11 +916,11 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
* what is advertised via BGP
*/
if (lnh) {
- if (!bpi->extra->vnc.export.local_nexthops) {
+ if (!bpi->extra->vnc->vnc.export.local_nexthops) {
/* TBD make arrangements to free when needed */
- bpi->extra->vnc.export.local_nexthops =
+ bpi->extra->vnc->vnc.export.local_nexthops =
list_new();
- bpi->extra->vnc.export.local_nexthops->del =
+ bpi->extra->vnc->vnc.export.local_nexthops->del =
rfapi_nexthop_free;
}
@@ -937,10 +930,9 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
struct listnode *node;
struct rfapi_nexthop *pLnh = NULL;
- for (ALL_LIST_ELEMENTS_RO(
- bpi->extra->vnc.export.local_nexthops,
- node, pLnh)) {
-
+ for (ALL_LIST_ELEMENTS_RO(bpi->extra->vnc->vnc.export
+ .local_nexthops,
+ node, pLnh)) {
if (prefix_same(&pLnh->addr, &lnh->addr)) {
break;
}
@@ -951,9 +943,9 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
*/
if (!pLnh) {
pLnh = rfapi_nexthop_new(lnh);
- listnode_add(
- bpi->extra->vnc.export.local_nexthops,
- pLnh);
+ listnode_add(bpi->extra->vnc->vnc.export
+ .local_nexthops,
+ pLnh);
}
}
@@ -1025,7 +1017,9 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
/* save backref to rfapi handle */
bgp_path_info_extra_get(new);
- new->extra->vnc.export.rfapi_handle = (void *)rfd;
+ new->extra->vnc = XCALLOC(MTYPE_BGP_ROUTE_EXTRA_VNC,
+ sizeof(struct bgp_path_info_extra_vnc));
+ new->extra->vnc->vnc.export.rfapi_handle = (void *)rfd;
encode_label(label_val, &new->extra->label[0]);
/* debug */
@@ -2091,24 +2085,7 @@ int rfapi_close(void *handle)
vnc_zlog_debug_verbose("%s: rfd=%p", __func__, rfd);
#ifdef RFAPI_WHO_IS_CALLING_ME
-#ifdef HAVE_GLIBC_BACKTRACE
-#define RFAPI_DEBUG_BACKTRACE_NENTRIES 5
- {
- void *buf[RFAPI_DEBUG_BACKTRACE_NENTRIES];
- char **syms;
- int i;
- size_t size;
-
- size = backtrace(buf, RFAPI_DEBUG_BACKTRACE_NENTRIES);
- syms = backtrace_symbols(buf, size);
- for (i = 0; i < size && i < RFAPI_DEBUG_BACKTRACE_NENTRIES;
- ++i) {
- vnc_zlog_debug_verbose("backtrace[%2d]: %s", i,
- syms[i]);
- }
- free(syms);
- }
-#endif
+ zlog_backtrace(LOG_INFO);
#endif
bgp = rfd->bgp;
diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c
index a93e186..168b8e4 100644
--- a/bgpd/rfapi/rfapi_import.c
+++ b/bgpd/rfapi/rfapi_import.c
@@ -44,11 +44,6 @@
#include "bgpd/rfapi/rfapi_encap_tlv.h"
#include "bgpd/rfapi/vnc_debug.h"
-#ifdef HAVE_GLIBC_BACKTRACE
-/* for backtrace and friends */
-#include <execinfo.h>
-#endif /* HAVE_GLIBC_BACKTRACE */
-
#undef DEBUG_MONITOR_MOVE_SHORTER
#undef DEBUG_RETURNED_NHL
#undef DEBUG_ROUTE_COUNTERS
@@ -79,32 +74,6 @@ struct rfapi_withdraw {
/*
* DEBUG FUNCTION
- * It's evil and fiendish. It's compiler-dependent.
- * ? Might need LDFLAGS -rdynamic to produce all function names
- */
-void rfapiDebugBacktrace(void)
-{
-#ifdef HAVE_GLIBC_BACKTRACE
-#define RFAPI_DEBUG_BACKTRACE_NENTRIES 200
- void *buf[RFAPI_DEBUG_BACKTRACE_NENTRIES];
- char **syms;
- size_t i;
- size_t size;
-
- size = backtrace(buf, RFAPI_DEBUG_BACKTRACE_NENTRIES);
- syms = backtrace_symbols(buf, size);
-
- for (i = 0; i < size && i < RFAPI_DEBUG_BACKTRACE_NENTRIES; ++i) {
- vnc_zlog_debug_verbose("backtrace[%2zu]: %s", i, syms[i]);
- }
-
- free(syms);
-#else
-#endif
-}
-
-/*
- * DEBUG FUNCTION
* Count remote routes and compare with actively-maintained values.
* Abort if they disagree.
*/
@@ -428,18 +397,22 @@ int rfapiGetUnAddrOfVpnBi(struct bgp_path_info *bpi, struct prefix *p)
* advertisement
*/
if (bpi->extra) {
- switch (bpi->extra->vnc.import.un_family) {
+ switch (bpi->extra->vnc->vnc.import.un_family) {
case AF_INET:
if (p) {
- p->family = bpi->extra->vnc.import.un_family;
- p->u.prefix4 = bpi->extra->vnc.import.un.addr4;
+ p->family =
+ bpi->extra->vnc->vnc.import.un_family;
+ p->u.prefix4 =
+ bpi->extra->vnc->vnc.import.un.addr4;
p->prefixlen = IPV4_MAX_BITLEN;
}
return 0;
case AF_INET6:
if (p) {
- p->family = bpi->extra->vnc.import.un_family;
- p->u.prefix6 = bpi->extra->vnc.import.un.addr6;
+ p->family =
+ bpi->extra->vnc->vnc.import.un_family;
+ p->u.prefix6 =
+ bpi->extra->vnc->vnc.import.un.addr6;
p->prefixlen = IPV6_MAX_BITLEN;
}
return 0;
@@ -475,9 +448,11 @@ static struct bgp_path_info *rfapiBgpInfoCreate(struct attr *attr,
new->attr = bgp_attr_intern(attr);
bgp_path_info_extra_get(new);
+ new->extra->vnc = XCALLOC(MTYPE_BGP_ROUTE_EXTRA_VNC,
+ sizeof(struct bgp_path_info_extra_vnc));
if (prd) {
- new->extra->vnc.import.rd = *prd;
- new->extra->vnc.import.create_time = monotime(NULL);
+ new->extra->vnc->vnc.import.rd = *prd;
+ new->extra->vnc->vnc.import.create_time = monotime(NULL);
}
if (label)
encode_label(*label, &new->extra->label[0]);
@@ -842,13 +817,13 @@ static void rfapiBgpInfoChainFree(struct bgp_path_info *bpi)
* If there is a timer waiting to delete this bpi, cancel
* the timer and delete immediately
*/
- if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)
- && bpi->extra->vnc.import.timer) {
+ if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) &&
+ bpi->extra->vnc->vnc.import.timer) {
struct rfapi_withdraw *wcb =
- EVENT_ARG(bpi->extra->vnc.import.timer);
+ EVENT_ARG(bpi->extra->vnc->vnc.import.timer);
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
- EVENT_OFF(bpi->extra->vnc.import.timer);
+ EVENT_OFF(bpi->extra->vnc->vnc.import.timer);
}
next = bpi->next;
@@ -1136,15 +1111,15 @@ static int rfapiVpnBiSamePtUn(struct bgp_path_info *bpi1,
*/
if (rfapiGetVncTunnelUnAddr(bpi1->attr, &pfx_un1)) {
if (bpi1->extra) {
- pfx_un1.family = bpi1->extra->vnc.import.un_family;
- switch (bpi1->extra->vnc.import.un_family) {
+ pfx_un1.family = bpi1->extra->vnc->vnc.import.un_family;
+ switch (bpi1->extra->vnc->vnc.import.un_family) {
case AF_INET:
pfx_un1.u.prefix4 =
- bpi1->extra->vnc.import.un.addr4;
+ bpi1->extra->vnc->vnc.import.un.addr4;
break;
case AF_INET6:
pfx_un1.u.prefix6 =
- bpi1->extra->vnc.import.un.addr6;
+ bpi1->extra->vnc->vnc.import.un.addr6;
break;
default:
pfx_un1.family = AF_UNSPEC;
@@ -1155,15 +1130,15 @@ static int rfapiVpnBiSamePtUn(struct bgp_path_info *bpi1,
if (rfapiGetVncTunnelUnAddr(bpi2->attr, &pfx_un2)) {
if (bpi2->extra) {
- pfx_un2.family = bpi2->extra->vnc.import.un_family;
- switch (bpi2->extra->vnc.import.un_family) {
+ pfx_un2.family = bpi2->extra->vnc->vnc.import.un_family;
+ switch (bpi2->extra->vnc->vnc.import.un_family) {
case AF_INET:
pfx_un2.u.prefix4 =
- bpi2->extra->vnc.import.un.addr4;
+ bpi2->extra->vnc->vnc.import.un.addr4;
break;
case AF_INET6:
pfx_un2.u.prefix6 =
- bpi2->extra->vnc.import.un.addr6;
+ bpi2->extra->vnc->vnc.import.un.addr6;
break;
default:
pfx_un2.family = AF_UNSPEC;
@@ -1268,9 +1243,8 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix,
new->prefix = *rprefix;
- if (bpi->extra
- && decode_rd_type(bpi->extra->vnc.import.rd.val)
- == RD_TYPE_VNC_ETH) {
+ if (bpi->extra && decode_rd_type(bpi->extra->vnc->vnc.import.rd.val) ==
+ RD_TYPE_VNC_ETH) {
/* ethernet */
struct rfapi_vn_option *vo;
@@ -1289,7 +1263,8 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix,
&vo->v.l2addr.tag_id);
/* local_nve_id comes from lower byte of RD type */
- vo->v.l2addr.local_nve_id = bpi->extra->vnc.import.rd.val[1];
+ vo->v.l2addr.local_nve_id =
+ bpi->extra->vnc->vnc.import.rd.val[1];
/* label comes from MP_REACH_NLRI label */
vo->v.l2addr.label = decode_label(&bpi->extra->label[0]);
@@ -1300,8 +1275,9 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix,
* If there is an auxiliary prefix (i.e., host IP address),
* use it as the nexthop prefix instead of the query prefix
*/
- if (bpi->extra->vnc.import.aux_prefix.family) {
- rfapiQprefix2Rprefix(&bpi->extra->vnc.import.aux_prefix,
+ if (bpi->extra->vnc->vnc.import.aux_prefix.family) {
+ rfapiQprefix2Rprefix(&bpi->extra->vnc->vnc.import
+ .aux_prefix,
&new->prefix);
}
}
@@ -1402,15 +1378,16 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix,
/*
* use cached UN address from ENCAP route
*/
- new->un_address.addr_family = bpi->extra->vnc.import.un_family;
+ new->un_address.addr_family =
+ bpi->extra->vnc->vnc.import.un_family;
switch (new->un_address.addr_family) {
case AF_INET:
new->un_address.addr.v4 =
- bpi->extra->vnc.import.un.addr4;
+ bpi->extra->vnc->vnc.import.un.addr4;
break;
case AF_INET6:
new->un_address.addr.v6 =
- bpi->extra->vnc.import.un.addr6;
+ bpi->extra->vnc->vnc.import.un.addr6;
break;
default:
zlog_warn("%s: invalid UN addr family (%d) for bpi %p",
@@ -1537,7 +1514,7 @@ static int rfapiNhlAddNodeRoutes(
if (is_l2) {
/* L2 routes: semantic nexthop in aux_prefix; VN addr
* ain't it */
- pfx_vn = bpi->extra->vnc.import.aux_prefix;
+ pfx_vn = bpi->extra->vnc->vnc.import.aux_prefix;
} else {
rfapiNexthop2Prefix(bpi->attr, &pfx_vn);
}
@@ -1709,7 +1686,7 @@ struct rfapi_next_hop_entry *rfapiRouteNode2NextHopList(
#ifdef DEBUG_RETURNED_NHL
vnc_zlog_debug_verbose("%s: called with node pfx=%rRN", __func__, rn);
- rfapiDebugBacktrace();
+ zlog_backtrace(LOG_INFO);
#endif
rfapiQprefix2Rprefix(p, &rprefix);
@@ -2011,9 +1988,10 @@ static int rfapi_bi_peer_rd_cmp(const void *b1, const void *b2)
/*
* compare RDs
*/
- return vnc_prefix_cmp(
- (const struct prefix *)&bpi1->extra->vnc.import.rd,
- (const struct prefix *)&bpi2->extra->vnc.import.rd);
+ return vnc_prefix_cmp((const struct prefix *)&bpi1->extra->vnc->vnc
+ .import.rd,
+ (const struct prefix *)&bpi2->extra->vnc->vnc
+ .import.rd);
}
/*
@@ -2038,8 +2016,8 @@ static int rfapi_bi_peer_rd_aux_cmp(const void *b1, const void *b2)
/*
* compare RDs
*/
- rc = vnc_prefix_cmp((struct prefix *)&bpi1->extra->vnc.import.rd,
- (struct prefix *)&bpi2->extra->vnc.import.rd);
+ rc = vnc_prefix_cmp((struct prefix *)&bpi1->extra->vnc->vnc.import.rd,
+ (struct prefix *)&bpi2->extra->vnc->vnc.import.rd);
if (rc) {
return rc;
}
@@ -2056,19 +2034,18 @@ static int rfapi_bi_peer_rd_aux_cmp(const void *b1, const void *b2)
* because there is no guarantee of the order the test key and
* the real key will be passed)
*/
- if ((bpi1->extra->vnc.import.aux_prefix.family == AF_ETHERNET
- && (bpi1->extra->vnc.import.aux_prefix.prefixlen == 1))
- || (bpi2->extra->vnc.import.aux_prefix.family == AF_ETHERNET
- && (bpi2->extra->vnc.import.aux_prefix.prefixlen == 1))) {
-
+ if ((bpi1->extra->vnc->vnc.import.aux_prefix.family == AF_ETHERNET &&
+ (bpi1->extra->vnc->vnc.import.aux_prefix.prefixlen == 1)) ||
+ (bpi2->extra->vnc->vnc.import.aux_prefix.family == AF_ETHERNET &&
+ (bpi2->extra->vnc->vnc.import.aux_prefix.prefixlen == 1))) {
/*
* wildcard aux address specified
*/
return 0;
}
- return vnc_prefix_cmp(&bpi1->extra->vnc.import.aux_prefix,
- &bpi2->extra->vnc.import.aux_prefix);
+ return vnc_prefix_cmp(&bpi1->extra->vnc->vnc.import.aux_prefix,
+ &bpi2->extra->vnc->vnc.import.aux_prefix);
}
@@ -2086,7 +2063,7 @@ static void rfapiItBiIndexAdd(struct agg_node *rn, /* Import table VPN node */
assert(bpi->extra);
vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %pRDP", __func__, bpi,
- bpi->peer, &bpi->extra->vnc.import.rd);
+ bpi->peer, &bpi->extra->vnc->vnc.import.rd);
sl = RFAPI_RDINDEX_W_ALLOC(rn);
if (!sl) {
@@ -2123,11 +2100,10 @@ static void rfapiItBiIndexDump(struct agg_node *rn)
char buf[RD_ADDRSTRLEN];
char buf_aux_pfx[PREFIX_STRLEN];
- prefix_rd2str(
- &k->extra->vnc.import.rd, buf, sizeof(buf),
- bgp_get_asnotation(k->peer ? k->peer->bgp : NULL));
- if (k->extra->vnc.import.aux_prefix.family) {
- prefix2str(&k->extra->vnc.import.aux_prefix,
+ prefix_rd2str(&k->extra->vnc->vnc.import.rd, buf, sizeof(buf),
+ bgp_get_asnotation(k->peer ? k->peer->bgp : NULL));
+ if (k->extra->vnc->vnc.import.aux_prefix.family) {
+ prefix2str(&k->extra->vnc->vnc.import.aux_prefix,
buf_aux_pfx, sizeof(buf_aux_pfx));
} else
strlcpy(buf_aux_pfx, "(none)", sizeof(buf_aux_pfx));
@@ -2146,6 +2122,7 @@ static struct bgp_path_info *rfapiItBiIndexSearch(
int rc;
struct bgp_path_info bpi_fake = {0};
struct bgp_path_info_extra bpi_extra = {0};
+ struct bgp_path_info_extra_vnc bpi_extra_vnc = { 0 };
struct bgp_path_info *bpi_result;
sl = RFAPI_RDINDEX(rn);
@@ -2178,27 +2155,25 @@ static struct bgp_path_info *rfapiItBiIndexSearch(
for (bpi_result = rn->info; bpi_result;
bpi_result = bpi_result->next) {
#ifdef DEBUG_BI_SEARCH
- vnc_zlog_debug_verbose(
- "%s: bpi has prd=%pRDP, peer=%p", __func__,
- &bpi_result->extra->vnc.import.rd,
- bpi_result->peer);
+ vnc_zlog_debug_verbose("%s: bpi has prd=%pRDP, peer=%p",
+ __func__,
+ &bpi_result->extra->vnc->vnc
+ .import.rd,
+ bpi_result->peer);
#endif
- if (peer == bpi_result->peer
- && !prefix_cmp((struct prefix *)&bpi_result->extra
- ->vnc.import.rd,
- (struct prefix *)prd)) {
-
+ if (peer == bpi_result->peer &&
+ !prefix_cmp((struct prefix *)&bpi_result->extra->vnc
+ ->vnc.import.rd,
+ (struct prefix *)prd)) {
#ifdef DEBUG_BI_SEARCH
vnc_zlog_debug_verbose(
"%s: peer and RD same, doing aux_prefix check",
__func__);
#endif
- if (!aux_prefix
- || !prefix_cmp(
- aux_prefix,
- &bpi_result->extra->vnc.import
- .aux_prefix)) {
-
+ if (!aux_prefix ||
+ !prefix_cmp(aux_prefix,
+ &bpi_result->extra->vnc->vnc
+ .import.aux_prefix)) {
#ifdef DEBUG_BI_SEARCH
vnc_zlog_debug_verbose("%s: match",
__func__);
@@ -2212,13 +2187,14 @@ static struct bgp_path_info *rfapiItBiIndexSearch(
bpi_fake.peer = peer;
bpi_fake.extra = &bpi_extra;
- bpi_fake.extra->vnc.import.rd = *prd;
+ bpi_fake.extra->vnc = &bpi_extra_vnc;
+ bpi_fake.extra->vnc->vnc.import.rd = *prd;
if (aux_prefix) {
- bpi_fake.extra->vnc.import.aux_prefix = *aux_prefix;
+ bpi_fake.extra->vnc->vnc.import.aux_prefix = *aux_prefix;
} else {
/* wildcard */
- bpi_fake.extra->vnc.import.aux_prefix.family = AF_ETHERNET;
- bpi_fake.extra->vnc.import.aux_prefix.prefixlen = 1;
+ bpi_fake.extra->vnc->vnc.import.aux_prefix.family = AF_ETHERNET;
+ bpi_fake.extra->vnc->vnc.import.aux_prefix.prefixlen = 1;
}
rc = skiplist_search(sl, (void *)&bpi_fake, (void *)&bpi_result);
@@ -2244,7 +2220,7 @@ static void rfapiItBiIndexDel(struct agg_node *rn, /* Import table VPN node */
int rc;
vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %pRDP", __func__, bpi,
- bpi->peer, &bpi->extra->vnc.import.rd);
+ bpi->peer, &bpi->extra->vnc->vnc.import.rd);
sl = RFAPI_RDINDEX(rn);
assert(sl);
@@ -2292,11 +2268,10 @@ rfapiMonitorEncapAdd(struct rfapi_import_table *import_table,
RFAPI_MONITOR_ENCAP_W_ALLOC(rn) = m;
/* for easy lookup when deleting vpn route */
- vpn_bpi->extra->vnc.import.hme = m;
+ vpn_bpi->extra->vnc->vnc.import.hme = m;
- vnc_zlog_debug_verbose(
- "%s: it=%p, vpn_bpi=%p, afi=%d, encap rn=%p, setting vpn_bpi->extra->vnc.import.hme=%p",
- __func__, import_table, vpn_bpi, afi, rn, m);
+ vnc_zlog_debug_verbose("%s: it=%p, vpn_bpi=%p, afi=%d, encap rn=%p, setting vpn_bpi->extra->vnc->vnc.import.hme=%p",
+ __func__, import_table, vpn_bpi, afi, rn, m);
RFAPI_CHECK_REFCOUNT(rn, SAFI_ENCAP, 0);
bgp_attr_intern(vpn_bpi->attr);
@@ -2310,7 +2285,7 @@ static void rfapiMonitorEncapDelete(struct bgp_path_info *vpn_bpi)
vnc_zlog_debug_verbose("%s: vpn_bpi=%p", __func__, vpn_bpi);
if (vpn_bpi->extra) {
struct rfapi_monitor_encap *hme =
- vpn_bpi->extra->vnc.import.hme;
+ vpn_bpi->extra->vnc->vnc.import.hme;
if (hme) {
@@ -2334,7 +2309,7 @@ static void rfapiMonitorEncapDelete(struct bgp_path_info *vpn_bpi)
agg_unlock_node(hme->rn); /* decr ref count */
XFREE(MTYPE_RFAPI_MONITOR_ENCAP, hme);
- vpn_bpi->extra->vnc.import.hme = NULL;
+ vpn_bpi->extra->vnc->vnc.import.hme = NULL;
}
}
}
@@ -2573,21 +2548,21 @@ static void rfapiCopyUnEncap2VPN(struct bgp_path_info *encap_bpi,
vnc_zlog_debug_verbose("%s: vpn_bpi->extra=%p", __func__,
vpn_bpi->extra);
- vpn_bpi->extra->vnc.import.un_family = AF_INET;
- vpn_bpi->extra->vnc.import.un.addr4 =
+ vpn_bpi->extra->vnc->vnc.import.un_family = AF_INET;
+ vpn_bpi->extra->vnc->vnc.import.un.addr4 =
encap_bpi->attr->mp_nexthop_global_in;
break;
case AF_INET6:
- vpn_bpi->extra->vnc.import.un_family = AF_INET6;
- vpn_bpi->extra->vnc.import.un.addr6 =
+ vpn_bpi->extra->vnc->vnc.import.un_family = AF_INET6;
+ vpn_bpi->extra->vnc->vnc.import.un.addr6 =
encap_bpi->attr->mp_nexthop_global;
break;
default:
zlog_warn("%s: invalid encap nexthop length: %d", __func__,
encap_bpi->attr->mp_nexthop_len);
- vpn_bpi->extra->vnc.import.un_family = AF_UNSPEC;
+ vpn_bpi->extra->vnc->vnc.import.un_family = AF_UNSPEC;
break;
}
}
@@ -2612,9 +2587,9 @@ rfapiWithdrawEncapUpdateCachedUn(struct rfapi_import_table *import_table,
__func__);
return 1;
}
- vpn_bpi->extra->vnc.import.un_family = AF_UNSPEC;
- memset(&vpn_bpi->extra->vnc.import.un, 0,
- sizeof(vpn_bpi->extra->vnc.import.un));
+ vpn_bpi->extra->vnc->vnc.import.un_family = AF_UNSPEC;
+ memset(&vpn_bpi->extra->vnc->vnc.import.un, 0,
+ sizeof(vpn_bpi->extra->vnc->vnc.import.un));
if (CHECK_FLAG(vpn_bpi->flags, BGP_PATH_VALID)) {
if (rfapiGetVncTunnelUnAddr(vpn_bpi->attr, NULL)) {
UNSET_FLAG(vpn_bpi->flags, BGP_PATH_VALID);
@@ -2785,9 +2760,9 @@ rfapiBiStartWithdrawTimer(struct rfapi_import_table *import_table,
assert(bpi->extra);
if (lifetime > UINT32_MAX / 1001) {
/* sub-optimal case, but will probably never happen */
- bpi->extra->vnc.import.timer = NULL;
+ bpi->extra->vnc->vnc.import.timer = NULL;
event_add_timer(bm->master, timer_service_func, wcb, lifetime,
- &bpi->extra->vnc.import.timer);
+ &bpi->extra->vnc->vnc.import.timer);
} else {
static uint32_t jitter;
uint32_t lifetime_msec;
@@ -2801,10 +2776,10 @@ rfapiBiStartWithdrawTimer(struct rfapi_import_table *import_table,
lifetime_msec = (lifetime * 1000) + jitter;
- bpi->extra->vnc.import.timer = NULL;
+ bpi->extra->vnc->vnc.import.timer = NULL;
event_add_timer_msec(bm->master, timer_service_func, wcb,
lifetime_msec,
- &bpi->extra->vnc.import.timer);
+ &bpi->extra->vnc->vnc.import.timer);
}
/* re-sort route list (BGP_PATH_REMOVED routes are last) */
@@ -3017,17 +2992,16 @@ static void rfapiBgpInfoFilteredImportEncap(
* Compare RDs
*
* RD of import table bpi is in
- * bpi->extra->vnc.import.rd RD of info_orig is in prd
+ * bpi->extra->vnc->vnc.import.rd RD of info_orig is in prd
*/
if (!bpi->extra) {
vnc_zlog_debug_verbose("%s: no bpi->extra",
__func__);
continue;
}
- if (prefix_cmp(
- (struct prefix *)&bpi->extra->vnc.import.rd,
- (struct prefix *)prd)) {
-
+ if (prefix_cmp((struct prefix *)&bpi->extra->vnc->vnc
+ .import.rd,
+ (struct prefix *)prd)) {
vnc_zlog_debug_verbose("%s: prd does not match",
__func__);
continue;
@@ -3071,13 +3045,14 @@ static void rfapiBgpInfoFilteredImportEncap(
* a previous withdraw, we must cancel its
* timer.
*/
- if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)
- && bpi->extra->vnc.import.timer) {
+ if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) &&
+ bpi->extra->vnc->vnc.import.timer) {
struct rfapi_withdraw *wcb = EVENT_ARG(
- bpi->extra->vnc.import.timer);
+ bpi->extra->vnc->vnc.import.timer);
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
- EVENT_OFF(bpi->extra->vnc.import.timer);
+ EVENT_OFF(bpi->extra->vnc->vnc.import
+ .timer);
}
if (action == FIF_ACTION_UPDATE) {
@@ -3163,12 +3138,12 @@ static void rfapiBgpInfoFilteredImportEncap(
vnc_zlog_debug_verbose(
"%s: removing holddown bpi matching NVE of new route",
__func__);
- if (bpi->extra->vnc.import.timer) {
+ if (bpi->extra->vnc->vnc.import.timer) {
struct rfapi_withdraw *wcb =
- EVENT_ARG(bpi->extra->vnc.import.timer);
+ EVENT_ARG(bpi->extra->vnc->vnc.import.timer);
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
- EVENT_OFF(bpi->extra->vnc.import.timer);
+ EVENT_OFF(bpi->extra->vnc->vnc.import.timer);
}
rfapiExpireEncapNow(import_table, rn, bpi);
}
@@ -3523,13 +3498,14 @@ void rfapiBgpInfoFilteredImportVPN(
* a previous withdraw, we must cancel its
* timer.
*/
- if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)
- && bpi->extra->vnc.import.timer) {
+ if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) &&
+ bpi->extra->vnc->vnc.import.timer) {
struct rfapi_withdraw *wcb = EVENT_ARG(
- bpi->extra->vnc.import.timer);
+ bpi->extra->vnc->vnc.import.timer);
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
- EVENT_OFF(bpi->extra->vnc.import.timer);
+ EVENT_OFF(bpi->extra->vnc->vnc.import
+ .timer);
import_table->holddown_count[afi] -= 1;
RFAPI_UPDATE_ITABLE_COUNT(
@@ -3602,7 +3578,7 @@ void rfapiBgpInfoFilteredImportVPN(
/* Not a big deal, just means VPN route got here first */
vnc_zlog_debug_verbose("%s: no encap route for vn addr %pFX",
__func__, &vn_prefix);
- info_new->extra->vnc.import.un_family = AF_UNSPEC;
+ info_new->extra->vnc->vnc.import.un_family = AF_UNSPEC;
}
if (rn) {
@@ -3624,7 +3600,7 @@ void rfapiBgpInfoFilteredImportVPN(
vnc_zlog_debug_verbose("%s: setting BPI's aux_prefix",
__func__);
- info_new->extra->vnc.import.aux_prefix = *aux_prefix;
+ info_new->extra->vnc->vnc.import.aux_prefix = *aux_prefix;
}
vnc_zlog_debug_verbose("%s: inserting bpi %p at prefix %pRN #%d",
@@ -3742,12 +3718,12 @@ void rfapiBgpInfoFilteredImportVPN(
vnc_zlog_debug_verbose(
"%s: removing holddown bpi matching NVE of new route",
__func__);
- if (bpi->extra->vnc.import.timer) {
+ if (bpi->extra->vnc->vnc.import.timer) {
struct rfapi_withdraw *wcb =
- EVENT_ARG(bpi->extra->vnc.import.timer);
+ EVENT_ARG(bpi->extra->vnc->vnc.import.timer);
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
- EVENT_OFF(bpi->extra->vnc.import.timer);
+ EVENT_OFF(bpi->extra->vnc->vnc.import.timer);
}
rfapiExpireVpnNow(import_table, rn, bpi, 0);
}
@@ -4479,12 +4455,10 @@ static void rfapiDeleteRemotePrefixesIt(
if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
if (!delete_holddown)
continue;
- if (bpi->extra->vnc.import.timer) {
- struct rfapi_withdraw *wcb =
- EVENT_ARG(
- bpi->extra->vnc
- .import
- .timer);
+ if (bpi->extra->vnc->vnc.import.timer) {
+ struct rfapi_withdraw *wcb = EVENT_ARG(
+ bpi->extra->vnc->vnc
+ .import.timer);
wcb->import_table
->holddown_count[afi] -=
@@ -4494,8 +4468,8 @@ static void rfapiDeleteRemotePrefixesIt(
afi, 1);
XFREE(MTYPE_RFAPI_WITHDRAW,
wcb);
- EVENT_OFF(bpi->extra->vnc.import
- .timer);
+ EVENT_OFF(bpi->extra->vnc->vnc
+ .import.timer);
}
} else {
if (!delete_active)
diff --git a/bgpd/rfapi/rfapi_import.h b/bgpd/rfapi/rfapi_import.h
index dd06afe..1a37e1c 100644
--- a/bgpd/rfapi/rfapi_import.h
+++ b/bgpd/rfapi/rfapi_import.h
@@ -57,8 +57,6 @@ struct rfapi_import_table {
extern uint8_t rfapiRfpCost(struct attr *attr);
-extern void rfapiDebugBacktrace(void);
-
extern void rfapiCheckRouteCount(void);
/*
diff --git a/bgpd/rfapi/rfapi_monitor.c b/bgpd/rfapi/rfapi_monitor.c
index 3fe957b..146e0d1 100644
--- a/bgpd/rfapi/rfapi_monitor.c
+++ b/bgpd/rfapi/rfapi_monitor.c
@@ -354,7 +354,7 @@ struct agg_node *rfapiMonitorGetAttachNode(struct rfapi_descriptor *rfd,
* If there is a cached ENCAP UN address, it's a usable
* VPN route
*/
- if (bpi->extra && bpi->extra->vnc.import.un_family) {
+ if (bpi->extra && bpi->extra->vnc->vnc.import.un_family) {
break;
}
diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c
index 5784f95..316904e 100644
--- a/bgpd/rfapi/rfapi_rib.c
+++ b/bgpd/rfapi/rfapi_rib.c
@@ -663,9 +663,8 @@ static void rfapiRibBi2Ri(struct bgp_path_info *bpi, struct rfapi_info *ri,
/*
* VN options
*/
- if (bpi->extra
- && decode_rd_type(bpi->extra->vnc.import.rd.val)
- == RD_TYPE_VNC_ETH) {
+ if (bpi->extra && decode_rd_type(bpi->extra->vnc->vnc.import.rd.val) ==
+ RD_TYPE_VNC_ETH) {
/* ethernet route */
struct rfapi_vn_option *vo;
@@ -678,8 +677,8 @@ static void rfapiRibBi2Ri(struct bgp_path_info *bpi, struct rfapi_info *ri,
/* copy from RD already stored in bpi, so we don't need it_node
*/
- memcpy(&vo->v.l2addr.macaddr, bpi->extra->vnc.import.rd.val + 2,
- ETH_ALEN);
+ memcpy(&vo->v.l2addr.macaddr,
+ bpi->extra->vnc->vnc.import.rd.val + 2, ETH_ALEN);
(void)rfapiEcommunityGetLNI(bgp_attr_get_ecommunity(bpi->attr),
&vo->v.l2addr.logical_net_id);
@@ -688,7 +687,8 @@ static void rfapiRibBi2Ri(struct bgp_path_info *bpi, struct rfapi_info *ri,
&vo->v.l2addr.tag_id);
/* local_nve_id comes from RD */
- vo->v.l2addr.local_nve_id = bpi->extra->vnc.import.rd.val[1];
+ vo->v.l2addr.local_nve_id =
+ bpi->extra->vnc->vnc.import.rd.val[1];
/* label comes from MP_REACH_NLRI label */
vo->v.l2addr.label = decode_label(&bpi->extra->label[0]);
@@ -701,8 +701,8 @@ static void rfapiRibBi2Ri(struct bgp_path_info *bpi, struct rfapi_info *ri,
/*
* If there is an auxiliary IP address (L2 can have it), copy it
*/
- if (bpi->extra && bpi->extra->vnc.import.aux_prefix.family) {
- ri->rk.aux_prefix = bpi->extra->vnc.import.aux_prefix;
+ if (bpi->extra && bpi->extra->vnc->vnc.import.aux_prefix.family) {
+ ri->rk.aux_prefix = bpi->extra->vnc->vnc.import.aux_prefix;
}
}
@@ -746,13 +746,13 @@ int rfapiRibPreloadBi(
memset((void *)&rk, 0, sizeof(rk));
rk.vn = *pfx_vn;
- rk.rd = bpi->extra->vnc.import.rd;
+ rk.rd = bpi->extra->vnc->vnc.import.rd;
/*
* If there is an auxiliary IP address (L2 can have it), copy it
*/
- if (bpi->extra->vnc.import.aux_prefix.family) {
- rk.aux_prefix = bpi->extra->vnc.import.aux_prefix;
+ if (bpi->extra->vnc->vnc.import.aux_prefix.family) {
+ rk.aux_prefix = bpi->extra->vnc->vnc.import.aux_prefix;
}
/*
@@ -1629,12 +1629,13 @@ void rfapiRibUpdatePendingNode(
ri = rfapi_info_new();
ri->rk.vn = pfx_nh;
- ri->rk.rd = bpi->extra->vnc.import.rd;
+ ri->rk.rd = bpi->extra->vnc->vnc.import.rd;
/*
* If there is an auxiliary IP address (L2 can have it), copy it
*/
- if (bpi->extra->vnc.import.aux_prefix.family) {
- ri->rk.aux_prefix = bpi->extra->vnc.import.aux_prefix;
+ if (bpi->extra->vnc->vnc.import.aux_prefix.family) {
+ ri->rk.aux_prefix =
+ bpi->extra->vnc->vnc.import.aux_prefix;
}
if (rfapiGetUnAddrOfVpnBi(bpi, &ri->un)) {
diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c
index 252b6d6..5da99db 100644
--- a/bgpd/rfapi/rfapi_vty.c
+++ b/bgpd/rfapi/rfapi_vty.c
@@ -419,22 +419,21 @@ void rfapi_vty_out_vncinfo(struct vty *vty, const struct prefix *p,
else
vty_out(vty, " label=%u",
decode_label(&bpi->extra->label[0]));
+ }
- if (bpi->attr->srv6_l3vpn || bpi->attr->srv6_vpn) {
- struct in6_addr *sid_tmp =
- bpi->attr->srv6_l3vpn
- ? (&bpi->attr->srv6_l3vpn->sid)
- : (&bpi->attr->srv6_vpn->sid);
- vty_out(vty, " sid=%pI6", sid_tmp);
-
- if (bpi->attr->srv6_l3vpn &&
- bpi->attr->srv6_l3vpn->loc_block_len != 0) {
- vty_out(vty, " sid_structure=[%d,%d,%d,%d]",
- bpi->attr->srv6_l3vpn->loc_block_len,
- bpi->attr->srv6_l3vpn->loc_node_len,
- bpi->attr->srv6_l3vpn->func_len,
- bpi->attr->srv6_l3vpn->arg_len);
- }
+ if (bpi->attr->srv6_l3vpn || bpi->attr->srv6_vpn) {
+ struct in6_addr *sid_tmp =
+ bpi->attr->srv6_l3vpn ? (&bpi->attr->srv6_l3vpn->sid)
+ : (&bpi->attr->srv6_vpn->sid);
+ vty_out(vty, " sid=%pI6", sid_tmp);
+
+ if (bpi->attr->srv6_l3vpn &&
+ bpi->attr->srv6_l3vpn->loc_block_len != 0) {
+ vty_out(vty, " sid_structure=[%d,%d,%d,%d]",
+ bpi->attr->srv6_l3vpn->loc_block_len,
+ bpi->attr->srv6_l3vpn->loc_node_len,
+ bpi->attr->srv6_l3vpn->func_len,
+ bpi->attr->srv6_l3vpn->arg_len);
}
}
@@ -519,9 +518,10 @@ void rfapiPrintBi(void *stream, struct bgp_path_info *bpi)
if (!bpi)
return;
- if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) && bpi->extra
- && bpi->extra->vnc.import.timer) {
- struct event *t = (struct event *)bpi->extra->vnc.import.timer;
+ if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) && bpi->extra &&
+ bpi->extra->vnc->vnc.import.timer) {
+ struct event *t =
+ (struct event *)bpi->extra->vnc->vnc.import.timer;
r = snprintf(p, REMAIN, " [%4lu] ",
event_timer_remain_second(t));
@@ -534,12 +534,12 @@ void rfapiPrintBi(void *stream, struct bgp_path_info *bpi)
if (bpi->extra) {
/* TBD This valid only for SAFI_MPLS_VPN, but not for encap */
- if (decode_rd_type(bpi->extra->vnc.import.rd.val)
- == RD_TYPE_VNC_ETH) {
+ if (decode_rd_type(bpi->extra->vnc->vnc.import.rd.val) ==
+ RD_TYPE_VNC_ETH) {
has_macaddr = 1;
- memcpy(macaddr.octet, bpi->extra->vnc.import.rd.val + 2,
- 6);
- l2hid = bpi->extra->vnc.import.rd.val[1];
+ memcpy(macaddr.octet,
+ bpi->extra->vnc->vnc.import.rd.val + 2, 6);
+ l2hid = bpi->extra->vnc->vnc.import.rd.val[1];
}
}
@@ -670,11 +670,11 @@ void rfapiPrintBi(void *stream, struct bgp_path_info *bpi)
l2o_buf.label, l2o_buf.logical_net_id, l2o_buf.local_nve_id,
HVTYNL);
}
- if (bpi->extra && bpi->extra->vnc.import.aux_prefix.family) {
+ if (bpi->extra && bpi->extra->vnc->vnc.import.aux_prefix.family) {
const char *sp;
- sp = rfapi_ntop(bpi->extra->vnc.import.aux_prefix.family,
- &bpi->extra->vnc.import.aux_prefix.u.prefix,
+ sp = rfapi_ntop(bpi->extra->vnc->vnc.import.aux_prefix.family,
+ &bpi->extra->vnc->vnc.import.aux_prefix.u.prefix,
buf, BUFSIZ);
buf[BUFSIZ - 1] = 0;
if (sp) {
@@ -1097,14 +1097,14 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
fp(out, "%-10s ", buf_lifetime);
}
- if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) && bpi->extra
- && bpi->extra->vnc.import.timer) {
-
+ if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) && bpi->extra &&
+ bpi->extra->vnc->vnc.import.timer) {
uint32_t remaining;
time_t age;
char buf_age[BUFSIZ];
- struct event *t = (struct event *)bpi->extra->vnc.import.timer;
+ struct event *t =
+ (struct event *)bpi->extra->vnc->vnc.import.timer;
remaining = event_timer_remain_second(t);
#ifdef RFAPI_REGISTRATIONS_REPORT_AGE
@@ -1125,11 +1125,10 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
fp(out, "%-10s ", buf_age);
} else if (RFAPI_LOCAL_BI(bpi)) {
-
char buf_age[BUFSIZ];
- if (bpi->extra && bpi->extra->vnc.import.create_time) {
- rfapiFormatAge(bpi->extra->vnc.import.create_time,
+ if (bpi->extra && bpi->extra->vnc->vnc.import.create_time) {
+ rfapiFormatAge(bpi->extra->vnc->vnc.import.create_time,
buf_age, BUFSIZ);
} else {
buf_age[0] = '?';
@@ -1145,13 +1144,14 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
* print that on the next line
*/
- if (bpi->extra && bpi->extra->vnc.import.aux_prefix.family) {
+ if (bpi->extra && bpi->extra->vnc->vnc.import.aux_prefix.family) {
const char *sp;
- sp = rfapi_ntop(
- bpi->extra->vnc.import.aux_prefix.family,
- &bpi->extra->vnc.import.aux_prefix.u.prefix,
- buf_ntop, BUFSIZ);
+ sp = rfapi_ntop(bpi->extra->vnc->vnc.import.aux_prefix
+ .family,
+ &bpi->extra->vnc->vnc.import.aux_prefix
+ .u.prefix,
+ buf_ntop, BUFSIZ);
buf_ntop[BUFSIZ - 1] = 0;
if (sp && strcmp(buf_vn, sp) != 0) {
@@ -1545,10 +1545,9 @@ void rfapiPrintAdvertisedInfo(struct vty *vty, struct rfapi_descriptor *rfd,
vty_out(vty, " bd=%p%s", bd, HVTYNL);
for (bpi = bgp_dest_get_bgp_path_info(bd); bpi; bpi = bpi->next) {
- if (bpi->peer == rfd->peer && bpi->type == type
- && bpi->sub_type == BGP_ROUTE_RFP && bpi->extra
- && bpi->extra->vnc.export.rfapi_handle == (void *)rfd) {
-
+ if (bpi->peer == rfd->peer && bpi->type == type &&
+ bpi->sub_type == BGP_ROUTE_RFP && bpi->extra &&
+ bpi->extra->vnc->vnc.export.rfapi_handle == (void *)rfd) {
rfapiPrintBi(vty, bpi);
printed = 1;
}
@@ -4151,6 +4150,7 @@ static int rfapi_vty_show_nve_summary(struct vty *vty,
case SHOW_NVE_SUMMARY_RESPONSES:
rfapiRibShowResponsesSummary(vty);
+ break;
case SHOW_NVE_SUMMARY_UNKNOWN_NVES:
case SHOW_NVE_SUMMARY_MAX:
diff --git a/bgpd/rfapi/vnc_import_bgp.c b/bgpd/rfapi/vnc_import_bgp.c
index 3fcc0e6..c067b7a 100644
--- a/bgpd/rfapi/vnc_import_bgp.c
+++ b/bgpd/rfapi/vnc_import_bgp.c
@@ -1696,8 +1696,8 @@ static void vnc_import_bgp_exterior_add_route_it(
have_usable_route = 1;
if (bpi_interior->extra) {
- prd = &bpi_interior->extra->vnc.import
- .rd;
+ prd = &bpi_interior->extra->vnc->vnc
+ .import.rd;
label = decode_label(
&bpi_interior->extra->label[0]);
} else
@@ -1865,8 +1865,8 @@ void vnc_import_bgp_exterior_del_route(
have_usable_route = 1;
if (bpi_interior->extra) {
- prd = &bpi_interior->extra->vnc.import
- .rd;
+ prd = &bpi_interior->extra->vnc->vnc
+ .import.rd;
label = decode_label(
&bpi_interior->extra->label[0]);
} else
@@ -2013,7 +2013,7 @@ void vnc_import_bgp_exterior_add_route_interior(
assert(pfx_exterior);
if (bpi_interior->extra) {
- prd = &bpi_interior->extra->vnc.import.rd;
+ prd = &bpi_interior->extra->vnc->vnc.import.rd;
label = decode_label(
&bpi_interior->extra->label[0]);
} else
@@ -2126,8 +2126,8 @@ void vnc_import_bgp_exterior_add_route_interior(
for (bpi = par->info; bpi; bpi = bpi->next) {
if (bpi->extra) {
- prd = &bpi->extra->vnc.import
- .rd;
+ prd = &bpi->extra->vnc->vnc
+ .import.rd;
label = decode_label(
&bpi->extra->label[0]);
} else
@@ -2148,8 +2148,8 @@ void vnc_import_bgp_exterior_add_route_interior(
* the new interior route at longer prefix.
*/
if (bpi_interior->extra) {
- prd = &bpi_interior->extra->vnc.import
- .rd;
+ prd = &bpi_interior->extra->vnc->vnc
+ .import.rd;
label = decode_label(
&bpi_interior->extra->label[0]);
} else
@@ -2267,7 +2267,7 @@ void vnc_import_bgp_exterior_add_route_interior(
* new interior route at the longer prefix.
*/
if (bpi_interior->extra) {
- prd = &bpi_interior->extra->vnc.import.rd;
+ prd = &bpi_interior->extra->vnc->vnc.import.rd;
label = decode_label(
&bpi_interior->extra->label[0]);
} else
@@ -2375,7 +2375,7 @@ void vnc_import_bgp_exterior_del_route_interior(
uint32_t label = 0;
if (bpi_interior->extra) {
- prd = &bpi_interior->extra->vnc.import.rd;
+ prd = &bpi_interior->extra->vnc->vnc.import.rd;
label = decode_label(&bpi_interior->extra->label[0]);
} else
prd = NULL;
@@ -2452,7 +2452,7 @@ void vnc_import_bgp_exterior_del_route_interior(
continue;
if (bpi->extra) {
- prd = &bpi->extra->vnc.import.rd;
+ prd = &bpi->extra->vnc->vnc.import.rd;
label = decode_label(
&bpi->extra->label[0]);
} else
@@ -2805,14 +2805,14 @@ void vnc_import_bgp_redist_disable(struct bgp *bgp, afi_t afi)
assert(bpi->extra);
- rfd = bpi->extra->vnc.export.rfapi_handle;
+ rfd = bpi->extra->vnc->vnc.export.rfapi_handle;
vnc_zlog_debug_verbose(
- "%s: deleting bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]",
+ "%s: deleting bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc->vnc.export.rfapi_handle=%p [passing rfd=%p]",
__func__, bpi, bpi->peer, bpi->type,
bpi->sub_type,
- (bpi->extra ? bpi->extra->vnc.export
- .rfapi_handle
+ (bpi->extra ? bpi->extra->vnc->vnc
+ .export.rfapi_handle
: NULL),
rfd);
diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c
index c886bee..82c08ca 100644
--- a/bgpd/rfapi/vnc_zebra.c
+++ b/bgpd/rfapi/vnc_zebra.c
@@ -872,7 +872,7 @@ static zclient_handler *const vnc_handlers[] = {
void vnc_zebra_init(struct event_loop *master)
{
/* Set default values. */
- zclient_vnc = zclient_new(master, &zclient_options_default,
+ zclient_vnc = zclient_new(master, &zclient_options_auxiliary,
vnc_handlers, array_size(vnc_handlers));
zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0, &bgpd_privs);
}
diff --git a/bgpd/subdir.am b/bgpd/subdir.am
index c2dd207..6d6fad0 100644
--- a/bgpd/subdir.am
+++ b/bgpd/subdir.am
@@ -77,6 +77,7 @@ bgpd_libbgp_a_SOURCES = \
bgpd/bgp_zebra.c \
bgpd/bgpd.c \
bgpd/bgp_trace.c \
+ bgpd/bgp_nhg.c \
# end
if ENABLE_BGP_VNC
@@ -160,6 +161,7 @@ noinst_HEADERS += \
bgpd/bgp_zebra.h \
bgpd/bgpd.h \
bgpd/bgp_trace.h \
+ bgpd/bgp_nhg.h \
\
bgpd/rfapi/bgp_rfapi_cfg.h \
bgpd/rfapi/rfapi_import.h \
@@ -214,6 +216,7 @@ clippy_scan += \
bgpd/bgp_rpki.c \
bgpd/bgp_vty.c \
bgpd/bgp_nexthop.c \
+ bgpd/bgp_snmp.c \
# end
nodist_bgpd_bgpd_SOURCES = \