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

nfp: provide infrastructure for offloading flower based TC filters

Adds a flower based TC offload handler for representor devices, this
is in addition to the bpf based offload handler. The changes in this
patch will be used in a follow-up patch to add tc flower offload to
the NFP.

The flower app enables tc offloads on representors by default.
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 8f15df60
...@@ -32,7 +32,8 @@ nfp-objs := \ ...@@ -32,7 +32,8 @@ nfp-objs := \
ifeq ($(CONFIG_NFP_APP_FLOWER),y) ifeq ($(CONFIG_NFP_APP_FLOWER),y)
nfp-objs += \ nfp-objs += \
flower/cmsg.o \ flower/cmsg.o \
flower/main.o flower/main.o \
flower/offload.o
endif endif
ifeq ($(CONFIG_BPF_SYSCALL),y) ifeq ($(CONFIG_BPF_SYSCALL),y)
......
...@@ -37,7 +37,9 @@ ...@@ -37,7 +37,9 @@
#include <net/devlink.h> #include <net/devlink.h>
#include <net/dst_metadata.h> #include <net/dst_metadata.h>
#include "main.h"
#include "../nfpcore/nfp_cpp.h" #include "../nfpcore/nfp_cpp.h"
#include "../nfpcore/nfp_nffw.h"
#include "../nfpcore/nfp_nsp.h" #include "../nfpcore/nfp_nsp.h"
#include "../nfp_app.h" #include "../nfp_app.h"
#include "../nfp_main.h" #include "../nfp_main.h"
...@@ -46,6 +48,8 @@ ...@@ -46,6 +48,8 @@
#include "../nfp_port.h" #include "../nfp_port.h"
#include "./cmsg.h" #include "./cmsg.h"
#define NFP_FLOWER_ALLOWED_VER 0x0001000000010000UL
/** /**
* struct nfp_flower_priv - Flower APP per-vNIC priv data * struct nfp_flower_priv - Flower APP per-vNIC priv data
* @nn: Pointer to vNIC * @nn: Pointer to vNIC
...@@ -313,6 +317,8 @@ static int nfp_flower_vnic_init(struct nfp_app *app, struct nfp_net *nn, ...@@ -313,6 +317,8 @@ static int nfp_flower_vnic_init(struct nfp_app *app, struct nfp_net *nn,
static int nfp_flower_init(struct nfp_app *app) static int nfp_flower_init(struct nfp_app *app)
{ {
const struct nfp_pf *pf = app->pf; const struct nfp_pf *pf = app->pf;
u64 version;
int err;
if (!pf->eth_tbl) { if (!pf->eth_tbl) {
nfp_warn(app->cpp, "FlowerNIC requires eth table\n"); nfp_warn(app->cpp, "FlowerNIC requires eth table\n");
...@@ -329,6 +335,18 @@ static int nfp_flower_init(struct nfp_app *app) ...@@ -329,6 +335,18 @@ static int nfp_flower_init(struct nfp_app *app)
return -EINVAL; return -EINVAL;
} }
version = nfp_rtsym_read_le(app->pf->rtbl, "hw_flower_version", &err);
if (err) {
nfp_warn(app->cpp, "FlowerNIC requires hw_flower_version memory symbol\n");
return err;
}
/* We need to ensure hardware has enough flower capabilities. */
if (version != NFP_FLOWER_ALLOWED_VER) {
nfp_warn(app->cpp, "FlowerNIC: unsupported firmware version\n");
return -EINVAL;
}
app->priv = kzalloc(sizeof(struct nfp_flower_priv), GFP_KERNEL); app->priv = kzalloc(sizeof(struct nfp_flower_priv), GFP_KERNEL);
if (!app->priv) if (!app->priv)
return -ENOMEM; return -ENOMEM;
...@@ -367,4 +385,6 @@ const struct nfp_app_type app_flower = { ...@@ -367,4 +385,6 @@ const struct nfp_app_type app_flower = {
.eswitch_mode_get = eswitch_mode_get, .eswitch_mode_get = eswitch_mode_get,
.repr_get = nfp_flower_repr_get, .repr_get = nfp_flower_repr_get,
.setup_tc = nfp_flower_setup_tc,
}; };
/*
* Copyright (C) 2017 Netronome Systems, Inc.
*
* This software is dual licensed under the GNU General License Version 2,
* June 1991 as shown in the file COPYING in the top-level directory of this
* source tree or the BSD 2-Clause License provided below. You have the
* option to license this software under the complete terms of either license.
*
* The BSD 2-Clause License:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __NFP_FLOWER_H__
#define __NFP_FLOWER_H__ 1
#include <linux/types.h>
struct tc_to_netdev;
struct net_device;
struct nfp_app;
int nfp_flower_setup_tc(struct nfp_app *app, struct net_device *netdev,
u32 handle, __be16 proto, struct tc_to_netdev *tc);
#endif
/*
* Copyright (C) 2017 Netronome Systems, Inc.
*
* This software is dual licensed under the GNU General License Version 2,
* June 1991 as shown in the file COPYING in the top-level directory of this
* source tree or the BSD 2-Clause License provided below. You have the
* option to license this software under the complete terms of either license.
*
* The BSD 2-Clause License:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <linux/skbuff.h>
#include <net/devlink.h>
#include <net/pkt_cls.h>
#include "cmsg.h"
#include "main.h"
#include "../nfpcore/nfp_cpp.h"
#include "../nfpcore/nfp_nsp.h"
#include "../nfp_app.h"
#include "../nfp_main.h"
#include "../nfp_net.h"
#include "../nfp_port.h"
/**
* nfp_flower_add_offload() - Adds a new flow to hardware.
* @app: Pointer to the APP handle
* @netdev: netdev structure.
* @flow: TC flower classifier offload structure.
*
* Adds a new flow to the repeated hash structure and action payload.
*
* Return: negative value on error, 0 if configured successfully.
*/
static int
nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
struct tc_cls_flower_offload *flow)
{
return -EOPNOTSUPP;
}
/**
* nfp_flower_del_offload() - Removes a flow from hardware.
* @app: Pointer to the APP handle
* @netdev: netdev structure.
* @flow: TC flower classifier offload structure
*
* Removes a flow from the repeated hash structure and clears the
* action payload.
*
* Return: negative value on error, 0 if removed successfully.
*/
static int
nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
struct tc_cls_flower_offload *flow)
{
return -EOPNOTSUPP;
}
/**
* nfp_flower_get_stats() - Populates flow stats obtained from hardware.
* @app: Pointer to the APP handle
* @flow: TC flower classifier offload structure
*
* Populates a flow statistics structure which which corresponds to a
* specific flow.
*
* Return: negative value on error, 0 if stats populated successfully.
*/
static int
nfp_flower_get_stats(struct nfp_app *app, struct tc_cls_flower_offload *flow)
{
return -EOPNOTSUPP;
}
static int
nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev,
struct tc_cls_flower_offload *flower)
{
switch (flower->command) {
case TC_CLSFLOWER_REPLACE:
return nfp_flower_add_offload(app, netdev, flower);
case TC_CLSFLOWER_DESTROY:
return nfp_flower_del_offload(app, netdev, flower);
case TC_CLSFLOWER_STATS:
return nfp_flower_get_stats(app, flower);
}
return -EOPNOTSUPP;
}
int nfp_flower_setup_tc(struct nfp_app *app, struct net_device *netdev,
u32 handle, __be16 proto, struct tc_to_netdev *tc)
{
if (TC_H_MAJ(handle) != TC_H_MAJ(TC_H_INGRESS))
return -EOPNOTSUPP;
if (!eth_proto_is_802_3(proto))
return -EOPNOTSUPP;
if (tc->type != TC_SETUP_CLSFLOWER)
return -EINVAL;
return nfp_flower_repr_offload(app, netdev, tc->cls_flower);
}
...@@ -3097,18 +3097,6 @@ static void nfp_net_stat64(struct net_device *netdev, ...@@ -3097,18 +3097,6 @@ static void nfp_net_stat64(struct net_device *netdev,
} }
} }
static int
nfp_net_setup_tc(struct net_device *netdev, u32 handle, u32 chain_index,
__be16 proto, struct tc_to_netdev *tc)
{
struct nfp_net *nn = netdev_priv(netdev);
if (chain_index)
return -EOPNOTSUPP;
return nfp_app_setup_tc(nn->app, netdev, handle, proto, tc);
}
static int nfp_net_set_features(struct net_device *netdev, static int nfp_net_set_features(struct net_device *netdev,
netdev_features_t features) netdev_features_t features)
{ {
...@@ -3424,7 +3412,7 @@ const struct net_device_ops nfp_net_netdev_ops = { ...@@ -3424,7 +3412,7 @@ const struct net_device_ops nfp_net_netdev_ops = {
.ndo_get_stats64 = nfp_net_stat64, .ndo_get_stats64 = nfp_net_stat64,
.ndo_vlan_rx_add_vid = nfp_net_vlan_rx_add_vid, .ndo_vlan_rx_add_vid = nfp_net_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = nfp_net_vlan_rx_kill_vid, .ndo_vlan_rx_kill_vid = nfp_net_vlan_rx_kill_vid,
.ndo_setup_tc = nfp_net_setup_tc, .ndo_setup_tc = nfp_port_setup_tc,
.ndo_tx_timeout = nfp_net_tx_timeout, .ndo_tx_timeout = nfp_net_tx_timeout,
.ndo_set_rx_mode = nfp_net_set_rx_mode, .ndo_set_rx_mode = nfp_net_set_rx_mode,
.ndo_change_mtu = nfp_net_change_mtu, .ndo_change_mtu = nfp_net_change_mtu,
......
...@@ -258,6 +258,7 @@ const struct net_device_ops nfp_repr_netdev_ops = { ...@@ -258,6 +258,7 @@ const struct net_device_ops nfp_repr_netdev_ops = {
.ndo_has_offload_stats = nfp_repr_has_offload_stats, .ndo_has_offload_stats = nfp_repr_has_offload_stats,
.ndo_get_offload_stats = nfp_repr_get_offload_stats, .ndo_get_offload_stats = nfp_repr_get_offload_stats,
.ndo_get_phys_port_name = nfp_port_get_phys_port_name, .ndo_get_phys_port_name = nfp_port_get_phys_port_name,
.ndo_setup_tc = nfp_port_setup_tc,
}; };
static void nfp_repr_clean(struct nfp_repr *repr) static void nfp_repr_clean(struct nfp_repr *repr)
...@@ -302,6 +303,11 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev, ...@@ -302,6 +303,11 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
netdev->netdev_ops = &nfp_repr_netdev_ops; netdev->netdev_ops = &nfp_repr_netdev_ops;
SWITCHDEV_SET_OPS(netdev, &nfp_port_switchdev_ops); SWITCHDEV_SET_OPS(netdev, &nfp_port_switchdev_ops);
if (nfp_app_has_tc(app)) {
netdev->features |= NETIF_F_HW_TC;
netdev->hw_features |= NETIF_F_HW_TC;
}
err = register_netdev(netdev); err = register_netdev(netdev);
if (err) if (err)
goto err_clean; goto err_clean;
......
...@@ -88,6 +88,21 @@ const struct switchdev_ops nfp_port_switchdev_ops = { ...@@ -88,6 +88,21 @@ const struct switchdev_ops nfp_port_switchdev_ops = {
.switchdev_port_attr_get = nfp_port_attr_get, .switchdev_port_attr_get = nfp_port_attr_get,
}; };
int nfp_port_setup_tc(struct net_device *netdev, u32 handle, u32 chain_index,
__be16 proto, struct tc_to_netdev *tc)
{
struct nfp_port *port;
if (chain_index)
return -EOPNOTSUPP;
port = nfp_port_from_netdev(netdev);
if (!port)
return -EOPNOTSUPP;
return nfp_app_setup_tc(port->app, netdev, handle, proto, tc);
}
struct nfp_port * struct nfp_port *
nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id) nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id)
{ {
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <net/devlink.h> #include <net/devlink.h>
struct tc_to_netdev;
struct net_device; struct net_device;
struct nfp_app; struct nfp_app;
struct nfp_pf; struct nfp_pf;
...@@ -108,6 +109,9 @@ struct nfp_port { ...@@ -108,6 +109,9 @@ struct nfp_port {
extern const struct switchdev_ops nfp_port_switchdev_ops; extern const struct switchdev_ops nfp_port_switchdev_ops;
int nfp_port_setup_tc(struct net_device *netdev, u32 handle, u32 chain_index,
__be16 proto, struct tc_to_netdev *tc);
struct nfp_port *nfp_port_from_netdev(struct net_device *netdev); struct nfp_port *nfp_port_from_netdev(struct net_device *netdev);
struct nfp_port * struct nfp_port *
nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id); nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id);
......
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