mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00
Merge c9e05b98d3
into 3dd4d417be
This commit is contained in:
commit
d6d6f68a07
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
1607
bgpd/bgp_bmp.c
1607
bgpd/bgp_bmp.c
File diff suppressed because it is too large
Load diff
126
bgpd/bgp_bmp.h
126
bgpd/bgp_bmp.h
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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); */
|
||||
|
|
|
@ -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);
|
||||
|
|
173
bgpd/bgp_route.c
173
bgpd/bgp_route.c
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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.
|
||||
|
|
112
doc/user/bmp.rst
112
doc/user/bmp.rst
|
@ -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.
|
||||
|
|
12
lib/pullwr.c
12
lib/pullwr.c
|
@ -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;
|
||||
|
|
|
@ -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
0
tests/bgpd/test_mpath.c
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
34
tests/topotests/bgp_bmp/bmp1/bmp-update-loc-rib-step3.json
Normal file
34
tests/topotests/bgp_bmp/bmp1/bmp-update-loc-rib-step3.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
28
tests/topotests/bgp_bmp/bmp1/bmp-withdraw-loc-rib-step3.json
Normal file
28
tests/topotests/bgp_bmp/bmp1/bmp-withdraw-loc-rib-step3.json
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
48
tests/topotests/bgp_bmp/r1/show-bgp-ipv4-update-step3.json
Normal file
48
tests/topotests/bgp_bmp/r1/show-bgp-ipv4-update-step3.json
Normal 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
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
48
tests/topotests/bgp_bmp/r1/show-bgp-ipv4-withdraw-step3.json
Normal file
48
tests/topotests/bgp_bmp/r1/show-bgp-ipv4-withdraw-step3.json
Normal 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
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
46
tests/topotests/bgp_bmp/r1/show-bgp-ipv6-update-step3.json
Normal file
46
tests/topotests/bgp_bmp/r1/show-bgp-ipv6-update-step3.json
Normal 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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"routes": {
|
||||
"2001::1111/128": null
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
21
tests/topotests/bgp_bmp/r3/bgpd.conf
Normal file
21
tests/topotests/bgp_bmp/r3/bgpd.conf
Normal 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
|
||||
!
|
8
tests/topotests/bgp_bmp/r3/zebra.conf
Normal file
8
tests/topotests/bgp_bmp/r3/zebra.conf
Normal 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
|
||||
!
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in a new issue