From: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
To: dev@dpdk.org
Cc: shaguna@chelsio.com, nirranjan@chelsio.com, indranil@chelsio.com
Subject: [dpdk-dev] [RFC v2 3/3] net/cxgbe: add flow actions to modify IP and TCP/UDP port address
Date: Mon, 13 Aug 2018 19:06:58 +0530 [thread overview]
Message-ID: <5d533a79f9b6ecc3af03e3c65cc694f6dfb9184f.1534166371.git.rahul.lakkireddy@chelsio.com> (raw)
In-Reply-To: <cover.1534166371.git.rahul.lakkireddy@chelsio.com>
In-Reply-To: <cover.1534166371.git.rahul.lakkireddy@chelsio.com>
From: Shagun Agrawal <shaguna@chelsio.com>
Query firmware for the new filter work request to offload flows with
actions to modify IP and TCP/UDP port addresses. When available,
translate IP and TCP/UDP port address modify actions to internal
hardware specification and offload the flow to hardware.
Signed-off-by: Shagun Agrawal <shaguna@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
---
v2:
- Re-based to tip.
drivers/net/cxgbe/base/common.h | 1 +
drivers/net/cxgbe/base/t4fw_interface.h | 50 ++++++++++++++++
drivers/net/cxgbe/cxgbe_filter.c | 21 ++++++-
drivers/net/cxgbe/cxgbe_filter.h | 23 ++++++++
drivers/net/cxgbe/cxgbe_flow.c | 100 +++++++++++++++++++++++++++++++-
drivers/net/cxgbe/cxgbe_main.c | 10 ++++
6 files changed, 200 insertions(+), 5 deletions(-)
diff --git a/drivers/net/cxgbe/base/common.h b/drivers/net/cxgbe/base/common.h
index 157201da2..bbd915f29 100644
--- a/drivers/net/cxgbe/base/common.h
+++ b/drivers/net/cxgbe/base/common.h
@@ -270,6 +270,7 @@ struct adapter_params {
bool ulptx_memwrite_dsgl; /* use of T5 DSGL allowed */
u8 fw_caps_support; /* 32-bit Port Capabilities */
+ bool filter2_wr_support; /* FW support for FILTER2_WR */
};
/* Firmware Port Capabilities types.
diff --git a/drivers/net/cxgbe/base/t4fw_interface.h b/drivers/net/cxgbe/base/t4fw_interface.h
index e80b58a32..832d22f93 100644
--- a/drivers/net/cxgbe/base/t4fw_interface.h
+++ b/drivers/net/cxgbe/base/t4fw_interface.h
@@ -61,6 +61,7 @@ enum fw_wr_opcodes {
FW_ETH_TX_PKTS_WR = 0x09,
FW_ETH_TX_PKT_VM_WR = 0x11,
FW_ETH_TX_PKTS_VM_WR = 0x12,
+ FW_FILTER2_WR = 0x77,
FW_ETH_TX_PKTS2_WR = 0x78,
};
@@ -197,6 +198,51 @@ struct fw_filter_wr {
__u8 sma[6];
};
+struct fw_filter2_wr {
+ __be32 op_pkd;
+ __be32 len16_pkd;
+ __be64 r3;
+ __be32 tid_to_iq;
+ __be32 del_filter_to_l2tix;
+ __be16 ethtype;
+ __be16 ethtypem;
+ __u8 frag_to_ovlan_vldm;
+ __u8 smac_sel;
+ __be16 rx_chan_rx_rpl_iq;
+ __be32 maci_to_matchtypem;
+ __u8 ptcl;
+ __u8 ptclm;
+ __u8 ttyp;
+ __u8 ttypm;
+ __be16 ivlan;
+ __be16 ivlanm;
+ __be16 ovlan;
+ __be16 ovlanm;
+ __u8 lip[16];
+ __u8 lipm[16];
+ __u8 fip[16];
+ __u8 fipm[16];
+ __be16 lp;
+ __be16 lpm;
+ __be16 fp;
+ __be16 fpm;
+ __be16 r7;
+ __u8 sma[6];
+ __be16 r8;
+ __u8 filter_type_swapmac;
+ __u8 natmode_to_ulp_type;
+ __be16 newlport;
+ __be16 newfport;
+ __u8 newlip[16];
+ __u8 newfip[16];
+ __be32 natseqcheck;
+ __be32 r9;
+ __be64 r10;
+ __be64 r11;
+ __be64 r12;
+ __be64 r13;
+};
+
#define S_FW_FILTER_WR_TID 12
#define V_FW_FILTER_WR_TID(x) ((x) << S_FW_FILTER_WR_TID)
@@ -300,6 +346,9 @@ struct fw_filter_wr {
#define S_FW_FILTER_WR_MATCHTYPEM 0
#define V_FW_FILTER_WR_MATCHTYPEM(x) ((x) << S_FW_FILTER_WR_MATCHTYPEM)
+#define S_FW_FILTER2_WR_NATMODE 5
+#define V_FW_FILTER2_WR_NATMODE(x) ((x) << S_FW_FILTER2_WR_NATMODE)
+
/******************************************************************************
* C O M M A N D s
*********************/
@@ -655,6 +704,7 @@ enum fw_params_param_dev {
FW_PARAMS_PARAM_DEV_FWREV = 0x0B, /* fw version */
FW_PARAMS_PARAM_DEV_TPREV = 0x0C, /* tp version */
FW_PARAMS_PARAM_DEV_ULPTX_MEMWRITE_DSGL = 0x17,
+ FW_PARAMS_PARAM_DEV_FILTER2_WR = 0x1D,
};
/*
diff --git a/drivers/net/cxgbe/cxgbe_filter.c b/drivers/net/cxgbe/cxgbe_filter.c
index 7f0d38001..deae1c37b 100644
--- a/drivers/net/cxgbe/cxgbe_filter.c
+++ b/drivers/net/cxgbe/cxgbe_filter.c
@@ -87,6 +87,9 @@ int validate_filter(struct adapter *adapter, struct ch_filter_specification *fs)
if (fs->val.iport >= adapter->params.nports)
return -ERANGE;
+ if (!fs->cap && fs->nat_mode && !adapter->params.filter2_wr_support)
+ return -EOPNOTSUPP;
+
return 0;
}
@@ -648,7 +651,7 @@ int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)
struct adapter *adapter = ethdev2adap(dev);
struct filter_entry *f = &adapter->tids.ftid_tab[fidx];
struct rte_mbuf *mbuf;
- struct fw_filter_wr *fwr;
+ struct fw_filter2_wr *fwr;
struct sge_ctrl_txq *ctrlq;
unsigned int port_id = ethdev2pinfo(dev)->port_id;
int ret;
@@ -663,13 +666,16 @@ int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)
mbuf->data_len = sizeof(*fwr);
mbuf->pkt_len = mbuf->data_len;
- fwr = rte_pktmbuf_mtod(mbuf, struct fw_filter_wr *);
+ fwr = rte_pktmbuf_mtod(mbuf, struct fw_filter2_wr *);
memset(fwr, 0, sizeof(*fwr));
/*
* Construct the work request to set the filter.
*/
- fwr->op_pkd = cpu_to_be32(V_FW_WR_OP(FW_FILTER_WR));
+ if (adapter->params.filter2_wr_support)
+ fwr->op_pkd = cpu_to_be32(V_FW_WR_OP(FW_FILTER2_WR));
+ else
+ fwr->op_pkd = cpu_to_be32(V_FW_WR_OP(FW_FILTER_WR));
fwr->len16_pkd = cpu_to_be32(V_FW_WR_LEN16(sizeof(*fwr) / 16));
fwr->tid_to_iq =
cpu_to_be32(V_FW_FILTER_WR_TID(f->tid) |
@@ -704,6 +710,15 @@ int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)
fwr->fp = cpu_to_be16(f->fs.val.fport);
fwr->fpm = cpu_to_be16(f->fs.mask.fport);
+ if (adapter->params.filter2_wr_support && f->fs.nat_mode) {
+ fwr->natmode_to_ulp_type =
+ V_FW_FILTER2_WR_NATMODE(f->fs.nat_mode);
+ memcpy(fwr->newlip, f->fs.nat_lip, sizeof(fwr->newlip));
+ memcpy(fwr->newfip, f->fs.nat_fip, sizeof(fwr->newfip));
+ fwr->newlport = cpu_to_be16(f->fs.nat_lport);
+ fwr->newfport = cpu_to_be16(f->fs.nat_fport);
+ }
+
/*
* Mark the filter as "pending" and ship off the Filter Work Request.
* When we get the Work Request Reply we'll clear the pending status.
diff --git a/drivers/net/cxgbe/cxgbe_filter.h b/drivers/net/cxgbe/cxgbe_filter.h
index af8fa7529..c85fa6d2c 100644
--- a/drivers/net/cxgbe/cxgbe_filter.h
+++ b/drivers/net/cxgbe/cxgbe_filter.h
@@ -100,6 +100,18 @@ struct ch_filter_specification {
uint32_t eport:2; /* egress port to switch packet out */
+ /*
+ * Switch proxy/rewrite fields. An ingress packet which matches a
+ * filter with "switch" set will be looped back out as an egress
+ * packet -- potentially with some Ethernet header rewriting.
+ */
+ uint32_t nat_mode:3; /* specify NAT operation mode */
+
+ uint8_t nat_lip[16]; /* local IP to use after NAT'ing */
+ uint8_t nat_fip[16]; /* foreign IP to use after NAT'ing */
+ uint16_t nat_lport; /* local port to use after NAT'ing */
+ uint16_t nat_fport; /* foreign port to use after NAT'ing */
+
/* Filter rule value/mask pairs. */
struct ch_filter_tuple val;
struct ch_filter_tuple mask;
@@ -111,6 +123,17 @@ enum {
FILTER_SWITCH
};
+enum {
+ NAT_MODE_NONE = 0, /* No NAT performed */
+ NAT_MODE_DIP, /* NAT on Dst IP */
+ NAT_MODE_DIP_DP, /* NAT on Dst IP, Dst Port */
+ NAT_MODE_DIP_DP_SIP, /* NAT on Dst IP, Dst Port and Src IP */
+ NAT_MODE_DIP_DP_SP, /* NAT on Dst IP, Dst Port and Src Port */
+ NAT_MODE_SIP_SP, /* NAT on Src IP and Src Port */
+ NAT_MODE_DIP_SIP_SP, /* NAT on Dst IP, Src IP and Src Port */
+ NAT_MODE_ALL /* NAT on entire 4-tuple */
+};
+
enum filter_type {
FILTER_TYPE_IPV4 = 0,
FILTER_TYPE_IPV6,
diff --git a/drivers/net/cxgbe/cxgbe_flow.c b/drivers/net/cxgbe/cxgbe_flow.c
index 01c945f1b..099aca61e 100644
--- a/drivers/net/cxgbe/cxgbe_flow.c
+++ b/drivers/net/cxgbe/cxgbe_flow.c
@@ -327,10 +327,54 @@ static int cxgbe_get_fidx(struct rte_flow *flow, unsigned int *fidx)
}
static int
-ch_rte_parse_atype_switch(const struct rte_flow_action *a,
+ch_rte_parse_nat(uint8_t nmode, struct ch_filter_specification *fs)
+{
+ /* nmode:
+ * BIT_0 = [src_ip], BIT_1 = [dst_ip]
+ * BIT_2 = [src_port], BIT_3 = [dst_port]
+ *
+ * Only below cases are supported as per our spec.
+ */
+ switch (nmode) {
+ case 0: /* 0000b */
+ fs->nat_mode = NAT_MODE_NONE;
+ break;
+ case 2: /* 0010b */
+ fs->nat_mode = NAT_MODE_DIP;
+ break;
+ case 5: /* 0101b */
+ fs->nat_mode = NAT_MODE_SIP_SP;
+ break;
+ case 7: /* 0111b */
+ fs->nat_mode = NAT_MODE_DIP_SIP_SP;
+ break;
+ case 10: /* 1010b */
+ fs->nat_mode = NAT_MODE_DIP_DP;
+ break;
+ case 11: /* 1011b */
+ fs->nat_mode = NAT_MODE_DIP_DP_SIP;
+ break;
+ case 14: /* 1110 */
+ fs->nat_mode = NAT_MODE_DIP_DP_SP;
+ break;
+ case 15: /* 1111b */
+ fs->nat_mode = NAT_MODE_ALL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+ch_rte_parse_atype_switch(const struct rte_flow_action *a, uint8_t *nmode,
struct ch_filter_specification *fs,
struct rte_flow_error *e)
{
+ const struct rte_flow_action_set_ipv4 *ipv4;
+ const struct rte_flow_action_set_ipv6 *ipv6;
+ const struct rte_flow_action_set_tp *tp_port;
const struct rte_flow_action_phy_port *port;
switch (a->type) {
@@ -338,6 +382,36 @@ ch_rte_parse_atype_switch(const struct rte_flow_action *a,
port = (const struct rte_flow_action_phy_port *)a->conf;
fs->eport = port->index;
break;
+ case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
+ ipv4 = (const struct rte_flow_action_set_ipv4 *)a->conf;
+ memcpy(fs->nat_fip, &ipv4->ipv4_addr, sizeof(ipv4->ipv4_addr));
+ *nmode |= 1 << 0;
+ break;
+ case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
+ ipv4 = (const struct rte_flow_action_set_ipv4 *)a->conf;
+ memcpy(fs->nat_lip, &ipv4->ipv4_addr, sizeof(ipv4->ipv4_addr));
+ *nmode |= 1 << 1;
+ break;
+ case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
+ ipv6 = (const struct rte_flow_action_set_ipv6 *)a->conf;
+ memcpy(fs->nat_fip, ipv6->ipv6_addr, sizeof(ipv6->ipv6_addr));
+ *nmode |= 1 << 0;
+ break;
+ case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
+ ipv6 = (const struct rte_flow_action_set_ipv6 *)a->conf;
+ memcpy(fs->nat_lip, ipv6->ipv6_addr, sizeof(ipv6->ipv6_addr));
+ *nmode |= 1 << 1;
+ break;
+ case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
+ tp_port = (const struct rte_flow_action_set_tp *)a->conf;
+ fs->nat_fport = be16_to_cpu(tp_port->port);
+ *nmode |= 1 << 2;
+ break;
+ case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
+ tp_port = (const struct rte_flow_action_set_tp *)a->conf;
+ fs->nat_lport = be16_to_cpu(tp_port->port);
+ *nmode |= 1 << 3;
+ break;
default:
/* We are not supposed to come here */
return rte_flow_error_set(e, EINVAL,
@@ -358,6 +432,7 @@ cxgbe_rtef_parse_actions(struct rte_flow *flow,
const struct rte_flow_action *a;
char abit = 0;
int ret;
+ uint8_t nmode = 0, nat_ipv4 = 0, nat_ipv6 = 0;
for (a = action; a->type != RTE_FLOW_ACTION_TYPE_END; a++) {
switch (a->type) {
@@ -391,7 +466,18 @@ cxgbe_rtef_parse_actions(struct rte_flow *flow,
case RTE_FLOW_ACTION_TYPE_COUNT:
fs->hitcnts = 1;
break;
+ /* switch actions */
+ case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
+ case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
+ nat_ipv4++;
+ goto action_switch;
+ case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
+ case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
+ nat_ipv6++;
+ case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
+ case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
case RTE_FLOW_ACTION_TYPE_PHY_PORT:
+action_switch:
/* We allow multiple switch actions, but switch is
* not compatible with either queue or drop
*/
@@ -399,7 +485,13 @@ cxgbe_rtef_parse_actions(struct rte_flow *flow,
return rte_flow_error_set(e, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, a,
"overlapping action specified");
- ret = ch_rte_parse_atype_switch(a, fs, e);
+ if (nat_ipv4 && nat_ipv6)
+ return rte_flow_error_set(e, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, a,
+ "Can't have one address ipv4 and the"
+ " other ipv6");
+
+ ret = ch_rte_parse_atype_switch(a, &nmode, fs, e);
if (ret)
return ret;
fs->action = FILTER_SWITCH;
@@ -412,6 +504,10 @@ cxgbe_rtef_parse_actions(struct rte_flow *flow,
}
}
+ if (ch_rte_parse_nat(nmode, fs))
+ return rte_flow_error_set(e, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, a,
+ "invalid settings for swich action");
return 0;
}
diff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c
index c3938e8db..4aeb3e074 100644
--- a/drivers/net/cxgbe/cxgbe_main.c
+++ b/drivers/net/cxgbe/cxgbe_main.c
@@ -1170,6 +1170,16 @@ static int adap_init0(struct adapter *adap)
goto bye;
}
+ /* See if FW supports FW_FILTER2 work request */
+ if (is_t4(adap->params.chip)) {
+ adap->params.filter2_wr_support = 0;
+ } else {
+ params[0] = FW_PARAM_DEV(FILTER2_WR);
+ ret = t4_query_params(adap, adap->mbox, adap->pf, 0,
+ 1, params, val);
+ adap->params.filter2_wr_support = (ret == 0 && val[0] != 0);
+ }
+
/* query tid-related parameters */
params[0] = FW_PARAM_DEV(NTID);
ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1,
--
2.14.1
prev parent reply other threads:[~2018-08-13 13:39 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-22 9:56 [dpdk-dev] [RFC 0/3] ethdev: add IP address and TCP/UDP port rewrite actions to flow API Rahul Lakkireddy
2018-06-22 9:56 ` [dpdk-dev] [RFC 1/3] ethdev: add flow api actions to modify IP addresses Rahul Lakkireddy
2018-06-22 9:56 ` [dpdk-dev] [RFC 2/3] ethdev: add flow api actions to modify TCP/UDP port numbers Rahul Lakkireddy
2018-06-22 9:56 ` [dpdk-dev] [RFC 3/3] net/cxgbe: add flow actions to modify IP and TCP/UDP port address Rahul Lakkireddy
2018-06-26 10:32 ` [dpdk-dev] [RFC 0/3] ethdev: add IP address and TCP/UDP port rewrite actions to flow API Thomas Monjalon
2018-07-02 9:09 ` Jack Min
2018-07-02 12:04 ` Rahul Lakkireddy
2018-07-03 2:27 ` Jack Min
2018-07-03 13:39 ` Rahul Lakkireddy
2018-07-04 1:11 ` Jack Min
2018-07-05 20:16 ` Adrien Mazarguil
2018-07-10 13:14 ` Rahul Lakkireddy
2018-08-01 23:35 ` Jack Min
2018-08-02 14:59 ` Rahul Lakkireddy
2018-08-13 13:36 ` [dpdk-dev] [RFC v2 " Rahul Lakkireddy
2018-08-13 13:36 ` [dpdk-dev] [RFC v2 1/3] ethdev: add flow api actions to modify IP addresses Rahul Lakkireddy
2018-09-18 7:56 ` Xiaoyu Min
2018-09-19 15:14 ` Rahul Lakkireddy
2018-08-13 13:36 ` [dpdk-dev] [RFC v2 2/3] ethdev: add flow api actions to modify TCP/UDP port numbers Rahul Lakkireddy
2018-09-18 9:29 ` Xiaoyu Min
2018-09-19 15:16 ` Rahul Lakkireddy
2018-08-13 13:36 ` Rahul Lakkireddy [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5d533a79f9b6ecc3af03e3c65cc694f6dfb9184f.1534166371.git.rahul.lakkireddy@chelsio.com \
--to=rahul.lakkireddy@chelsio.com \
--cc=dev@dpdk.org \
--cc=indranil@chelsio.com \
--cc=nirranjan@chelsio.com \
--cc=shaguna@chelsio.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).