From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id E7020A0567; Wed, 11 Mar 2020 10:17:59 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 6714F1C0AA; Wed, 11 Mar 2020 10:17:00 +0100 (CET) Received: from stargate.chelsio.com (stargate.chelsio.com [12.32.117.8]) by dpdk.org (Postfix) with ESMTP id 678441C08D for ; Wed, 11 Mar 2020 10:16:58 +0100 (CET) Received: from localhost (scalar.blr.asicdesigners.com [10.193.185.94]) by stargate.chelsio.com (8.13.8/8.13.8) with ESMTP id 02B9GuB5014342; Wed, 11 Mar 2020 02:16:57 -0700 From: Rahul Lakkireddy To: dev@dpdk.org Cc: nirranjan@chelsio.com, kaara.satwik@chelsio.com Date: Wed, 11 Mar 2020 14:35:49 +0530 Message-Id: <922dac5cf352f830d98d89016e253caf37fdfcc6.1583906144.git.kaara.satwik@chelsio.com> X-Mailer: git-send-email 2.5.3 In-Reply-To: References: In-Reply-To: References: Subject: [dpdk-dev] [PATCH 7/9] net/cxgbe: add rte_flow support for Source MAC Rewrite X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Karra Satwik Add support to rewrite Source MAC addresses. The new Source MAC address is written into a free entry in the SMT table and the corresponding SMT index is used by hardware to rewrite the Source MAC address of the packets hitting the flow. Signed-off-by: Karra Satwik Signed-off-by: Rahul Lakkireddy --- drivers/net/cxgbe/base/t4_msg.h | 40 +++++ drivers/net/cxgbe/base/t4_tcb.h | 8 + drivers/net/cxgbe/base/t4fw_interface.h | 7 +- drivers/net/cxgbe/cxgbe_filter.c | 35 ++++- drivers/net/cxgbe/cxgbe_filter.h | 3 + drivers/net/cxgbe/cxgbe_flow.c | 14 ++ drivers/net/cxgbe/cxgbe_main.c | 4 + drivers/net/cxgbe/smt.c | 187 ++++++++++++++++++++++++ drivers/net/cxgbe/smt.h | 5 + 9 files changed, 300 insertions(+), 3 deletions(-) diff --git a/drivers/net/cxgbe/base/t4_msg.h b/drivers/net/cxgbe/base/t4_msg.h index 9e052b0f0..a6ddaa7b0 100644 --- a/drivers/net/cxgbe/base/t4_msg.h +++ b/drivers/net/cxgbe/base/t4_msg.h @@ -12,10 +12,12 @@ enum { CPL_ABORT_REQ = 0xA, CPL_ABORT_RPL = 0xB, CPL_L2T_WRITE_REQ = 0x12, + CPL_SMT_WRITE_REQ = 0x14, CPL_TID_RELEASE = 0x1A, CPL_L2T_WRITE_RPL = 0x23, CPL_ACT_OPEN_RPL = 0x25, CPL_ABORT_RPL_RSS = 0x2D, + CPL_SMT_WRITE_RPL = 0x2E, CPL_SET_TCB_RPL = 0x3A, CPL_ACT_OPEN_REQ6 = 0x83, CPL_SGE_EGR_UPDATE = 0xA5, @@ -465,6 +467,44 @@ struct cpl_l2t_write_rpl { __u8 rsvd[3]; }; +struct cpl_smt_write_req { + WR_HDR; + union opcode_tid ot; + __be32 params; + __be16 pfvf1; + __u8 src_mac1[6]; + __be16 pfvf0; + __u8 src_mac0[6]; +}; + +struct cpl_t6_smt_write_req { + WR_HDR; + union opcode_tid ot; + __be32 params; + __be64 tag; + __be16 pfvf0; + __u8 src_mac0[6]; + __be32 local_ip; + __be32 rsvd; +}; + +struct cpl_smt_write_rpl { + RSS_HDR + union opcode_tid ot; + u8 status; + u8 rsvd[3]; +}; + +/* cpl_smt_{read,write}_req.params fields */ +#define S_SMTW_OVLAN_IDX 16 +#define V_SMTW_OVLAN_IDX(x) ((x) << S_SMTW_OVLAN_IDX) + +#define S_SMTW_IDX 20 +#define V_SMTW_IDX(x) ((x) << S_SMTW_IDX) + +#define S_SMTW_NORPL 31 +#define V_SMTW_NORPL(x) ((x) << S_SMTW_NORPL) + /* rx_pkt.l2info fields */ #define S_RXF_UDP 22 #define V_RXF_UDP(x) ((x) << S_RXF_UDP) diff --git a/drivers/net/cxgbe/base/t4_tcb.h b/drivers/net/cxgbe/base/t4_tcb.h index 834169ab4..afd03b735 100644 --- a/drivers/net/cxgbe/base/t4_tcb.h +++ b/drivers/net/cxgbe/base/t4_tcb.h @@ -6,6 +6,12 @@ #ifndef _T4_TCB_DEFS_H #define _T4_TCB_DEFS_H +/* 31:24 */ +#define W_TCB_SMAC_SEL 0 +#define S_TCB_SMAC_SEL 24 +#define M_TCB_SMAC_SEL 0xffULL +#define V_TCB_SMAC_SEL(x) ((x) << S_TCB_SMAC_SEL) + /* 95:32 */ #define W_TCB_T_FLAGS 1 @@ -34,6 +40,8 @@ #define S_TF_CCTRL_ECE 60 +#define S_TF_CCTRL_CWR 61 + #define S_TF_CCTRL_RFR 62 #endif /* _T4_TCB_DEFS_H */ diff --git a/drivers/net/cxgbe/base/t4fw_interface.h b/drivers/net/cxgbe/base/t4fw_interface.h index 3684c8006..51ebe4f7a 100644 --- a/drivers/net/cxgbe/base/t4fw_interface.h +++ b/drivers/net/cxgbe/base/t4fw_interface.h @@ -248,6 +248,9 @@ struct fw_filter2_wr { #define S_FW_FILTER_WR_DMAC 19 #define V_FW_FILTER_WR_DMAC(x) ((x) << S_FW_FILTER_WR_DMAC) +#define S_FW_FILTER_WR_SMAC 18 +#define V_FW_FILTER_WR_SMAC(x) ((x) << S_FW_FILTER_WR_SMAC) + #define S_FW_FILTER_WR_INSVLAN 17 #define V_FW_FILTER_WR_INSVLAN(x) ((x) << S_FW_FILTER_WR_INSVLAN) @@ -1335,8 +1338,8 @@ struct fw_vi_cmd { #define FW_VI_MAC_ID_BASED_FREE 0x3FC enum fw_vi_mac_smac { - FW_VI_MAC_MPS_TCAM_ENTRY, - FW_VI_MAC_SMT_AND_MPSTCAM + FW_VI_MAC_MPS_TCAM_ENTRY = 0x0, + FW_VI_MAC_SMT_AND_MPSTCAM = 0x3 }; enum fw_vi_mac_entry_types { diff --git a/drivers/net/cxgbe/cxgbe_filter.c b/drivers/net/cxgbe/cxgbe_filter.c index b009217f8..c5f5e41e3 100644 --- a/drivers/net/cxgbe/cxgbe_filter.c +++ b/drivers/net/cxgbe/cxgbe_filter.c @@ -10,6 +10,7 @@ #include "cxgbe_filter.h" #include "clip_tbl.h" #include "l2t.h" +#include "smt.h" /** * Initialize Hash Filters @@ -604,6 +605,17 @@ static int cxgbe_set_hash_filter(struct rte_eth_dev *dev, } } + /* If the new filter requires Source MAC rewriting then we need to + * allocate a SMT entry for the filter + */ + if (f->fs.newsmac) { + f->smt = cxgbe_smt_alloc_switching(f->dev, f->fs.smac); + if (!f->smt) { + ret = -EAGAIN; + goto out_err; + } + } + atid = cxgbe_alloc_atid(t, f); if (atid < 0) goto out_err; @@ -758,6 +770,20 @@ static int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx) return -ENOMEM; } + /* If the new filter requires Source MAC rewriting then we need to + * allocate a SMT entry for the filter + */ + if (f->fs.newsmac) { + f->smt = cxgbe_smt_alloc_switching(f->dev, f->fs.smac); + if (!f->smt) { + if (f->l2t) { + cxgbe_l2t_release(f->l2t); + f->l2t = NULL; + } + return -ENOMEM; + } + } + ctrlq = &adapter->sge.ctrlq[port_id]; mbuf = rte_pktmbuf_alloc(ctrlq->mb_pool); if (!mbuf) { @@ -788,6 +814,7 @@ static 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_SMAC(f->fs.newsmac) | V_FW_FILTER_WR_DMAC(f->fs.newdmac) | V_FW_FILTER_WR_INSVLAN (f->fs.newvlan == VLAN_INSERT || @@ -806,7 +833,7 @@ static int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx) V_FW_FILTER_WR_IVLAN_VLDM(f->fs.mask.ivlan_vld) | V_FW_FILTER_WR_OVLAN_VLD(f->fs.val.ovlan_vld) | V_FW_FILTER_WR_OVLAN_VLDM(f->fs.mask.ovlan_vld)); - fwr->smac_sel = 0; + fwr->smac_sel = f->smt ? f->smt->hw_idx : 0; fwr->rx_chan_rx_rpl_iq = cpu_to_be16(V_FW_FILTER_WR_RX_CHAN(0) | V_FW_FILTER_WR_RX_RPL_IQ(adapter->sge.fw_evtq.abs_id @@ -1144,6 +1171,12 @@ void cxgbe_hash_filter_rpl(struct adapter *adap, if (f->fs.newvlan == VLAN_INSERT || f->fs.newvlan == VLAN_REWRITE) set_tcb_tflag(adap, tid, S_TF_CCTRL_RFR, 1, 1); + if (f->fs.newsmac) { + set_tcb_tflag(adap, tid, S_TF_CCTRL_CWR, 1, 1); + set_tcb_field(adap, tid, W_TCB_SMAC_SEL, + V_TCB_SMAC_SEL(M_TCB_SMAC_SEL), + V_TCB_SMAC_SEL(f->smt->hw_idx), 1); + } break; } default: diff --git a/drivers/net/cxgbe/cxgbe_filter.h b/drivers/net/cxgbe/cxgbe_filter.h index 7a1e72ded..e79c052de 100644 --- a/drivers/net/cxgbe/cxgbe_filter.h +++ b/drivers/net/cxgbe/cxgbe_filter.h @@ -100,9 +100,11 @@ struct ch_filter_specification { uint32_t iq:10; /* ingress queue */ uint32_t eport:2; /* egress port to switch packet out */ + uint32_t newsmac:1; /* rewrite source MAC address */ uint32_t newdmac:1; /* rewrite destination MAC address */ uint32_t swapmac:1; /* swap SMAC/DMAC for loopback packet */ uint32_t newvlan:2; /* rewrite VLAN Tag */ + uint8_t smac[RTE_ETHER_ADDR_LEN]; /* new source MAC address */ uint8_t dmac[RTE_ETHER_ADDR_LEN]; /* new destination MAC address */ uint16_t vlan; /* VLAN Tag to insert */ @@ -181,6 +183,7 @@ struct filter_entry { struct filter_ctx *ctx; /* caller's completion hook */ struct clip_entry *clipt; /* CLIP Table entry for IPv6 */ struct l2t_entry *l2t; /* Layer Two Table entry for dmac */ + struct smt_entry *smt; /* Source Mac Table entry for smac */ struct rte_eth_dev *dev; /* Port's rte eth device */ void *private; /* For use by apps using filter_entry */ diff --git a/drivers/net/cxgbe/cxgbe_flow.c b/drivers/net/cxgbe/cxgbe_flow.c index b009005c5..13fd78aaf 100644 --- a/drivers/net/cxgbe/cxgbe_flow.c +++ b/drivers/net/cxgbe/cxgbe_flow.c @@ -795,6 +795,19 @@ ch_rte_parse_atype_switch(const struct rte_flow_action *a, "found"); fs->swapmac = 1; break; + case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC: + item_index = cxgbe_get_flow_item_index(items, + RTE_FLOW_ITEM_TYPE_ETH); + if (item_index < 0) + return rte_flow_error_set(e, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, a, + "No RTE_FLOW_ITEM_TYPE_ETH " + "found"); + mac = (const struct rte_flow_action_set_mac *)a->conf; + + fs->newsmac = 1; + memcpy(fs->smac, mac->mac_addr, sizeof(fs->smac)); + break; case RTE_FLOW_ACTION_TYPE_SET_MAC_DST: item_index = cxgbe_get_flow_item_index(items, RTE_FLOW_ITEM_TYPE_ETH); @@ -883,6 +896,7 @@ cxgbe_rtef_parse_actions(struct rte_flow *flow, goto action_switch; case RTE_FLOW_ACTION_TYPE_SET_TP_SRC: case RTE_FLOW_ACTION_TYPE_SET_TP_DST: + case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC: case RTE_FLOW_ACTION_TYPE_SET_MAC_DST: action_switch: /* We allow multiple switch actions, but switch is diff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c index 1ab6f8fba..df54e54f5 100644 --- a/drivers/net/cxgbe/cxgbe_main.c +++ b/drivers/net/cxgbe/cxgbe_main.c @@ -107,6 +107,10 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp, const struct cpl_l2t_write_rpl *p = (const void *)rsp; cxgbe_do_l2t_write_rpl(q->adapter, p); + } else if (opcode == CPL_SMT_WRITE_RPL) { + const struct cpl_smt_write_rpl *p = (const void *)rsp; + + cxgbe_do_smt_write_rpl(q->adapter, p); } else { dev_err(adapter, "unexpected CPL %#x on FW event queue\n", opcode); diff --git a/drivers/net/cxgbe/smt.c b/drivers/net/cxgbe/smt.c index cf40c8a8a..e8f38676e 100644 --- a/drivers/net/cxgbe/smt.c +++ b/drivers/net/cxgbe/smt.c @@ -6,6 +6,193 @@ #include "base/common.h" #include "smt.h" +void cxgbe_do_smt_write_rpl(struct adapter *adap, + const struct cpl_smt_write_rpl *rpl) +{ + unsigned int smtidx = G_TID_TID(GET_TID(rpl)); + struct smt_data *s = adap->smt; + + if (unlikely(rpl->status != CPL_ERR_NONE)) { + struct smt_entry *e = &s->smtab[smtidx]; + + dev_err(adap, + "Unexpected SMT_WRITE_RPL status %u for entry %u\n", + rpl->status, smtidx); + t4_os_lock(&e->lock); + e->state = SMT_STATE_ERROR; + t4_os_unlock(&e->lock); + } +} + +static int write_smt_entry(struct rte_eth_dev *dev, struct smt_entry *e) +{ + unsigned int port_id = ethdev2pinfo(dev)->port_id; + struct adapter *adap = ethdev2adap(dev); + struct cpl_t6_smt_write_req *t6req; + struct smt_data *s = adap->smt; + struct cpl_smt_write_req *req; + struct sge_ctrl_txq *ctrlq; + struct rte_mbuf *mbuf; + u8 row; + + ctrlq = &adap->sge.ctrlq[port_id]; + mbuf = rte_pktmbuf_alloc(ctrlq->mb_pool); + if (!mbuf) + return -ENOMEM; + + if (CHELSIO_CHIP_VERSION(adap->params.chip) <= CHELSIO_T5) { + mbuf->data_len = sizeof(*req); + mbuf->pkt_len = mbuf->data_len; + + /* Source MAC Table (SMT) contains 256 SMAC entries + * organized in 128 rows of 2 entries each. + */ + req = rte_pktmbuf_mtod(mbuf, struct cpl_smt_write_req *); + INIT_TP_WR(req, 0); + + /* Each row contains an SMAC pair. + * LSB selects the SMAC entry within a row + */ + if (e->idx & 1) { + req->pfvf1 = 0x0; + rte_memcpy(req->src_mac1, e->src_mac, + RTE_ETHER_ADDR_LEN); + + /* fill pfvf0/src_mac0 with entry + * at prev index from smt-tab. + */ + req->pfvf0 = 0x0; + rte_memcpy(req->src_mac0, s->smtab[e->idx - 1].src_mac, + RTE_ETHER_ADDR_LEN); + } else { + req->pfvf0 = 0x0; + rte_memcpy(req->src_mac0, e->src_mac, + RTE_ETHER_ADDR_LEN); + + /* fill pfvf1/src_mac1 with entry + * at next index from smt-tab + */ + req->pfvf1 = 0x0; + rte_memcpy(req->src_mac1, s->smtab[e->idx + 1].src_mac, + RTE_ETHER_ADDR_LEN); + } + row = (e->hw_idx >> 1); + } else { + mbuf->data_len = sizeof(*t6req); + mbuf->pkt_len = mbuf->data_len; + + /* Source MAC Table (SMT) contains 256 SMAC entries */ + t6req = rte_pktmbuf_mtod(mbuf, struct cpl_t6_smt_write_req *); + INIT_TP_WR(t6req, 0); + + /* fill pfvf0/src_mac0 from smt-tab */ + t6req->pfvf0 = 0x0; + rte_memcpy(t6req->src_mac0, s->smtab[e->idx].src_mac, + RTE_ETHER_ADDR_LEN); + row = e->hw_idx; + req = (struct cpl_smt_write_req *)t6req; + } + + OPCODE_TID(req) = + cpu_to_be32(MK_OPCODE_TID(CPL_SMT_WRITE_REQ, + e->hw_idx | + V_TID_QID(adap->sge.fw_evtq.abs_id))); + + req->params = cpu_to_be32(V_SMTW_NORPL(0) | + V_SMTW_IDX(row) | + V_SMTW_OVLAN_IDX(0)); + t4_mgmt_tx(ctrlq, mbuf); + + return 0; +} + +/** + * find_or_alloc_smte - Find/Allocate a free SMT entry + * @s: SMT table + * @smac: Source MAC address to compare/add + * Returns pointer to the SMT entry found/created + * + * Finds/Allocates an SMT entry to be used by switching rule of a filter. + */ +static struct smt_entry *find_or_alloc_smte(struct smt_data *s, u8 *smac) +{ + struct smt_entry *e, *end, *first_free = NULL; + + for (e = &s->smtab[0], end = &s->smtab[s->smt_size]; e != end; ++e) { + if (!rte_atomic32_read(&e->refcnt)) { + if (!first_free) + first_free = e; + } else { + if (e->state == SMT_STATE_SWITCHING) { + /* This entry is actually in use. See if we can + * re-use it ? + */ + if (!memcmp(e->src_mac, smac, + RTE_ETHER_ADDR_LEN)) + goto found; + } + } + } + + if (!first_free) + return NULL; + + e = first_free; + e->state = SMT_STATE_UNUSED; + +found: + return e; +} + +static struct smt_entry *t4_smt_alloc_switching(struct rte_eth_dev *dev, + u16 pfvf, u8 *smac) +{ + struct adapter *adap = ethdev2adap(dev); + struct smt_data *s = adap->smt; + struct smt_entry *e; + int ret; + + t4_os_write_lock(&s->lock); + e = find_or_alloc_smte(s, smac); + if (e) { + t4_os_lock(&e->lock); + if (!rte_atomic32_read(&e->refcnt)) { + e->pfvf = pfvf; + rte_memcpy(e->src_mac, smac, RTE_ETHER_ADDR_LEN); + ret = write_smt_entry(dev, e); + if (ret) { + e->pfvf = 0; + memset(e->src_mac, 0, RTE_ETHER_ADDR_LEN); + t4_os_unlock(&e->lock); + e = NULL; + goto out_write_unlock; + } + e->state = SMT_STATE_SWITCHING; + rte_atomic32_set(&e->refcnt, 1); + } else { + rte_atomic32_inc(&e->refcnt); + } + t4_os_unlock(&e->lock); + } + +out_write_unlock: + t4_os_write_unlock(&s->lock); + return e; +} + +/** + * cxgbe_smt_alloc_switching - Allocate an SMT entry for switching rule + * @dev: rte_eth_dev pointer + * @smac: MAC address to add to SMT + * Returns pointer to the SMT entry created + * + * Allocates an SMT entry to be used by switching rule of a filter. + */ +struct smt_entry *cxgbe_smt_alloc_switching(struct rte_eth_dev *dev, u8 *smac) +{ + return t4_smt_alloc_switching(dev, 0x0, smac); +} + /** * Initialize Source MAC Table */ diff --git a/drivers/net/cxgbe/smt.h b/drivers/net/cxgbe/smt.h index aa4afcce2..be1fab8ba 100644 --- a/drivers/net/cxgbe/smt.h +++ b/drivers/net/cxgbe/smt.h @@ -5,6 +5,8 @@ #ifndef __CXGBE_SMT_H_ #define __CXGBE_SMT_H_ +#include "base/t4_msg.h" + enum { SMT_STATE_SWITCHING, SMT_STATE_UNUSED, @@ -34,6 +36,9 @@ struct smt_data { struct smt_data *t4_init_smt(u32 smt_start_idx, u32 smt_size); void t4_cleanup_smt(struct adapter *adap); +void cxgbe_do_smt_write_rpl(struct adapter *adap, + const struct cpl_smt_write_rpl *rpl); +struct smt_entry *cxgbe_smt_alloc_switching(struct rte_eth_dev *dev, u8 *smac); #endif /* __CXGBE_SMT_H_ */ -- 2.25.0