This commit is contained in:
lsang6WIND 2025-04-29 16:22:43 +00:00 committed by GitHub
commit d6d6f68a07
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
63 changed files with 2749 additions and 606 deletions

View file

@ -162,8 +162,8 @@ bool bgp_adj_out_lookup(struct peer *peer, struct bgp_dest *dest,
}
void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr,
uint32_t addpath_id, struct bgp_labels *labels)
void bgp_adj_in_set(struct bgp_dest *dest, afi_t afi, safi_t safi, struct peer *peer,
struct attr *attr, uint32_t addpath_id, struct bgp_labels *labels)
{
struct bgp_adj_in *adj;
@ -182,28 +182,27 @@ void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr,
}
adj = XCALLOC(MTYPE_BGP_ADJ_IN, sizeof(struct bgp_adj_in));
adj->peer = peer_lock(peer); /* adj_in peer reference */
adj->peer->stat_adj_in_count[afi][safi]++;
adj->attr = bgp_attr_intern(attr);
adj->uptime = monotime(NULL);
adj->addpath_rx_id = addpath_id;
adj->labels = bgp_labels_intern(labels);
BGP_ADJ_IN_ADD(dest, adj);
peer->stat_pfx_adj_rib_in++;
bgp_dest_lock_node(dest);
}
void bgp_adj_in_remove(struct bgp_dest **dest, struct bgp_adj_in *bai)
void bgp_adj_in_remove(struct bgp_dest **dest, afi_t afi, safi_t safi, struct bgp_adj_in *bai)
{
bgp_attr_unintern(&bai->attr);
bgp_labels_unintern(&bai->labels);
if (bai->peer)
bai->peer->stat_pfx_adj_rib_in--;
BGP_ADJ_IN_DEL(*dest, bai);
bai->peer->stat_adj_in_count[afi][safi]--;
*dest = bgp_dest_unlock_node(*dest);
peer_unlock(bai->peer); /* adj_in peer reference */
XFREE(MTYPE_BGP_ADJ_IN, bai);
}
bool bgp_adj_in_unset(struct bgp_dest **dest, struct peer *peer,
bool bgp_adj_in_unset(struct bgp_dest **dest, afi_t afi, safi_t safi, struct peer *peer,
uint32_t addpath_id)
{
struct bgp_adj_in *adj;
@ -218,7 +217,7 @@ bool bgp_adj_in_unset(struct bgp_dest **dest, struct peer *peer,
adj_next = adj->next;
if (adj->peer == peer && adj->addpath_rx_id == addpath_id)
bgp_adj_in_remove(dest, adj);
bgp_adj_in_remove(dest, afi, safi, adj);
adj = adj_next;

View file

@ -140,12 +140,12 @@ struct bgp_synchronize {
/* Prototypes. */
extern bool bgp_adj_out_lookup(struct peer *peer, struct bgp_dest *dest,
uint32_t addpath_tx_id);
extern void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer,
struct attr *attr, uint32_t addpath_id,
struct bgp_labels *labels);
extern bool bgp_adj_in_unset(struct bgp_dest **dest, struct peer *peer,
extern void bgp_adj_in_set(struct bgp_dest *dest, afi_t afi, safi_t safi, struct peer *peer,
struct attr *attr, uint32_t addpath_id, struct bgp_labels *labels);
extern bool bgp_adj_in_unset(struct bgp_dest **dest, afi_t afi, safi_t safi, struct peer *peer,
uint32_t addpath_id);
extern void bgp_adj_in_remove(struct bgp_dest **dest, struct bgp_adj_in *bai);
extern void bgp_adj_in_remove(struct bgp_dest **dest, afi_t afi, safi_t safi,
struct bgp_adj_in *bai);
extern unsigned int bgp_advertise_attr_hash_key(const void *p);
extern bool bgp_advertise_attr_hash_cmp(const void *p1, const void *p2);

File diff suppressed because it is too large Load diff

View file

@ -12,6 +12,7 @@
#include "pullwr.h"
#include "qobj.h"
#include "resolver.h"
#include "bgp_updgrp.h"
#define BMP_VERSION_3 3
@ -29,9 +30,11 @@
#define BMP_READ_BUFSIZ 1024
/* bmp->state */
#define BMP_None 0
#define BMP_PeerUp 2
#define BMP_Run 3
enum BMP_State {
BMP_StartupIdle,
BMP_PeerUp,
BMP_Run,
};
/* This one is for BMP Route Monitoring messages, i.e. delivering updates
* in somewhat processed (as opposed to fully raw, see mirroring below) form.
@ -60,6 +63,10 @@ struct bmp_queue_entry {
struct bmp_qlist_item bli;
struct bmp_qhash_item bhi;
uint32_t addpath_id;
#define BMP_QUEUE_FLAGS_NONE (0)
uint8_t flags;
struct prefix p;
uint64_t peerid;
afi_t afi;
@ -116,7 +123,7 @@ struct bmp {
struct pullwr *pullwr;
int state;
enum BMP_State state;
/* queue positions must remain synced with refcounts in the items.
* Whenever appending a queue item, we need to know the correct number
@ -124,8 +131,10 @@ 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_queue_entry *mon_in_queuepos;
struct bmp_queue_entry *mon_loc_queuepos;
struct bmp_queue_entry *mon_out_queuepos;
struct bmp_mirrorq *mirrorpos;
bool mirror_lost;
@ -225,9 +234,12 @@ struct bmp_targets {
* - 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)
#define BMP_MON_IN_PREPOLICY (1 << 0)
#define BMP_MON_IN_POSTPOLICY (1 << 1)
#define BMP_MON_LOC_RIB (1 << 2)
#define BMP_MON_OUT_PREPOLICY (1 << 3)
#define BMP_MON_OUT_POSTPOLICY (1 << 4)
uint8_t afimon[AFI_MAX][SAFI_MAX];
bool mirror;
@ -237,11 +249,14 @@ struct bmp_targets {
struct event *t_stats;
struct bmp_session_head sessions;
struct bmp_qhash_head updhash;
struct bmp_qlist_head updlist;
struct bmp_qhash_head mon_in_updhash;
struct bmp_qlist_head mon_in_updlist;
struct bmp_qhash_head locupdhash;
struct bmp_qlist_head locupdlist;
struct bmp_qhash_head mon_loc_updhash;
struct bmp_qlist_head mon_loc_updlist;
struct bmp_qhash_head mon_out_updhash;
struct bmp_qlist_head mon_out_updlist;
struct bmp_imported_bgps_head imported_bgps;
@ -270,6 +285,54 @@ struct bmp_bgp_peer {
size_t open_tx_len;
};
/* every bgp_path_info that bmp currently has locked for rib-out-prepolicy
* when this is allocated the bgp_path_info is locked using bgp_path_info_lock
* when freed unlocked using bpg_path_info_unlock
*/
PREDECL_HASH(bmp_lbpi_h);
struct bmp_bpi_lock {
/* hashset field */
struct bmp_lbpi_h_item lbpi_h;
struct bmp_bpi_lock *next;
/* bgp instance associated with bpi and dest
* needed for differentiation between vrfs/views
*/
struct bgp *bgp;
/* locked bgp_path_info */
struct bgp_path_info *locked;
/* dest of locked bgp_path_info for lookup */
struct bgp_dest *dest;
/* lock, one for each bqe in the rib-out queue
* when each bqe is allocated we increment this lock
* when freed we decrement it
* after all bqe are processed, it should be 0
* so the bpi can be unlocked (and maybe freed)
*/
int lock;
};
#define BMP_LBPI_LOOKUP_DEST(head, prev, lookup, target_dest, target_bgp, condition) \
struct bmp_bpi_lock _dummy_lbpi = { \
.dest = (target_dest), \
.bgp = (target_bgp), \
}; \
\
struct bmp_bpi_lock *(head) = NULL, *(prev) = NULL, *(lookup) = NULL; \
\
(head) = bmp_lbpi_h_find(&bmp_lbpi, &_dummy_lbpi); \
\
for ((lookup) = (head); (lookup); (lookup) = ((prev) = (lookup))->next) { \
if ((condition)) \
break; \
}
#define BMP_LBPI_LOOKUP_BPI(head, prev, lookup, target_bpi, target_bgp) \
BMP_LBPI_LOOKUP_DEST((head), (prev), (lookup), (target_bpi)->net, (target_bgp), \
((lookup)->locked == (target_bpi)))
/* per struct bgp * data */
PREDECL_HASH(bmp_bgph);
@ -302,6 +365,8 @@ struct bmp_bgp {
size_t mirror_qsize, mirror_qsizemax;
size_t mirror_qsizelimit;
uint32_t startup_delay_ms;
};
extern bool bmp_bgp_update_vrf_status(enum bmp_vrf_state *vrf_state, struct bgp *bgp,
@ -314,26 +379,31 @@ enum {
BMP_PEERDOWN_REMOTE_NOTIFY = 3,
BMP_PEERDOWN_REMOTE_CLOSE = 4,
BMP_PEERDOWN_ENDMONITOR = 5,
/* RFC9069 - 8.4 */
BMP_PEERDOWN_LOCAL_TLV = 6,
};
enum {
BMP_STATS_PFX_REJECTED = 0,
BMP_STATS_PFX_DUP_ADV = 1,
BMP_STATS_PFX_DUP_WITHDRAW = 2,
BMP_STATS_UPD_LOOP_CLUSTER = 3,
BMP_STATS_UPD_LOOP_ASPATH = 4,
BMP_STATS_UPD_LOOP_ORIGINATOR = 5,
BMP_STATS_UPD_LOOP_CONFED = 6,
BMP_STATS_SIZE_ADJ_RIB_IN = 7,
BMP_STATS_SIZE_LOC_RIB = 8,
BMP_STATS_SIZE_ADJ_RIB_IN_SAFI = 9,
BMP_STATS_SIZE_LOC_RIB_IN_SAFI = 10,
BMP_STATS_UPD_7606_WITHDRAW = 11,
BMP_STATS_PFX_7606_WITHDRAW = 12,
BMP_STATS_UPD_DUP = 13,
BMP_STATS_FRR_NH_INVALID = 65531,
BMP_STATS_PFX_REJECTED = 0,
BMP_STATS_PFX_DUP_ADV = 1,
BMP_STATS_PFX_DUP_WITHDRAW = 2,
BMP_STATS_UPD_LOOP_CLUSTER = 3,
BMP_STATS_UPD_LOOP_ASPATH = 4,
BMP_STATS_UPD_LOOP_ORIGINATOR = 5,
BMP_STATS_UPD_LOOP_CONFED = 6,
BMP_STATS_SIZE_ADJ_RIB_IN = 7,
BMP_STATS_SIZE_LOC_RIB = 8,
BMP_STATS_SIZE_ADJ_RIB_IN_SAFI = 9,
BMP_STATS_SIZE_LOC_RIB_SAFI = 10,
BMP_STATS_UPD_7606_WITHDRAW = 11,
BMP_STATS_PFX_7606_WITHDRAW = 12,
BMP_STATS_UPD_DUP = 13,
BMP_STATS_SIZE_ADJ_RIB_OUT_PRE = 14,
BMP_STATS_SIZE_ADJ_RIB_OUT_POST = 15,
BMP_STATS_SIZE_ADJ_RIB_OUT_PRE_SAFI = 16,
BMP_STATS_SIZE_ADJ_RIB_OUT_POST_SAFI = 17,
BMP_STATS_FRR_NH_INVALID = 65531,
};
DECLARE_MGROUP(BMP);

View file

@ -98,6 +98,21 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi,
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
advmap_attr = *pi->attr;
bool selected = bgp_check_selected(pi, peer, addpath_capable, afi, safi);
if (selected) {
bgp_adj_out_updated(subgrp, dest, pi,
!addpath_capable
? 0
: bgp_addpath_id_for_peer(peer, afi,
safi,
&pi->tx_addpath),
&attr, false,
update_type == UPDATE_TYPE_ADVERTISE ? false
: true);
}
/* Fill temp path_info */
prep_for_rmap_apply(&path, &path_extra, dest, pi, pi->peer, NULL,
&advmap_attr);
@ -105,9 +120,7 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi,
RESET_FLAG(advmap_attr.rmap_change_flags);
ret = route_map_apply(rmap, dest_p, &path);
if (ret != RMAP_PERMITMATCH ||
!bgp_check_selected(pi, peer, addpath_capable, afi,
safi)) {
if (ret != RMAP_PERMITMATCH || !selected) {
bgp_attr_flush(&advmap_attr);
continue;
}
@ -120,8 +133,8 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi,
* be advertised as expected.
*/
if (update_type == UPDATE_TYPE_ADVERTISE &&
subgroup_announce_check(dest, pi, subgrp, dest_p,
&attr, &advmap_attr)) {
subgroup_announce_check(dest, pi, subgrp, dest_p, &attr, &advmap_attr,
0)) {
if (!bgp_adj_out_set_subgroup(dest, subgrp,
&attr, pi))
bgp_attr_flush(&attr);

View file

@ -1471,8 +1471,7 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
}
/* Compute the best path. */
bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
afi, safi);
bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new, afi, safi, NULL);
old_select = old_and_new.old;
new_select = old_and_new.new;

View file

@ -106,8 +106,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp,
SET_FLAG(pi->flags, BGP_PATH_UNSORTED);
/* Compute the best path. */
bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
afi, safi);
bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new, afi, safi, NULL);
old_select = old_and_new.old;
new_select = old_and_new.new;

View file

@ -410,6 +410,42 @@ static void bgp_path_info_mpath_attr_set(struct bgp_path_info *path,
mpath->mp_attr = attr;
}
void bgp_mpath_diff_insert(struct bgp_mpath_diff_head *diff, struct bgp_path_info *bpi, bool update)
{
if (!diff)
return;
if (!bpi) {
zlog_warn("%s: path info given is null", __func__);
return;
}
struct bgp_path_info_mpath_diff *item = XCALLOC(MTYPE_BGP_MPATH_DIFF,
sizeof(struct bgp_path_info_mpath_diff));
item->path = bpi;
item->update = update;
bgp_path_info_lock(bpi);
if (bpi->net)
bgp_dest_lock_node(bpi->net);
bgp_mpath_diff_add_tail(diff, item);
}
void bgp_mpath_diff_clear(struct bgp_mpath_diff_head *diff)
{
struct bgp_path_info_mpath_diff *mp_diff;
if (!diff)
return;
while ((mp_diff = bgp_mpath_diff_pop(diff))) {
if (mp_diff->path && mp_diff->path->net)
bgp_dest_unlock_node(mp_diff->path->net);
if (mp_diff->path)
bgp_path_info_unlock(mp_diff->path);
XFREE(MTYPE_BGP_MPATH_DIFF, mp_diff);
}
}
/*
* bgp_path_info_mpath_update
*
@ -418,7 +454,8 @@ static void bgp_path_info_mpath_attr_set(struct bgp_path_info *path,
*/
void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
struct bgp_path_info *new_best, struct bgp_path_info *old_best,
uint32_t num_candidates, struct bgp_maxpaths_cfg *mpath_cfg)
uint32_t num_candidates, struct bgp_maxpaths_cfg *mpath_cfg,
struct bgp_mpath_diff_head *mpath_diff_list)
{
uint16_t maxpaths, mpath_count, old_mpath_count;
uint64_t bwval;
@ -518,8 +555,10 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
if (cur_iterator != new_best)
SET_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH);
if (!old_mpath)
if (!old_mpath) {
mpath_changed = true;
bgp_mpath_diff_insert(mpath_diff_list, cur_iterator, true);
}
if (ecommunity_linkbw_present(bgp_attr_get_ecommunity(cur_iterator->attr),
&bwval) ||
@ -544,6 +583,7 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
*/
mpath_changed = true;
UNSET_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH);
bgp_mpath_diff_insert(mpath_diff_list, cur_iterator, false);
}
cur_iterator = cur_iterator->next;

View file

@ -35,6 +35,22 @@ struct bgp_path_info_mpath {
uint64_t cum_bw;
};
DEFINE_MTYPE_STATIC(BGPD, BGP_MPATH_DIFF, "multipath diff in decision process");
PREDECL_LIST(bgp_mpath_diff);
struct bgp_path_info_mpath_diff {
struct bgp_mpath_diff_item next;
struct bgp_path_info *path;
bool update;
};
DECLARE_LIST(bgp_mpath_diff, struct bgp_path_info_mpath_diff, next);
extern void bgp_mpath_diff_insert(struct bgp_mpath_diff_head *diff, struct bgp_path_info *bpi,
bool update);
extern void bgp_mpath_diff_clear(struct bgp_mpath_diff_head *diff);
/* Functions to support maximum-paths configuration */
extern int bgp_maximum_paths_set(struct bgp *bgp, afi_t afi, safi_t safi,
int peertype, uint16_t maxpaths,
@ -49,7 +65,8 @@ extern int bgp_path_info_nexthop_cmp(struct bgp_path_info *bpi1, struct bgp_path
extern void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
struct bgp_path_info *new_best,
struct bgp_path_info *old_best, uint32_t num_candidates,
struct bgp_maxpaths_cfg *mpath_cfg);
struct bgp_maxpaths_cfg *mpath_cfg,
struct bgp_mpath_diff_head *mpath_diff_list);
extern void
bgp_path_info_mpath_aggregate_update(struct bgp_path_info *new_best,
struct bgp_path_info *old_best);

View file

@ -637,12 +637,30 @@ void bgp_keepalive_send(struct peer_connection *connection)
bgp_writes_on(connection);
}
struct stream *bgp_open_make(struct peer *peer, uint16_t send_holdtime, as_t local_as,
struct in_addr *id)
uint16_t bgp_peer_get_send_holdtime(struct peer *peer)
{
if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER))
return peer->holdtime;
else
return peer->bgp->default_holdtime;
}
as_t bgp_peer_get_local_as(struct peer *peer)
{
if (peer->change_local_as)
return peer->change_local_as;
else
return peer->local_as;
}
struct stream *bgp_open_make(struct peer *peer, struct in_addr *id)
{
struct stream *s = stream_new(BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE);
bool ext_opt_params = false;
uint16_t send_holdtime = bgp_peer_get_send_holdtime(peer);
as_t local_as = bgp_peer_get_local_as(peer);
/* Make open packet. */
bgp_packet_set_marker(s, BGP_MSG_OPEN);
@ -686,22 +704,10 @@ struct stream *bgp_open_make(struct peer *peer, uint16_t send_holdtime, as_t loc
void bgp_open_send(struct peer_connection *connection)
{
struct stream *s;
uint16_t send_holdtime;
as_t local_as;
struct peer *peer = connection->peer;
if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER))
send_holdtime = peer->holdtime;
else
send_holdtime = peer->bgp->default_holdtime;
s = bgp_open_make(peer, &peer->local_id);
/* local-as Change */
if (peer->change_local_as)
local_as = peer->change_local_as;
else
local_as = peer->local_as;
s = bgp_open_make(peer, send_holdtime, local_as, &peer->local_id);
/* Dump packet if debug option is set. */
/* bgp_packet_dump (s); */

View file

@ -49,8 +49,9 @@ DECLARE_HOOK(bgp_packet_send,
/* Packet send and receive function prototypes. */
extern void bgp_keepalive_send(struct peer_connection *connection);
extern struct stream *bgp_open_make(struct peer *peer, uint16_t send_holdtime, as_t local_as,
struct in_addr *id);
extern as_t bgp_peer_get_local_as(struct peer *peer);
extern uint16_t bgp_peer_get_send_holdtime(struct peer *peer);
extern struct stream *bgp_open_make(struct peer *peer, struct in_addr *id);
extern void bgp_open_send(struct peer_connection *connection);
extern void bgp_notify_send(struct peer_connection *connection, uint8_t code,
uint8_t sub_code);

View file

@ -97,6 +97,8 @@ DEFINE_HOOK(bgp_route_update,
struct bgp_path_info *old_route, struct bgp_path_info *new_route),
(bgp, afi, safi, bn, old_route, new_route));
DEFINE_HOOK(bgp_process_main_one_end, (struct bgp * bgp, struct bgp_path_info *path), (bgp, path));
/* Extern from bgp_dump.c */
extern const char *bgp_origin_str[];
extern const char *bgp_origin_long_str[];
@ -162,9 +164,12 @@ static inline char *bgp_route_dump_path_info_flags(struct bgp_path_info *pi,
}
DEFINE_HOOK(bgp_process,
(struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
struct peer *peer, bool withdraw),
(bgp, afi, safi, bn, peer, withdraw));
(struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn, uint32_t addpath_id,
struct peer *peer, bool post),
(bgp, afi, safi, bn, addpath_id, peer, post));
DEFINE_HOOK(bgp_process_main_one, (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *dest),
(bgp, afi, safi, dest));
/** Test if path is suppressed. */
bool bgp_path_suppressed(struct bgp_path_info *pi)
@ -528,8 +533,6 @@ void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest,
bgp_dest_lock_node(dest);
peer_lock(pi->peer); /* bgp_path_info peer reference */
bgp_dest_set_defer_flag(dest, false);
if (pi->peer)
pi->peer->stat_pfx_loc_rib++;
hook_call(bgp_snmp_update_stats, dest, pi, true);
}
@ -548,8 +551,6 @@ struct bgp_dest *bgp_path_info_reap(struct bgp_dest *dest,
pi->next = NULL;
pi->prev = NULL;
if (pi->peer)
pi->peer->stat_pfx_loc_rib--;
hook_call(bgp_snmp_update_stats, dest, pi, false);
bgp_path_info_unlock(pi);
@ -562,8 +563,6 @@ static struct bgp_dest *bgp_path_info_reap_unsorted(struct bgp_dest *dest,
pi->next = NULL;
pi->prev = NULL;
if (pi->peer)
pi->peer->stat_pfx_loc_rib--;
hook_call(bgp_snmp_update_stats, dest, pi, false);
bgp_path_info_unlock(pi);
@ -2154,9 +2153,8 @@ void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
}
bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
struct update_subgroup *subgrp,
const struct prefix *p, struct attr *attr,
struct attr *post_attr)
struct update_subgroup *subgrp, const struct prefix *p,
struct attr *attr, struct attr *post_attr, uint8_t special_cond)
{
struct bgp_filter *filter;
struct peer *from;
@ -2190,6 +2188,11 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
bgp = SUBGRP_INST(subgrp);
piattr = bgp_path_info_mpath_count(pi) > 1 ? bgp_path_info_mpath_attr(pi) : pi->attr;
/* special conditions for bmp rib-out pre-policy check */
bool ignore_policy = CHECK_FLAG(special_cond, BGP_ANNCHK_SPECIAL_IGNORE_OUT_POLICY);
bool ignore_path_status = CHECK_FLAG(special_cond, BGP_ANNCHK_SPECIAL_IGNORE_PATH_STATUS);
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
peer->pmax_out[afi][safi] != 0 &&
subgrp->pscount >= peer->pmax_out[afi][safi]) {
@ -2229,21 +2232,21 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
/* With addpath we may be asked to TX all kinds of paths so make sure
* pi is valid */
if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
|| CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
|| CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
if (!ignore_path_status &&
(!CHECK_FLAG(pi->flags, BGP_PATH_VALID) || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY) ||
CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))) {
return false;
}
/* If this is not the bestpath then check to see if there is an enabled
* addpath
* feature that requires us to advertise it */
if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
if (!ignore_path_status && !CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
if (!bgp_addpath_capable(pi, peer, afi, safi))
return false;
/* Aggregate-address suppress check. */
if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
if (!ignore_policy && bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
return false;
/*
@ -2332,7 +2335,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
}
/* ORF prefix-list filter check */
if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) &&
if (!ignore_policy && CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) &&
CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV))
if (peer->orf_plist[afi][safi]) {
if (prefix_list_apply(peer->orf_plist[afi][safi], p)
@ -2368,7 +2371,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
}
/* Output filter check. */
if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
if (!ignore_policy && bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer,
p);
@ -2547,9 +2550,11 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
bgp_otc_egress(peer, attr))
return false;
if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
filter->advmap.aname &&
route_map_lookup_by_name(filter->advmap.aname)) {
bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
bgp_peer_as_override(bgp, afi, safi, peer, attr);
if (!ignore_policy && filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
filter->advmap.aname && route_map_lookup_by_name(filter->advmap.aname)) {
struct bgp_path_info rmap_path = {0};
struct bgp_path_info_extra dummy_rmap_path_extra = {0};
struct attr dummy_attr = *attr;
@ -2574,8 +2579,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
}
/* Route map & unsuppress-map apply. */
if (!post_attr &&
(ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
if (!ignore_policy && !post_attr && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
struct bgp_path_info rmap_path = {0};
struct bgp_path_info_extra dummy_rmap_path_extra = {0};
struct attr dummy_attr = {0};
@ -2950,10 +2954,9 @@ static void bgp_route_select_timer_expire(struct event *thread)
bgp_best_path_select_defer(bgp, afi, safi);
}
void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
struct bgp_maxpaths_cfg *mpath_cfg,
struct bgp_path_info_pair *result, afi_t afi,
safi_t safi)
void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest, struct bgp_maxpaths_cfg *mpath_cfg,
struct bgp_path_info_pair *result, afi_t afi, safi_t safi,
struct bgp_mpath_diff_head *mpath_diff_list)
{
struct bgp_path_info *new_select, *look_thru;
struct bgp_path_info *old_select, *worse, *first;
@ -3134,6 +3137,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
if (old_select != first &&
CHECK_FLAG(first->flags, BGP_PATH_REMOVED)) {
bgp_mpath_diff_insert(mpath_diff_list, first, false);
dest = bgp_path_info_reap_unsorted(dest, first);
assert(dest);
} else {
@ -3389,7 +3393,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
}
}
bgp_path_info_mpath_update(bgp, dest, new_select, old_select, num_candidates, mpath_cfg);
bgp_path_info_mpath_update(bgp, dest, new_select, old_select, num_candidates, mpath_cfg,
mpath_diff_list);
bgp_path_info_mpath_aggregate_update(new_select, old_select);
bgp_addpath_update_ids(bgp, dest, afi, safi);
@ -3439,9 +3444,11 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp,
*/
advertise = bgp_check_advertise(bgp, dest, safi);
bgp_adj_out_updated(subgrp, dest, selected, addpath_tx_id, &attr, false,
selected && advertise ? false : true);
if (selected) {
if (subgroup_announce_check(dest, selected, subgrp, p, pattr,
NULL)) {
if (subgroup_announce_check(dest, selected, subgrp, p, pattr, NULL, 0)) {
/* Route is selected, if the route is already installed
* in FIB, then it is advertised
*/
@ -3811,9 +3818,14 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
return;
}
hook_call(bgp_process_main_one, bgp, afi, safi, dest);
struct bgp_mpath_diff_head mpath_diff;
bgp_mpath_diff_init(&mpath_diff);
/* Best path selection. */
bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
afi, safi);
bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new, afi, safi,
&mpath_diff);
old_select = old_and_new.old;
new_select = old_and_new.new;
@ -3836,6 +3848,35 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
__func__, dest, bgp->name_pretty, afi2str(afi),
safi2str(safi), old_select, new_select);
struct bgp_path_info_mpath_diff *diff;
/* call bmp hook for loc-rib route update / withdraw after flags were
* set
*/
if (old_select || new_select) {
if (old_select)
bgp_path_info_lock(old_select);
hook_call(bgp_route_update, bgp, afi, safi, dest, old_select, new_select);
}
if (debug)
zlog_debug("%s: multipath diff %p computed, mpath_changed=%d", __func__,
&mpath_diff, (int)bgp_mpath_diff_count(&mpath_diff));
frr_each (bgp_mpath_diff, &mpath_diff, diff) {
if (diff->path) {
if (debug)
zlog_debug("[%s] bpi: %p, dest=%pBD peer=%pBP, rx_id=%" PRIu32,
diff->update ? "+" : "-", diff->path, diff->path->net,
diff->path->peer, diff->path->addpath_rx_id);
hook_call(bgp_route_update, bgp, afi, safi, dest, diff->path,
diff->update ? diff->path : NULL);
} else if (debug)
zlog_debug("[%s] diff: %p no path", diff->update ? "+" : "-", diff);
}
/* If best route remains the same and this is not due to user-initiated
* clear, see exactly what needs to be done.
*/
@ -3889,7 +3930,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
bgp_zebra_clear_route_change_flags(dest);
UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
return;
goto out;
}
/* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
@ -3916,6 +3958,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
/* TODO BMP insert rib update hook */
if (old_select)
bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
if (new_select) {
if (debug)
zlog_debug("%s: %pBD setting SELECTED flag", __func__,
@ -3933,15 +3976,6 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
}
/* 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) {
@ -4003,7 +4037,33 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
bgp_path_info_reap(dest, old_select);
return;
out:
if (old_select) {
if (old_select->peer)
old_select->peer->stat_loc_rib_count[afi][safi]--;
hook_call(bgp_process_main_one_end, bgp, old_select);
bgp_path_info_unlock(old_select);
}
if (new_select && new_select->peer)
new_select->peer->stat_loc_rib_count[afi][safi]++;
struct bgp_path_info *mpath;
frr_each (bgp_mpath_diff, &mpath_diff, diff) {
mpath = diff->path;
if (!mpath)
continue;
if (mpath->peer)
mpath->peer->stat_loc_rib_count[afi][safi] += diff->update ? 1 : -1;
hook_call(bgp_process_main_one_end, bgp, mpath);
}
bgp_mpath_diff_clear(&mpath_diff);
bgp_mpath_diff_fini(&mpath_diff);
}
/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
@ -4691,7 +4751,7 @@ void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
}
}
hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
hook_call(bgp_process, peer->bgp, afi, safi, dest, pi ? pi->addpath_rx_id : 0, peer, true);
bgp_process(peer->bgp, dest, pi, afi, safi);
}
@ -5043,7 +5103,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp_attr_set_evpn_overlay(attr, evpn);
p_evpn = NULL;
}
bgp_adj_in_set(dest, peer, attr, addpath_id, &bgp_labels);
bgp_adj_in_set(dest, afi, safi, peer, attr, addpath_id, &bgp_labels);
}
/* Check previously received route. */
@ -5328,7 +5388,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
pi->uptime = monotime(NULL);
same_attr = attrhash_cmp(pi->attr, attr_new);
hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
hook_call(bgp_process, bgp, afi, safi, dest, addpath_id, peer, true);
/* Same attribute comes in. */
if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED) && same_attr &&
@ -5709,7 +5769,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
bgp_evpn_import_route(bgp, afi, safi, p, new);
hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
hook_call(bgp_process, bgp, afi, safi, dest, addpath_id, peer, true);
/* Process change. */
bgp_process(bgp, dest, new, afi, safi);
@ -5750,7 +5810,7 @@ filtered:
XFREE(MTYPE_BGP_ROUTE, new);
}
hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
hook_call(bgp_process, bgp, afi, safi, dest, addpath_id, peer, false);
if (bgp_debug_update(peer, p, NULL, 1)) {
if (!peer->rcvd_attr_printed) {
@ -5839,9 +5899,9 @@ void bgp_withdraw(struct peer *peer, const struct prefix *p,
* and
* if there was no entry, we don't need to do anything more.
*/
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
&& peer != bgp->peer_self)
if (!bgp_adj_in_unset(&dest, peer, addpath_id)) {
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) &&
peer != bgp->peer_self) {
if (!bgp_adj_in_unset(&dest, afi, safi, peer, addpath_id)) {
assert(dest);
peer->stat_pfx_dup_withdraw++;
@ -5858,6 +5918,9 @@ void bgp_withdraw(struct peer *peer, const struct prefix *p,
return;
}
hook_call(bgp_process, peer->bgp, afi, safi, dest, addpath_id, peer, false);
}
/* Lookup withdrawn route. */
assert(dest);
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
@ -6426,7 +6489,7 @@ static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
ain_next = ain->next;
if (ain->peer == peer)
bgp_adj_in_remove(&dest, ain);
bgp_adj_in_remove(&dest, afi, safi, ain);
ain = ain_next;
@ -6674,7 +6737,7 @@ static int walk_batch_table_helper(struct bgp_clearing_info *cinfo,
ain_next = ain->next;
if (bgp_clearing_batch_check_peer(cinfo, ain->peer))
bgp_adj_in_remove(&dest, ain);
bgp_adj_in_remove(&dest, table->afi, table->safi, ain);
ain = ain_next;
@ -6905,7 +6968,7 @@ void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
ain_next = ain->next;
if (ain->peer == peer)
bgp_adj_in_remove(&dest, ain);
bgp_adj_in_remove(&dest, afi, safi, ain);
ain = ain_next;

View file

@ -14,6 +14,7 @@
#include "bgp_table.h"
#include "bgp_addpath_types.h"
#include "bgp_rpki.h"
#include "bgp_mpath.h"
struct bgp_nexthop_cache;
struct bgp_route_evpn;
@ -329,6 +330,8 @@ struct bgp_path_info {
#define BGP_PATH_MPLSVPN_LABEL_NH (1 << 17)
#define BGP_PATH_MPLSVPN_NH_LABEL_BIND (1 << 18)
#define BGP_PATH_UNSORTED (1 << 19)
#define BGP_PATH_BMP_LOCKED (1 << 20)
#define BGP_PATH_BMP_ADJIN_CHG (1 << 21)
/*
* BGP_PATH_MULTIPATH_NEW is set on those bgp_path_info
* nodes that we have decided should possibly be in the
@ -337,7 +340,7 @@ struct bgp_path_info {
* decide on whether or not a bgp_path_info is on
* the actual ecmp path.
*/
#define BGP_PATH_MULTIPATH_NEW (1 << 20)
#define BGP_PATH_MULTIPATH_NEW (1 << 22)
/* BGP route type. This can be static, RIP, OSPF, BGP etc. */
uint8_t type;
@ -730,9 +733,13 @@ static inline bool bgp_check_withdrawal(struct bgp *bgp, struct bgp_dest *dest,
/* called before bgp_process() */
DECLARE_HOOK(bgp_process,
(struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
struct peer *peer, bool withdraw),
(bgp, afi, safi, bn, peer, withdraw));
(struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn, uint32_t addpath_id,
struct peer *peer, bool post),
(bgp, afi, safi, bn, addpath_id, peer, post));
/* called before bgp_process() */
DECLARE_HOOK(bgp_process_main_one, (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *dest),
(bgp, afi, safi, dest));
/* called when a route is updated in the rib */
DECLARE_HOOK(bgp_route_update,
@ -740,6 +747,9 @@ DECLARE_HOOK(bgp_route_update,
struct bgp_path_info *old_route, struct bgp_path_info *new_route),
(bgp, afi, safi, bn, old_route, new_route));
DECLARE_HOOK(bgp_process_main_one_end, (struct bgp * bgp, struct bgp_path_info *path), (bgp, path));
/* BGP show options */
#define BGP_SHOW_OPT_JSON (1 << 0)
#define BGP_SHOW_OPT_WIDE (1 << 1)
@ -931,11 +941,14 @@ extern void subgroup_process_announce_selected(struct update_subgroup *subgrp,
safi_t safi,
uint32_t addpath_tx_id);
extern bool subgroup_announce_check(struct bgp_dest *dest,
struct bgp_path_info *pi,
struct update_subgroup *subgrp,
const struct prefix *p, struct attr *attr,
struct attr *post_attr);
/* used by bmp to ignore certain conditions in rib-out pre-policy check */
#define BGP_ANNCHK_SPECIAL_IGNORE_OUT_POLICY (1 << 0)
#define BGP_ANNCHK_SPECIAL_IGNORE_PATH_STATUS (1 << 1)
#define BGP_ANNCHK_SPECIAL_PREPOLICY \
(BGP_ANNCHK_SPECIAL_IGNORE_OUT_POLICY | BGP_ANNCHK_SPECIAL_IGNORE_PATH_STATUS)
extern bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
struct update_subgroup *subgrp, const struct prefix *p,
struct attr *attr, struct attr *post_attr, uint8_t special_cond);
/* for encap/vpn */
extern struct bgp_dest *bgp_safi_node_lookup(struct bgp_table *table,
@ -954,9 +967,8 @@ extern void bgp_attr_add_llgr_community(struct attr *attr);
extern void bgp_attr_add_gshut_community(struct attr *attr);
extern void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
struct bgp_maxpaths_cfg *mpath_cfg,
struct bgp_path_info_pair *result, afi_t afi,
safi_t safi);
struct bgp_maxpaths_cfg *mpath_cfg, struct bgp_path_info_pair *result,
afi_t afi, safi_t safi, struct bgp_mpath_diff_head *mpath_diff_list);
extern void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest);
extern bool bgp_zebra_has_route_changed(struct bgp_path_info *selected);

View file

@ -57,6 +57,11 @@
(PEER_CAP_ORF_PREFIX_SM_RCV | PEER_CAP_ADDPATH_AF_TX_ADV | \
PEER_CAP_ADDPATH_AF_RX_RCV | PEER_CAP_ENHE_AF_NEGO)
DECLARE_HOOK(bgp_adj_out_updated,
(struct update_subgroup * subgrp, struct bgp_dest *dest, struct bgp_path_info *path,
uint32_t addpath_id, struct attr *attr, bool post_policy, bool withdraw),
(subgrp, dest, path, addpath_id, attr, post_policy, withdraw));
enum bpacket_attr_vec_type { BGP_ATTR_VEC_NH = 0, BGP_ATTR_VEC_MAX };
typedef struct {
@ -443,9 +448,14 @@ extern bool bgp_adj_out_set_subgroup(struct bgp_dest *dest,
struct update_subgroup *subgrp,
struct attr *attr,
struct bgp_path_info *path);
extern void bgp_adj_out_updated(struct update_subgroup *subgrp, struct bgp_dest *dest,
struct bgp_path_info *path, uint32_t addpath_tx, struct attr *attr,
bool post_policy, bool withdraw);
extern void bgp_adj_out_unset_subgroup(struct bgp_dest *dest,
struct update_subgroup *subgrp,
char withdraw, uint32_t addpath_tx_id);
extern struct bgp_adj_out *adj_lookup(struct bgp_dest *dest, struct update_subgroup *subgrp,
uint32_t addpath_tx_id);
void subgroup_announce_table(struct update_subgroup *subgrp,
struct bgp_table *table);
extern void subgroup_trigger_write(struct update_subgroup *subgrp);

View file

@ -36,6 +36,10 @@
#include "bgpd/bgp_advertise.h"
#include "bgpd/bgp_addpath.h"
DEFINE_HOOK(bgp_adj_out_updated,
(struct update_subgroup * subgrp, struct bgp_dest *dest, struct bgp_path_info *path,
uint32_t addpath_id, struct attr *attr, bool post_policy, bool withdraw),
(subgrp, dest, path, addpath_id, attr, post_policy, withdraw));
/********************
* PRIVATE FUNCTIONS
@ -59,9 +63,8 @@ static int bgp_adj_out_compare(const struct bgp_adj_out *o1,
}
RB_GENERATE(bgp_adj_out_rb, bgp_adj_out, adj_entry, bgp_adj_out_compare);
static inline struct bgp_adj_out *adj_lookup(struct bgp_dest *dest,
struct update_subgroup *subgrp,
uint32_t addpath_tx_id)
inline struct bgp_adj_out *adj_lookup(struct bgp_dest *dest, struct update_subgroup *subgrp,
uint32_t addpath_tx_id)
{
struct bgp_adj_out lookup;
@ -265,6 +268,10 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)
adj->addpath_tx_id);
}
}
if (!adj)
bgp_adj_out_updated(subgrp, ctx->dest, NULL, 0,
NULL, false, true);
}
goto done;
@ -530,6 +537,19 @@ bgp_advertise_clean_subgroup(struct update_subgroup *subgrp,
return next;
}
/* call the bgp_adj_out_updated hook for bmp rib-out monitoring */
void bgp_adj_out_updated(struct update_subgroup *subgrp, struct bgp_dest *dest,
struct bgp_path_info *path, uint32_t addpath_tx, struct attr *attr,
bool post_policy, bool withdraw)
{
if (path && !withdraw && CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
/* path is removed, enforcing withdraw state */
withdraw = true;
}
hook_call(bgp_adj_out_updated, subgrp, dest, path, addpath_tx, attr, post_policy, withdraw);
}
bool bgp_adj_out_set_subgroup(struct bgp_dest *dest,
struct update_subgroup *subgrp, struct attr *attr,
struct bgp_path_info *path)
@ -662,6 +682,7 @@ bool bgp_adj_out_set_subgroup(struct bgp_dest *dest,
subgrp->version = MAX(subgrp->version, dest->version);
bgp_adj_out_updated(subgrp, dest, path, adj->addpath_tx_id, attr, true, false);
return true;
}
@ -712,6 +733,9 @@ void bgp_adj_out_unset_subgroup(struct bgp_dest *dest,
if (trigger_write)
subgroup_trigger_write(subgrp);
bgp_adj_out_updated(subgrp, dest, NULL, adj->addpath_tx_id, NULL, true,
withdraw);
} else {
/* Free allocated information. */
adj_free(adj);
@ -999,6 +1023,8 @@ void subgroup_default_originate(struct update_subgroup *subgrp, bool withdraw)
dest = bgp_safi_node_lookup(bgp->rib[afi][safi_rib], safi_rib, &p,
NULL);
// TODO add missing BMP hook call for default-originate in rib-out pre-policy
if (withdraw) {
/* Withdraw the default route advertised using default
* originate
@ -1017,9 +1043,8 @@ void subgroup_default_originate(struct update_subgroup *subgrp, bool withdraw)
continue;
if (subgroup_announce_check(dest, pi, subgrp,
bgp_dest_get_prefix(
dest),
&attr, NULL)) {
bgp_dest_get_prefix(dest), &attr, NULL,
0)) {
if (!bgp_adj_out_set_subgroup(dest,
subgrp,
&attr, pi))

View file

@ -4002,6 +4002,9 @@ void bgp_instance_down(struct bgp *bgp)
struct listnode *node;
struct listnode *next;
/* notify BMP of instance state changed */
hook_call(bgp_instance_state, bgp);
/* Cleanup evpn instance state */
bgp_evpn_instance_down(bgp);

View file

@ -1887,8 +1887,10 @@ struct peer {
uint32_t stat_pfx_dup_withdraw;
uint32_t stat_pfx_withdraw; /* RFC7606: treat-as-withdraw */
uint32_t stat_pfx_discard; /* The number of prefixes with discarded attributes */
uint64_t stat_pfx_loc_rib; /* RFC7854 : Number of routes in Loc-RIB */
uint64_t stat_pfx_adj_rib_in; /* RFC7854 : Number of routes in Adj-RIBs-In */
uint32_t stat_upd_7606; /* RFC7606: treat-as-withdraw */
uint32_t stat_adj_in_count[AFI_MAX][SAFI_MAX]; /* RFC7854 : Number of routes in Adj-RIB-In */
uint32_t stat_loc_rib_count[AFI_MAX][SAFI_MAX]; /* RFC7854 : Number of routes in Loc-RIB */
/* no need for stat_adj_out_count here, it is in struct update_subgroup */
/* BGP state count */
uint32_t established; /* Established */

View file

@ -4,46 +4,37 @@
BMP
***
RFC 7854
========
RFC 7854: BMP Adj-RIB-In
========================
Missing features (non exhaustive):
- Per-Peer Header
- Peer Type Flag
- Peer Distingsher
- Peer Up
- Peer Down
- Reason codes (according to TODO comments in code)
Peer Type Flag and Peer Distinguisher can be implemented easily using RFC 9069's base code.
RFC 9069
========
RFC 9069: BMP Local-RIB
=======================
Everything that isn't listed here is implemented and should be working.
Missing features (should be exhaustive):
- Per-Peer Header
- Timestamp
- set to 0
- value is now saved `struct bgp_path_info -> locrib_uptime`
- needs testing
- Peer Up/Down
- VRF/Table Name TLV
- code for TLV exists
- need better RFC understanding
- Peer Down Only
- Reason code (bc not supported in RFC 7854 either)
- Statistics Report
RFC8671: BMP Adj-RIB-Out
========================
Adj-RIB-Out pre-policy monitoring uses tricks to work because soft-reconfiguration outbound does not exist.
So what we do is we call the BGP function (subgroup_announce_check) which decides whether to announce or not to peers,
while ignoring the outbound policy + some conditions specific to Adj-RIB-Out Post-policy.
This allows us to guess whether the route would've been in Adj-RIB-Out Pre-policy or not. However, we cannot compute
all pre-policy stats as a consequence.
- Stat Type = 8: (64-bit Gauge) Number of routes in Loc-RIB.
- Stat Type = 10: Number of routes in per-AFI/SAFI Loc-RIB. The value is
structured as: 2-byte AFI, 1-byte SAFI, followed by a 64-bit Gauge.
Everything that isn't listed here is implemented and should be working.
- Per-Peer Header
- Timestamp: not recorded, set to 0
- Stats
- adj-rib-out pre-policy counters (cannot be done since adj-rib-out pre-policy is not saved)
ECMP Support
============
The RX Add-Path ID is exported for Adj-RIB-In Pre/Post-policy and Local-RIB.
The TX Add-Path ID is exported for Adj-RIB-Out Pre/Post-policy.

View file

@ -12,8 +12,8 @@ Implementation characteristics
The `BMP` implementation in FRR has the following properties:
- only the :rfc:`7854` features are currently implemented. This means protocol
version 3 without any extensions. It is not possible to use an older draft
- :rfc:`7854`, :rfc:`9069`, :rfc:`8671` features are currently implemented. This means protocol
version 3 without Local-RIB and Adj-RIB-Out Monitoring support. It is not possible to use an older draft
protocol version of BMP.
- the following statistics codes are implemented:
@ -23,10 +23,16 @@ The `BMP` implementation in FRR has the following properties:
- 3: count of **prefixes** with loop in cluster id
- 4: count of **prefixes** with loop in AS-path
- 5: count of **prefixes** with loop in originator
- 7: count of **routes** in adj-rib-in (pre-policy)
- 8: count of **routes** in local-rib
- 9: count of **routes** per afi/safi in adj-rib-in (pre-policy)
- 10: count of **routes** per afi/safi in local-rib
- 7: count of **routes** in adj-rib-in
- 8: count of **routes** in Loc-RIB
- 11: count of updates subjected to :rfc:`7607` "treat as withdrawal"
handling due to errors
- 15: count of routes in adj-rib-out post-policy
- 17: count of routes per afi/safi in adj-rib-out post-policy
- 65531: *experimental* count of prefixes rejected due to invalid next-hop
Note that stat items 3, 4 and 5 are specified to count updates, but FRR
@ -42,20 +48,11 @@ The `BMP` implementation in FRR has the following properties:
EVPN and VPN SAFIs. Other SAFIs (VPN, Labeled-Unicast, Flowspec, etc.) are not
currently supported.
- monitoring peers that have BGP **add-path** enabled on the session will
result in somewhat unpredictable behaviour. Currently, the outcome is:
- monitoring peers that have BGP **add-path** enabled on will have the following behaviour:
- route mirroring functions as intended, messages are copied verbatim
- the add-path ID is never included in route monitoring messages
- if multiple paths were received from a peer, an unpredictable path is
picked and sent on the BMP session. The selection will differ for
pre-policy and post-policy monitoring sessions.
- as long as any path is present, something will be advertised on BMP
sessions. Only after the last path is gone a withdrawal will be sent on
BMP sessions.
- updates to additional paths will trigger BMP route monitoring messages.
There is no guarantee on consistency regarding which path is sent in these
messages.
- the add-path ID is always included in route monitoring messages
- routes from peers without add-path have the "default" 0 path-id included
- the received path-id will be included for Adj-RIB-In and Local-RIB
- monitoring peers with :rfc:`5549` extended next-hops has not been tested.
@ -73,7 +70,7 @@ All of FRR's BMP configuration options are located inside the
:clicmd:`router bgp ASN` block. Configure BGP first before proceeding to BMP
setup.
There is one option that applies to the BGP instance as a whole:
There are two options that apply to the BGP instance as a whole:
.. clicmd:: bmp mirror buffer-limit(0-4294967294)
@ -93,6 +90,33 @@ There is one option that applies to the BGP instance as a whole:
BMP Route Monitoring is not affected by this option.
.. clicmd:: bmp startup-delay delay (0-4294967294)
This sets the delay (in milliseconds) after module startup
for BMP sessions to become active.
This setting is useful for BMP Monitoring because it allows BMP
to wait a bit for BGP to converge and the whole BGP state. It avoids
sending empty RIB content during synchronization on startup followed
by multiple incremental updates. It also avoids RIB-Out Pre-Policy Monitoring
to send duplicated messages on startup triggered by the reconfiguration of peer
policies.
This setting applies to all sessions defined in the same BGP Instance.
On module initialization (at BGP Startup), the time is recorded. Then,
established sessions will wait "delay" after this recorded time to start
sending BMP Mirroring, the initial BMP Monitoring synchronization and
following BMP Monitoring Messages containing incremental updates.
BMP Peer Up Messages are sent if the peer becomes available during this
period of time.
The startup delay is applied for BMP startup only. BMP Sessions configured
while the daemon is running will only wait if this initial timer has not expired
yet.
BMP Session Establishment is not affected by this option.
All other configuration is managed per targets:
.. clicmd:: bmp targets NAME
@ -153,9 +177,9 @@ associated with a particular ``bmp targets``:
Send BMP Statistics (counter) messages whose code is defined as
experimental (in the [65531-65534] range).
.. clicmd:: bmp monitor AFI SAFI <pre-policy|post-policy|loc-rib>
.. clicmd:: bmp monitor AFI SAFI <rib-in|loc-rib|rib-out> <pre-policy|post-policy>
Perform Route Monitoring for the specified AFI and SAFI. Only IPv4 and
Perform Route Monitoring for the specified AFI, SAFI and RIB. Only IPv4 and
IPv6 are currently valid for AFI. SAFI valid values are currently
unicast, multicast, evpn and vpn.
Other AFI/SAFI combinations may be added in the future.
@ -163,6 +187,11 @@ associated with a particular ``bmp targets``:
All BGP neighbors are included in Route Monitoring. Options to select
a subset of BGP sessions may be added in the future.
Pre-Policy and Post-Policy flags do not apply to Local-RIB monitoring.
BMP Local-RIB Monitoring is defined in :rfc:`9069`
BMP RIB-Out Monitoring is defined in :rfc:`8671`
.. clicmd:: bmp mirror
Perform Route Mirroring for all BGP neighbors. Since this provides a
@ -176,3 +205,50 @@ associated with a particular ``bmp targets``:
Perform Route Mirroring and Route Monitoring from an other BGP
instance.
BMP Troubleshooting
-------------------
When encountering problems with BMP, it may be interesting to know the current
state of the latter.
.. clicmd:: show bmp
Displays information about the current state of BMP including targets, sessions,
configured modes, global settings, ...
.. code-block:: frr
BMP Module started at Fri Feb 24 13:05:50 2023
BMP state for BGP VRF default:
Route Mirroring 0 bytes (0 messages) pending
0 bytes maximum buffer used
Startup delay : 10000ms
Targets "my_targets":
Route Mirroring disabled
Route Monitoring IPv4 unicast rib-out pre-policy rib-out post-policy
Listeners:
Outbound connections:
remote state timer local
----------------------------------------------------------------------
99.99.99.99:12345 Up 99.99.99.99:12345 00:00:04 (unspec)
1 connected clients:
remote uptime state MonSent MirrSent MirrLost ByteSent ByteQ ByteQKernel
---------------------------------------------------------------------------------------------------------------
99.99.99.99:12345 00:00:04 Startup-Wait 0 0 0 61 0 0
Here we have a single BGP instance running on VRF default. No specific mirroring settings but a
startup delay of 10000ms.
This instance has a single target with rib-out pre-policy and post-policy monitoring, no mirroring.
This target has a single session open with client 99.99.99.99 on port 12345 which is in state Startup-Wait.
This session will start sending monitoring messages as soon as the current time is
"Fri Feb 24 13:05:50 2023" + 10000ms = "Fri Feb 24 13:06:00 2023" which explains why it is in
Startup-Wait mode and has not sent Monitoring Messages yet.

View file

@ -84,6 +84,18 @@ void pullwr_bump(struct pullwr *pullwr)
event_add_timer(pullwr->tm, pullwr_run, pullwr, 0, &pullwr->writer);
}
/* call this function to schedule a pullwr_bump after a certain timeout
*
* uint32_t timeout is the wait time before pullwr_bump, in milliseconds
*/
void pullwr_timeout(struct pullwr *pullwr, uint32_t timeout)
{
if (pullwr->writer)
return;
event_add_timer_msec(pullwr->tm, pullwr_run, pullwr, timeout, &pullwr->writer);
}
static size_t pullwr_iov(struct pullwr *pullwr, struct iovec *iov)
{
size_t len1;

View file

@ -86,6 +86,7 @@ extern void pullwr_cfg(struct pullwr *pullwr, int64_t max_spin_usec,
size_t write_threshold);
extern void pullwr_bump(struct pullwr *pullwr);
extern void pullwr_timeout(struct pullwr *pullwr, uint32_t timeout);
extern void pullwr_write(struct pullwr *pullwr,
const void *data, size_t len);

0
tests/bgpd/test_mpath.c Normal file
View file

View file

@ -12,7 +12,8 @@
"peer_bgp_id": "192.168.0.1",
"peer_distinguisher": "0:0",
"peer_type": "loc-rib instance",
"policy": "loc-rib"
"policy": "loc-rib",
"path_id": 0
},
"2001::1111/128": {
"afi": 2,
@ -27,7 +28,8 @@
"peer_distinguisher": "0:0",
"peer_type": "loc-rib instance",
"policy": "loc-rib",
"safi": 1
"safi": 1,
"path_id": 0
}
}
}

View file

@ -0,0 +1,34 @@
{
"loc-rib": {
"update": {
"1.1.1.0/31": {
"as_path": "65501 65502",
"bgp_nexthop": "192.168.0.3",
"bmp_log_type": "update",
"ip_prefix": "1.1.1.0/31",
"is_filtered": false,
"origin": "IGP",
"path_id": 0,
"peer_asn": 65501,
"peer_bgp_id": "192.168.0.1",
"peer_distinguisher": "0:0",
"peer_type": "loc-rib instance",
"policy": "loc-rib"
},
"3.3.3.0/31": {
"as_path": "65501 65502",
"bgp_nexthop": "192.168.0.3",
"bmp_log_type": "update",
"ip_prefix": "3.3.3.0/31",
"is_filtered": false,
"origin": "IGP",
"path_id": 0,
"peer_asn": 65501,
"peer_bgp_id": "192.168.0.1",
"peer_distinguisher": "0:0",
"peer_type": "loc-rib instance",
"policy": "loc-rib"
}
}
}
}

View file

@ -0,0 +1,38 @@
{
"rib-in-post-policy": {
"update": {
"172.31.0.15/32": {
"as_path": "65501 65502",
"bgp_nexthop": "192.168.0.2",
"bmp_log_type": "update",
"ip_prefix": "172.31.0.15/32",
"ipv6": false,
"origin": "IGP",
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "444:1",
"peer_ip": "192.168.0.2",
"peer_type": "route distinguisher instance",
"policy": "rib-in-post-policy",
"path_id": 0
},
"2001::1111/128": {
"afi": 2,
"as_path": "65501 65502",
"bmp_log_type": "update",
"ip_prefix": "2001::1111/128",
"ipv6": true,
"nxhp_ip": "192:168::2",
"origin": "IGP",
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "555:1",
"peer_ip": "192:168::2",
"peer_type": "route distinguisher instance",
"policy": "rib-in-post-policy",
"safi": 1,
"path_id": 0
}
}
}
}

View file

@ -1,5 +1,5 @@
{
"pre-policy": {
"rib-in-post-policy": {
"update": {
"172.31.0.15/32": {
"afi": 1,
@ -16,7 +16,7 @@
"peer_distinguisher": "0:0",
"peer_ip": "192.168.0.2",
"peer_type": "global instance",
"policy": "pre-policy",
"policy": "rib-in-post-policy",
"rd": "444:2",
"safi": 128
},
@ -36,7 +36,7 @@
"peer_distinguisher": "0:0",
"peer_ip": "192:168::2",
"peer_type": "global instance",
"policy": "pre-policy",
"policy": "rib-in-post-policy",
"rd": "555:2",
"safi": 128
}

View file

@ -0,0 +1,38 @@
{
"rib-in-pre-policy": {
"update": {
"172.31.0.15/32": {
"as_path": "65501 65502",
"bgp_nexthop": "192.168.0.2",
"bmp_log_type": "update",
"ip_prefix": "172.31.0.15/32",
"ipv6": false,
"origin": "IGP",
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "444:1",
"peer_ip": "192.168.0.2",
"peer_type": "route distinguisher instance",
"policy": "rib-in-pre-policy",
"path_id": 0
},
"2001::1111/128": {
"afi": 2,
"as_path": "65501 65502",
"bmp_log_type": "update",
"ip_prefix": "2001::1111/128",
"ipv6": true,
"nxhp_ip": "192:168::2",
"origin": "IGP",
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "555:1",
"peer_ip": "192:168::2",
"peer_type": "route distinguisher instance",
"policy": "rib-in-pre-policy",
"safi": 1,
"path_id": 0
}
}
}
}

View file

@ -1,5 +1,5 @@
{
"post-policy": {
"rib-in-pre-policy": {
"update": {
"172.31.0.15/32": {
"afi": 1,
@ -16,7 +16,7 @@
"peer_distinguisher": "0:0",
"peer_ip": "192.168.0.2",
"peer_type": "global instance",
"policy": "post-policy",
"policy": "rib-in-pre-policy",
"rd": "444:2",
"safi": 128
},
@ -36,7 +36,7 @@
"peer_distinguisher": "0:0",
"peer_ip": "192:168::2",
"peer_type": "global instance",
"policy": "post-policy",
"policy": "rib-in-pre-policy",
"rd": "555:2",
"safi": 128
}

View file

@ -1,5 +1,5 @@
{
"pre-policy": {
"rib-out-post-policy": {
"update": {
"172.31.0.15/32": {
"as_path": "65501 65502",
@ -9,11 +9,12 @@
"ipv6": false,
"origin": "IGP",
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_bgp_id": "192.168.0.3",
"peer_distinguisher": "0:0",
"peer_ip": "192.168.0.2",
"peer_ip": "192.168.0.3",
"peer_type": "global instance",
"policy": "pre-policy"
"policy": "rib-out-post-policy",
"path_id": 0
},
"2001::1111/128": {
"afi": 2,
@ -24,12 +25,13 @@
"nxhp_ip": "192:168::2",
"origin": "IGP",
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_bgp_id": "192.168.0.3",
"peer_distinguisher": "0:0",
"peer_ip": "192:168::2",
"peer_ip": "192:168::3",
"peer_type": "global instance",
"policy": "pre-policy",
"safi": 1
"policy": "rib-out-post-policy",
"safi": 1,
"path_id": 0
}
}
}

View file

@ -1,5 +1,5 @@
{
"post-policy": {
"rib-out-pre-policy": {
"update": {
"172.31.0.15/32": {
"as_path": "65501 65502",
@ -9,11 +9,12 @@
"ipv6": false,
"origin": "IGP",
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_bgp_id": "192.168.0.3",
"peer_distinguisher": "0:0",
"peer_ip": "192.168.0.2",
"peer_ip": "192.168.0.3",
"peer_type": "global instance",
"policy": "post-policy"
"policy": "rib-out-pre-policy",
"path_id": 0
},
"2001::1111/128": {
"afi": 2,
@ -24,12 +25,13 @@
"nxhp_ip": "192:168::2",
"origin": "IGP",
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_bgp_id": "192.168.0.3",
"peer_distinguisher": "0:0",
"peer_ip": "192:168::2",
"peer_ip": "192:168::3",
"peer_type": "global instance",
"policy": "post-policy",
"safi": 1
"policy": "rib-out-pre-policy",
"safi": 1,
"path_id": 0
}
}
}

View file

@ -9,7 +9,8 @@
"peer_bgp_id": "192.168.0.1",
"peer_distinguisher": "0:0",
"peer_type": "loc-rib instance",
"policy": "loc-rib"
"policy": "loc-rib",
"path_id": 0
},
"2001::1111/128": {
"afi": 2,
@ -21,7 +22,8 @@
"peer_distinguisher": "0:0",
"peer_type": "loc-rib instance",
"policy": "loc-rib",
"safi": 1
"safi": 1,
"path_id": 0
}
}
}

View file

@ -0,0 +1,28 @@
{
"loc-rib": {
"withdraw": {
"1.1.1.0/31": {
"bmp_log_type": "withdraw",
"ip_prefix": "1.1.1.0/31",
"is_filtered": false,
"peer_asn": 65501,
"peer_bgp_id": "192.168.0.1",
"peer_distinguisher": "0:0",
"peer_type": "loc-rib instance",
"policy": "loc-rib",
"path_id": 0
},
"3.3.3.0/31": {
"bmp_log_type": "withdraw",
"ip_prefix": "3.3.3.0/31",
"is_filtered": false,
"peer_asn": 65501,
"peer_bgp_id": "192.168.0.1",
"peer_distinguisher": "0:0",
"peer_type": "loc-rib instance",
"policy": "loc-rib",
"path_id": 0
}
}
}
}

View file

@ -0,0 +1,32 @@
{
"rib-in-post-policy": {
"withdraw": {
"172.31.0.15/32": {
"bmp_log_type": "withdraw",
"ip_prefix": "172.31.0.15/32",
"ipv6": false,
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "444:1",
"peer_ip": "192.168.0.2",
"peer_type": "route distinguisher instance",
"policy": "rib-in-post-policy",
"path_id": 0
},
"2001::1111/128": {
"afi": 2,
"bmp_log_type": "withdraw",
"ip_prefix": "2001::1111/128",
"ipv6": true,
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "555:1",
"peer_ip": "192:168::2",
"peer_type": "route distinguisher instance",
"policy": "rib-in-post-policy",
"safi": 1,
"path_id": 0
}
}
}
}

View file

@ -1,5 +1,5 @@
{
"post-policy": {
"rib-in-post-policy": {
"withdraw": {
"2001::1111/128": {
"afi": 2,
@ -12,7 +12,7 @@
"peer_distinguisher": "0:0",
"peer_ip": "192:168::2",
"peer_type": "global instance",
"policy": "post-policy",
"policy": "rib-in-post-policy",
"rd": "555:2",
"safi": 128
},
@ -27,7 +27,7 @@
"peer_distinguisher": "0:0",
"peer_ip": "192.168.0.2",
"peer_type": "global instance",
"policy": "post-policy",
"policy": "rib-in-post-policy",
"rd": "444:2",
"safi": 128
}

View file

@ -0,0 +1,32 @@
{
"rib-in-pre-policy": {
"withdraw": {
"172.31.0.15/32": {
"bmp_log_type": "withdraw",
"ip_prefix": "172.31.0.15/32",
"ipv6": false,
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "444:1",
"peer_ip": "192.168.0.2",
"peer_type": "route distinguisher instance",
"policy": "rib-in-pre-policy",
"path_id": 0
},
"2001::1111/128": {
"afi": 2,
"bmp_log_type": "withdraw",
"ip_prefix": "2001::1111/128",
"ipv6": true,
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "555:1",
"peer_ip": "192:168::2",
"peer_type": "route distinguisher instance",
"policy": "rib-in-pre-policy",
"safi": 1,
"path_id": 0
}
}
}
}

View file

@ -1,5 +1,5 @@
{
"pre-policy": {
"rib-in-pre-policy": {
"withdraw": {
"2001::1111/128": {
"afi": 2,
@ -12,7 +12,7 @@
"peer_distinguisher": "0:0",
"peer_ip": "192:168::2",
"peer_type": "global instance",
"policy": "pre-policy",
"policy": "rib-in-pre-policy",
"rd": "555:2",
"safi": 128
},
@ -27,7 +27,7 @@
"peer_distinguisher": "0:0",
"peer_ip": "192.168.0.2",
"peer_type": "global instance",
"policy": "pre-policy",
"policy": "rib-in-pre-policy",
"rd": "444:2",
"safi": 128
}

View file

@ -1,16 +1,17 @@
{
"post-policy": {
"rib-out-post-policy": {
"withdraw": {
"172.31.0.15/32": {
"bmp_log_type": "withdraw",
"ip_prefix": "172.31.0.15/32",
"ipv6": false,
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_bgp_id": "192.168.0.3",
"peer_distinguisher": "0:0",
"peer_ip": "192.168.0.2",
"peer_ip": "192.168.0.3",
"peer_type": "global instance",
"policy": "post-policy"
"policy": "rib-out-post-policy",
"path_id": 0
},
"2001::1111/128": {
"afi": 2,
@ -18,12 +19,13 @@
"ip_prefix": "2001::1111/128",
"ipv6": true,
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_bgp_id": "192.168.0.3",
"peer_distinguisher": "0:0",
"peer_ip": "192:168::2",
"peer_ip": "192:168::3",
"peer_type": "global instance",
"policy": "post-policy",
"safi": 1
"policy": "rib-out-post-policy",
"safi": 1,
"path_id": 0
}
}
}

View file

@ -1,16 +1,17 @@
{
"pre-policy": {
"rib-out-pre-policy": {
"withdraw": {
"172.31.0.15/32": {
"bmp_log_type": "withdraw",
"ip_prefix": "172.31.0.15/32",
"ipv6": false,
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_bgp_id": "192.168.0.3",
"peer_distinguisher": "0:0",
"peer_ip": "192.168.0.2",
"peer_ip": "192.168.0.3",
"peer_type": "global instance",
"policy": "pre-policy"
"policy": "rib-out-pre-policy",
"path_id": 0
},
"2001::1111/128": {
"afi": 2,
@ -18,12 +19,13 @@
"ip_prefix": "2001::1111/128",
"ipv6": true,
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_bgp_id": "192.168.0.3",
"peer_distinguisher": "0:0",
"peer_ip": "192:168::2",
"peer_ip": "192:168::3",
"peer_type": "global instance",
"policy": "pre-policy",
"safi": 1
"policy": "rib-out-pre-policy",
"safi": 1,
"path_id": 0
}
}
}

View file

@ -6,19 +6,22 @@
"bgp_nexthop": "192.168.0.2",
"bmp_log_type": "update",
"ip_prefix": "172.31.0.15/32",
"peer_distinguisher": "65501:2",
"is_filtered": false,
"origin": "IGP",
"peer_asn": 65501,
"peer_bgp_id": "192.168.0.1",
"peer_distinguisher": "444:1",
"peer_type": "loc-rib instance",
"policy": "loc-rib"
"policy": "loc-rib",
"path_id": 0
},
"2111::1111/128": {
"afi": 2,
"as_path": "65501 65502",
"bmp_log_type": "update",
"ip_prefix": "2111::1111/128",
"peer_distinguisher": "65501:2",
"is_filtered": false,
"nxhp_ip": "192:168::2",
"origin": "IGP",
@ -27,7 +30,8 @@
"peer_distinguisher": "555:1",
"peer_type": "loc-rib instance",
"policy": "loc-rib",
"safi": 1
"safi": 1,
"path_id": 0
}
}
}

View file

@ -1,5 +1,5 @@
{
"post-policy": {
"rib-in-pre-policy": {
"update": {
"172.31.0.15/32": {
"as_path": "65501 65502",
@ -13,13 +13,14 @@
"peer_distinguisher": "444:1",
"peer_ip": "192.168.0.2",
"peer_type": "route distinguisher instance",
"policy": "post-policy"
"policy": "rib-in-pre-policy",
"path_id": 0
},
"2111::1111/128": {
"2001::1111/128": {
"afi": 2,
"as_path": "65501 65502",
"bmp_log_type": "update",
"ip_prefix": "2111::1111/128",
"ip_prefix": "2001::1111/128",
"ipv6": true,
"nxhp_ip": "192:168::2",
"origin": "IGP",
@ -28,8 +29,9 @@
"peer_distinguisher": "555:1",
"peer_ip": "192:168::2",
"peer_type": "route distinguisher instance",
"policy": "post-policy",
"safi": 1
"policy": "rib-in-pre-policy",
"safi": 1,
"path_id": 0
}
}
}

View file

@ -1,5 +1,5 @@
{
"pre-policy": {
"rib-in-post-policy": {
"update": {
"172.31.0.15/32": {
"as_path": "65501 65502",
@ -13,13 +13,14 @@
"peer_distinguisher": "444:1",
"peer_ip": "192.168.0.2",
"peer_type": "route distinguisher instance",
"policy": "pre-policy"
"policy": "rib-in-post-policy",
"path_id": 0
},
"2111::1111/128": {
"2001::1111/128": {
"afi": 2,
"as_path": "65501 65502",
"bmp_log_type": "update",
"ip_prefix": "2111::1111/128",
"ip_prefix": "2001::1111/128",
"ipv6": true,
"nxhp_ip": "192:168::2",
"origin": "IGP",
@ -28,8 +29,9 @@
"peer_distinguisher": "555:1",
"peer_ip": "192:168::2",
"peer_type": "route distinguisher instance",
"policy": "pre-policy",
"safi": 1
"policy": "rib-in-post-policy",
"safi": 1,
"path_id": 0
}
}
}

View file

@ -0,0 +1,38 @@
{
"rib-in-post-policy": {
"update": {
"172.31.0.15/32": {
"as_path": "65501 65502",
"bgp_nexthop": "192.168.0.2",
"bmp_log_type": "update",
"ip_prefix": "172.31.0.15/32",
"ipv6": false,
"origin": "IGP",
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "65501:2",
"peer_ip": "192.168.0.2",
"peer_type": "route distinguisher instance",
"policy": "rib-in-post-policy",
"path_id": 0
},
"2111::1111/128": {
"afi": 2,
"as_path": "65501 65502",
"bmp_log_type": "update",
"ip_prefix": "2111::1111/128",
"ipv6": true,
"nxhp_ip": "192:168::2",
"origin": "IGP",
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "65501:2",
"peer_ip": "192:168::2",
"peer_type": "route distinguisher instance",
"policy": "rib-in-post-policy",
"safi": 1,
"path_id": 0
}
}
}
}

View file

@ -0,0 +1,38 @@
{
"rib-in-pre-policy": {
"update": {
"172.31.0.15/32": {
"as_path": "65501 65502",
"bgp_nexthop": "192.168.0.2",
"bmp_log_type": "update",
"ip_prefix": "172.31.0.15/32",
"ipv6": false,
"origin": "IGP",
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "65501:2",
"peer_ip": "192.168.0.2",
"peer_type": "route distinguisher instance",
"policy": "rib-in-pre-policy",
"path_id": 0
},
"2111::1111/128": {
"afi": 2,
"as_path": "65501 65502",
"bmp_log_type": "update",
"ip_prefix": "2111::1111/128",
"ipv6": true,
"nxhp_ip": "192:168::2",
"origin": "IGP",
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "65501:2",
"peer_ip": "192:168::2",
"peer_type": "route distinguisher instance",
"policy": "rib-in-pre-policy",
"safi": 1,
"path_id": 0
}
}
}
}

View file

@ -0,0 +1,38 @@
{
"rib-out-post-policy": {
"update": {
"172.31.0.15/32": {
"as_path": "65501 65502",
"bgp_nexthop": "0.0.0.0",
"bmp_log_type": "update",
"ip_prefix": "172.31.0.15/32",
"ipv6": false,
"origin": "IGP",
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "65501:2",
"peer_ip": "192.168.0.2",
"peer_type": "route distinguisher instance",
"policy": "rib-out-post-policy",
"path_id": 0
},
"2111::1111/128": {
"afi": 2,
"as_path": "65501 65502",
"bmp_log_type": "update",
"ip_prefix": "2111::1111/128",
"ipv6": true,
"nxhp_ip": "::",
"origin": "IGP",
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "65501:2",
"peer_ip": "192:168::2",
"peer_type": "route distinguisher instance",
"policy": "rib-out-post-policy",
"safi": 1,
"path_id": 0
}
}
}
}

View file

@ -0,0 +1,38 @@
{
"rib-out-pre-policy": {
"update": {
"172.31.0.15/32": {
"as_path": "65501 65502",
"bgp_nexthop": "192.168.0.2",
"bmp_log_type": "update",
"ip_prefix": "172.31.0.15/32",
"ipv6": false,
"origin": "IGP",
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "65501:2",
"peer_ip": "192.168.0.2",
"peer_type": "route distinguisher instance",
"policy": "rib-out-pre-policy",
"path_id": 0
},
"2111::1111/128": {
"afi": 2,
"as_path": "65501 65502",
"bmp_log_type": "update",
"ip_prefix": "2111::1111/128",
"ipv6": true,
"nxhp_ip": "192:168::2",
"origin": "IGP",
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "65501:2",
"peer_ip": "192:168::2",
"peer_type": "route distinguisher instance",
"policy": "rib-out-pre-policy",
"safi": 1,
"path_id": 0
}
}
}
}

View file

@ -21,7 +21,20 @@
"peer_distinguisher": "555:1",
"peer_type": "loc-rib instance",
"policy": "loc-rib",
"safi": 1
"path_id": 0
},
"2111::1111/128": {
"afi": 2,
"bmp_log_type": "withdraw",
"ip_prefix": "2111::1111/128",
"peer_distinguisher": "65501:2",
"is_filtered": false,
"peer_asn": 65501,
"peer_bgp_id": "192.168.0.1",
"peer_type": "loc-rib instance",
"policy": "loc-rib",
"safi": 1,
"path_id": 0
}
}
}

View file

@ -1,5 +1,5 @@
{
"post-policy": {
"rib-in-post-policy": {
"withdraw": {
"172.31.0.15/32": {
"bmp_log_type": "withdraw",
@ -10,20 +10,22 @@
"peer_distinguisher": "444:1",
"peer_ip": "192.168.0.2",
"peer_type": "route distinguisher instance",
"policy": "post-policy"
"policy": "rib-in-post-policy",
"path_id": 0
},
"2111::1111/128": {
"2001::1111/128": {
"afi": 2,
"bmp_log_type": "withdraw",
"ip_prefix": "2111::1111/128",
"ip_prefix": "2001::1111/128",
"ipv6": true,
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "555:1",
"peer_ip": "192:168::2",
"peer_type": "route distinguisher instance",
"policy": "post-policy",
"policy": "rib-in-post-policy",
"safi": 1
"path_id": 0
}
}
}

View file

@ -1,5 +1,5 @@
{
"pre-policy": {
"rib-in-pre-policy": {
"withdraw": {
"172.31.0.15/32": {
"bmp_log_type": "withdraw",
@ -10,20 +10,22 @@
"peer_distinguisher": "444:1",
"peer_ip": "192.168.0.2",
"peer_type": "route distinguisher instance",
"policy": "pre-policy"
"policy": "rib-in-pre-policy",
"path_id": 0
},
"2111::1111/128": {
"2001::1111/128": {
"afi": 2,
"bmp_log_type": "withdraw",
"ip_prefix": "2111::1111/128",
"ip_prefix": "2001::1111/128",
"ipv6": true,
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "555:1",
"peer_ip": "192:168::2",
"peer_type": "route distinguisher instance",
"policy": "pre-policy",
"safi": 1
"policy": "rib-in-pre-policy",
"safi": 1,
"path_id": 0
}
}
}

View file

@ -0,0 +1,32 @@
{
"rib-in-post-policy": {
"withdraw": {
"172.31.0.15/32": {
"bmp_log_type": "withdraw",
"ip_prefix": "172.31.0.15/32",
"ipv6": false,
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "65501:2",
"peer_ip": "192.168.0.2",
"peer_type": "route distinguisher instance",
"policy": "rib-in-post-policy",
"path_id": 0
},
"2111::1111/128": {
"afi": 2,
"bmp_log_type": "withdraw",
"ip_prefix": "2111::1111/128",
"ipv6": true,
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "65501:2",
"peer_ip": "192:168::2",
"peer_type": "route distinguisher instance",
"policy": "rib-in-post-policy",
"safi": 1,
"path_id": 0
}
}
}
}

View file

@ -0,0 +1,32 @@
{
"rib-in-pre-policy": {
"withdraw": {
"172.31.0.15/32": {
"bmp_log_type": "withdraw",
"ip_prefix": "172.31.0.15/32",
"ipv6": false,
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "65501:2",
"peer_ip": "192.168.0.2",
"peer_type": "route distinguisher instance",
"policy": "rib-in-pre-policy",
"path_id": 0
},
"2111::1111/128": {
"afi": 2,
"bmp_log_type": "withdraw",
"ip_prefix": "2111::1111/128",
"ipv6": true,
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "65501:2",
"peer_ip": "192:168::2",
"peer_type": "route distinguisher instance",
"policy": "rib-in-pre-policy",
"safi": 1,
"path_id": 0
}
}
}
}

View file

@ -0,0 +1,32 @@
{
"rib-out-post-policy": {
"withdraw": {
"172.31.0.15/32": {
"bmp_log_type": "withdraw",
"ip_prefix": "172.31.0.15/32",
"ipv6": false,
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "65501:2",
"peer_ip": "192.168.0.2",
"peer_type": "route distinguisher instance",
"policy": "rib-out-post-policy",
"path_id": 0
},
"2111::1111/128": {
"afi": 2,
"bmp_log_type": "withdraw",
"ip_prefix": "2111::1111/128",
"ipv6": true,
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "65501:2",
"peer_ip": "192:168::2",
"peer_type": "route distinguisher instance",
"policy": "rib-out-post-policy",
"safi": 1,
"path_id": 0
}
}
}
}

View file

@ -0,0 +1,32 @@
{
"rib-out-pre-policy": {
"withdraw": {
"172.31.0.15/32": {
"bmp_log_type": "withdraw",
"ip_prefix": "172.31.0.15/32",
"ipv6": false,
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "65501:2",
"peer_ip": "192.168.0.2",
"peer_type": "route distinguisher instance",
"policy": "rib-out-pre-policy",
"path_id": 0
},
"2111::1111/128": {
"afi": 2,
"bmp_log_type": "withdraw",
"ip_prefix": "2111::1111/128",
"ipv6": true,
"peer_asn": 65502,
"peer_bgp_id": "192.168.0.2",
"peer_distinguisher": "65501:2",
"peer_ip": "192:168::2",
"peer_type": "route distinguisher instance",
"policy": "rib-out-pre-policy",
"safi": 1,
"path_id": 0
}
}
}
}

View file

@ -1,5 +1,17 @@
interface r1-eth0
ip address 192.0.2.1/24
router bgp 65501
bgp router-id 192.168.0.1
bgp log-neighbor-changes
no bgp ebgp-requires-policy
neighbor 192.168.0.2 remote-as 65502
neighbor 192:168::2 remote-as 65502
neighbor 192.168.0.3 remote-as 65502
neighbor 192:168::3 remote-as 65502
neighbor 192.168.0.2 solo
neighbor 192:168::2 solo
neighbor 192.168.0.3 solo
neighbor 192:168::3 solo
!
interface r1-eth1
ip address 192.168.0.1/24
@ -8,18 +20,25 @@ interface r1-eth1
router bgp 65501
bmp targets bmp1
bmp connect 192.0.2.10 port 1789 min-retry 100 max-retry 10000
bmp monitor ipv4 unicast pre-policy
bmp monitor ipv6 unicast pre-policy
bmp monitor ipv4 vpn pre-policy
bmp monitor ipv6 vpn pre-policy
bmp monitor ipv4 unicast post-policy
bmp monitor ipv6 unicast post-policy
bmp monitor ipv4 vpn post-policy
bmp monitor ipv6 vpn post-policy
bmp monitor ipv4 unicast rib-in pre-policy
bmp monitor ipv6 unicast rib-in pre-policy
bmp monitor ipv4 vpn rib-in pre-policy
bmp monitor ipv6 vpn rib-in pre-policy
bmp monitor ipv4 unicast rib-in post-policy
bmp monitor ipv6 unicast rib-in post-policy
bmp monitor ipv4 vpn rib-in post-policy
bmp monitor ipv6 vpn rib-in post-policy
!
bmp monitor ipv4 unicast loc-rib
bmp monitor ipv6 unicast loc-rib
bmp monitor ipv4 vpn loc-rib
bmp monitor ipv6 vpn loc-rib
!
bmp monitor ipv4 unicast rib-out pre-policy
bmp monitor ipv6 unicast rib-out pre-policy
bmp monitor ipv4 unicast rib-out post-policy
bmp monitor ipv6 unicast rib-out post-policy
!
exit
!
router bgp 65501
@ -44,11 +63,16 @@ router bgp 65501
neighbor 192.168.0.2 activate
neighbor 192.168.0.2 soft-reconfiguration inbound
no neighbor 192:168::2 activate
neighbor 192.168.0.3 activate
neighbor 192.168.0.3 soft-reconfiguration inbound
no neighbor 192:168::3 activate
exit-address-family
!
address-family ipv6 unicast
neighbor 192:168::2 activate
neighbor 192:168::2 soft-reconfiguration inbound
neighbor 192:168::3 activate
neighbor 192:168::3 soft-reconfiguration inbound
exit-address-family
!
router bgp 65501 vrf vrf1
@ -67,5 +91,5 @@ router bgp 65501 vrf vrf1
rt vpn both 54:200
export vpn
import vpn
exit-address-family
exit-address-family
exit

View file

@ -0,0 +1,48 @@
{
"routes": {
"1.1.1.0/31": [
{
"valid": true,
"pathFrom": "external",
"prefix": "1.1.1.0",
"prefixLen": 31,
"network": "1.1.1.0/31",
"metric": 0,
"weight": 0,
"peerId": "192.168.0.3",
"path": "65502",
"origin": "IGP",
"nexthops": [
{
"ip": "192.168.0.3",
"hostname": "r3",
"afi": "ipv4",
"used": true
}
]
}
],
"3.3.3.0/31": [
{
"valid": true,
"pathFrom": "external",
"prefix": "3.3.3.0",
"prefixLen": 31,
"network": "3.3.3.0/31",
"metric": 0,
"weight": 0,
"peerId": "192.168.0.3",
"path": "65502",
"origin": "IGP",
"nexthops": [
{
"ip": "192.168.0.3",
"hostname": "r3",
"afi": "ipv4",
"used": true
}
]
}
]
}
}

View file

@ -0,0 +1,48 @@
{
"routes": {
"1.1.1.0/31": [
{
"valid": true,
"pathFrom": "external",
"prefix": "1.1.1.0",
"prefixLen": 31,
"network": "1.1.1.0/31",
"metric": 0,
"weight": 0,
"peerId": "192.168.0.3",
"path": "65502",
"origin": "IGP",
"nexthops": [
{
"ip": "192.168.0.3",
"hostname": "r3",
"afi": "ipv4",
"used": true
}
]
}
],
"3.3.3.0/31": [
{
"valid": true,
"pathFrom": "external",
"prefix": "3.3.3.0",
"prefixLen": 31,
"network": "3.3.3.0/31",
"metric": 0,
"weight": 0,
"peerId": "192.168.0.3",
"path": "65502",
"origin": "IGP",
"nexthops": [
{
"ip": "192.168.0.3",
"hostname": "r3",
"afi": "ipv4",
"used": true
}
]
}
]
}
}

View file

@ -0,0 +1,46 @@
{
"routes": {
"192:168::/64": [
{
"valid": true,
"pathFrom": "external",
"prefix": "192:168::",
"prefixLen": 64,
"network": "192:168::/64",
"metric": 0,
"weight": 0,
"peerId": "192:168::2",
"path": "65502",
"origin": "incomplete",
"nexthops": [
{
"ip": "192:168::2",
"hostname": "r2",
"afi": "ipv6",
"scope": "global"
}
]
},
{
"valid": true,
"pathFrom": "external",
"prefix": "192:168::",
"prefixLen": 64,
"network": "192:168::/64",
"metric": 0,
"weight": 0,
"peerId": "192:168::3",
"path": "65502",
"origin": "incomplete",
"nexthops": [
{
"ip": "192:168::3",
"hostname": "r3",
"afi": "ipv6",
"scope": "global"
}
]
}
]
}
}

View file

@ -0,0 +1,5 @@
{
"routes": {
"2001::1111/128": null
}
}

View file

@ -14,23 +14,35 @@ router bgp 65501 vrf vrf1
!
bmp targets bmp1
bmp connect 192.0.2.10 port 1789 min-retry 100 max-retry 10000
bmp monitor ipv4 unicast pre-policy
bmp monitor ipv6 unicast pre-policy
bmp monitor ipv4 unicast post-policy
bmp monitor ipv6 unicast post-policy
bmp monitor ipv4 unicast rib-in pre-policy
bmp monitor ipv6 unicast rib-in pre-policy
bmp monitor ipv4 unicast rib-in post-policy
bmp monitor ipv6 unicast rib-in post-policy
bmp monitor ipv4 unicast loc-rib
bmp monitor ipv6 unicast loc-rib
bmp monitor ipv4 unicast rib-out pre-policy
bmp monitor ipv6 unicast rib-out pre-policy
bmp monitor ipv4 unicast rib-out post-policy
bmp monitor ipv6 unicast rib-out post-policy
exit
!
address-family ipv4 unicast
<<<<<<< HEAD:tests/topotests/bgp_bmp/r1vrf/frr.conf
rd vpn export 444:1
=======
rd vpn export 65501:2
>>>>>>> bb5cc3e9fd81 (tests: bmp tests for adj-rib-out and ecmp):tests/topotests/bgp_bmp_vrf/r1/bgpd.conf
neighbor 192.168.0.2 activate
neighbor 192.168.0.2 soft-reconfiguration inbound
no neighbor 192:168::2 activate
exit-address-family
!
address-family ipv6 unicast
<<<<<<< HEAD:tests/topotests/bgp_bmp/r1vrf/frr.conf
rd vpn export 555:1
=======
rd vpn export 65501:2
>>>>>>> bb5cc3e9fd81 (tests: bmp tests for adj-rib-out and ecmp):tests/topotests/bgp_bmp_vrf/r1/bgpd.conf
neighbor 192:168::2 activate
neighbor 192:168::2 soft-reconfiguration inbound
exit-address-family

View file

@ -16,6 +16,8 @@ router bgp 65502
neighbor 192.168.0.1 timers delayopen 5
neighbor 192:168::1 remote-as 65501
neighbor 192:168::1 timers delayopen 5
neighbor 192.168.0.1 solo
neighbor 192:168::1 solo
!
address-family ipv4 unicast
neighbor 192.168.0.1 activate

View file

@ -0,0 +1,21 @@
router bgp 65502
bgp router-id 192.168.0.3
bgp log-neighbor-changes
no bgp ebgp-requires-policy
no bgp network import-check
neighbor 192.168.0.1 remote-as 65501
neighbor 192:168::1 remote-as 65501
neighbor 192.168.0.1 solo
neighbor 192:168::1 solo
!
address-family ipv4 unicast
neighbor 192.168.0.1 activate
no neighbor 192:168::1 activate
redistribute connected
exit-address-family
!
address-family ipv6 unicast
neighbor 192:168::1 activate
redistribute connected
exit-address-family
!

View file

@ -0,0 +1,8 @@
interface r3-eth0
ip address 192.168.0.3/24
ipv6 address 192:168::3/64
!
interface r3-eth1
ip address 172.31.0.3/24
ipv6 address 172:31::3/64
!

View file

@ -47,21 +47,113 @@ class NlriIPv4Unicast:
@staticmethod
def parse(data):
"""parses prefixes from withdrawn_routes or nrli data"""
(prefix_len,) = struct.unpack_from("!B", data)
prefix = padding(data[1:], 4)
return {"ip_prefix": f"{ipaddress.IPv4Address(prefix)}/{prefix_len}"}
# we have an add-path id, this check is simpler than the unnecessary (i think?)
# detect_addpath_prefix_ipv46(data, max_bit_length=32) procedure
if len(data) > 5:
(addpath_id, prefix_len) = struct.unpack_from("!IB", data)
addpath_id = {"path_id": addpath_id}
prefix = padding(data[5:], 4)
else:
(prefix_len,) = struct.unpack_from("!B", data)
addpath_id = {}
prefix = padding(data[1:], 4)
return {
"ip_prefix": f"{ipaddress.IPv4Address(prefix)}/{prefix_len}",
**addpath_id,
}
# ------------------------------------------------------------------------------
"""
this is the addpath detection from wireshark, not perfect but works in our use cases
static int detect_add_path_prefix46(tvbuff_t *tvb, gint offset, gint end, gint max_bit_length)
in packet-bgp.c BGP dissector from Wireshark
"""
def detect_addpath_prefix_ipv46(data, max_bit_length):
end = len(data)
# proof by contradiction
# assuming this a well-formatted add-path prefix
# if we find an error it means there was no path-id, or a badly formatted one
# prefix length would be right after path id
# (i don't understand why they loop this check in range(4, end, 4) in Wireshark)
offset = 4
prefix_len = data[offset]
# the prefix length is bigger than the maximum allowed size
if prefix_len > max_bit_length:
return False
addr_len = (prefix_len + 7) // 8
offset += 1 + addr_len
# the prefix length announces a prefix bigger than what we have
if offset > end:
return False
# the prefix length tells us that the last byte will have more some 0 padding bits
# and those bits are not set to 0
if prefix_len % 8 > 0 and data[offset - 1] & (0xFF >> (prefix_len % 8)) > 0:
return False
# proof by contradiction
# assuming there is not an add-path prefix, and this is well formatted
# if we find an error it may mean there was a path-id
# assuming there is no add-path path-id
offset = 0
while offset < end:
# prefix length would be first
prefix_len = data[offset]
# prefix length is zero and we have more than one byte of address so maybe this was a path-id
if prefix_len == 0 and end - offset > 1:
return True
# invalid prefix length so maybe this was a path-id
if prefix_len > max_bit_length:
return True
addr_len = (prefix_len + 7) // 8
offset += 1 + addr_len
# the prefix length announces a prefix bigger than what we have
if offset > end:
return True # maybe this was a path-id
# the prefix length tells us that the last byte will have more some 0 padding bits
# and those bits are not set to 0
if prefix_len % 8 > 0 and data[offset - 1] & (0xFF >> (prefix_len % 8)) > 0:
return True # maybe it was a path-id
# we don't know if it's add-path so let's say no
return False
class NlriIPv6Unicast:
@staticmethod
def parse(data):
"""parses prefixes from withdrawn_routes or nrli data"""
(prefix_len,) = struct.unpack_from("!B", data)
prefix = padding(data[1:], 16)
return {"ip_prefix": f"{ipaddress.IPv6Address(prefix)}/{prefix_len}"}
# we have an add-path id
if detect_addpath_prefix_ipv46(data, max_bit_length=128):
(addpath_id, prefix_len) = struct.unpack_from("!IB", data)
addpath_id = {"path_id": addpath_id}
prefix = padding(data[5:], 16)
else:
(prefix_len,) = struct.unpack_from("!B", data)
addpath_id = {}
prefix = padding(data[1:], 16)
return {
"ip_prefix": f"{ipaddress.IPv6Address(prefix)}/{prefix_len}",
**addpath_id,
}
# ------------------------------------------------------------------------------

View file

@ -281,7 +281,11 @@ class BMPPerPeerMessage:
is_as_path = bool(peer_flags & IS_AS_PATH)
is_post_policy = bool(peer_flags & IS_POST_POLICY)
is_ipv6 = bool(peer_flags & IS_IPV6)
msg["policy"] = "post-policy" if is_post_policy else "pre-policy"
msg["policy"] = (
("rib-out" if is_adj_rib_out else "rib-in")
+ "-"
+ ("post-policy" if is_post_policy else "pre-policy")
)
msg["ipv6"] = is_ipv6
msg["peer_ip"] = bin2str_ipaddress(peer_address, is_ipv6)