nfp: compile flower vxlan tunnel metadata match fields
Compile ovs-tc flower vxlan metadata match fields for offloading. Only support offload of tunnel data when the VXLAN port specifically matches well known port 4789. Signed-off-by: John Hurley <john.hurley@netronome.com> Signed-off-by: Simon Horman <simon.horman@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
79ede4ae2d
commit
611aec101a
@ -83,6 +83,14 @@
|
|||||||
#define NFP_FL_PUSH_VLAN_CFI BIT(12)
|
#define NFP_FL_PUSH_VLAN_CFI BIT(12)
|
||||||
#define NFP_FL_PUSH_VLAN_VID GENMASK(11, 0)
|
#define NFP_FL_PUSH_VLAN_VID GENMASK(11, 0)
|
||||||
|
|
||||||
|
/* Tunnel ports */
|
||||||
|
#define NFP_FL_PORT_TYPE_TUN 0x50000000
|
||||||
|
|
||||||
|
enum nfp_flower_tun_type {
|
||||||
|
NFP_FL_TUNNEL_NONE = 0,
|
||||||
|
NFP_FL_TUNNEL_VXLAN = 2,
|
||||||
|
};
|
||||||
|
|
||||||
struct nfp_fl_output {
|
struct nfp_fl_output {
|
||||||
__be16 a_op;
|
__be16 a_op;
|
||||||
__be16 flags;
|
__be16 flags;
|
||||||
@ -230,6 +238,36 @@ struct nfp_flower_ipv6 {
|
|||||||
struct in6_addr ipv6_dst;
|
struct in6_addr ipv6_dst;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Flow Frame VXLAN --> Tunnel details (4W/16B)
|
||||||
|
* -----------------------------------------------------------------
|
||||||
|
* 3 2 1
|
||||||
|
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
* | ipv4_addr_src |
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
* | ipv4_addr_dst |
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
* | tun_flags | tos | ttl |
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
* | gpe_flags | Reserved | Next Protocol |
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
* | VNI | Reserved |
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
*/
|
||||||
|
struct nfp_flower_vxlan {
|
||||||
|
__be32 ip_src;
|
||||||
|
__be32 ip_dst;
|
||||||
|
__be16 tun_flags;
|
||||||
|
u8 tos;
|
||||||
|
u8 ttl;
|
||||||
|
u8 gpe_flags;
|
||||||
|
u8 reserved[2];
|
||||||
|
u8 nxt_proto;
|
||||||
|
__be32 tun_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NFP_FL_TUN_VNI_OFFSET 8
|
||||||
|
|
||||||
/* The base header for a control message packet.
|
/* The base header for a control message packet.
|
||||||
* Defines an 8-bit version, and an 8-bit type, padded
|
* Defines an 8-bit version, and an 8-bit type, padded
|
||||||
* to a 32-bit word. Rest of the packet is type-specific.
|
* to a 32-bit word. Rest of the packet is type-specific.
|
||||||
|
@ -58,6 +58,8 @@ struct nfp_app;
|
|||||||
#define NFP_FL_MASK_REUSE_TIME_NS 40000
|
#define NFP_FL_MASK_REUSE_TIME_NS 40000
|
||||||
#define NFP_FL_MASK_ID_LOCATION 1
|
#define NFP_FL_MASK_ID_LOCATION 1
|
||||||
|
|
||||||
|
#define NFP_FL_VXLAN_PORT 4789
|
||||||
|
|
||||||
struct nfp_fl_mask_id {
|
struct nfp_fl_mask_id {
|
||||||
struct circ_buf mask_id_free_list;
|
struct circ_buf mask_id_free_list;
|
||||||
struct timespec64 *last_used;
|
struct timespec64 *last_used;
|
||||||
|
@ -77,14 +77,17 @@ nfp_flower_compile_meta(struct nfp_flower_meta_one *frame, u8 key_type)
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
nfp_flower_compile_port(struct nfp_flower_in_port *frame, u32 cmsg_port,
|
nfp_flower_compile_port(struct nfp_flower_in_port *frame, u32 cmsg_port,
|
||||||
bool mask_version)
|
bool mask_version, enum nfp_flower_tun_type tun_type)
|
||||||
{
|
{
|
||||||
if (mask_version) {
|
if (mask_version) {
|
||||||
frame->in_port = cpu_to_be32(~0);
|
frame->in_port = cpu_to_be32(~0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
frame->in_port = cpu_to_be32(cmsg_port);
|
if (tun_type)
|
||||||
|
frame->in_port = cpu_to_be32(NFP_FL_PORT_TYPE_TUN | tun_type);
|
||||||
|
else
|
||||||
|
frame->in_port = cpu_to_be32(cmsg_port);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -189,15 +192,53 @@ nfp_flower_compile_ipv6(struct nfp_flower_ipv6 *frame,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nfp_flower_compile_vxlan(struct nfp_flower_vxlan *frame,
|
||||||
|
struct tc_cls_flower_offload *flow,
|
||||||
|
bool mask_version)
|
||||||
|
{
|
||||||
|
struct fl_flow_key *target = mask_version ? flow->mask : flow->key;
|
||||||
|
struct flow_dissector_key_ipv4_addrs *vxlan_ips;
|
||||||
|
struct flow_dissector_key_keyid *vni;
|
||||||
|
|
||||||
|
/* Wildcard TOS/TTL/GPE_FLAGS/NXT_PROTO for now. */
|
||||||
|
memset(frame, 0, sizeof(struct nfp_flower_vxlan));
|
||||||
|
|
||||||
|
if (dissector_uses_key(flow->dissector,
|
||||||
|
FLOW_DISSECTOR_KEY_ENC_KEYID)) {
|
||||||
|
u32 temp_vni;
|
||||||
|
|
||||||
|
vni = skb_flow_dissector_target(flow->dissector,
|
||||||
|
FLOW_DISSECTOR_KEY_ENC_KEYID,
|
||||||
|
target);
|
||||||
|
temp_vni = be32_to_cpu(vni->keyid) << NFP_FL_TUN_VNI_OFFSET;
|
||||||
|
frame->tun_id = cpu_to_be32(temp_vni);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dissector_uses_key(flow->dissector,
|
||||||
|
FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) {
|
||||||
|
vxlan_ips =
|
||||||
|
skb_flow_dissector_target(flow->dissector,
|
||||||
|
FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
|
||||||
|
target);
|
||||||
|
frame->ip_src = vxlan_ips->src;
|
||||||
|
frame->ip_dst = vxlan_ips->dst;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int nfp_flower_compile_flow_match(struct tc_cls_flower_offload *flow,
|
int nfp_flower_compile_flow_match(struct tc_cls_flower_offload *flow,
|
||||||
struct nfp_fl_key_ls *key_ls,
|
struct nfp_fl_key_ls *key_ls,
|
||||||
struct net_device *netdev,
|
struct net_device *netdev,
|
||||||
struct nfp_fl_payload *nfp_flow)
|
struct nfp_fl_payload *nfp_flow)
|
||||||
{
|
{
|
||||||
|
enum nfp_flower_tun_type tun_type = NFP_FL_TUNNEL_NONE;
|
||||||
int err;
|
int err;
|
||||||
u8 *ext;
|
u8 *ext;
|
||||||
u8 *msk;
|
u8 *msk;
|
||||||
|
|
||||||
|
if (key_ls->key_layer & NFP_FLOWER_LAYER_VXLAN)
|
||||||
|
tun_type = NFP_FL_TUNNEL_VXLAN;
|
||||||
|
|
||||||
memset(nfp_flow->unmasked_data, 0, key_ls->key_size);
|
memset(nfp_flow->unmasked_data, 0, key_ls->key_size);
|
||||||
memset(nfp_flow->mask_data, 0, key_ls->key_size);
|
memset(nfp_flow->mask_data, 0, key_ls->key_size);
|
||||||
|
|
||||||
@ -216,14 +257,14 @@ int nfp_flower_compile_flow_match(struct tc_cls_flower_offload *flow,
|
|||||||
/* Populate Exact Port data. */
|
/* Populate Exact Port data. */
|
||||||
err = nfp_flower_compile_port((struct nfp_flower_in_port *)ext,
|
err = nfp_flower_compile_port((struct nfp_flower_in_port *)ext,
|
||||||
nfp_repr_get_port_id(netdev),
|
nfp_repr_get_port_id(netdev),
|
||||||
false);
|
false, tun_type);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
/* Populate Mask Port Data. */
|
/* Populate Mask Port Data. */
|
||||||
err = nfp_flower_compile_port((struct nfp_flower_in_port *)msk,
|
err = nfp_flower_compile_port((struct nfp_flower_in_port *)msk,
|
||||||
nfp_repr_get_port_id(netdev),
|
nfp_repr_get_port_id(netdev),
|
||||||
true);
|
true, tun_type);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -291,5 +332,16 @@ int nfp_flower_compile_flow_match(struct tc_cls_flower_offload *flow,
|
|||||||
msk += sizeof(struct nfp_flower_ipv6);
|
msk += sizeof(struct nfp_flower_ipv6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key_ls->key_layer & NFP_FLOWER_LAYER_VXLAN) {
|
||||||
|
/* Populate Exact VXLAN Data. */
|
||||||
|
nfp_flower_compile_vxlan((struct nfp_flower_vxlan *)ext,
|
||||||
|
flow, false);
|
||||||
|
/* Populate Mask VXLAN Data. */
|
||||||
|
nfp_flower_compile_vxlan((struct nfp_flower_vxlan *)msk,
|
||||||
|
flow, true);
|
||||||
|
ext += sizeof(struct nfp_flower_vxlan);
|
||||||
|
msk += sizeof(struct nfp_flower_vxlan);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -52,8 +52,25 @@
|
|||||||
BIT(FLOW_DISSECTOR_KEY_PORTS) | \
|
BIT(FLOW_DISSECTOR_KEY_PORTS) | \
|
||||||
BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | \
|
BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | \
|
||||||
BIT(FLOW_DISSECTOR_KEY_VLAN) | \
|
BIT(FLOW_DISSECTOR_KEY_VLAN) | \
|
||||||
|
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_CONTROL) | \
|
||||||
|
BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) | \
|
||||||
BIT(FLOW_DISSECTOR_KEY_IP))
|
BIT(FLOW_DISSECTOR_KEY_IP))
|
||||||
|
|
||||||
|
#define NFP_FLOWER_WHITELIST_TUN_DISSECTOR \
|
||||||
|
(BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) | \
|
||||||
|
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_PORTS))
|
||||||
|
|
||||||
|
#define NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R \
|
||||||
|
(BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) | \
|
||||||
|
BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | \
|
||||||
|
BIT(FLOW_DISSECTOR_KEY_ENC_PORTS))
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nfp_flower_xmit_flow(struct net_device *netdev,
|
nfp_flower_xmit_flow(struct net_device *netdev,
|
||||||
struct nfp_fl_payload *nfp_flow, u8 mtype)
|
struct nfp_fl_payload *nfp_flow, u8 mtype)
|
||||||
@ -125,15 +142,58 @@ nfp_flower_calculate_key_layers(struct nfp_fl_key_ls *ret_key_ls,
|
|||||||
if (flow->dissector->used_keys & ~NFP_FLOWER_WHITELIST_DISSECTOR)
|
if (flow->dissector->used_keys & ~NFP_FLOWER_WHITELIST_DISSECTOR)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
/* If any tun dissector is used then the required set must be used. */
|
||||||
|
if (flow->dissector->used_keys & NFP_FLOWER_WHITELIST_TUN_DISSECTOR &&
|
||||||
|
(flow->dissector->used_keys & NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R)
|
||||||
|
!= NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
key_layer_two = 0;
|
||||||
|
key_layer = NFP_FLOWER_LAYER_PORT | NFP_FLOWER_LAYER_MAC;
|
||||||
|
key_size = sizeof(struct nfp_flower_meta_one) +
|
||||||
|
sizeof(struct nfp_flower_in_port) +
|
||||||
|
sizeof(struct nfp_flower_mac_mpls);
|
||||||
|
|
||||||
if (dissector_uses_key(flow->dissector,
|
if (dissector_uses_key(flow->dissector,
|
||||||
FLOW_DISSECTOR_KEY_ENC_CONTROL)) {
|
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_ports *enc_ports = NULL;
|
||||||
struct flow_dissector_key_control *mask_enc_ctl =
|
struct flow_dissector_key_control *mask_enc_ctl =
|
||||||
skb_flow_dissector_target(flow->dissector,
|
skb_flow_dissector_target(flow->dissector,
|
||||||
FLOW_DISSECTOR_KEY_ENC_CONTROL,
|
FLOW_DISSECTOR_KEY_ENC_CONTROL,
|
||||||
flow->mask);
|
flow->mask);
|
||||||
/* We are expecting a tunnel. For now we ignore offloading. */
|
struct flow_dissector_key_control *enc_ctl =
|
||||||
if (mask_enc_ctl->addr_type)
|
skb_flow_dissector_target(flow->dissector,
|
||||||
|
FLOW_DISSECTOR_KEY_ENC_CONTROL,
|
||||||
|
flow->key);
|
||||||
|
if (mask_enc_ctl->addr_type != 0xffff ||
|
||||||
|
enc_ctl->addr_type != FLOW_DISSECTOR_KEY_IPV4_ADDRS)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
/* These fields are already verified as used. */
|
||||||
|
mask_ipv4 =
|
||||||
|
skb_flow_dissector_target(flow->dissector,
|
||||||
|
FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
|
||||||
|
flow->mask);
|
||||||
|
if (mask_ipv4->dst != cpu_to_be32(~0))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
mask_enc_ports =
|
||||||
|
skb_flow_dissector_target(flow->dissector,
|
||||||
|
FLOW_DISSECTOR_KEY_ENC_PORTS,
|
||||||
|
flow->mask);
|
||||||
|
enc_ports =
|
||||||
|
skb_flow_dissector_target(flow->dissector,
|
||||||
|
FLOW_DISSECTOR_KEY_ENC_PORTS,
|
||||||
|
flow->key);
|
||||||
|
|
||||||
|
if (mask_enc_ports->dst != cpu_to_be16(~0) ||
|
||||||
|
enc_ports->dst != htons(NFP_FL_VXLAN_PORT))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
key_layer |= NFP_FLOWER_LAYER_VXLAN;
|
||||||
|
key_size += sizeof(struct nfp_flower_vxlan);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
|
if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
|
||||||
@ -151,12 +211,6 @@ nfp_flower_calculate_key_layers(struct nfp_fl_key_ls *ret_key_ls,
|
|||||||
FLOW_DISSECTOR_KEY_IP,
|
FLOW_DISSECTOR_KEY_IP,
|
||||||
flow->mask);
|
flow->mask);
|
||||||
|
|
||||||
key_layer_two = 0;
|
|
||||||
key_layer = NFP_FLOWER_LAYER_PORT | NFP_FLOWER_LAYER_MAC;
|
|
||||||
key_size = sizeof(struct nfp_flower_meta_one) +
|
|
||||||
sizeof(struct nfp_flower_in_port) +
|
|
||||||
sizeof(struct nfp_flower_mac_mpls);
|
|
||||||
|
|
||||||
if (mask_basic && mask_basic->n_proto) {
|
if (mask_basic && mask_basic->n_proto) {
|
||||||
/* Ethernet type is present in the key. */
|
/* Ethernet type is present in the key. */
|
||||||
switch (key_basic->n_proto) {
|
switch (key_basic->n_proto) {
|
||||||
|
Loading…
Reference in New Issue
Block a user