Commit 58fedcad authored by David S. Miller's avatar David S. Miller

Merge branch 'nfp-flower-fixes-and-typo-in-ethtool-stats-name'

Jakub Kicinski says:

====================
nfp: flower fixes and typo in ethtool stats name

This set comes from the flower offload team.  From Pieter we have a fix
to the semantics of the flag telling FW whether to allocate or free
a mask and correction of a typo in name of one of the MAC statistics
(reveive -> received, we use past participle to match HW docs).

Dirk fixes propagation of max MTU to representors.

John improves VXLAN offload.  The old code was not using egress_dev at
all, so Jiri missed it in his conversion.  The validation of ingress
port is still not perfect, we will have to wait for shared block dust
to settle to tackle it.  This is how John explains the cases:

The following example rule is now correctly offloaded in net-next kernel:

tc filter add dev vxlan0 ... enc_dst_port 4789 ... skip_sw \
  action redirect dev nfp_p0

The following rule will not be offloaded to the NFP (previously it
incorrectly matched vxlan packets - it shouldn't as ingress dev is not
a vxlan netdev):

tc filter add dev nfp_p0 ... enc_dst_port 4789 ... skip_sw \
  action redirect dev nfp_p0

Rules that are not matching on tunnels and are an egress offload are
rejected. The standard match code assumes the offloaded repr is the
ingress port. Rejecting egress offloads removes the chances of false
interpretation of the rules on the NFP.

A know issue is that the following rule example could still be offloaded
and incorrectly match tunnel data:

tc filter add dev dummy ... enc_dst_port 4789 ... skip_sw \
  action redirect dev nfp_p0

Because the egress register callback does not give information on the
ingress netdev, the patch assumes that if it is not a repr then it is
the correct tunnel netdev. This may not be the case. The chances of this
happening is reduced as it is enforced that the rule match on the well
known vxlan port but it is still possible.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a52b04bc 0115552e
...@@ -125,6 +125,21 @@ nfp_flower_repr_netdev_stop(struct nfp_app *app, struct nfp_repr *repr) ...@@ -125,6 +125,21 @@ nfp_flower_repr_netdev_stop(struct nfp_app *app, struct nfp_repr *repr)
return nfp_flower_cmsg_portmod(repr, false); return nfp_flower_cmsg_portmod(repr, false);
} }
static int
nfp_flower_repr_netdev_init(struct nfp_app *app, struct net_device *netdev)
{
return tc_setup_cb_egdev_register(netdev,
nfp_flower_setup_tc_egress_cb,
netdev_priv(netdev));
}
static void
nfp_flower_repr_netdev_clean(struct nfp_app *app, struct net_device *netdev)
{
tc_setup_cb_egdev_unregister(netdev, nfp_flower_setup_tc_egress_cb,
netdev_priv(netdev));
}
static void nfp_flower_sriov_disable(struct nfp_app *app) static void nfp_flower_sriov_disable(struct nfp_app *app)
{ {
struct nfp_flower_priv *priv = app->priv; struct nfp_flower_priv *priv = app->priv;
...@@ -452,6 +467,9 @@ const struct nfp_app_type app_flower = { ...@@ -452,6 +467,9 @@ const struct nfp_app_type app_flower = {
.vnic_init = nfp_flower_vnic_init, .vnic_init = nfp_flower_vnic_init,
.vnic_clean = nfp_flower_vnic_clean, .vnic_clean = nfp_flower_vnic_clean,
.repr_init = nfp_flower_repr_netdev_init,
.repr_clean = nfp_flower_repr_netdev_clean,
.repr_open = nfp_flower_repr_netdev_open, .repr_open = nfp_flower_repr_netdev_open,
.repr_stop = nfp_flower_repr_netdev_stop, .repr_stop = nfp_flower_repr_netdev_stop,
......
...@@ -52,8 +52,7 @@ struct nfp_app; ...@@ -52,8 +52,7 @@ struct nfp_app;
#define NFP_FLOWER_MASK_ELEMENT_RS 1 #define NFP_FLOWER_MASK_ELEMENT_RS 1
#define NFP_FLOWER_MASK_HASH_BITS 10 #define NFP_FLOWER_MASK_HASH_BITS 10
#define NFP_FL_META_FLAG_NEW_MASK 128 #define NFP_FL_META_FLAG_MANAGE_MASK BIT(7)
#define NFP_FL_META_FLAG_LAST_MASK 1
#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
...@@ -197,5 +196,7 @@ void nfp_tunnel_del_ipv4_off(struct nfp_app *app, __be32 ipv4); ...@@ -197,5 +196,7 @@ void nfp_tunnel_del_ipv4_off(struct nfp_app *app, __be32 ipv4);
void nfp_tunnel_add_ipv4_off(struct nfp_app *app, __be32 ipv4); void nfp_tunnel_add_ipv4_off(struct nfp_app *app, __be32 ipv4);
void nfp_tunnel_request_route(struct nfp_app *app, struct sk_buff *skb); void nfp_tunnel_request_route(struct nfp_app *app, struct sk_buff *skb);
void nfp_tunnel_keep_alive(struct nfp_app *app, struct sk_buff *skb); void nfp_tunnel_keep_alive(struct nfp_app *app, struct sk_buff *skb);
int nfp_flower_setup_tc_egress_cb(enum tc_setup_type type, void *type_data,
void *cb_priv);
#endif #endif
...@@ -282,7 +282,7 @@ nfp_check_mask_add(struct nfp_app *app, char *mask_data, u32 mask_len, ...@@ -282,7 +282,7 @@ nfp_check_mask_add(struct nfp_app *app, char *mask_data, u32 mask_len,
id = nfp_add_mask_table(app, mask_data, mask_len); id = nfp_add_mask_table(app, mask_data, mask_len);
if (id < 0) if (id < 0)
return false; return false;
*meta_flags |= NFP_FL_META_FLAG_NEW_MASK; *meta_flags |= NFP_FL_META_FLAG_MANAGE_MASK;
} }
*mask_id = id; *mask_id = id;
...@@ -299,6 +299,9 @@ nfp_check_mask_remove(struct nfp_app *app, char *mask_data, u32 mask_len, ...@@ -299,6 +299,9 @@ nfp_check_mask_remove(struct nfp_app *app, char *mask_data, u32 mask_len,
if (!mask_entry) if (!mask_entry)
return false; return false;
if (meta_flags)
*meta_flags &= ~NFP_FL_META_FLAG_MANAGE_MASK;
*mask_id = mask_entry->mask_id; *mask_id = mask_entry->mask_id;
mask_entry->ref_cnt--; mask_entry->ref_cnt--;
if (!mask_entry->ref_cnt) { if (!mask_entry->ref_cnt) {
...@@ -306,7 +309,7 @@ nfp_check_mask_remove(struct nfp_app *app, char *mask_data, u32 mask_len, ...@@ -306,7 +309,7 @@ nfp_check_mask_remove(struct nfp_app *app, char *mask_data, u32 mask_len,
nfp_release_mask_id(app, *mask_id); nfp_release_mask_id(app, *mask_id);
kfree(mask_entry); kfree(mask_entry);
if (meta_flags) if (meta_flags)
*meta_flags |= NFP_FL_META_FLAG_LAST_MASK; *meta_flags |= NFP_FL_META_FLAG_MANAGE_MASK;
} }
return true; return true;
......
...@@ -131,7 +131,8 @@ static bool nfp_flower_check_higher_than_mac(struct tc_cls_flower_offload *f) ...@@ -131,7 +131,8 @@ static bool nfp_flower_check_higher_than_mac(struct tc_cls_flower_offload *f)
static int static int
nfp_flower_calculate_key_layers(struct nfp_fl_key_ls *ret_key_ls, nfp_flower_calculate_key_layers(struct nfp_fl_key_ls *ret_key_ls,
struct tc_cls_flower_offload *flow) struct tc_cls_flower_offload *flow,
bool egress)
{ {
struct flow_dissector_key_basic *mask_basic = NULL; struct flow_dissector_key_basic *mask_basic = NULL;
struct flow_dissector_key_basic *key_basic = NULL; struct flow_dissector_key_basic *key_basic = NULL;
...@@ -167,6 +168,9 @@ nfp_flower_calculate_key_layers(struct nfp_fl_key_ls *ret_key_ls, ...@@ -167,6 +168,9 @@ nfp_flower_calculate_key_layers(struct nfp_fl_key_ls *ret_key_ls,
skb_flow_dissector_target(flow->dissector, skb_flow_dissector_target(flow->dissector,
FLOW_DISSECTOR_KEY_ENC_CONTROL, FLOW_DISSECTOR_KEY_ENC_CONTROL,
flow->key); flow->key);
if (!egress)
return -EOPNOTSUPP;
if (mask_enc_ctl->addr_type != 0xffff || if (mask_enc_ctl->addr_type != 0xffff ||
enc_ctl->addr_type != FLOW_DISSECTOR_KEY_IPV4_ADDRS) enc_ctl->addr_type != FLOW_DISSECTOR_KEY_IPV4_ADDRS)
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -194,6 +198,9 @@ nfp_flower_calculate_key_layers(struct nfp_fl_key_ls *ret_key_ls, ...@@ -194,6 +198,9 @@ nfp_flower_calculate_key_layers(struct nfp_fl_key_ls *ret_key_ls,
key_layer |= NFP_FLOWER_LAYER_VXLAN; key_layer |= NFP_FLOWER_LAYER_VXLAN;
key_size += sizeof(struct nfp_flower_vxlan); key_size += sizeof(struct nfp_flower_vxlan);
} else if (egress) {
/* Reject non tunnel matches offloaded to egress repr. */
return -EOPNOTSUPP;
} }
if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_BASIC)) { if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
...@@ -315,7 +322,7 @@ nfp_flower_allocate_new(struct nfp_fl_key_ls *key_layer) ...@@ -315,7 +322,7 @@ nfp_flower_allocate_new(struct nfp_fl_key_ls *key_layer)
*/ */
static int 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, bool egress)
{ {
struct nfp_flower_priv *priv = app->priv; struct nfp_flower_priv *priv = app->priv;
struct nfp_fl_payload *flow_pay; struct nfp_fl_payload *flow_pay;
...@@ -326,7 +333,7 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev, ...@@ -326,7 +333,7 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
if (!key_layer) if (!key_layer)
return -ENOMEM; return -ENOMEM;
err = nfp_flower_calculate_key_layers(key_layer, flow); err = nfp_flower_calculate_key_layers(key_layer, flow, egress);
if (err) if (err)
goto err_free_key_ls; goto err_free_key_ls;
...@@ -447,7 +454,7 @@ nfp_flower_get_stats(struct nfp_app *app, struct tc_cls_flower_offload *flow) ...@@ -447,7 +454,7 @@ nfp_flower_get_stats(struct nfp_app *app, struct tc_cls_flower_offload *flow)
static int static int
nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev, nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev,
struct tc_cls_flower_offload *flower) struct tc_cls_flower_offload *flower, bool egress)
{ {
if (!eth_proto_is_802_3(flower->common.protocol) || if (!eth_proto_is_802_3(flower->common.protocol) ||
flower->common.chain_index) flower->common.chain_index)
...@@ -455,7 +462,7 @@ nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev, ...@@ -455,7 +462,7 @@ nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev,
switch (flower->command) { switch (flower->command) {
case TC_CLSFLOWER_REPLACE: case TC_CLSFLOWER_REPLACE:
return nfp_flower_add_offload(app, netdev, flower); return nfp_flower_add_offload(app, netdev, flower, egress);
case TC_CLSFLOWER_DESTROY: case TC_CLSFLOWER_DESTROY:
return nfp_flower_del_offload(app, netdev, flower); return nfp_flower_del_offload(app, netdev, flower);
case TC_CLSFLOWER_STATS: case TC_CLSFLOWER_STATS:
...@@ -465,6 +472,23 @@ nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev, ...@@ -465,6 +472,23 @@ nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
int nfp_flower_setup_tc_egress_cb(enum tc_setup_type type, void *type_data,
void *cb_priv)
{
struct nfp_repr *repr = cb_priv;
if (!tc_can_offload(repr->netdev))
return -EOPNOTSUPP;
switch (type) {
case TC_SETUP_CLSFLOWER:
return nfp_flower_repr_offload(repr->app, repr->netdev,
type_data, true);
default:
return -EOPNOTSUPP;
}
}
static int nfp_flower_setup_tc_block_cb(enum tc_setup_type type, static int nfp_flower_setup_tc_block_cb(enum tc_setup_type type,
void *type_data, void *cb_priv) void *type_data, void *cb_priv)
{ {
...@@ -476,7 +500,7 @@ static int nfp_flower_setup_tc_block_cb(enum tc_setup_type type, ...@@ -476,7 +500,7 @@ static int nfp_flower_setup_tc_block_cb(enum tc_setup_type type,
switch (type) { switch (type) {
case TC_SETUP_CLSFLOWER: case TC_SETUP_CLSFLOWER:
return nfp_flower_repr_offload(repr->app, repr->netdev, return nfp_flower_repr_offload(repr->app, repr->netdev,
type_data); type_data, false);
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
...@@ -76,6 +76,8 @@ extern const struct nfp_app_type app_flower; ...@@ -76,6 +76,8 @@ extern const struct nfp_app_type app_flower;
* @vnic_free: free up app's vNIC state * @vnic_free: free up app's vNIC state
* @vnic_init: vNIC netdev was registered * @vnic_init: vNIC netdev was registered
* @vnic_clean: vNIC netdev about to be unregistered * @vnic_clean: vNIC netdev about to be unregistered
* @repr_init: representor about to be registered
* @repr_clean: representor about to be unregistered
* @repr_open: representor netdev open callback * @repr_open: representor netdev open callback
* @repr_stop: representor netdev stop callback * @repr_stop: representor netdev stop callback
* @start: start application logic * @start: start application logic
...@@ -109,6 +111,9 @@ struct nfp_app_type { ...@@ -109,6 +111,9 @@ struct nfp_app_type {
int (*vnic_init)(struct nfp_app *app, struct nfp_net *nn); int (*vnic_init)(struct nfp_app *app, struct nfp_net *nn);
void (*vnic_clean)(struct nfp_app *app, struct nfp_net *nn); void (*vnic_clean)(struct nfp_app *app, struct nfp_net *nn);
int (*repr_init)(struct nfp_app *app, struct net_device *netdev);
void (*repr_clean)(struct nfp_app *app, struct net_device *netdev);
int (*repr_open)(struct nfp_app *app, struct nfp_repr *repr); int (*repr_open)(struct nfp_app *app, struct nfp_repr *repr);
int (*repr_stop)(struct nfp_app *app, struct nfp_repr *repr); int (*repr_stop)(struct nfp_app *app, struct nfp_repr *repr);
...@@ -212,6 +217,21 @@ static inline int nfp_app_repr_stop(struct nfp_app *app, struct nfp_repr *repr) ...@@ -212,6 +217,21 @@ static inline int nfp_app_repr_stop(struct nfp_app *app, struct nfp_repr *repr)
return app->type->repr_stop(app, repr); return app->type->repr_stop(app, repr);
} }
static inline int
nfp_app_repr_init(struct nfp_app *app, struct net_device *netdev)
{
if (!app->type->repr_init)
return 0;
return app->type->repr_init(app, netdev);
}
static inline void
nfp_app_repr_clean(struct nfp_app *app, struct net_device *netdev)
{
if (app->type->repr_clean)
app->type->repr_clean(app, netdev);
}
static inline int nfp_app_start(struct nfp_app *app, struct nfp_net *ctrl) static inline int nfp_app_start(struct nfp_app *app, struct nfp_net *ctrl)
{ {
app->ctrl = ctrl; app->ctrl = ctrl;
......
...@@ -104,7 +104,7 @@ static const struct nfp_et_stat nfp_mac_et_stats[] = { ...@@ -104,7 +104,7 @@ static const struct nfp_et_stat nfp_mac_et_stats[] = {
{ "rx_frame_too_long_errors", { "rx_frame_too_long_errors",
NFP_MAC_STATS_RX_FRAME_TOO_LONG_ERRORS, }, NFP_MAC_STATS_RX_FRAME_TOO_LONG_ERRORS, },
{ "rx_range_length_errors", NFP_MAC_STATS_RX_RANGE_LENGTH_ERRORS, }, { "rx_range_length_errors", NFP_MAC_STATS_RX_RANGE_LENGTH_ERRORS, },
{ "rx_vlan_reveive_ok", NFP_MAC_STATS_RX_VLAN_REVEIVE_OK, }, { "rx_vlan_received_ok", NFP_MAC_STATS_RX_VLAN_RECEIVED_OK, },
{ "rx_errors", NFP_MAC_STATS_RX_IN_ERRORS, }, { "rx_errors", NFP_MAC_STATS_RX_IN_ERRORS, },
{ "rx_broadcast_pkts", NFP_MAC_STATS_RX_IN_BROADCAST_PKTS, }, { "rx_broadcast_pkts", NFP_MAC_STATS_RX_IN_BROADCAST_PKTS, },
{ "rx_drop_events", NFP_MAC_STATS_RX_DROP_EVENTS, }, { "rx_drop_events", NFP_MAC_STATS_RX_DROP_EVENTS, },
......
...@@ -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 = {
static void nfp_repr_clean(struct nfp_repr *repr) static void nfp_repr_clean(struct nfp_repr *repr)
{ {
unregister_netdev(repr->netdev); unregister_netdev(repr->netdev);
nfp_app_repr_clean(repr->app, repr->netdev);
dst_release((struct dst_entry *)repr->dst); dst_release((struct dst_entry *)repr->dst);
nfp_port_free(repr->port); nfp_port_free(repr->port);
} }
...@@ -297,6 +298,8 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev, ...@@ -297,6 +298,8 @@ 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;
netdev->ethtool_ops = &nfp_port_ethtool_ops; netdev->ethtool_ops = &nfp_port_ethtool_ops;
netdev->max_mtu = pf_netdev->max_mtu;
SWITCHDEV_SET_OPS(netdev, &nfp_port_switchdev_ops); SWITCHDEV_SET_OPS(netdev, &nfp_port_switchdev_ops);
if (nfp_app_has_tc(app)) { if (nfp_app_has_tc(app)) {
...@@ -304,12 +307,18 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev, ...@@ -304,12 +307,18 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
netdev->hw_features |= NETIF_F_HW_TC; netdev->hw_features |= NETIF_F_HW_TC;
} }
err = register_netdev(netdev); err = nfp_app_repr_init(app, netdev);
if (err) if (err)
goto err_clean; goto err_clean;
err = register_netdev(netdev);
if (err)
goto err_repr_clean;
return 0; return 0;
err_repr_clean:
nfp_app_repr_clean(app, netdev);
err_clean: err_clean:
dst_release((struct dst_entry *)repr->dst); dst_release((struct dst_entry *)repr->dst);
return err; return err;
......
...@@ -157,7 +157,7 @@ void nfp_devlink_port_unregister(struct nfp_port *port); ...@@ -157,7 +157,7 @@ void nfp_devlink_port_unregister(struct nfp_port *port);
/* unused 0x008 */ /* unused 0x008 */
#define NFP_MAC_STATS_RX_FRAME_TOO_LONG_ERRORS (NFP_MAC_STATS_BASE + 0x010) #define NFP_MAC_STATS_RX_FRAME_TOO_LONG_ERRORS (NFP_MAC_STATS_BASE + 0x010)
#define NFP_MAC_STATS_RX_RANGE_LENGTH_ERRORS (NFP_MAC_STATS_BASE + 0x018) #define NFP_MAC_STATS_RX_RANGE_LENGTH_ERRORS (NFP_MAC_STATS_BASE + 0x018)
#define NFP_MAC_STATS_RX_VLAN_REVEIVE_OK (NFP_MAC_STATS_BASE + 0x020) #define NFP_MAC_STATS_RX_VLAN_RECEIVED_OK (NFP_MAC_STATS_BASE + 0x020)
#define NFP_MAC_STATS_RX_IN_ERRORS (NFP_MAC_STATS_BASE + 0x028) #define NFP_MAC_STATS_RX_IN_ERRORS (NFP_MAC_STATS_BASE + 0x028)
#define NFP_MAC_STATS_RX_IN_BROADCAST_PKTS (NFP_MAC_STATS_BASE + 0x030) #define NFP_MAC_STATS_RX_IN_BROADCAST_PKTS (NFP_MAC_STATS_BASE + 0x030)
#define NFP_MAC_STATS_RX_DROP_EVENTS (NFP_MAC_STATS_BASE + 0x038) #define NFP_MAC_STATS_RX_DROP_EVENTS (NFP_MAC_STATS_BASE + 0x038)
......
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