diff options
| author | Louis Scalbert <louis.scalbert@6wind.com> | 2023-04-19 13:40:13 +0200 |
|---|---|---|
| committer | Louis Scalbert <louis.scalbert@6wind.com> | 2023-09-18 14:57:03 +0200 |
| commit | 39a8d354c11f6f063fa5154f5807e7a0c9b04b46 (patch) | |
| tree | 274eb91b310d78b045f9b00f0dca42a797e30764 | |
| parent | c8172af6825ad4b10e68b33b8edc22e6e2dc1524 (diff) | |
bgpd: store bgp link-state prefixes
Add the ability to store link-state prefixes in the BGP table.
Store a raw copy of the BGP link state NLRI TLVs as received in the
packet in 'p.u.prefix_linkstate.ptr'.
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
| -rw-r--r-- | bgpd/bgp_errors.c | 6 | ||||
| -rw-r--r-- | bgpd/bgp_errors.h | 1 | ||||
| -rw-r--r-- | bgpd/bgp_linkstate_tlv.c | 73 | ||||
| -rw-r--r-- | bgpd/bgp_linkstate_tlv.h | 12 | ||||
| -rw-r--r-- | bgpd/bgp_packet.c | 5 | ||||
| -rw-r--r-- | bgpd/bgp_table.c | 3 | ||||
| -rw-r--r-- | bgpd/subdir.am | 2 | ||||
| -rw-r--r-- | lib/table.c | 14 |
8 files changed, 114 insertions, 2 deletions
diff --git a/bgpd/bgp_errors.c b/bgpd/bgp_errors.c index cfcefed996..2f9f16f800 100644 --- a/bgpd/bgp_errors.c +++ b/bgpd/bgp_errors.c @@ -450,6 +450,12 @@ static struct log_ref ferr_bgp_err[] = { .suggestion = "Gather log files from the router and open an issue, Restart FRR" }, { + .code = EC_BGP_LINKSTATE_PACKET, + .title = "BGP Link-State packet processing error", + .description = "The BGP Link-State subsystem has detected a error in the send or receive of a packet", + .suggestion = "Gather log files from both sides of the peering relationship and open an issue" + }, + { .code = EC_BGP_DOPPELGANGER_CONFIG, .title = "BGP has detected a configuration overwrite during peer collision resolution", .description = "As part of BGP startup, the peer and ourselves can start connections to each other at the same time. During this process BGP received additional configuration, but it was only applied to one of the two nascent connections. Depending on the result of collision detection and resolution this configuration might be lost. To remedy this, after performing collision detection and resolution the peer session has been reset in order to apply the new configuration.", diff --git a/bgpd/bgp_errors.h b/bgpd/bgp_errors.h index 4567f87835..bc6b5a4a3d 100644 --- a/bgpd/bgp_errors.h +++ b/bgpd/bgp_errors.h @@ -59,6 +59,7 @@ enum bgp_log_refs { EC_BGP_EVPN_INSTANCE_MISMATCH, EC_BGP_FLOWSPEC_PACKET, EC_BGP_FLOWSPEC_INSTALLATION, + EC_BGP_LINKSTATE_PACKET, EC_BGP_ASPATH_FEWER_HOPS, EC_BGP_DEFUNCT_SNPA_LEN, EC_BGP_MISSING_ATTRIBUTE, diff --git a/bgpd/bgp_linkstate_tlv.c b/bgpd/bgp_linkstate_tlv.c new file mode 100644 index 0000000000..60f2c029cd --- /dev/null +++ b/bgpd/bgp_linkstate_tlv.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* BGP Link-State TLV Serializer/Deserializer + * Copyright 2023 6WIND S.A. + */ + +#include <zebra.h> + +#include "bgpd/bgpd.h" +#include "bgpd/bgp_route.h" +#include "bgpd/bgp_debug.h" +#include "bgpd/bgp_errors.h" +#include "bgpd/bgp_linkstate_tlv.h" + + +static uint16_t pnt_decode16(uint8_t **pnt) +{ + uint16_t data; + + *pnt = ptr_get_be16(*pnt, &data); + + return data; +} + +int bgp_nlri_parse_linkstate(struct peer *peer, struct attr *attr, + struct bgp_nlri *packet, int withdraw) +{ + uint8_t *pnt; + uint8_t *lim; + afi_t afi; + safi_t safi; + uint16_t length = 0; + struct prefix p; + + /* Start processing the NLRI - there may be multiple in the MP_REACH */ + pnt = packet->nlri; + lim = pnt + packet->length; + afi = packet->afi; + safi = packet->safi; + + for (; pnt < lim; pnt += length) { + /* Clear prefix structure. */ + memset(&p, 0, sizeof(p)); + + /* All linkstate NLRI begin with NRLI type and length. */ + if (pnt + 4 > lim) + return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW; + + p.u.prefix_linkstate.nlri_type = pnt_decode16(&pnt); + length = pnt_decode16(&pnt); + /* When packet overflow occur return immediately. */ + if (pnt + length > lim) { + flog_err( + EC_BGP_LINKSTATE_PACKET, + "Link-State NLRI length inconsistent (size %u seen)", + length); + return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW; + } + p.family = AF_LINKSTATE; + + p.u.prefix_linkstate.ptr = (uintptr_t)pnt; + p.prefixlen = length; + + /* Process the route. */ + if (withdraw) + bgp_withdraw(peer, &p, 0, afi, safi, ZEBRA_ROUTE_BGP, + BGP_ROUTE_NORMAL, NULL, NULL, 0, NULL); + else + bgp_update(peer, &p, 0, attr, afi, safi, + ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, + NULL, 0, 0, NULL); + } + return BGP_NLRI_PARSE_OK; +} diff --git a/bgpd/bgp_linkstate_tlv.h b/bgpd/bgp_linkstate_tlv.h new file mode 100644 index 0000000000..cb2c6ac99c --- /dev/null +++ b/bgpd/bgp_linkstate_tlv.h @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* BGP Link-State TLV Serializer/Deserializer header + * Copyright 2023 6WIND S.A. + */ + +#ifndef BGP_LINKSTATE_TLV_H +#define BGP_LINKSTATE_TLV_H + +extern int bgp_nlri_parse_linkstate(struct peer *peer, struct attr *attr, + struct bgp_nlri *packet, int withdraw); + +#endif /* BGP_LINKSTATE_TLV_H */ diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 9525ea016a..4eb56ad754 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -48,6 +48,7 @@ #include "bgpd/bgp_io.h" #include "bgpd/bgp_keepalives.h" #include "bgpd/bgp_flowspec.h" +#include "bgpd/bgp_linkstate_tlv.h" #include "bgpd/bgp_trace.h" DEFINE_HOOK(bgp_packet_dump, @@ -349,7 +350,11 @@ int bgp_nlri_parse(struct peer *peer, struct attr *attr, return bgp_nlri_parse_evpn(peer, attr, packet, mp_withdraw); case SAFI_FLOWSPEC: return bgp_nlri_parse_flowspec(peer, attr, packet, mp_withdraw); + case SAFI_LINKSTATE: + return bgp_nlri_parse_linkstate(peer, attr, packet, + mp_withdraw); } + return BGP_NLRI_PARSE_ERROR; } diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c index 8465ada996..b9265dd81b 100644 --- a/bgpd/bgp_table.c +++ b/bgpd/bgp_table.c @@ -117,6 +117,9 @@ static void bgp_node_destroy(route_table_delegate_t *delegate, node->info = NULL; } + if (family2afi(node->p.family) == AFI_LINKSTATE) + prefix_linkstate_ptr_free(&node->p); + XFREE(MTYPE_ROUTE_NODE, node); } diff --git a/bgpd/subdir.am b/bgpd/subdir.am index c2dd207a49..9326edc0fd 100644 --- a/bgpd/subdir.am +++ b/bgpd/subdir.am @@ -51,6 +51,7 @@ bgpd_libbgp_a_SOURCES = \ bgpd/bgp_label.c \ bgpd/bgp_labelpool.c \ bgpd/bgp_lcommunity.c \ + bgpd/bgp_linkstate_tlv.c \ bgpd/bgp_mac.c \ bgpd/bgp_memory.c \ bgpd/bgp_mpath.c \ @@ -133,6 +134,7 @@ noinst_HEADERS += \ bgpd/bgp_label.h \ bgpd/bgp_labelpool.h \ bgpd/bgp_lcommunity.h \ + bgpd/bgp_linkstate_tlv.h \ bgpd/bgp_mac.h \ bgpd/bgp_memory.h \ bgpd/bgp_mpath.h \ diff --git a/lib/table.c b/lib/table.c index 1910bd0427..dbfc3f8b91 100644 --- a/lib/table.c +++ b/lib/table.c @@ -281,15 +281,22 @@ struct route_node *route_node_get(struct route_table *table, const uint8_t *prefix = &p->u.prefix; node = rn_hash_node_find(&table->hash, &search); - if (node && node->info) + if (node && node->info) { + if (family2afi(p->family) == AFI_LINKSTATE) + prefix_linkstate_ptr_free(p); + return route_lock_node(node); + } match = NULL; node = table->top; while (node && node->p.prefixlen <= prefixlen && prefix_match(&node->p, p)) { - if (node->p.prefixlen == prefixlen) + if (node->p.prefixlen == prefixlen) { + if (family2afi(p->family) == AFI_LINKSTATE) + prefix_linkstate_ptr_free(p); return route_lock_node(node); + } match = node; node = node->link[prefix_bit(prefix, node->p.prefixlen)]; @@ -324,6 +331,9 @@ struct route_node *route_node_get(struct route_table *table, table->count++; route_lock_node(new); + if (family2afi(p->family) == AFI_LINKSTATE) + prefix_linkstate_ptr_free(p); + return new; } |
