Skip to content

Commit

Permalink
Merge branch 'nfp-flower-add-Geneve-tunnel-support'
Browse files Browse the repository at this point in the history
Simon Horman says:

====================
nfp: flower: add Geneve tunnel support

John Hurley says:

This patchset adds support for offloading the encap and decap of Geneve
tunnels to the NFP. In both cases, specifying well known port 6081 is a
requirement for rule offload.

Geneve firmware support has been recently added, so the patchset includes
the reading of a fw symbol that defines a bitmap of newly supported
features. Geneve will only be offloaded if the fw supports it. The new
symbol is added in fw r5646.

Geneve option fields are not supported as either a match or an action due
there current exclussion from TC flower. Because Geneve (as both a match
and action) behaves the same as other udp tunnels such as VXLAN, generic
functions are created that handle both Geneve and VXLAN. It is anticapated
that these functions will be modified to support options in future
patches.

The removal of an unused variable 'tun_dst_mask' is included as a separate
patch here. This does not affect functionality.

Also included are modifications to the test framework to check that the
new encap and decap features are functioning correctly.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Dec 19, 2017
2 parents f988008 + 3ca3059 commit f39a5c0
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 82 deletions.
75 changes: 44 additions & 31 deletions drivers/net/ethernet/netronome/nfp/flower/action.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ static bool nfp_fl_netdev_is_tunnel_type(struct net_device *out_dev,
if (!strcmp(out_dev->rtnl_link_ops->kind, "vxlan"))
return tun_type == NFP_FL_TUNNEL_VXLAN;

if (!strcmp(out_dev->rtnl_link_ops->kind, "geneve"))
return tun_type == NFP_FL_TUNNEL_GENEVE;

return false;
}

Expand Down Expand Up @@ -136,11 +139,23 @@ nfp_fl_output(struct nfp_fl_output *output, const struct tc_action *action,
return 0;
}

static bool nfp_fl_supported_tun_port(const struct tc_action *action)
static enum nfp_flower_tun_type
nfp_fl_get_tun_from_act_l4_port(struct nfp_app *app,
const struct tc_action *action)
{
struct ip_tunnel_info *tun = tcf_tunnel_info(action);

return tun->key.tp_dst == htons(NFP_FL_VXLAN_PORT);
struct nfp_flower_priv *priv = app->priv;

switch (tun->key.tp_dst) {
case htons(NFP_FL_VXLAN_PORT):
return NFP_FL_TUNNEL_VXLAN;
case htons(NFP_FL_GENEVE_PORT):
if (priv->flower_ext_feats & NFP_FL_FEATS_GENEVE)
return NFP_FL_TUNNEL_GENEVE;
/* FALLTHROUGH */
default:
return NFP_FL_TUNNEL_NONE;
}
}

static struct nfp_fl_pre_tunnel *nfp_fl_pre_tunnel(char *act_data, int act_len)
Expand All @@ -165,38 +180,33 @@ static struct nfp_fl_pre_tunnel *nfp_fl_pre_tunnel(char *act_data, int act_len)
}

static int
nfp_fl_set_vxlan(struct nfp_fl_set_vxlan *set_vxlan,
const struct tc_action *action,
struct nfp_fl_pre_tunnel *pre_tun)
nfp_fl_set_ipv4_udp_tun(struct nfp_fl_set_ipv4_udp_tun *set_tun,
const struct tc_action *action,
struct nfp_fl_pre_tunnel *pre_tun,
enum nfp_flower_tun_type tun_type)
{
struct ip_tunnel_info *vxlan = tcf_tunnel_info(action);
size_t act_size = sizeof(struct nfp_fl_set_vxlan);
u32 tmp_set_vxlan_type_index = 0;
size_t act_size = sizeof(struct nfp_fl_set_ipv4_udp_tun);
struct ip_tunnel_info *ip_tun = tcf_tunnel_info(action);
u32 tmp_set_ip_tun_type_index = 0;
/* Currently support one pre-tunnel so index is always 0. */
int pretun_idx = 0;

if (vxlan->options_len) {
/* Do not support options e.g. vxlan gpe. */
if (ip_tun->options_len)
return -EOPNOTSUPP;
}

set_vxlan->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL;
set_vxlan->head.len_lw = act_size >> NFP_FL_LW_SIZ;
set_tun->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL;
set_tun->head.len_lw = act_size >> NFP_FL_LW_SIZ;

/* Set tunnel type and pre-tunnel index. */
tmp_set_vxlan_type_index |=
FIELD_PREP(NFP_FL_IPV4_TUNNEL_TYPE, NFP_FL_TUNNEL_VXLAN) |
tmp_set_ip_tun_type_index |=
FIELD_PREP(NFP_FL_IPV4_TUNNEL_TYPE, tun_type) |
FIELD_PREP(NFP_FL_IPV4_PRE_TUN_INDEX, pretun_idx);

set_vxlan->tun_type_index = cpu_to_be32(tmp_set_vxlan_type_index);

set_vxlan->tun_id = vxlan->key.tun_id;
set_vxlan->tun_flags = vxlan->key.tun_flags;
set_vxlan->ipv4_ttl = vxlan->key.ttl;
set_vxlan->ipv4_tos = vxlan->key.tos;
set_tun->tun_type_index = cpu_to_be32(tmp_set_ip_tun_type_index);
set_tun->tun_id = ip_tun->key.tun_id;

/* Complete pre_tunnel action. */
pre_tun->ipv4_dst = vxlan->key.u.ipv4.dst;
pre_tun->ipv4_dst = ip_tun->key.u.ipv4.dst;

return 0;
}
Expand Down Expand Up @@ -433,8 +443,8 @@ nfp_flower_loop_action(const struct tc_action *a,
struct net_device *netdev,
enum nfp_flower_tun_type *tun_type, int *tun_out_cnt)
{
struct nfp_fl_set_ipv4_udp_tun *set_tun;
struct nfp_fl_pre_tunnel *pre_tun;
struct nfp_fl_set_vxlan *s_vxl;
struct nfp_fl_push_vlan *psh_v;
struct nfp_fl_pop_vlan *pop_v;
struct nfp_fl_output *output;
Expand Down Expand Up @@ -482,26 +492,29 @@ nfp_flower_loop_action(const struct tc_action *a,

nfp_fl_push_vlan(psh_v, a);
*a_len += sizeof(struct nfp_fl_push_vlan);
} else if (is_tcf_tunnel_set(a) && nfp_fl_supported_tun_port(a)) {
} else if (is_tcf_tunnel_set(a)) {
struct nfp_repr *repr = netdev_priv(netdev);
*tun_type = nfp_fl_get_tun_from_act_l4_port(repr->app, a);
if (*tun_type == NFP_FL_TUNNEL_NONE)
return -EOPNOTSUPP;

/* Pre-tunnel action is required for tunnel encap.
* This checks for next hop entries on NFP.
* If none, the packet falls back before applying other actions.
*/
if (*a_len + sizeof(struct nfp_fl_pre_tunnel) +
sizeof(struct nfp_fl_set_vxlan) > NFP_FL_MAX_A_SIZ)
sizeof(struct nfp_fl_set_ipv4_udp_tun) > NFP_FL_MAX_A_SIZ)
return -EOPNOTSUPP;

*tun_type = NFP_FL_TUNNEL_VXLAN;
pre_tun = nfp_fl_pre_tunnel(nfp_fl->action_data, *a_len);
nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL);
*a_len += sizeof(struct nfp_fl_pre_tunnel);

s_vxl = (struct nfp_fl_set_vxlan *)&nfp_fl->action_data[*a_len];
err = nfp_fl_set_vxlan(s_vxl, a, pre_tun);
set_tun = (void *)&nfp_fl->action_data[*a_len];
err = nfp_fl_set_ipv4_udp_tun(set_tun, a, pre_tun, *tun_type);
if (err)
return err;

*a_len += sizeof(struct nfp_fl_set_vxlan);
*a_len += sizeof(struct nfp_fl_set_ipv4_udp_tun);
} else if (is_tcf_tunnel_release(a)) {
/* Tunnel decap is handled by default so accept action. */
return 0;
Expand Down
43 changes: 25 additions & 18 deletions drivers/net/ethernet/netronome/nfp/flower/cmsg.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
#include "../nfp_app.h"
#include "../nfpcore/nfp_cpp.h"

#define NFP_FLOWER_LAYER_META BIT(0)
#define NFP_FLOWER_LAYER_EXT_META BIT(0)
#define NFP_FLOWER_LAYER_PORT BIT(1)
#define NFP_FLOWER_LAYER_MAC BIT(2)
#define NFP_FLOWER_LAYER_TP BIT(3)
Expand All @@ -50,6 +50,8 @@
#define NFP_FLOWER_LAYER_CT BIT(6)
#define NFP_FLOWER_LAYER_VXLAN BIT(7)

#define NFP_FLOWER_LAYER2_GENEVE BIT(5)

#define NFP_FLOWER_MASK_VLAN_PRIO GENMASK(15, 13)
#define NFP_FLOWER_MASK_VLAN_CFI BIT(12)
#define NFP_FLOWER_MASK_VLAN_VID GENMASK(11, 0)
Expand Down Expand Up @@ -105,6 +107,7 @@
enum nfp_flower_tun_type {
NFP_FL_TUNNEL_NONE = 0,
NFP_FL_TUNNEL_VXLAN = 2,
NFP_FL_TUNNEL_GENEVE = 4,
};

struct nfp_fl_act_head {
Expand Down Expand Up @@ -170,16 +173,13 @@ struct nfp_fl_pre_tunnel {
__be32 extra[3];
};

struct nfp_fl_set_vxlan {
struct nfp_fl_set_ipv4_udp_tun {
struct nfp_fl_act_head head;
__be16 reserved;
__be64 tun_id;
__be64 tun_id __packed;
__be32 tun_type_index;
__be16 tun_flags;
u8 ipv4_ttl;
u8 ipv4_tos;
__be32 extra[2];
} __packed;
__be32 extra[3];
};

/* Metadata with L2 (1W/4B)
* ----------------------------------------------------------------
Expand All @@ -198,6 +198,18 @@ struct nfp_flower_meta_tci {
__be16 tci;
};

/* Extended metadata for additional key_layers (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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | nfp_flow_key_layer2 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct nfp_flower_ext_meta {
__be32 nfp_flow_key_layer2;
};

/* Port details (1W/4B)
* ----------------------------------------------------------------
* 3 2 1
Expand Down Expand Up @@ -296,7 +308,7 @@ struct nfp_flower_ipv6 {
struct in6_addr ipv6_dst;
};

/* Flow Frame VXLAN --> Tunnel details (4W/16B)
/* Flow Frame IPv4 UDP TUNNEL --> 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
Expand All @@ -305,22 +317,17 @@ struct nfp_flower_ipv6 {
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ipv4_addr_dst |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | tun_flags | tos | ttl |
* | Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | gpe_flags | Reserved | Next Protocol |
* | Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | VNI | Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct nfp_flower_vxlan {
struct nfp_flower_ipv4_udp_tun {
__be32 ip_src;
__be32 ip_dst;
__be16 tun_flags;
u8 tos;
u8 ttl;
u8 gpe_flags;
u8 reserved[2];
u8 nxt_proto;
__be32 reserved[2];
__be32 tun_id;
};

Expand Down
10 changes: 9 additions & 1 deletion drivers/net/ethernet/netronome/nfp/flower/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ static int nfp_flower_init(struct nfp_app *app)
{
const struct nfp_pf *pf = app->pf;
struct nfp_flower_priv *app_priv;
u64 version;
u64 version, features;
int err;

if (!pf->eth_tbl) {
Expand Down Expand Up @@ -424,6 +424,14 @@ static int nfp_flower_init(struct nfp_app *app)
if (err)
goto err_free_app_priv;

/* Extract the extra features supported by the firmware. */
features = nfp_rtsym_read_le(app->pf->rtbl,
"_abi_flower_extra_features", &err);
if (err)
app_priv->flower_ext_feats = 0;
else
app_priv->flower_ext_feats = features;

return 0;

err_free_app_priv:
Expand Down
11 changes: 10 additions & 1 deletion drivers/net/ethernet/netronome/nfp/flower/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
#ifndef __NFP_FLOWER_H__
#define __NFP_FLOWER_H__ 1

#include "cmsg.h"

#include <linux/circ_buf.h>
#include <linux/hashtable.h>
#include <linux/time64.h>
Expand All @@ -58,6 +60,10 @@ struct nfp_app;
#define NFP_FL_MASK_ID_LOCATION 1

#define NFP_FL_VXLAN_PORT 4789
#define NFP_FL_GENEVE_PORT 6081

/* Extra features bitmap. */
#define NFP_FL_FEATS_GENEVE BIT(0)

struct nfp_fl_mask_id {
struct circ_buf mask_id_free_list;
Expand All @@ -77,6 +83,7 @@ struct nfp_fl_stats_id {
* @nn: Pointer to vNIC
* @mask_id_seed: Seed used for mask hash table
* @flower_version: HW version of flower
* @flower_ext_feats: Bitmap of extra features the HW supports
* @stats_ids: List of free stats ids
* @mask_ids: List of free mask ids
* @mask_table: Hash table used to store masks
Expand All @@ -101,6 +108,7 @@ struct nfp_flower_priv {
struct nfp_net *nn;
u32 mask_id_seed;
u64 flower_version;
u64 flower_ext_feats;
struct nfp_fl_stats_id stats_ids;
struct nfp_fl_mask_id mask_ids;
DECLARE_HASHTABLE(mask_table, NFP_FLOWER_MASK_HASH_BITS);
Expand Down Expand Up @@ -172,7 +180,8 @@ int nfp_flower_setup_tc(struct nfp_app *app, struct net_device *netdev,
int nfp_flower_compile_flow_match(struct tc_cls_flower_offload *flow,
struct nfp_fl_key_ls *key_ls,
struct net_device *netdev,
struct nfp_fl_payload *nfp_flow);
struct nfp_fl_payload *nfp_flow,
enum nfp_flower_tun_type tun_type);
int nfp_flower_compile_action(struct tc_cls_flower_offload *flow,
struct net_device *netdev,
struct nfp_fl_payload *nfp_flow);
Expand Down
Loading

0 comments on commit f39a5c0

Please sign in to comment.