summaryrefslogtreecommitdiff
path: root/proto/bgp
diff options
context:
space:
mode:
Diffstat (limited to 'proto/bgp')
-rw-r--r--proto/bgp/attrs.c43
-rw-r--r--proto/bgp/bgp.h1
-rw-r--r--proto/bgp/config.Y4
3 files changed, 47 insertions, 1 deletions
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index de45cae0..0ca40581 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -21,6 +21,7 @@
#include "lib/resource.h"
#include "lib/string.h"
#include "lib/unaligned.h"
+#include "lib/tunnel_encaps.h"
#include "bgp.h"
@@ -916,6 +917,39 @@ bgp_decode_otc(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *da
static void
+bgp_export_tunnel_encap(struct bgp_export_state *s UNUSED, eattr *a)
+{
+ if (a->u.ptr->length == 0)
+ UNSET(a);
+
+ /*
+ * TODO: In situations where a tunnel could be encoded using a barebones TLV,
+ * it MUST be encoded using the corresponding Encapsulation Extended
+ * Community. (RFC9012 section 4.1)
+ */
+}
+
+static void
+bgp_decode_tunnel_encap(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
+{
+ bgp_set_attr_data(to, s->pool, BA_TUNNEL_ENCAP, flags, data, len);
+}
+
+static int
+bgp_encode_tunnel_encap(struct bgp_write_state *s UNUSED, eattr *a, byte *buf, uint size)
+{
+ return bgp_put_attr(buf, size, EA_ID(a->id), a->flags, a->u.ptr->data, a->u.ptr->length);
+}
+
+static void
+bgp_format_tunnel_encap(const eattr *a, byte *buf, uint size)
+{
+ int l = format_tunnel_encap(a->u.ptr, buf, size);
+ if (l > 0)
+ ADVANCE(buf, size, l);
+}
+
+static void
bgp_export_mpls_label_stack(struct bgp_export_state *s, eattr *a)
{
net_addr *n = s->route->net->n.addr;
@@ -1135,6 +1169,15 @@ static const struct bgp_attr_desc bgp_attr_table[] = {
.encode = bgp_encode_u32,
.decode = bgp_decode_otc,
},
+ [BA_TUNNEL_ENCAP] = {
+ .name = "tunnel_encap",
+ .type = EAF_TYPE_TUNNEL_ENCAP,
+ .flags = BAF_OPTIONAL | BAF_TRANSITIVE,
+ .export = bgp_export_tunnel_encap,
+ .encode = bgp_encode_tunnel_encap,
+ .decode = bgp_decode_tunnel_encap,
+ .format = bgp_format_tunnel_encap,
+ },
[BA_MPLS_LABEL_STACK] = {
.name = "mpls_label_stack",
.type = EAF_TYPE_INT_SET,
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index c11433ec..178ff827 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -702,6 +702,7 @@ byte *bgp_create_end_mark_(struct bgp_channel *c, byte *buf);
#define BA_EXT_COMMUNITY 0x10 /* RFC 4360 */
#define BA_AS4_PATH 0x11 /* RFC 6793 */
#define BA_AS4_AGGREGATOR 0x12 /* RFC 6793 */
+#define BA_TUNNEL_ENCAP 0x17 /* RFC 9012 */
#define BA_AIGP 0x1a /* RFC 7311 */
#define BA_LARGE_COMMUNITY 0x20 /* RFC 8092 */
#define BA_ONLY_TO_CUSTOMER 0x23 /* RFC 9234 */
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index ba50446a..f7949b63 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -32,7 +32,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE,
LIVED, STALE, IMPORT, IBGP, EBGP, MANDATORY, INTERNAL, EXTERNAL, SETS,
DYNAMIC, RANGE, NAME, DIGITS, BGP_AIGP, AIGP, ORIGINATE, COST, ENFORCE,
FIRST, FREE, VALIDATE, BASE, ROLE, ROLES, PEER, PROVIDER, CUSTOMER,
- RS_SERVER, RS_CLIENT, REQUIRE, BGP_OTC, GLOBAL)
+ RS_SERVER, RS_CLIENT, REQUIRE, BGP_OTC, GLOBAL, BGP_TUNNEL_ENCAP)
%type <i> bgp_nh
%type <i32> bgp_afi
@@ -361,6 +361,8 @@ dynamic_attr: BGP_LARGE_COMMUNITY
{ $$ = f_new_dynamic_attr(EAF_TYPE_LC_SET, T_LCLIST, EA_CODE(PROTOCOL_BGP, BA_LARGE_COMMUNITY)); } ;
dynamic_attr: BGP_OTC
{ $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(PROTOCOL_BGP, BA_ONLY_TO_CUSTOMER)); } ;
+dynamic_attr: BGP_TUNNEL_ENCAP
+ { $$ = f_new_dynamic_attr(EAF_TYPE_TUNNEL_ENCAP, T_TLVLIST, EA_CODE(PROTOCOL_BGP, BA_TUNNEL_ENCAP)); } ;