forked from Mirror/frr
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>
This commit is contained in:
parent
c8172af682
commit
39a8d354c1
|
@ -449,6 +449,12 @@ static struct log_ref ferr_bgp_err[] = {
|
||||||
.description = "The BGP flowspec subsystem has detected that there was a failure for installation/removal/modification of Flowspec from the dataplane",
|
.description = "The BGP flowspec subsystem has detected that there was a failure for installation/removal/modification of Flowspec from the dataplane",
|
||||||
.suggestion = "Gather log files from the router and open an issue, Restart FRR"
|
.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,
|
.code = EC_BGP_DOPPELGANGER_CONFIG,
|
||||||
.title = "BGP has detected a configuration overwrite during peer collision resolution",
|
.title = "BGP has detected a configuration overwrite during peer collision resolution",
|
||||||
|
|
|
@ -59,6 +59,7 @@ enum bgp_log_refs {
|
||||||
EC_BGP_EVPN_INSTANCE_MISMATCH,
|
EC_BGP_EVPN_INSTANCE_MISMATCH,
|
||||||
EC_BGP_FLOWSPEC_PACKET,
|
EC_BGP_FLOWSPEC_PACKET,
|
||||||
EC_BGP_FLOWSPEC_INSTALLATION,
|
EC_BGP_FLOWSPEC_INSTALLATION,
|
||||||
|
EC_BGP_LINKSTATE_PACKET,
|
||||||
EC_BGP_ASPATH_FEWER_HOPS,
|
EC_BGP_ASPATH_FEWER_HOPS,
|
||||||
EC_BGP_DEFUNCT_SNPA_LEN,
|
EC_BGP_DEFUNCT_SNPA_LEN,
|
||||||
EC_BGP_MISSING_ATTRIBUTE,
|
EC_BGP_MISSING_ATTRIBUTE,
|
||||||
|
|
73
bgpd/bgp_linkstate_tlv.c
Normal file
73
bgpd/bgp_linkstate_tlv.c
Normal file
|
@ -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;
|
||||||
|
}
|
12
bgpd/bgp_linkstate_tlv.h
Normal file
12
bgpd/bgp_linkstate_tlv.h
Normal file
|
@ -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 */
|
|
@ -48,6 +48,7 @@
|
||||||
#include "bgpd/bgp_io.h"
|
#include "bgpd/bgp_io.h"
|
||||||
#include "bgpd/bgp_keepalives.h"
|
#include "bgpd/bgp_keepalives.h"
|
||||||
#include "bgpd/bgp_flowspec.h"
|
#include "bgpd/bgp_flowspec.h"
|
||||||
|
#include "bgpd/bgp_linkstate_tlv.h"
|
||||||
#include "bgpd/bgp_trace.h"
|
#include "bgpd/bgp_trace.h"
|
||||||
|
|
||||||
DEFINE_HOOK(bgp_packet_dump,
|
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);
|
return bgp_nlri_parse_evpn(peer, attr, packet, mp_withdraw);
|
||||||
case SAFI_FLOWSPEC:
|
case SAFI_FLOWSPEC:
|
||||||
return bgp_nlri_parse_flowspec(peer, attr, packet, mp_withdraw);
|
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;
|
return BGP_NLRI_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,9 @@ static void bgp_node_destroy(route_table_delegate_t *delegate,
|
||||||
node->info = NULL;
|
node->info = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (family2afi(node->p.family) == AFI_LINKSTATE)
|
||||||
|
prefix_linkstate_ptr_free(&node->p);
|
||||||
|
|
||||||
XFREE(MTYPE_ROUTE_NODE, node);
|
XFREE(MTYPE_ROUTE_NODE, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ bgpd_libbgp_a_SOURCES = \
|
||||||
bgpd/bgp_label.c \
|
bgpd/bgp_label.c \
|
||||||
bgpd/bgp_labelpool.c \
|
bgpd/bgp_labelpool.c \
|
||||||
bgpd/bgp_lcommunity.c \
|
bgpd/bgp_lcommunity.c \
|
||||||
|
bgpd/bgp_linkstate_tlv.c \
|
||||||
bgpd/bgp_mac.c \
|
bgpd/bgp_mac.c \
|
||||||
bgpd/bgp_memory.c \
|
bgpd/bgp_memory.c \
|
||||||
bgpd/bgp_mpath.c \
|
bgpd/bgp_mpath.c \
|
||||||
|
@ -133,6 +134,7 @@ noinst_HEADERS += \
|
||||||
bgpd/bgp_label.h \
|
bgpd/bgp_label.h \
|
||||||
bgpd/bgp_labelpool.h \
|
bgpd/bgp_labelpool.h \
|
||||||
bgpd/bgp_lcommunity.h \
|
bgpd/bgp_lcommunity.h \
|
||||||
|
bgpd/bgp_linkstate_tlv.h \
|
||||||
bgpd/bgp_mac.h \
|
bgpd/bgp_mac.h \
|
||||||
bgpd/bgp_memory.h \
|
bgpd/bgp_memory.h \
|
||||||
bgpd/bgp_mpath.h \
|
bgpd/bgp_mpath.h \
|
||||||
|
|
14
lib/table.c
14
lib/table.c
|
@ -281,15 +281,22 @@ struct route_node *route_node_get(struct route_table *table,
|
||||||
const uint8_t *prefix = &p->u.prefix;
|
const uint8_t *prefix = &p->u.prefix;
|
||||||
|
|
||||||
node = rn_hash_node_find(&table->hash, &search);
|
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);
|
return route_lock_node(node);
|
||||||
|
}
|
||||||
|
|
||||||
match = NULL;
|
match = NULL;
|
||||||
node = table->top;
|
node = table->top;
|
||||||
while (node && node->p.prefixlen <= prefixlen
|
while (node && node->p.prefixlen <= prefixlen
|
||||||
&& prefix_match(&node->p, p)) {
|
&& 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);
|
return route_lock_node(node);
|
||||||
|
}
|
||||||
|
|
||||||
match = node;
|
match = node;
|
||||||
node = node->link[prefix_bit(prefix, node->p.prefixlen)];
|
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++;
|
table->count++;
|
||||||
route_lock_node(new);
|
route_lock_node(new);
|
||||||
|
|
||||||
|
if (family2afi(p->family) == AFI_LINKSTATE)
|
||||||
|
prefix_linkstate_ptr_free(p);
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue