net/cxgbe: add flow operations to offload VLAN actions

Add flow API operations to offload vlan push, pop, and rewrite actions.
For vlan push or rewrite actions, allocate and program an entry from
L2T table. Use the L2T index to program vlan actions for LETCAM
(maskfull) and HASH (maskless) filters.

Signed-off-by: Shagun Agrawal <shaguna@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
This commit is contained in:
Shagun Agrawal 2018-08-27 18:22:30 +05:30 committed by Ferruh Yigit
parent 23af667f15
commit 1decc62b1c
6 changed files with 109 additions and 3 deletions

View File

@ -54,6 +54,12 @@ New Features
Also, make sure to start the actual text at the margin.
=========================================================
* **Add support to offload more flow match and actions for CXGBE PMD**
Flow API support has been enhanced for CXGBE Poll Mode Driver to offload:
* Action items: push/pop/rewrite vlan header.
API Changes
-----------

View File

@ -138,6 +138,12 @@ struct work_request_hdr {
#define V_TCAM_BYPASS(x) ((__u64)(x) << S_TCAM_BYPASS)
#define F_TCAM_BYPASS V_TCAM_BYPASS(1ULL)
#define S_L2T_IDX 36
#define V_L2T_IDX(x) ((__u64)(x) << S_L2T_IDX)
#define S_NAGLE 49
#define V_NAGLE(x) ((__u64)(x) << S_NAGLE)
/* option 2 fields */
#define S_RSS_QUEUE 0
#define V_RSS_QUEUE(x) ((x) << S_RSS_QUEUE)

View File

@ -6,6 +6,9 @@
#ifndef _T4_TCB_DEFS_H
#define _T4_TCB_DEFS_H
/* 95:32 */
#define W_TCB_T_FLAGS 1
/* 105:96 */
#define W_TCB_RSS_INFO 3
#define S_TCB_RSS_INFO 0
@ -23,4 +26,6 @@
#define M_TCB_T_RTT_TS_RECENT_AGE 0xffffffffULL
#define V_TCB_T_RTT_TS_RECENT_AGE(x) ((x) << S_TCB_T_RTT_TS_RECENT_AGE)
#define S_TF_CCTRL_RFR 62
#endif /* _T4_TCB_DEFS_H */

View File

@ -8,6 +8,7 @@
#include "t4_regs.h"
#include "cxgbe_filter.h"
#include "clip_tbl.h"
#include "l2t.h"
/**
* Initialize Hash Filters
@ -164,6 +165,16 @@ static void set_tcb_field(struct adapter *adapter, unsigned int ftid,
t4_mgmt_tx(ctrlq, mbuf);
}
/**
* Set one of the t_flags bits in the TCB.
*/
static void set_tcb_tflag(struct adapter *adap, unsigned int ftid,
unsigned int bit_pos, unsigned int val, int no_reply)
{
set_tcb_field(adap, ftid, W_TCB_T_FLAGS, 1ULL << bit_pos,
(unsigned long long)val << bit_pos, no_reply);
}
/**
* Build a CPL_SET_TCB_FIELD message as payload of a ULP_TX_PKT command.
*/
@ -425,7 +436,10 @@ static void mk_act_open_req6(struct filter_entry *f, struct rte_mbuf *mbuf,
req->local_ip_lo = local_lo;
req->peer_ip_hi = peer_hi;
req->peer_ip_lo = peer_lo;
req->opt0 = cpu_to_be64(V_DELACK(f->fs.hitcnts) |
req->opt0 = cpu_to_be64(V_NAGLE(f->fs.newvlan == VLAN_REMOVE ||
f->fs.newvlan == VLAN_REWRITE) |
V_DELACK(f->fs.hitcnts) |
V_L2T_IDX(f->l2t ? f->l2t->idx : 0) |
V_SMAC_SEL((cxgbe_port_viid(f->dev) & 0x7F)
<< 1) |
V_TX_CHAN(f->fs.eport) |
@ -468,7 +482,10 @@ static void mk_act_open_req(struct filter_entry *f, struct rte_mbuf *mbuf,
f->fs.val.lip[2] << 16 | f->fs.val.lip[3] << 24;
req->peer_ip = f->fs.val.fip[0] | f->fs.val.fip[1] << 8 |
f->fs.val.fip[2] << 16 | f->fs.val.fip[3] << 24;
req->opt0 = cpu_to_be64(V_DELACK(f->fs.hitcnts) |
req->opt0 = cpu_to_be64(V_NAGLE(f->fs.newvlan == VLAN_REMOVE ||
f->fs.newvlan == VLAN_REWRITE) |
V_DELACK(f->fs.hitcnts) |
V_L2T_IDX(f->l2t ? f->l2t->idx : 0) |
V_SMAC_SEL((cxgbe_port_viid(f->dev) & 0x7F)
<< 1) |
V_TX_CHAN(f->fs.eport) |
@ -518,6 +535,22 @@ static int cxgbe_set_hash_filter(struct rte_eth_dev *dev,
f->dev = dev;
f->fs.iq = iq;
/*
* If the new filter requires loopback Destination MAC and/or VLAN
* rewriting then we need to allocate a Layer 2 Table (L2T) entry for
* the filter.
*/
if (f->fs.newvlan == VLAN_INSERT ||
f->fs.newvlan == VLAN_REWRITE) {
/* allocate L2T entry for new filter */
f->l2t = cxgbe_l2t_alloc_switching(dev, f->fs.vlan,
f->fs.eport, f->fs.dmac);
if (!f->l2t) {
ret = -ENOMEM;
goto out_err;
}
}
atid = cxgbe_alloc_atid(t, f);
if (atid < 0)
goto out_err;
@ -653,6 +686,19 @@ int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)
unsigned int port_id = ethdev2pinfo(dev)->port_id;
int ret;
/*
* If the new filter requires loopback Destination MAC and/or VLAN
* rewriting then we need to allocate a Layer 2 Table (L2T) entry for
* the filter.
*/
if (f->fs.newvlan) {
/* allocate L2T entry for new filter */
f->l2t = cxgbe_l2t_alloc_switching(f->dev, f->fs.vlan,
f->fs.eport, f->fs.dmac);
if (!f->l2t)
return -ENOMEM;
}
ctrlq = &adapter->sge.ctrlq[port_id];
mbuf = rte_pktmbuf_alloc(ctrlq->mb_pool);
if (!mbuf) {
@ -680,9 +726,16 @@ int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)
cpu_to_be32(V_FW_FILTER_WR_DROP(f->fs.action == FILTER_DROP) |
V_FW_FILTER_WR_DIRSTEER(f->fs.dirsteer) |
V_FW_FILTER_WR_LPBK(f->fs.action == FILTER_SWITCH) |
V_FW_FILTER_WR_INSVLAN
(f->fs.newvlan == VLAN_INSERT ||
f->fs.newvlan == VLAN_REWRITE) |
V_FW_FILTER_WR_RMVLAN
(f->fs.newvlan == VLAN_REMOVE ||
f->fs.newvlan == VLAN_REWRITE) |
V_FW_FILTER_WR_HITCNTS(f->fs.hitcnts) |
V_FW_FILTER_WR_TXCHAN(f->fs.eport) |
V_FW_FILTER_WR_PRIO(f->fs.prio));
V_FW_FILTER_WR_PRIO(f->fs.prio) |
V_FW_FILTER_WR_L2TIX(f->l2t ? f->l2t->idx : 0));
fwr->ethtype = cpu_to_be16(f->fs.val.ethtype);
fwr->ethtypem = cpu_to_be16(f->fs.mask.ethtype);
fwr->smac_sel = 0;
@ -1046,6 +1099,9 @@ void hash_filter_rpl(struct adapter *adap, const struct cpl_act_open_rpl *rpl)
V_TCB_TIMESTAMP(0ULL) |
V_TCB_T_RTT_TS_RECENT_AGE(0ULL),
1);
if (f->fs.newvlan == VLAN_INSERT ||
f->fs.newvlan == VLAN_REWRITE)
set_tcb_tflag(adap, tid, S_TF_CCTRL_RFR, 1, 1);
break;
}
default:

View File

@ -99,6 +99,9 @@ struct ch_filter_specification {
uint32_t iq:10; /* ingress queue */
uint32_t eport:2; /* egress port to switch packet out */
uint32_t newvlan:2; /* rewrite VLAN Tag */
uint8_t dmac[ETHER_ADDR_LEN]; /* new destination MAC address */
uint16_t vlan; /* VLAN Tag to insert */
/* Filter rule value/mask pairs. */
struct ch_filter_tuple val;
@ -111,6 +114,12 @@ enum {
FILTER_SWITCH
};
enum {
VLAN_REMOVE = 1,
VLAN_INSERT,
VLAN_REWRITE
};
enum filter_type {
FILTER_TYPE_IPV4 = 0,
FILTER_TYPE_IPV6,

View File

@ -331,9 +331,30 @@ ch_rte_parse_atype_switch(const struct rte_flow_action *a,
struct ch_filter_specification *fs,
struct rte_flow_error *e)
{
const struct rte_flow_action_of_set_vlan_vid *vlanid;
const struct rte_flow_action_of_push_vlan *pushvlan;
const struct rte_flow_action_phy_port *port;
switch (a->type) {
case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
vlanid = (const struct rte_flow_action_of_set_vlan_vid *)
a->conf;
fs->newvlan = VLAN_REWRITE;
fs->vlan = vlanid->vlan_vid;
break;
case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
pushvlan = (const struct rte_flow_action_of_push_vlan *)
a->conf;
if (pushvlan->ethertype != ETHER_TYPE_VLAN)
return rte_flow_error_set(e, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, a,
"only ethertype 0x8100 "
"supported for push vlan.");
fs->newvlan = VLAN_INSERT;
break;
case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
fs->newvlan = VLAN_REMOVE;
break;
case RTE_FLOW_ACTION_TYPE_PHY_PORT:
port = (const struct rte_flow_action_phy_port *)a->conf;
fs->eport = port->index;
@ -391,6 +412,9 @@ cxgbe_rtef_parse_actions(struct rte_flow *flow,
case RTE_FLOW_ACTION_TYPE_COUNT:
fs->hitcnts = 1;
break;
case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
case RTE_FLOW_ACTION_TYPE_PHY_PORT:
/* We allow multiple switch actions, but switch is
* not compatible with either queue or drop