Skip to content

Commit

Permalink
Merge branch 'offloading-tc-rules-hw'
Browse files Browse the repository at this point in the history
Hadar Hen Zion says:

====================
Offloading tc rules using underline Hardware device

This series adds flower classifier support in offloading tc rules when the
Software ingress device is different from the Hardware ingress device,
such as when dealing with IP tunnels

The first two patches are a small fixes to flower, checking the skip_hw flag
wasn't set before calling the Hardware offloading functions which will try to
offload the rule.

The next two patches are infrastructure patches, a preparation for the fourth
patch which is adding support in flower to offload rules when the ingress
device is not a Hardware device and therefore can't offload.
In this case ndo_setup_tc is called with the mirred (egress) device.

The last three patchs are adding mlx5e support to offload rules using the new
"egress_device" flag.

Thanks,
Hadar

Changes from v0:
- check if CONFIG_NET_CLS_ACT is defined befor calling tc_action_ops get_dev()
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Dec 2, 2016
2 parents 25429d7 + ebe0687 commit 9aac3c1
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 54 deletions.
2 changes: 1 addition & 1 deletion drivers/net/ethernet/mellanox/mlx5/core/en_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3811,7 +3811,7 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
rep.load = mlx5e_nic_rep_load;
rep.unload = mlx5e_nic_rep_unload;
rep.vport = FDB_UPLINK_VPORT;
rep.priv_data = priv;
rep.netdev = netdev;
mlx5_eswitch_register_vport_rep(esw, 0, &rep);
}
}
Expand Down
25 changes: 18 additions & 7 deletions drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,8 @@ int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv)

int mlx5e_nic_rep_load(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep)
{
struct mlx5e_priv *priv = rep->priv_data;
struct net_device *netdev = rep->netdev;
struct mlx5e_priv *priv = netdev_priv(netdev);

if (test_bit(MLX5E_STATE_OPENED, &priv->state))
return mlx5e_add_sqs_fwd_rules(priv);
Expand All @@ -226,7 +227,8 @@ void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv)
void mlx5e_nic_rep_unload(struct mlx5_eswitch *esw,
struct mlx5_eswitch_rep *rep)
{
struct mlx5e_priv *priv = rep->priv_data;
struct net_device *netdev = rep->netdev;
struct mlx5e_priv *priv = netdev_priv(netdev);

if (test_bit(MLX5E_STATE_OPENED, &priv->state))
mlx5e_remove_sqs_fwd_rules(priv);
Expand Down Expand Up @@ -287,6 +289,14 @@ static int mlx5e_rep_ndo_setup_tc(struct net_device *dev, u32 handle,
if (TC_H_MAJ(handle) != TC_H_MAJ(TC_H_INGRESS))
return -EOPNOTSUPP;

if (tc->egress_dev) {
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
struct net_device *uplink_dev = mlx5_eswitch_get_uplink_netdev(esw);

return uplink_dev->netdev_ops->ndo_setup_tc(uplink_dev, handle,
proto, tc);
}

switch (tc->type) {
case TC_SETUP_CLSFLOWER:
switch (tc->cls_flower->command) {
Expand Down Expand Up @@ -384,6 +394,8 @@ static const struct net_device_ops mlx5e_netdev_ops_rep = {
.ndo_get_phys_port_name = mlx5e_rep_get_phys_port_name,
.ndo_setup_tc = mlx5e_rep_ndo_setup_tc,
.ndo_get_stats64 = mlx5e_rep_get_stats,
.ndo_udp_tunnel_add = mlx5e_add_vxlan_port,
.ndo_udp_tunnel_del = mlx5e_del_vxlan_port,
.ndo_has_offload_stats = mlx5e_has_offload_stats,
.ndo_get_offload_stats = mlx5e_get_offload_stats,
};
Expand Down Expand Up @@ -553,7 +565,7 @@ int mlx5e_vport_rep_load(struct mlx5_eswitch *esw,
return -EINVAL;
}

rep->priv_data = netdev_priv(netdev);
rep->netdev = netdev;

err = mlx5e_attach_netdev(esw->dev, netdev);
if (err) {
Expand All @@ -575,7 +587,7 @@ int mlx5e_vport_rep_load(struct mlx5_eswitch *esw,
mlx5e_detach_netdev(esw->dev, netdev);

err_destroy_netdev:
mlx5e_destroy_netdev(esw->dev, rep->priv_data);
mlx5e_destroy_netdev(esw->dev, netdev_priv(netdev));

return err;

Expand All @@ -584,10 +596,9 @@ int mlx5e_vport_rep_load(struct mlx5_eswitch *esw,
void mlx5e_vport_rep_unload(struct mlx5_eswitch *esw,
struct mlx5_eswitch_rep *rep)
{
struct mlx5e_priv *priv = rep->priv_data;
struct net_device *netdev = priv->netdev;
struct net_device *netdev = rep->netdev;

unregister_netdev(netdev);
mlx5e_detach_netdev(esw->dev, netdev);
mlx5e_destroy_netdev(esw->dev, priv);
mlx5e_destroy_netdev(esw->dev, netdev_priv(netdev));
}
3 changes: 2 additions & 1 deletion drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ struct mlx5_eswitch_rep {
struct mlx5_eswitch_rep *rep);
u16 vport;
u8 hw_id[ETH_ALEN];
void *priv_data;
struct net_device *netdev;

struct mlx5_flow_handle *vport_rx_rule;
struct list_head vport_sqs_list;
Expand Down Expand Up @@ -318,6 +318,7 @@ void mlx5_eswitch_register_vport_rep(struct mlx5_eswitch *esw,
struct mlx5_eswitch_rep *rep);
void mlx5_eswitch_unregister_vport_rep(struct mlx5_eswitch *esw,
int vport_index);
struct net_device *mlx5_eswitch_get_uplink_netdev(struct mlx5_eswitch *esw);

int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
struct mlx5_esw_flow_attr *attr);
Expand Down
12 changes: 11 additions & 1 deletion drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,7 @@ void mlx5_eswitch_register_vport_rep(struct mlx5_eswitch *esw,
rep->load = __rep->load;
rep->unload = __rep->unload;
rep->vport = __rep->vport;
rep->priv_data = __rep->priv_data;
rep->netdev = __rep->netdev;
ether_addr_copy(rep->hw_id, __rep->hw_id);

INIT_LIST_HEAD(&rep->vport_sqs_list);
Expand All @@ -990,3 +990,13 @@ void mlx5_eswitch_unregister_vport_rep(struct mlx5_eswitch *esw,

rep->valid = false;
}

struct net_device *mlx5_eswitch_get_uplink_netdev(struct mlx5_eswitch *esw)
{
#define UPLINK_REP_INDEX 0
struct mlx5_esw_offload *offloads = &esw->offloads;
struct mlx5_eswitch_rep *rep;

rep = &offloads->vport_reps[UPLINK_REP_INDEX];
return rep->netdev;
}
1 change: 1 addition & 0 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,7 @@ struct tc_to_netdev {
struct tc_cls_matchall_offload *cls_mall;
struct tc_cls_bpf_offload *cls_bpf;
};
bool egress_dev;
};

/* These structures hold the attributes of xdp state that are being passed
Expand Down
2 changes: 2 additions & 0 deletions include/net/act_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ struct tc_action_ops {
int (*walk)(struct net *, struct sk_buff *,
struct netlink_callback *, int, const struct tc_action_ops *);
void (*stats_update)(struct tc_action *, u64, u32, u64);
int (*get_dev)(const struct tc_action *a, struct net *net,
struct net_device **mirred_dev);
};

struct tc_action_net {
Expand Down
21 changes: 17 additions & 4 deletions include/net/pkt_cls.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
struct tcf_exts *src);
int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts);
int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts);
int tcf_exts_get_dev(struct net_device *dev, struct tcf_exts *exts,
struct net_device **hw_dev);

/**
* struct tcf_pkt_info - packet information
Expand Down Expand Up @@ -425,16 +427,14 @@ struct tc_cls_u32_offload {
};
};

static inline bool tc_should_offload(const struct net_device *dev,
const struct tcf_proto *tp, u32 flags)
static inline bool tc_can_offload(const struct net_device *dev,
const struct tcf_proto *tp)
{
const struct Qdisc *sch = tp->q;
const struct Qdisc_class_ops *cops = sch->ops->cl_ops;

if (!(dev->features & NETIF_F_HW_TC))
return false;
if (flags & TCA_CLS_FLAGS_SKIP_HW)
return false;
if (!dev->netdev_ops->ndo_setup_tc)
return false;
if (cops && cops->tcf_cl_offload)
Expand All @@ -443,6 +443,19 @@ static inline bool tc_should_offload(const struct net_device *dev,
return true;
}

static inline bool tc_skip_hw(u32 flags)
{
return (flags & TCA_CLS_FLAGS_SKIP_HW) ? true : false;
}

static inline bool tc_should_offload(const struct net_device *dev,
const struct tcf_proto *tp, u32 flags)
{
if (tc_skip_hw(flags))
return false;
return tc_can_offload(dev, tp);
}

static inline bool tc_skip_sw(u32 flags)
{
return (flags & TCA_CLS_FLAGS_SKIP_SW) ? true : false;
Expand Down
12 changes: 12 additions & 0 deletions net/sched/act_mirred.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,17 @@ static struct notifier_block mirred_device_notifier = {
.notifier_call = mirred_device_event,
};

static int tcf_mirred_device(const struct tc_action *a, struct net *net,
struct net_device **mirred_dev)
{
int ifindex = tcf_mirred_ifindex(a);

*mirred_dev = __dev_get_by_index(net, ifindex);
if (!mirred_dev)
return -EINVAL;
return 0;
}

static struct tc_action_ops act_mirred_ops = {
.kind = "mirred",
.type = TCA_ACT_MIRRED,
Expand All @@ -327,6 +338,7 @@ static struct tc_action_ops act_mirred_ops = {
.walk = tcf_mirred_walker,
.lookup = tcf_mirred_search,
.size = sizeof(struct tcf_mirred),
.get_dev = tcf_mirred_device,
};

static __net_init int mirred_init_net(struct net *net)
Expand Down
24 changes: 24 additions & 0 deletions net/sched/cls_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,30 @@ int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts)
}
EXPORT_SYMBOL(tcf_exts_dump_stats);

int tcf_exts_get_dev(struct net_device *dev, struct tcf_exts *exts,
struct net_device **hw_dev)
{
#ifdef CONFIG_NET_CLS_ACT
const struct tc_action *a;
LIST_HEAD(actions);

if (tc_no_actions(exts))
return -EINVAL;

tcf_exts_to_list(exts, &actions);
list_for_each_entry(a, &actions, list) {
if (a->ops->get_dev) {
a->ops->get_dev(a, dev_net(dev), hw_dev);
break;
}
}
if (*hw_dev)
return 0;
#endif
return -EOPNOTSUPP;
}
EXPORT_SYMBOL(tcf_exts_get_dev);

static int __init tc_filter_init(void)
{
rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_ctl_tfilter, NULL, NULL);
Expand Down
Loading

0 comments on commit 9aac3c1

Please sign in to comment.