Commit af9d842c authored by Pieter Jansen van Vuuren's avatar Pieter Jansen van Vuuren Committed by David S. Miller

nfp: extend flower add flow offload

Extends the flower flow add function by calculating which match
fields are present in the flower offload structure and allocating
the appropriate space to describe these.
Signed-off-by: default avatarPieter Jansen van Vuuren <pieter.jansenvanvuuren@netronome.com>
Signed-off-by: default avatarSimon Horman <simon.horman@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8a276873
...@@ -40,6 +40,147 @@ ...@@ -40,6 +40,147 @@
#include "../nfp_app.h" #include "../nfp_app.h"
#define NFP_FLOWER_LAYER_META BIT(0)
#define NFP_FLOWER_LAYER_PORT BIT(1)
#define NFP_FLOWER_LAYER_MAC BIT(2)
#define NFP_FLOWER_LAYER_TP BIT(3)
#define NFP_FLOWER_LAYER_IPV4 BIT(4)
#define NFP_FLOWER_LAYER_IPV6 BIT(5)
#define NFP_FLOWER_LAYER_CT BIT(6)
#define NFP_FLOWER_LAYER_VXLAN BIT(7)
#define NFP_FLOWER_LAYER_ETHER BIT(3)
#define NFP_FLOWER_LAYER_ARP BIT(4)
/* Metadata without L2 (1W/4B)
* ----------------------------------------------------------------
* 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | key_layers | mask_id | reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct nfp_flower_meta_one {
u8 nfp_flow_key_layer;
u8 mask_id;
u16 reserved;
};
/* Metadata with L2 (1W/4B)
* ----------------------------------------------------------------
* 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | key_type | mask_id | PCP |p| vlan outermost VID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* ^ ^
* NOTE: | TCI |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct nfp_flower_meta_two {
u8 nfp_flow_key_layer;
u8 mask_id;
__be16 tci;
};
/* Port details (1W/4B)
* ----------------------------------------------------------------
* 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | port_ingress |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct nfp_flower_in_port {
__be32 in_port;
};
/* L2 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | mac_addr_dst, 31 - 0 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | mac_addr_dst, 47 - 32 | mac_addr_src, 15 - 0 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | mac_addr_src, 47 - 16 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | mpls outermost label | TC |B| reserved |q|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct nfp_flower_mac_mpls {
u8 mac_dst[6];
u8 mac_src[6];
__be32 mpls_lse;
};
/* L4 ports (for UDP, TCP, SCTP) (1W/4B)
* 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | port_src | port_dst |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct nfp_flower_tp_ports {
__be16 port_src;
__be16 port_dst;
};
/* L3 IPv4 details (3W/12B)
* 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | DSCP |ECN| protocol | reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ipv4_addr_src |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ipv4_addr_dst |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct nfp_flower_ipv4 {
u8 tos;
u8 proto;
u8 ttl;
u8 reserved;
__be32 ipv4_src;
__be32 ipv4_dst;
};
/* L3 IPv6 details (10W/40B)
* 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | DSCP |ECN| protocol | reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ipv6_exthdr | res | ipv6_flow_label |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ipv6_addr_src, 31 - 0 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ipv6_addr_src, 63 - 32 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ipv6_addr_src, 95 - 64 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ipv6_addr_src, 127 - 96 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ipv6_addr_dst, 31 - 0 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ipv6_addr_dst, 63 - 32 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ipv6_addr_dst, 95 - 64 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ipv6_addr_dst, 127 - 96 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct nfp_flower_ipv6 {
u8 tos;
u8 proto;
u8 ttl;
u8 reserved;
__be32 ipv6_flow_label_exthdr;
struct in6_addr ipv6_src;
struct in6_addr ipv6_dst;
};
/* 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.
......
...@@ -40,6 +40,30 @@ struct tc_to_netdev; ...@@ -40,6 +40,30 @@ struct tc_to_netdev;
struct net_device; struct net_device;
struct nfp_app; struct nfp_app;
struct nfp_fl_key_ls {
u32 key_layer_two;
u8 key_layer;
int key_size;
};
struct nfp_fl_rule_metadata {
u8 key_len;
u8 mask_len;
u8 act_len;
u8 flags;
__be32 host_ctx_id;
__be64 host_cookie __packed;
__be64 flow_version __packed;
__be32 shortcut;
};
struct nfp_fl_payload {
struct nfp_fl_rule_metadata meta;
char *unmasked_data;
char *mask_data;
char *action_data;
};
int nfp_flower_setup_tc(struct nfp_app *app, struct net_device *netdev, int nfp_flower_setup_tc(struct nfp_app *app, struct net_device *netdev,
u32 handle, __be16 proto, struct tc_to_netdev *tc); u32 handle, __be16 proto, struct tc_to_netdev *tc);
#endif #endif
...@@ -44,6 +44,138 @@ ...@@ -44,6 +44,138 @@
#include "../nfp_net.h" #include "../nfp_net.h"
#include "../nfp_port.h" #include "../nfp_port.h"
static bool nfp_flower_check_higher_than_mac(struct tc_cls_flower_offload *f)
{
return dissector_uses_key(f->dissector,
FLOW_DISSECTOR_KEY_IPV4_ADDRS) ||
dissector_uses_key(f->dissector,
FLOW_DISSECTOR_KEY_IPV6_ADDRS) ||
dissector_uses_key(f->dissector,
FLOW_DISSECTOR_KEY_PORTS) ||
dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ICMP);
}
static int
nfp_flower_calculate_key_layers(struct nfp_fl_key_ls *ret_key_ls,
struct tc_cls_flower_offload *flow)
{
struct flow_dissector_key_control *mask_enc_ctl;
struct flow_dissector_key_basic *mask_basic;
struct flow_dissector_key_basic *key_basic;
u32 key_layer_two;
u8 key_layer;
int key_size;
mask_enc_ctl = skb_flow_dissector_target(flow->dissector,
FLOW_DISSECTOR_KEY_ENC_CONTROL,
flow->mask);
mask_basic = skb_flow_dissector_target(flow->dissector,
FLOW_DISSECTOR_KEY_BASIC,
flow->mask);
key_basic = skb_flow_dissector_target(flow->dissector,
FLOW_DISSECTOR_KEY_BASIC,
flow->key);
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);
/* We are expecting a tunnel. For now we ignore offloading. */
if (mask_enc_ctl->addr_type)
return -EOPNOTSUPP;
if (mask_basic->n_proto) {
/* Ethernet type is present in the key. */
switch (key_basic->n_proto) {
case cpu_to_be16(ETH_P_IP):
key_layer |= NFP_FLOWER_LAYER_IPV4;
key_size += sizeof(struct nfp_flower_ipv4);
break;
case cpu_to_be16(ETH_P_IPV6):
key_layer |= NFP_FLOWER_LAYER_IPV6;
key_size += sizeof(struct nfp_flower_ipv6);
break;
/* Currently we do not offload ARP
* because we rely on it to get to the host.
*/
case cpu_to_be16(ETH_P_ARP):
return -EOPNOTSUPP;
/* Will be included in layer 2. */
case cpu_to_be16(ETH_P_8021Q):
break;
default:
/* Other ethtype - we need check the masks for the
* remainder of the key to ensure we can offload.
*/
if (nfp_flower_check_higher_than_mac(flow))
return -EOPNOTSUPP;
break;
}
}
if (mask_basic->ip_proto) {
/* Ethernet type is present in the key. */
switch (key_basic->ip_proto) {
case IPPROTO_TCP:
case IPPROTO_UDP:
case IPPROTO_SCTP:
case IPPROTO_ICMP:
case IPPROTO_ICMPV6:
key_layer |= NFP_FLOWER_LAYER_TP;
key_size += sizeof(struct nfp_flower_tp_ports);
break;
default:
/* Other ip proto - we need check the masks for the
* remainder of the key to ensure we can offload.
*/
return -EOPNOTSUPP;
}
}
ret_key_ls->key_layer = key_layer;
ret_key_ls->key_layer_two = key_layer_two;
ret_key_ls->key_size = key_size;
return 0;
}
static struct nfp_fl_payload *
nfp_flower_allocate_new(struct nfp_fl_key_ls *key_layer)
{
struct nfp_fl_payload *flow_pay;
flow_pay = kmalloc(sizeof(*flow_pay), GFP_KERNEL);
if (!flow_pay)
return NULL;
flow_pay->meta.key_len = key_layer->key_size;
flow_pay->unmasked_data = kmalloc(key_layer->key_size, GFP_KERNEL);
if (!flow_pay->unmasked_data)
goto err_free_flow;
flow_pay->meta.mask_len = key_layer->key_size;
flow_pay->mask_data = kmalloc(key_layer->key_size, GFP_KERNEL);
if (!flow_pay->mask_data)
goto err_free_unmasked;
flow_pay->meta.flags = 0;
return flow_pay;
err_free_unmasked:
kfree(flow_pay->unmasked_data);
err_free_flow:
kfree(flow_pay);
return NULL;
}
/** /**
* nfp_flower_add_offload() - Adds a new flow to hardware. * nfp_flower_add_offload() - Adds a new flow to hardware.
* @app: Pointer to the APP handle * @app: Pointer to the APP handle
...@@ -58,7 +190,34 @@ static int ...@@ -58,7 +190,34 @@ static int
nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev, nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
struct tc_cls_flower_offload *flow) struct tc_cls_flower_offload *flow)
{ {
return -EOPNOTSUPP; struct nfp_fl_payload *flow_pay;
struct nfp_fl_key_ls *key_layer;
int err;
key_layer = kmalloc(sizeof(*key_layer), GFP_KERNEL);
if (!key_layer)
return -ENOMEM;
err = nfp_flower_calculate_key_layers(key_layer, flow);
if (err)
goto err_free_key_ls;
flow_pay = nfp_flower_allocate_new(key_layer);
if (!flow_pay) {
err = -ENOMEM;
goto err_free_key_ls;
}
/* TODO: Complete flower_add_offload. */
err = -EOPNOTSUPP;
kfree(flow_pay->mask_data);
kfree(flow_pay->unmasked_data);
kfree(flow_pay);
err_free_key_ls:
kfree(key_layer);
return err;
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment