Skip to content

Commit

Permalink
Merge branch 'octeon-tc-offloads'
Browse files Browse the repository at this point in the history
Naveen Mamindlapalli says:

====================
Add tc hardware offloads

This patch series adds support for tc hardware offloads.

Patch #1 adds support for offloading flows that matches IP tos and IP
         protocol which will be used by tc hw offload support. Also
         added ethtool n-tuple filter to code to offload the flows
         matching the above fields.
Patch #2 adds tc flower hardware offload support on ingress traffic.
Patch #3 adds TC flower offload stats.
Patch #4 adds tc TC_MATCHALL egress ratelimiting offload.

* tc flower hardware offload in PF driver

The driver parses the flow match fields and actions received from the tc
subsystem and adds/delete MCAM rules for the same. Each flow contains set
of match and action fields. If the action or fields are not supported,
the rule cannot be offloaded to hardware. The tc uses same set of MCAM
rules allocated for ethtool n-tuple filters. So, at a time only one entity
can offload the flows to hardware, they're made mutually exclusive in the
driver.

Following match and actions are supported.

Match: Eth dst_mac, EtherType, 802.1Q {vlan_id,vlan_prio}, vlan EtherType,
       IP proto {tcp,udp,sctp,icmp,icmp6}, IPv4 tos, IPv4{dst_ip,src_ip},
       L4 proto {dst_port|src_port number}.
Actions: drop, accept, vlan pop, redirect to another port on the device.

The Hardware stats are also supported. Currently only packet counter stats
are updated.

* tc egress rate limiting support
Added TC-MATCHALL classifier offload with police action applied for all
egress traffic on the specified interface.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 18, 2021
2 parents a04be4b + e638a83 commit 3122216
Show file tree
Hide file tree
Showing 11 changed files with 961 additions and 6 deletions.
14 changes: 14 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/af/mbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ M(NPC_MCAM_READ_ENTRY, 0x600f, npc_mcam_read_entry, \
npc_mcam_read_entry_rsp) \
M(NPC_MCAM_READ_BASE_RULE, 0x6011, npc_read_base_steer_rule, \
msg_req, npc_mcam_read_base_rule_rsp) \
M(NPC_MCAM_GET_STATS, 0x6012, npc_mcam_entry_stats, \
npc_mcam_get_stats_req, \
npc_mcam_get_stats_rsp) \
/* NIX mbox IDs (range 0x8000 - 0xFFFF) */ \
M(NIX_LF_ALLOC, 0x8000, nix_lf_alloc, \
nix_lf_alloc_req, nix_lf_alloc_rsp) \
Expand Down Expand Up @@ -1195,6 +1198,17 @@ struct npc_mcam_read_base_rule_rsp {
struct mcam_entry entry;
};

struct npc_mcam_get_stats_req {
struct mbox_msghdr hdr;
u16 entry; /* mcam entry */
};

struct npc_mcam_get_stats_rsp {
struct mbox_msghdr hdr;
u64 stat; /* counter stats */
u8 stat_ena; /* enabled */
};

enum ptp_op {
PTP_OP_ADJFINE = 0,
PTP_OP_GET_CLOCK = 1,
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/af/npc.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ enum key_fields {
NPC_IPPROTO_SCTP,
NPC_IPPROTO_AH,
NPC_IPPROTO_ESP,
NPC_IPPROTO_ICMP,
NPC_IPPROTO_ICMP6,
NPC_SPORT_TCP,
NPC_DPORT_TCP,
NPC_SPORT_UDP,
Expand Down
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
39 changes: 39 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2806,3 +2806,42 @@ int rvu_mbox_handler_npc_read_base_steer_rule(struct rvu *rvu,
out:
return rc;
}

int rvu_mbox_handler_npc_mcam_entry_stats(struct rvu *rvu,
struct npc_mcam_get_stats_req *req,
struct npc_mcam_get_stats_rsp *rsp)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
u16 index, cntr;
int blkaddr;
u64 regval;
u32 bank;

blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0)
return NPC_MCAM_INVALID_REQ;

mutex_lock(&mcam->lock);

index = req->entry & (mcam->banksize - 1);
bank = npc_get_bank(mcam, req->entry);

/* read MCAM entry STAT_ACT register */
regval = rvu_read64(rvu, blkaddr, NPC_AF_MCAMEX_BANKX_STAT_ACT(index, bank));

if (!(regval & BIT_ULL(9))) {
rsp->stat_ena = 0;
mutex_unlock(&mcam->lock);
return 0;
}

cntr = regval & 0x1FF;

rsp->stat_ena = 1;
rsp->stat = rvu_read64(rvu, blkaddr, NPC_AF_MATCH_STATX(cntr));
rsp->stat &= BIT_ULL(48) - 1;

mutex_unlock(&mcam->lock);

return 0;
}
17 changes: 15 additions & 2 deletions drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ static const char * const npc_flow_names[] = {
[NPC_IPPROTO_TCP] = "ip proto tcp",
[NPC_IPPROTO_UDP] = "ip proto udp",
[NPC_IPPROTO_SCTP] = "ip proto sctp",
[NPC_IPPROTO_ICMP] = "ip proto icmp",
[NPC_IPPROTO_ICMP6] = "ip proto icmp6",
[NPC_IPPROTO_AH] = "ip proto AH",
[NPC_IPPROTO_ESP] = "ip proto ESP",
[NPC_SPORT_TCP] = "tcp source port",
Expand Down Expand Up @@ -427,6 +429,7 @@ do { \
* packet header fields below.
* Example: Source IP is 4 bytes and starts at 12th byte of IP header
*/
NPC_SCAN_HDR(NPC_TOS, NPC_LID_LC, NPC_LT_LC_IP, 1, 1);
NPC_SCAN_HDR(NPC_SIP_IPV4, NPC_LID_LC, NPC_LT_LC_IP, 12, 4);
NPC_SCAN_HDR(NPC_DIP_IPV4, NPC_LID_LC, NPC_LT_LC_IP, 16, 4);
NPC_SCAN_HDR(NPC_SIP_IPV6, NPC_LID_LC, NPC_LT_LC_IP6, 8, 16);
Expand Down Expand Up @@ -477,9 +480,12 @@ static void npc_set_features(struct rvu *rvu, int blkaddr, u8 intf)
BIT_ULL(NPC_IPPROTO_SCTP);
}

/* for AH, check if corresponding layer type is present in the key */
if (npc_check_field(rvu, blkaddr, NPC_LD, intf))
/* for AH/ICMP/ICMPv6/, check if corresponding layer type is present in the key */
if (npc_check_field(rvu, blkaddr, NPC_LD, intf)) {
*features |= BIT_ULL(NPC_IPPROTO_AH);
*features |= BIT_ULL(NPC_IPPROTO_ICMP);
*features |= BIT_ULL(NPC_IPPROTO_ICMP6);
}

/* for ESP, check if corresponding layer type is present in the key */
if (npc_check_field(rvu, blkaddr, NPC_LE, intf))
Expand Down Expand Up @@ -769,6 +775,12 @@ static void npc_update_flow(struct rvu *rvu, struct mcam_entry *entry,
if (features & BIT_ULL(NPC_IPPROTO_SCTP))
npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_SCTP,
0, ~0ULL, 0, intf);
if (features & BIT_ULL(NPC_IPPROTO_ICMP))
npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_ICMP,
0, ~0ULL, 0, intf);
if (features & BIT_ULL(NPC_IPPROTO_ICMP6))
npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_ICMP6,
0, ~0ULL, 0, intf);

if (features & BIT_ULL(NPC_OUTER_VID))
npc_update_entry(rvu, NPC_LB, entry,
Expand Down Expand Up @@ -798,6 +810,7 @@ do { \
NPC_WRITE_FLOW(NPC_SMAC, smac, smac_val, 0, smac_mask, 0);
NPC_WRITE_FLOW(NPC_ETYPE, etype, ntohs(pkt->etype), 0,
ntohs(mask->etype), 0);
NPC_WRITE_FLOW(NPC_TOS, tos, pkt->tos, 0, mask->tos, 0);
NPC_WRITE_FLOW(NPC_SIP_IPV4, ip4src, ntohl(pkt->ip4src), 0,
ntohl(mask->ip4src), 0);
NPC_WRITE_FLOW(NPC_DIP_IPV4, ip4dst, ntohl(pkt->ip4dst), 0,
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
20 changes: 20 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,8 @@ 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)
#define OTX2_FLAG_TC_MATCHALL_EGRESS_ENABLED BIT_ULL(12)
u64 flags;

struct otx2_qset qset;
Expand Down Expand Up @@ -347,6 +361,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 +817,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 */
47 changes: 45 additions & 2 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 Expand Up @@ -301,6 +306,35 @@ static int otx2_prepare_ipv4_flow(struct ethtool_rx_flow_spec *fsp,
sizeof(pmask->ip4dst));
req->features |= BIT_ULL(NPC_DIP_IPV4);
}
if (ipv4_usr_mask->tos) {
pkt->tos = ipv4_usr_hdr->tos;
pmask->tos = ipv4_usr_mask->tos;
req->features |= BIT_ULL(NPC_TOS);
}
if (ipv4_usr_mask->proto) {
switch (ipv4_usr_hdr->proto) {
case IPPROTO_ICMP:
req->features |= BIT_ULL(NPC_IPPROTO_ICMP);
break;
case IPPROTO_TCP:
req->features |= BIT_ULL(NPC_IPPROTO_TCP);
break;
case IPPROTO_UDP:
req->features |= BIT_ULL(NPC_IPPROTO_UDP);
break;
case IPPROTO_SCTP:
req->features |= BIT_ULL(NPC_IPPROTO_SCTP);
break;
case IPPROTO_AH:
req->features |= BIT_ULL(NPC_IPPROTO_AH);
break;
case IPPROTO_ESP:
req->features |= BIT_ULL(NPC_IPPROTO_ESP);
break;
default:
return -EOPNOTSUPP;
}
}
pkt->etype = cpu_to_be16(ETH_P_IP);
pmask->etype = cpu_to_be16(0xFFFF);
req->features |= BIT_ULL(NPC_ETYPE);
Expand All @@ -325,6 +359,11 @@ static int otx2_prepare_ipv4_flow(struct ethtool_rx_flow_spec *fsp,
sizeof(pmask->ip4dst));
req->features |= BIT_ULL(NPC_DIP_IPV4);
}
if (ipv4_l4_mask->tos) {
pkt->tos = ipv4_l4_hdr->tos;
pmask->tos = ipv4_l4_mask->tos;
req->features |= BIT_ULL(NPC_TOS);
}
if (ipv4_l4_mask->psrc) {
memcpy(&pkt->sport, &ipv4_l4_hdr->psrc,
sizeof(pkt->sport));
Expand Down Expand Up @@ -375,10 +414,14 @@ static int otx2_prepare_ipv4_flow(struct ethtool_rx_flow_spec *fsp,
sizeof(pmask->ip4dst));
req->features |= BIT_ULL(NPC_DIP_IPV4);
}
if (ah_esp_mask->tos) {
pkt->tos = ah_esp_hdr->tos;
pmask->tos = ah_esp_mask->tos;
req->features |= BIT_ULL(NPC_TOS);
}

/* NPC profile doesn't extract AH/ESP header fields */
if ((ah_esp_mask->spi & ah_esp_hdr->spi) ||
(ah_esp_mask->tos & ah_esp_mask->tos))
if (ah_esp_mask->spi & ah_esp_hdr->spi)
return -EOPNOTSUPP;

if (flow_type == AH_V4_FLOW)
Expand Down
Loading

0 comments on commit 3122216

Please sign in to comment.