Skip to content

Commit

Permalink
octeontx2-pf: Add tc flower hardware offload on ingress traffic
Browse files Browse the repository at this point in the history
This patch adds support for tc flower hardware offload on ingress
traffic. Since the tc-flower filter rules use the same set of MCAM
rules as the n-tuple filters, the n-tuple filters and tc flower
rules are mutually exclusive. When one of the feature is enabled
using ethtool, the other feature is disabled in the driver. By default
the driver enables n-tuple filters during initialization.

The following flow keys are supported.
    -> Ethernet: dst_mac
    -> L2 proto: all protocols
    -> VLAN (802.1q): vlan_id/vlan_prio
    -> IPv4: dst_ip/src_ip/ip_proto{tcp|udp|sctp|icmp}/ip_tos
    -> IPv6: ip_proto{icmpv6}
    -> L4(tcp/udp/sctp): dst_port/src_port

The following flow actions are supported.
    -> drop
    -> accept
    -> redirect
    -> vlan pop

The flow action supports multiple actions when vlan pop is specified
as the first action. The redirect action supports redirecting to the
PF/VF of same PCI device. Redirecting to other PCI NIX devices is not
supported.

Example #1: Add a tc filter rule to drop UDP traffic with dest port 80
    # ethtool -K eth0 hw-tc-offload on
    # tc qdisc add dev eth0 ingress
    # tc filter add dev eth0 protocol ip parent ffff: flower ip_proto \
          udp dst_port 80 action drop

Example #2: Add a tc filter rule to redirect ingress traffic on eth0
with vlan id 3 to eth6 (ex: eth0 vf0) after stripping the vlan hdr.
    # ethtool -K eth0 hw-tc-offload on
    # tc qdisc add dev eth0 ingress
    # tc filter add dev eth0 parent ffff: protocol 802.1Q flower \
          vlan_id 3 vlan_ethtype ipv4 action vlan pop action mirred \
          ingress redirect dev eth6

Example #3: List the ingress filter rules
    # tc -s filter show dev eth4 ingress

Example #4: Delete tc flower filter rule with handle 0x1
    # tc filter del dev eth0 ingress protocol ip pref 49152 \
      handle 1 flower

Signed-off-by: Naveen Mamindlapalli <naveenm@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Naveen Mamindlapalli authored and davem330 committed Mar 18, 2021
1 parent 2b9cef6 commit 1d4d9e4
Show file tree
Hide file tree
Showing 6 changed files with 551 additions and 2 deletions.
2 changes: 1 addition & 1 deletion drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2002,7 +2002,7 @@ static void rvu_dbg_npc_mcam_show_flows(struct seq_file *s,
seq_printf(s, "mask 0x%x\n", ntohs(rule->mask.etype));
break;
case NPC_OUTER_VID:
seq_printf(s, "%d ", ntohs(rule->packet.vlan_tci));
seq_printf(s, "0x%x ", ntohs(rule->packet.vlan_tci));
seq_printf(s, "mask 0x%x\n",
ntohs(rule->mask.vlan_tci));
break;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/marvell/octeontx2/nic/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ obj-$(CONFIG_OCTEONTX2_PF) += rvu_nicpf.o
obj-$(CONFIG_OCTEONTX2_VF) += rvu_nicvf.o

rvu_nicpf-y := otx2_pf.o otx2_common.o otx2_txrx.o otx2_ethtool.o \
otx2_ptp.o otx2_flows.o cn10k.o
otx2_ptp.o otx2_flows.o otx2_tc.o cn10k.o
rvu_nicvf-y := otx2_vf.o

ccflags-y += -I$(srctree)/drivers/net/ethernet/marvell/octeontx2/af
19 changes: 19 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <linux/ptp_clock_kernel.h>
#include <linux/timecounter.h>
#include <linux/soc/marvell/octeontx2/asm.h>
#include <net/pkt_cls.h>

#include <mbox.h>
#include <npc.h>
Expand Down Expand Up @@ -264,6 +265,7 @@ struct otx2_flow_config {
#define OTX2_MAX_NTUPLE_FLOWS 32
#define OTX2_MAX_UNICAST_FLOWS 8
#define OTX2_MAX_VLAN_FLOWS 1
#define OTX2_MAX_TC_FLOWS OTX2_MAX_NTUPLE_FLOWS
#define OTX2_MCAM_COUNT (OTX2_MAX_NTUPLE_FLOWS + \
OTX2_MAX_UNICAST_FLOWS + \
OTX2_MAX_VLAN_FLOWS)
Expand All @@ -274,10 +276,20 @@ struct otx2_flow_config {
#define OTX2_PER_VF_VLAN_FLOWS 2 /* rx+tx per VF */
#define OTX2_VF_VLAN_RX_INDEX 0
#define OTX2_VF_VLAN_TX_INDEX 1
u32 tc_flower_offset;
u32 ntuple_max_flows;
u32 tc_max_flows;
struct list_head flow_list;
};

struct otx2_tc_info {
/* hash table to store TC offloaded flows */
struct rhashtable flow_table;
struct rhashtable_params flow_ht_params;
DECLARE_BITMAP(tc_entries_bitmap, OTX2_MAX_TC_FLOWS);
unsigned long num_entries;
};

struct dev_hw_ops {
int (*sq_aq_init)(void *dev, u16 qidx, u16 sqb_aura);
void (*sqe_flush)(void *dev, struct otx2_snd_queue *sq,
Expand Down Expand Up @@ -305,6 +317,7 @@ struct otx2_nic {
#define OTX2_FLAG_PF_SHUTDOWN BIT_ULL(8)
#define OTX2_FLAG_RX_PAUSE_ENABLED BIT_ULL(9)
#define OTX2_FLAG_TX_PAUSE_ENABLED BIT_ULL(10)
#define OTX2_FLAG_TC_FLOWER_SUPPORT BIT_ULL(11)
u64 flags;

struct otx2_qset qset;
Expand Down Expand Up @@ -347,6 +360,7 @@ struct otx2_nic {
struct hwtstamp_config tstamp;

struct otx2_flow_config *flow_cfg;
struct otx2_tc_info tc_info;
};

static inline bool is_otx2_lbkvf(struct pci_dev *pdev)
Expand Down Expand Up @@ -802,4 +816,9 @@ int otx2_add_macfilter(struct net_device *netdev, const u8 *mac);
int otx2_enable_rxvlan(struct otx2_nic *pf, bool enable);
int otx2_install_rxvlan_offload_flow(struct otx2_nic *pfvf);
u16 otx2_get_max_mtu(struct otx2_nic *pfvf);
/* tc support */
int otx2_init_tc(struct otx2_nic *nic);
void otx2_shutdown_tc(struct otx2_nic *nic);
int otx2_setup_tc(struct net_device *netdev, enum tc_setup_type type,
void *type_data);
#endif /* OTX2_COMMON_H */
5 changes: 5 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,13 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf)
flow_cfg->ntuple_max_flows = rsp->count;
flow_cfg->ntuple_offset = 0;
pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT;
flow_cfg->tc_max_flows = flow_cfg->ntuple_max_flows;
pfvf->flags |= OTX2_FLAG_TC_FLOWER_SUPPORT;
} else {
flow_cfg->vf_vlan_offset = 0;
flow_cfg->ntuple_offset = flow_cfg->vf_vlan_offset +
vf_vlan_max_flows;
flow_cfg->tc_flower_offset = flow_cfg->ntuple_offset;
flow_cfg->unicast_offset = flow_cfg->ntuple_offset +
OTX2_MAX_NTUPLE_FLOWS;
flow_cfg->rx_vlan_offset = flow_cfg->unicast_offset +
Expand All @@ -69,6 +72,7 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf)
pfvf->flags |= OTX2_FLAG_UCAST_FLTR_SUPPORT;
pfvf->flags |= OTX2_FLAG_RX_VLAN_SUPPORT;
pfvf->flags |= OTX2_FLAG_VF_VLAN_SUPPORT;
pfvf->flags |= OTX2_FLAG_TC_FLOWER_SUPPORT;
}

for (i = 0; i < rsp->count; i++)
Expand All @@ -93,6 +97,7 @@ int otx2_mcam_flow_init(struct otx2_nic *pf)
INIT_LIST_HEAD(&pf->flow_cfg->flow_list);

pf->flow_cfg->ntuple_max_flows = OTX2_MAX_NTUPLE_FLOWS;
pf->flow_cfg->tc_max_flows = pf->flow_cfg->ntuple_max_flows;

err = otx2_alloc_mcam_entries(pf);
if (err)
Expand Down
37 changes: 37 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1760,6 +1760,24 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK;
}

static netdev_features_t otx2_fix_features(struct net_device *dev,
netdev_features_t features)
{
/* check if n-tuple filters are ON */
if ((features & NETIF_F_HW_TC) && (dev->features & NETIF_F_NTUPLE)) {
netdev_info(dev, "Disabling n-tuple filters\n");
features &= ~NETIF_F_NTUPLE;
}

/* check if tc hw offload is ON */
if ((features & NETIF_F_NTUPLE) && (dev->features & NETIF_F_HW_TC)) {
netdev_info(dev, "Disabling TC hardware offload\n");
features &= ~NETIF_F_HW_TC;
}

return features;
}

static void otx2_set_rx_mode(struct net_device *netdev)
{
struct otx2_nic *pf = netdev_priv(netdev);
Expand Down Expand Up @@ -1822,6 +1840,12 @@ static int otx2_set_features(struct net_device *netdev,
if ((changed & NETIF_F_NTUPLE) && !ntuple)
otx2_destroy_ntuple_flows(pf);

if ((netdev->features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC) &&
pf->tc_info.num_entries) {
netdev_err(netdev, "Can't disable TC hardware offload while flows are active\n");
return -EBUSY;
}

return 0;
}

Expand Down Expand Up @@ -2220,6 +2244,7 @@ static const struct net_device_ops otx2_netdev_ops = {
.ndo_open = otx2_open,
.ndo_stop = otx2_stop,
.ndo_start_xmit = otx2_xmit,
.ndo_fix_features = otx2_fix_features,
.ndo_set_mac_address = otx2_set_mac_address,
.ndo_change_mtu = otx2_change_mtu,
.ndo_set_rx_mode = otx2_set_rx_mode,
Expand All @@ -2230,6 +2255,7 @@ static const struct net_device_ops otx2_netdev_ops = {
.ndo_set_vf_mac = otx2_set_vf_mac,
.ndo_set_vf_vlan = otx2_set_vf_vlan,
.ndo_get_vf_config = otx2_get_vf_config,
.ndo_setup_tc = otx2_setup_tc,
};

static int otx2_wq_init(struct otx2_nic *pf)
Expand Down Expand Up @@ -2449,6 +2475,10 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
NETIF_F_HW_VLAN_STAG_RX;
netdev->features |= netdev->hw_features;

/* HW supports tc offload but mutually exclusive with n-tuple filters */
if (pf->flags & OTX2_FLAG_TC_FLOWER_SUPPORT)
netdev->hw_features |= NETIF_F_HW_TC;

netdev->gso_max_segs = OTX2_MAX_GSO_SEGS;
netdev->watchdog_timeo = OTX2_TX_TIMEOUT;

Expand All @@ -2470,6 +2500,10 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)

otx2_set_ethtool_ops(netdev);

err = otx2_init_tc(pf);
if (err)
goto err_mcam_flow_del;

/* Enable link notifications */
otx2_cgx_config_linkevents(pf, true);

Expand All @@ -2479,6 +2513,8 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)

return 0;

err_mcam_flow_del:
otx2_mcam_flow_del(pf);
err_unreg_netdev:
unregister_netdev(netdev);
err_del_mcam_entries:
Expand Down Expand Up @@ -2646,6 +2682,7 @@ static void otx2_remove(struct pci_dev *pdev)

otx2_ptp_destroy(pf);
otx2_mcam_flow_del(pf);
otx2_shutdown_tc(pf);
otx2_detach_resources(&pf->mbox);
if (pf->hw.lmt_base)
iounmap(pf->hw.lmt_base);
Expand Down

0 comments on commit 1d4d9e4

Please sign in to comment.