]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: store bgp link-state prefixes
authorLouis Scalbert <louis.scalbert@6wind.com>
Wed, 19 Apr 2023 11:40:13 +0000 (13:40 +0200)
committerLouis Scalbert <louis.scalbert@6wind.com>
Mon, 18 Sep 2023 12:57:03 +0000 (14:57 +0200)
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>
bgpd/bgp_errors.c
bgpd/bgp_errors.h
bgpd/bgp_linkstate_tlv.c [new file with mode: 0644]
bgpd/bgp_linkstate_tlv.h [new file with mode: 0644]
bgpd/bgp_packet.c
bgpd/bgp_table.c
bgpd/subdir.am
lib/table.c

index cfcefed996a504f4bc8d2b98786c20f06eb92cc2..2f9f16f8007fba80c1536b6af2bc42f6246d9868 100644 (file)
@@ -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",
                .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",
index 4567f87835480fda2750fa02f58ecc262388b44a..bc6b5a4a3daa540cef2211d5a35a3ac703bee33d 100644 (file)
@@ -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 (file)
index 0000000..60f2c02
--- /dev/null
@@ -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 (file)
index 0000000..cb2c6ac
--- /dev/null
@@ -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 */
index 9525ea016a10689478550d838c7f75c6a7c4f765..4eb56ad75456827d6574efb1c201869d7cf9b275 100644 (file)
@@ -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;
 }
 
index 8465ada996710da24f587d1a28ecf1d4a2159777..b9265dd81b915ac21a984bf9d019416e85933368 100644 (file)
@@ -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);
 }
 
index c2dd207a49d19471a59fbc3b55366075306e1b3b..9326edc0fddc640afeb8bd5df628740f05abcd32 100644 (file)
@@ -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 \
index 1910bd042727ae25dd810428573c74336b43375c..dbfc3f8b915d044946f6fbf6b5849159725aa83e 100644 (file)
@@ -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;
 }