summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2023-01-02 15:36:39 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2023-01-02 15:36:39 +0100
commit156d22654003635621248a15031ccefb39bfaffa (patch)
tree2d41aa12866c075bc039925e1c908e178f0c0cd1 /src
parent6cec0716ccecda3d3d70ec9f8f6be0d8da4bb419 (diff)
src: add geneve matching support
Add support for GENEVE vni and (ether) type header field. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/parser_bison.y32
-rw-r--r--src/proto.c28
-rw-r--r--src/scanner.l2
3 files changed, 59 insertions, 3 deletions
diff --git a/src/parser_bison.y b/src/parser_bison.y
index b2973995..10270f12 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -444,6 +444,8 @@ int nft_lex(void *, void *, void *);
%token GRE "gre"
+%token GENEVE "geneve"
+
%token SCTP "sctp"
%token CHUNK "chunk"
%token DATA "data"
@@ -904,9 +906,12 @@ int nft_lex(void *, void *, void *);
%type <val> tcpopt_field_maxseg tcpopt_field_mptcp tcpopt_field_sack tcpopt_field_tsopt tcpopt_field_window
%type <tcp_kind_field> tcp_hdr_option_kind_and_field
-%type <expr> inner_eth_expr inner_inet_expr inner_expr vxlan_hdr_expr gre_hdr_expr
-%destructor { expr_free($$); } inner_eth_expr inner_inet_expr inner_expr vxlan_hdr_expr gre_hdr_expr
-%type <val> vxlan_hdr_field gre_hdr_field
+%type <expr> inner_eth_expr inner_inet_expr inner_expr
+%destructor { expr_free($$); } inner_eth_expr inner_inet_expr inner_expr
+
+%type <expr> vxlan_hdr_expr geneve_hdr_expr gre_hdr_expr
+%destructor { expr_free($$); } vxlan_hdr_expr geneve_hdr_expr gre_hdr_expr
+%type <val> vxlan_hdr_field geneve_hdr_field gre_hdr_field
%type <stmt> optstrip_stmt
%destructor { stmt_free($$); } optstrip_stmt
@@ -5347,6 +5352,7 @@ payload_expr : payload_raw_expr
| sctp_hdr_expr
| th_hdr_expr
| vxlan_hdr_expr
+ | geneve_hdr_expr
| gre_hdr_expr
;
@@ -5644,6 +5650,26 @@ vxlan_hdr_field : VNI { $$ = VXLANHDR_VNI; }
| FLAGS { $$ = VXLANHDR_FLAGS; }
;
+geneve_hdr_expr : GENEVE geneve_hdr_field
+ {
+ struct expr *expr;
+
+ expr = payload_expr_alloc(&@$, &proto_geneve, $2);
+ expr->payload.inner_desc = &proto_geneve;
+ $$ = expr;
+ }
+ | GENEVE inner_expr
+ {
+ $$ = $2;
+ $$->location = @$;
+ $$->payload.inner_desc = &proto_geneve;
+ }
+ ;
+
+geneve_hdr_field : VNI { $$ = GNVHDR_VNI; }
+ | TYPE { $$ = GNVHDR_TYPE; }
+ ;
+
gre_hdr_expr : GRE gre_hdr_field close_scope_gre
{
$$ = payload_expr_alloc(&@$, &proto_gre, $2);
diff --git a/src/proto.c b/src/proto.c
index 3bb4ae74..0986a380 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -90,6 +90,7 @@ int proto_find_num(const struct proto_desc *base,
static const struct proto_desc *inner_protocols[] = {
&proto_vxlan,
+ &proto_geneve,
&proto_gre,
};
@@ -542,6 +543,7 @@ const struct proto_desc proto_udp = {
},
.protocols = {
PROTO_LINK(0, &proto_vxlan),
+ PROTO_LINK(0, &proto_geneve),
},
};
@@ -1216,6 +1218,32 @@ const struct proto_desc proto_vxlan = {
};
/*
+ * GENEVE
+ */
+
+const struct proto_desc proto_geneve = {
+ .name = "geneve",
+ .id = PROTO_DESC_GENEVE,
+ .base = PROTO_BASE_INNER_HDR,
+ .templates = {
+ [GNVHDR_TYPE] = HDR_TYPE("type", &ethertype_type, struct gnvhdr, type),
+ [GNVHDR_VNI] = HDR_BITFIELD("vni", &integer_type, (4 * BITS_PER_BYTE), 24),
+ },
+ .protocols = {
+ PROTO_LINK(__constant_htons(ETH_P_IP), &proto_ip),
+ PROTO_LINK(__constant_htons(ETH_P_ARP), &proto_arp),
+ PROTO_LINK(__constant_htons(ETH_P_IPV6), &proto_ip6),
+ PROTO_LINK(__constant_htons(ETH_P_8021Q), &proto_vlan),
+ },
+ .inner = {
+ .hdrsize = sizeof(struct gnvhdr),
+ .flags = NFT_INNER_HDRSIZE | NFT_INNER_LL | NFT_INNER_NH | NFT_INNER_TH,
+ .type = NFT_INNER_GENEVE,
+ },
+};
+
+
+/*
* Dummy protocol for netdev tables.
*/
const struct proto_desc proto_netdev = {
diff --git a/src/scanner.l b/src/scanner.l
index 3d9888ab..1ac46d1a 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -625,6 +625,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"vxlan" { return VXLAN; }
"vni" { return VNI; }
+"geneve" { return GENEVE; }
+
"gre" { scanner_push_start_cond(yyscanner, SCANSTATE_GRE); return GRE; }
"tcp" { scanner_push_start_cond(yyscanner, SCANSTATE_TCP); return TCP; }