diff options
| -rw-r--r-- | drivers/net/ethernet/netronome/nfp/flower/cmsg.h | 6 | ||||
| -rw-r--r-- | drivers/net/ethernet/netronome/nfp/flower/match.c | 25 | ||||
| -rw-r--r-- | drivers/net/ethernet/netronome/nfp/flower/offload.c | 38 | 
3 files changed, 69 insertions, 0 deletions
| diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h index f2aeae88cbf0..325954b829c8 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h +++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h @@ -52,6 +52,7 @@  #define NFP_FLOWER_LAYER_VXLAN		BIT(7)  #define NFP_FLOWER_LAYER2_GENEVE	BIT(5) +#define NFP_FLOWER_LAYER2_GENEVE_OP	BIT(6)  #define NFP_FLOWER_MASK_VLAN_PRIO	GENMASK(15, 13)  #define NFP_FLOWER_MASK_VLAN_CFI	BIT(12) @@ -85,6 +86,7 @@  /* Maximum allowed geneve options */  #define NFP_FL_MAX_GENEVE_OPT_ACT	32  #define NFP_FL_MAX_GENEVE_OPT_CNT	64 +#define NFP_FL_MAX_GENEVE_OPT_KEY	32  /* Action opcodes */  #define NFP_FL_ACTION_OPCODE_OUTPUT		0 @@ -381,6 +383,10 @@ struct nfp_flower_ipv4_udp_tun {  	__be32 tun_id;  }; +struct nfp_flower_geneve_options { +	u8 data[NFP_FL_MAX_GENEVE_OPT_KEY]; +}; +  #define NFP_FL_TUN_VNI_OFFSET 8  /* The base header for a control message packet. diff --git a/drivers/net/ethernet/netronome/nfp/flower/match.c b/drivers/net/ethernet/netronome/nfp/flower/match.c index b1cbe6927cba..a0c72f277faa 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/match.c +++ b/drivers/net/ethernet/netronome/nfp/flower/match.c @@ -262,6 +262,21 @@ nfp_flower_compile_ipv6(struct nfp_flower_ipv6 *frame,  	nfp_flower_compile_ip_ext(&frame->ip_ext, flow, mask_version);  } +static int +nfp_flower_compile_geneve_opt(void *key_buf, struct tc_cls_flower_offload *flow, +			      bool mask_version) +{ +	struct fl_flow_key *target = mask_version ? flow->mask : flow->key; +	struct flow_dissector_key_enc_opts *opts; + +	opts = skb_flow_dissector_target(flow->dissector, +					 FLOW_DISSECTOR_KEY_ENC_OPTS, +					 target); +	memcpy(key_buf, opts->data, opts->len); + +	return 0; +} +  static void  nfp_flower_compile_ipv4_udp_tun(struct nfp_flower_ipv4_udp_tun *frame,  				struct tc_cls_flower_offload *flow, @@ -424,6 +439,16 @@ int nfp_flower_compile_flow_match(struct tc_cls_flower_offload *flow,  			nfp_flow->nfp_tun_ipv4_addr = tun_dst;  			nfp_tunnel_add_ipv4_off(netdev_repr->app, tun_dst);  		} + +		if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_GENEVE_OP) { +			err = nfp_flower_compile_geneve_opt(ext, flow, false); +			if (err) +				return err; + +			err = nfp_flower_compile_geneve_opt(msk, flow, true); +			if (err) +				return err; +		}  	}  	return 0; diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c index d2230a0e49b9..2edab01c3beb 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c @@ -66,6 +66,7 @@  	 BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | \  	 BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) | \  	 BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) | \ +	 BIT(FLOW_DISSECTOR_KEY_ENC_OPTS) | \  	 BIT(FLOW_DISSECTOR_KEY_ENC_IP) | \  	 BIT(FLOW_DISSECTOR_KEY_MPLS) | \  	 BIT(FLOW_DISSECTOR_KEY_IP)) @@ -75,6 +76,7 @@  	 BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) | \  	 BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | \  	 BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | \ +	 BIT(FLOW_DISSECTOR_KEY_ENC_OPTS) | \  	 BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) | \  	 BIT(FLOW_DISSECTOR_KEY_ENC_IP)) @@ -141,6 +143,21 @@ static bool nfp_flower_check_higher_than_mac(struct tc_cls_flower_offload *f)  }  static int +nfp_flower_calc_opt_layer(struct flow_dissector_key_enc_opts *enc_opts, +			  u32 *key_layer_two, int *key_size) +{ +	if (enc_opts->len > NFP_FL_MAX_GENEVE_OPT_KEY) +		return -EOPNOTSUPP; + +	if (enc_opts->len > 0) { +		*key_layer_two |= NFP_FLOWER_LAYER2_GENEVE_OP; +		*key_size += sizeof(struct nfp_flower_geneve_options); +	} + +	return 0; +} + +static int  nfp_flower_calculate_key_layers(struct nfp_app *app,  				struct nfp_fl_key_ls *ret_key_ls,  				struct tc_cls_flower_offload *flow, @@ -153,6 +170,7 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,  	u32 key_layer_two;  	u8 key_layer;  	int key_size; +	int err;  	if (flow->dissector->used_keys & ~NFP_FLOWER_WHITELIST_DISSECTOR)  		return -EOPNOTSUPP; @@ -178,6 +196,7 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,  			       FLOW_DISSECTOR_KEY_ENC_CONTROL)) {  		struct flow_dissector_key_ipv4_addrs *mask_ipv4 = NULL;  		struct flow_dissector_key_ports *mask_enc_ports = NULL; +		struct flow_dissector_key_enc_opts *enc_op = NULL;  		struct flow_dissector_key_ports *enc_ports = NULL;  		struct flow_dissector_key_control *mask_enc_ctl =  			skb_flow_dissector_target(flow->dissector, @@ -214,11 +233,21 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,  		if (mask_enc_ports->dst != cpu_to_be16(~0))  			return -EOPNOTSUPP; +		if (dissector_uses_key(flow->dissector, +				       FLOW_DISSECTOR_KEY_ENC_OPTS)) { +			enc_op = skb_flow_dissector_target(flow->dissector, +							   FLOW_DISSECTOR_KEY_ENC_OPTS, +							   flow->key); +		} +  		switch (enc_ports->dst) {  		case htons(NFP_FL_VXLAN_PORT):  			*tun_type = NFP_FL_TUNNEL_VXLAN;  			key_layer |= NFP_FLOWER_LAYER_VXLAN;  			key_size += sizeof(struct nfp_flower_ipv4_udp_tun); + +			if (enc_op) +				return -EOPNOTSUPP;  			break;  		case htons(NFP_FL_GENEVE_PORT):  			if (!(priv->flower_ext_feats & NFP_FL_FEATS_GENEVE)) @@ -228,6 +257,15 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,  			key_size += sizeof(struct nfp_flower_ext_meta);  			key_layer_two |= NFP_FLOWER_LAYER2_GENEVE;  			key_size += sizeof(struct nfp_flower_ipv4_udp_tun); + +			if (!enc_op) +				break; +			if (!(priv->flower_ext_feats & NFP_FL_FEATS_GENEVE_OPT)) +				return -EOPNOTSUPP; +			err = nfp_flower_calc_opt_layer(enc_op, &key_layer_two, +							&key_size); +			if (err) +				return err;  			break;  		default:  			return -EOPNOTSUPP; | 
