From: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
To: dev@dpdk.org
Cc: shaguna@chelsio.com, indranil@chelsio.com, nirranjan@chelsio.com
Subject: [dpdk-dev] [RFC 3/3] net/cxgbe: add flow actions to modify IP and TCP/UDP port address
Date: Fri, 22 Jun 2018 15:26:05 +0530 [thread overview]
Message-ID: <22b7a1f11b2076719c3fee60306eec860ea3eed1.1529650435.git.rahul.lakkireddy@chelsio.com> (raw)
In-Reply-To: <cover.1529650435.git.rahul.lakkireddy@chelsio.com>
In-Reply-To: <cover.1529650435.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>
---
drivers/net/cxgbe/base/common.h | 1 +
drivers/net/cxgbe/base/t4fw_interface.h | 50 +++++++++++++
drivers/net/cxgbe/cxgbe_filter.c | 23 +++++-
drivers/net/cxgbe/cxgbe_filter.h | 26 ++++++-
drivers/net/cxgbe/cxgbe_flow.c | 127 ++++++++++++++++++++++++++++++++
drivers/net/cxgbe/cxgbe_main.c | 10 +++
6 files changed, 233 insertions(+), 4 deletions(-)
diff --git a/drivers/net/cxgbe/base/common.h b/drivers/net/cxgbe/base/common.h
index e524f7931..f4b2e14cd 100644
--- a/drivers/net/cxgbe/base/common.h
+++ b/drivers/net/cxgbe/base/common.h
@@ -256,6 +256,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 842aa1263..d20d73590 100644
--- a/drivers/net/cxgbe/base/t4fw_interface.h
+++ b/drivers/net/cxgbe/base/t4fw_interface.h
@@ -59,6 +59,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,
};
@@ -185,6 +186,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)
@@ -288,6 +334,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
*********************/
@@ -642,6 +691,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 d098b9308..6744b6a60 100644
--- a/drivers/net/cxgbe/cxgbe_filter.c
+++ b/drivers/net/cxgbe/cxgbe_filter.c
@@ -30,6 +30,10 @@ int validate_filter(struct adapter *adapter, struct ch_filter_specification *fs)
#undef S
#undef U
+
+ if (fs->nat_mode && !adapter->params.filter2_wr_support)
+ return -EOPNOTSUPP;
+
return 0;
}
@@ -193,7 +197,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;
@@ -208,13 +212,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) |
@@ -224,6 +231,7 @@ int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)
fwr->del_filter_to_l2tix =
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_HITCNTS(f->fs.hitcnts) |
V_FW_FILTER_WR_PRIO(f->fs.prio));
fwr->ethtype = cpu_to_be16(f->fs.val.ethtype);
@@ -244,6 +252,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 4df37b9cd..609751474 100644
--- a/drivers/net/cxgbe/cxgbe_filter.h
+++ b/drivers/net/cxgbe/cxgbe_filter.h
@@ -97,6 +97,18 @@ struct ch_filter_specification {
uint32_t dirsteer:1; /* 0 => RSS, 1 => steer to iq */
uint32_t iq:10; /* ingress queue */
+ /*
+ * 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;
@@ -104,7 +116,19 @@ struct ch_filter_specification {
enum {
FILTER_PASS = 0, /* default */
- FILTER_DROP
+ FILTER_DROP,
+ 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 {
diff --git a/drivers/net/cxgbe/cxgbe_flow.c b/drivers/net/cxgbe/cxgbe_flow.c
index 23b7d00b3..1ef330a0f 100644
--- a/drivers/net/cxgbe/cxgbe_flow.c
+++ b/drivers/net/cxgbe/cxgbe_flow.c
@@ -249,6 +249,97 @@ static int cxgbe_get_fidx(struct rte_flow *flow, unsigned int *fidx)
return 0;
}
+static int
+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_of_set_nw_ipv4 *ipv4;
+ const struct rte_flow_action_of_set_nw_ipv6 *ipv6;
+ const struct rte_flow_action_of_set_tp *port;
+
+ switch (a->type) {
+ case RTE_FLOW_ACTION_TYPE_OF_SET_NW_IPV4_SRC:
+ ipv4 = (const struct rte_flow_action_of_set_nw_ipv4 *)a->conf;
+ memcpy(fs->nat_fip, &ipv4->ipv4_addr, sizeof(ipv4->ipv4_addr));
+ *nmode |= 1 << 0;
+ break;
+ case RTE_FLOW_ACTION_TYPE_OF_SET_NW_IPV4_DST:
+ ipv4 = (const struct rte_flow_action_of_set_nw_ipv4 *)a->conf;
+ memcpy(fs->nat_lip, &ipv4->ipv4_addr, sizeof(ipv4->ipv4_addr));
+ *nmode |= 1 << 1;
+ break;
+ case RTE_FLOW_ACTION_TYPE_OF_SET_NW_IPV6_SRC:
+ ipv6 = (const struct rte_flow_action_of_set_nw_ipv6 *)a->conf;
+ memcpy(fs->nat_fip, ipv6->ipv6_addr, sizeof(ipv6->ipv6_addr));
+ *nmode |= 1 << 0;
+ break;
+ case RTE_FLOW_ACTION_TYPE_OF_SET_NW_IPV6_DST:
+ ipv6 = (const struct rte_flow_action_of_set_nw_ipv6 *)a->conf;
+ memcpy(fs->nat_lip, ipv6->ipv6_addr, sizeof(ipv6->ipv6_addr));
+ *nmode |= 1 << 1;
+ break;
+ case RTE_FLOW_ACTION_TYPE_OF_SET_TP_SRC:
+ port = (const struct rte_flow_action_of_set_tp *)a->conf;
+ fs->nat_fport = be16_to_cpu(port->port);
+ *nmode |= 1 << 2;
+ break;
+ case RTE_FLOW_ACTION_TYPE_OF_SET_TP_DST:
+ port = (const struct rte_flow_action_of_set_tp *)a->conf;
+ fs->nat_lport = be16_to_cpu(port->port);
+ *nmode |= 1 << 3;
+ break;
+ default:
+ /* We are not supposed to come here */
+ return rte_flow_error_set(e, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, a,
+ "Action not supported");
+ }
+
+ return 0;
+}
+
static int
cxgbe_rtef_parse_actions(struct rte_flow *flow,
const struct rte_flow_action action[],
@@ -257,6 +348,8 @@ cxgbe_rtef_parse_actions(struct rte_flow *flow,
struct ch_filter_specification *fs = &flow->fs;
const struct rte_flow_action_queue *q;
const struct rte_flow_action *a;
+ int ret;
+ uint8_t nmode = 0, nat_ipv4 = 0, nat_ipv6 = 0;
char abit = 0;
for (a = action; a->type != RTE_FLOW_ACTION_TYPE_END; a++) {
@@ -291,6 +384,36 @@ 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_OF_SET_NW_IPV4_SRC:
+ case RTE_FLOW_ACTION_TYPE_OF_SET_NW_IPV4_DST:
+ nat_ipv4++;
+ goto action_switch;
+ case RTE_FLOW_ACTION_TYPE_OF_SET_NW_IPV6_SRC:
+ case RTE_FLOW_ACTION_TYPE_OF_SET_NW_IPV6_DST:
+ nat_ipv6++;
+ case RTE_FLOW_ACTION_TYPE_OF_SET_TP_SRC:
+ case RTE_FLOW_ACTION_TYPE_OF_SET_TP_DST:
+action_switch:
+ /* We allow multiple switch actions, but switch is
+ * not compatible with either queue or drop
+ */
+ if (abit++ && fs->action != FILTER_SWITCH)
+ return rte_flow_error_set(e, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, a,
+ "overlapping action specified");
+ 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;
+ break;
default:
/* Not supported action : return error */
return rte_flow_error_set(e, ENOTSUP,
@@ -299,6 +422,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 21ad380ae..50d93e7da 100644
--- a/drivers/net/cxgbe/cxgbe_main.c
+++ b/drivers/net/cxgbe/cxgbe_main.c
@@ -990,6 +990,16 @@ static int adap_init0(struct adapter *adap)
if (ret < 0)
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
next prev parent reply other threads:[~2018-06-22 9:57 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 ` Rahul Lakkireddy [this message]
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 ` [dpdk-dev] [RFC v2 3/3] net/cxgbe: add flow actions to modify IP and TCP/UDP port address Rahul Lakkireddy
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=22b7a1f11b2076719c3fee60306eec860ea3eed1.1529650435.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).