Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bgpd: BMP Loc-Rib Monitoring (RFC9069) Implementation #11800

Merged
merged 23 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9d21958
bgpd: basic loc rib monitoring (no syncing yet, not rfc compliant enc…
mxyns Jul 22, 2022
66e0c6f
bgpd: peer flag set for loc-rib monitoring (left set to 0 in other ca…
mxyns Jul 22, 2022
2c1900e
bgpd: correct loc rib update queue cleanup
mxyns Jul 22, 2022
8f0a017
bgpd: peer distinguisher set to vrf id
mxyns Jul 25, 2022
3d07f70
bgpd: fixed bmp vpnv4 monitoring withdraws instead of updates
mxyns Jul 26, 2022
c551295
bgpd: bmp afi/safi sync for loc-rib
mxyns Jul 27, 2022
f9af347
bgpd: bmp set peer distinguisher with RD
mxyns Jul 27, 2022
f838578
bgpd: bmp loc-rib RFC9069 compliant monitoring messages
mxyns Jul 28, 2022
24f3d9f
bgpd: safer vrf/table name (RFC9069) info tlv
mxyns Jul 28, 2022
bbf6cb6
bgpd: bmp loc-rib end-of-rib message add peer distinguisher
mxyns Jul 28, 2022
6691e1d
bgpd: temporary set timestamp to 0 for loc rib monitoring messages
mxyns Jul 29, 2022
90ffa97
bgpd: beginning to add rib_uptime field for loc-rib timestamp
mxyns Jul 29, 2022
257ca34
bgpd: cleanup bmp_get_peer_distinguisher function
mxyns Aug 8, 2022
0a09b49
bgpd: removed temporary dev logs
mxyns Aug 8, 2022
6da477b
bgpd: refactored bmp_route_update & cleanup TODOs
mxyns Aug 8, 2022
8557a13
bgpd: Update bmp.rst documentation
mxyns Aug 8, 2022
19b3ead
bgpd: bmp locrib monitoring unlock node after lookup
mxyns Aug 12, 2022
1cca53e
bgpd: applied styling and fixed warnings
mxyns Aug 12, 2022
66d564a
bgpd: loc-rib uptime moved to bgp_path_info_extra and set in header
mxyns Sep 28, 2022
fa17129
bgpd: skip bmp messages when vrf id is unknown
mxyns Feb 6, 2023
9607070
bgpd: bmp unset v6 flag + address PR#14188 comments
mxyns Sep 11, 2023
e65db90
tests: rework bmp policy message logging
Aug 11, 2023
e7adf27
tests: extend the bmp test to support bmp loc-rib
Aug 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
541 changes: 436 additions & 105 deletions bgpd/bgp_bmp.c

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions bgpd/bgp_bmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ struct bmp {
* ahead we need to make sure that refcount is decremented. Also, on
* disconnects we need to walk the queue and drop our reference.
*/
struct bmp_queue_entry *locrib_queuepos;
struct bmp_queue_entry *queuepos;
struct bmp_mirrorq *mirrorpos;
bool mirror_lost;
Expand Down Expand Up @@ -215,12 +216,14 @@ struct bmp_targets {
int stat_msec;

/* only supporting:
* - IPv4 / unicast & multicast
* - IPv6 / unicast & multicast
* - IPv4 / unicast & multicast & VPN
* - IPv6 / unicast & multicast & VPN
* - L2VPN / EVPN
*/
#define BMP_MON_PREPOLICY (1 << 0)
#define BMP_MON_POSTPOLICY (1 << 1)
#define BMP_MON_LOC_RIB (1 << 2)

uint8_t afimon[AFI_MAX][SAFI_MAX];
bool mirror;

Expand All @@ -232,6 +235,9 @@ struct bmp_targets {
struct bmp_qhash_head updhash;
struct bmp_qlist_head updlist;

struct bmp_qhash_head locupdhash;
struct bmp_qlist_head locupdlist;

uint64_t cnt_accept, cnt_aclrefused;

QOBJ_FIELDS;
Expand Down
15 changes: 15 additions & 0 deletions bgpd/bgp_route.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ DEFINE_HOOK(bgp_rpki_prefix_status,
const struct prefix *prefix),
(peer, attr, prefix));

DEFINE_HOOK(bgp_route_update,
(struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
struct bgp_path_info *old_route, struct bgp_path_info *new_route),
(bgp, afi, safi, bn, old_route, new_route));

/* Extern from bgp_dump.c */
extern const char *bgp_origin_str[];
extern const char *bgp_origin_long_str[];
Expand Down Expand Up @@ -3435,6 +3440,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
&bgp->t_rmap_def_originate_eval);
}

/* TODO BMP insert rib update hook */
if (old_select)
bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
if (new_select) {
Expand All @@ -3447,6 +3453,15 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
}

/* call bmp hook for loc-rib route update / withdraw after flags were
* set
*/
if (old_select || new_select) {
hook_call(bgp_route_update, bgp, afi, safi, dest, old_select,
new_select);
}


#ifdef ENABLE_BGP_VNC
if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
if (old_select != new_select) {
Expand Down
9 changes: 9 additions & 0 deletions bgpd/bgp_route.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,9 @@ struct bgp_path_info_extra {
mpls_label_t label[BGP_MAX_LABELS];
uint32_t num_labels;

/* timestamp of the rib installation */
time_t bgp_rib_uptime;

/*For EVPN*/
struct bgp_path_info_extra_evpn *evpn;

Expand Down Expand Up @@ -674,6 +677,12 @@ DECLARE_HOOK(bgp_process,
struct peer *peer, bool withdraw),
(bgp, afi, safi, bn, peer, withdraw));

/* called when a route is updated in the rib */
DECLARE_HOOK(bgp_route_update,
(struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
struct bgp_path_info *old_route, struct bgp_path_info *new_route),
(bgp, afi, safi, bn, old_route, new_route));

/* BGP show options */
#define BGP_SHOW_OPT_JSON (1 << 0)
#define BGP_SHOW_OPT_WIDE (1 << 1)
Expand Down
3 changes: 2 additions & 1 deletion bgpd/bgp_trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,12 @@ TRACEPOINT_LOGLEVEL(frr_bgp, bmp_mirror_packet, TRACE_INFO)
TRACEPOINT_EVENT(
frr_bgp,
bmp_eor,
TP_ARGS(afi_t, afi, safi_t, safi, uint8_t, flags),
TP_ARGS(afi_t, afi, safi_t, safi, uint8_t, flags, peer_type_flag),
TP_FIELDS(
ctf_integer(afi_t, afi, afi)
ctf_integer(safi_t, safi, safi)
ctf_integer(uint8_t, flags, flags)
ctf_integer(uint8_t, peer_type_flag, peer_type_flag)
)
)

Expand Down
49 changes: 49 additions & 0 deletions doc/developer/bmp.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
.. _bmp:

***
BMP
***

RFC 7854
========
Missing features (non exhaustive):
- Per-Peer Header

- Peer Type Flag
- Peer Distingsher

- Peer Up

- 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
========
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

- 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.
1 change: 1 addition & 0 deletions doc/developer/subdir.am
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
dev_RSTFILES = \
doc/developer/bgp-typecodes.rst \
doc/developer/bgpd.rst \
doc/developer/bmp.rst \
doc/developer/building-frr-for-alpine.rst \
doc/developer/building-frr-for-archlinux.rst \
doc/developer/building-frr-for-centos6.rst \
Expand Down
8 changes: 4 additions & 4 deletions doc/user/bmp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ The `BMP` implementation in FRR has the following properties:
successfully. OPEN messages for failed sessions cannot currently be
mirrored.

- **route monitoring** is available for IPv4 and IPv6 AFIs, unicast and
multicast SAFIs. Other SAFIs (VPN, Labeled-Unicast, Flowspec, etc.) are not
- **route monitoring** is available for IPv4 and IPv6 AFIs, unicast, multicast,
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
Expand Down Expand Up @@ -146,10 +146,10 @@ associated with a particular ``bmp targets``:
Send BMP Statistics (counter) messages at the specified interval (in
milliseconds.)

.. clicmd:: bmp monitor AFI SAFI <pre-policy|post-policy>
.. clicmd:: bmp monitor AFI SAFI <pre-policy|post-policy|loc-rib>

Perform Route Monitoring for the specified AFI and SAFI. Only IPv4 and
IPv6 are currently valid for AFI. SAFI valid values are currently
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.

Expand Down
11 changes: 7 additions & 4 deletions tests/topotests/bgp_bmp/test_bgp_bmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@

PRE_POLICY = "pre-policy"
POST_POLICY = "post-policy"
LOC_RIB = "loc-rib"


def build_topo(tgen):
Expand Down Expand Up @@ -120,7 +121,7 @@ def get_bmp_messages():
return messages


def check_for_prefixes(expected_prefixes, bmp_log_type, post_policy):
def check_for_prefixes(expected_prefixes, bmp_log_type, policy):
"""
Check for the presence of the given prefixes in the BMP server logs with
the given message type and the set policy.
Expand All @@ -138,7 +139,7 @@ def check_for_prefixes(expected_prefixes, bmp_log_type, post_policy):
if "ip_prefix" in m.keys()
and "bmp_log_type" in m.keys()
and m["bmp_log_type"] == bmp_log_type
and m["post_policy"] == post_policy
and m["policy"] == policy
]

# check for prefixes
Expand Down Expand Up @@ -202,15 +203,15 @@ def unicast_prefixes(policy):

logger.info("checking for updated prefixes")
# check
test_func = partial(check_for_prefixes, prefixes, "update", policy == POST_POLICY)
test_func = partial(check_for_prefixes, prefixes, "update", policy)
success, _ = topotest.run_and_expect(test_func, True, wait=0.5)
assert success, "Checking the updated prefixes has been failed !."

# withdraw prefixes
configure_prefixes(tgen, "r2", 65502, "unicast", prefixes, update=False)
logger.info("checking for withdrawed prefxies")
# check
test_func = partial(check_for_prefixes, prefixes, "withdraw", policy == POST_POLICY)
test_func = partial(check_for_prefixes, prefixes, "withdraw", policy)
success, _ = topotest.run_and_expect(test_func, True, wait=0.5)
assert success, "Checking the withdrawed prefixes has been failed !."

Expand Down Expand Up @@ -239,6 +240,8 @@ def test_bmp_bgp_unicast():
unicast_prefixes(PRE_POLICY)
logger.info("*** Unicast prefixes post-policy logging ***")
unicast_prefixes(POST_POLICY)
logger.info("*** Unicast prefixes loc-rib logging ***")
unicast_prefixes(LOC_RIB)


if __name__ == "__main__":
Expand Down
3 changes: 2 additions & 1 deletion tests/topotests/lib/bmp_collector/bmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,14 +252,15 @@ def dissect(cls, data):

if peer_type == 0x03:
msg['is_filtered'] = bool(peer_flags & IS_FILTERED)
msg['policy'] = 'loc-rib'
else:
# peer_flags = 0x0000 0000
# ipv6, post-policy, as-path, adj-rib-out, reserverdx4
is_adj_rib_out = bool(peer_flags & IS_ADJ_RIB_OUT)
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['post_policy'] = is_post_policy
msg['policy'] = 'post-policy' if is_post_policy else 'pre-policy'
msg['ipv6'] = is_ipv6
msg['peer_ip'] = bin2str_ipaddress(peer_address, is_ipv6)

Expand Down