Add support for GENEVE vni and (ether) type header field.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
PROTO_DESC_VLAN,
PROTO_DESC_ETHER,
PROTO_DESC_VXLAN,
+ PROTO_DESC_GENEVE,
PROTO_DESC_GRE,
__PROTO_DESC_MAX
};
VXLANHDR_FLAGS,
};
+struct gnvhdr {
+ uint16_t flags;
+ uint16_t type;
+ uint32_t vni;
+};
+enum geneve_hdr_fields {
+ GNVHDR_INVALID,
+ GNVHDR_VNI,
+ GNVHDR_TYPE,
+};
+
struct grehdr {
uint16_t flags;
uint16_t protocol;
};
extern const struct proto_desc proto_vxlan;
+extern const struct proto_desc proto_geneve;
extern const struct proto_desc proto_gre;
extern const struct proto_desc proto_icmp;
%token GRE "gre"
+%token GENEVE "geneve"
+
%token SCTP "sctp"
%token CHUNK "chunk"
%token DATA "data"
%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
| sctp_hdr_expr
| th_hdr_expr
| vxlan_hdr_expr
+ | geneve_hdr_expr
| gre_hdr_expr
;
| 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);
static const struct proto_desc *inner_protocols[] = {
&proto_vxlan,
+ &proto_geneve,
&proto_gre,
};
},
.protocols = {
PROTO_LINK(0, &proto_vxlan),
+ PROTO_LINK(0, &proto_geneve),
},
};
},
};
+/*
+ * GENEVE
+ */
+
+const struct proto_desc proto_geneve = {
+ .name = "geneve",
+ .id = PROTO_DESC_GENEVE,
+ .base = PROTO_BASE_INNER_HDR,
+ .templates = {
+ [GNVHDR_TYPE] = HDR_TYPE("type", ðertype_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.
*/
"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; }