Commit 31222162 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'octeon-tc-offloads'



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: default avatarDavid S. Miller <davem@davemloft.net>
parents a04be4b6 e638a83f
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -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)	\
@@ -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,
+2 −0
Original line number Diff line number Diff line
@@ -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,
+1 −1
Original line number Diff line number Diff line
@@ -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;
+39 −0
Original line number Diff line number Diff line
@@ -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;
}
+15 −2
Original line number Diff line number Diff line
@@ -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",
@@ -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);
@@ -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))
@@ -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,
@@ -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,
Loading