Show a patch.

GET /api/patches/45194/
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 45194,
    "url": "http://patches.dpdk.org/api/patches/45194/",
    "web_url": "http://patches.dpdk.org/patch/45194/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk"
    },
    "msgid": "<8e2942b14f0cb2f2f24f3582b2b51173129501cf.1537776502.git.rahul.lakkireddy@chelsio.com>",
    "date": "2018-09-24T08:28:19",
    "name": "[3/3] net/cxgbe: add flow actions to modify IP and TCP/UDP port address",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "71c1afb7918590d5b1c5a62ef47e2291c24cb6d4",
    "submitter": {
        "id": 241,
        "url": "http://patches.dpdk.org/api/people/241/",
        "name": "Rahul Lakkireddy",
        "email": "rahul.lakkireddy@chelsio.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@intel.com"
    },
    "mbox": "http://patches.dpdk.org/patch/45194/mbox/",
    "series": [
        {
            "id": 1460,
            "url": "http://patches.dpdk.org/api/series/1460/",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=1460",
            "date": "2018-09-24T08:28:17",
            "name": "ethdev: add IP address and TCP/UDP port rewrite actions to flow API",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/1460/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/45194/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/45194/checks/",
    "tags": {},
    "headers": {
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "X-Original-To": "patchwork@dpdk.org",
        "List-Post": "<mailto:dev@dpdk.org>",
        "References": [
            "<cover.1537776502.git.rahul.lakkireddy@chelsio.com>",
            "<cover.1537776502.git.rahul.lakkireddy@chelsio.com>"
        ],
        "X-BeenThere": "dev@dpdk.org",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "Subject": "[dpdk-dev] [PATCH 3/3] net/cxgbe: add flow actions to modify IP and\n\tTCP/UDP port address",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>",
        "From": "Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id C88704F94;\n\tMon, 24 Sep 2018 10:28:54 +0200 (CEST)",
            "from stargate.chelsio.com (stargate.chelsio.com [12.32.117.8])\n\tby dpdk.org (Postfix) with ESMTP id 5F46D4CC5\n\tfor <dev@dpdk.org>; Mon, 24 Sep 2018 10:28:51 +0200 (CEST)",
            "from localhost (scalar.blr.asicdesigners.com [10.193.185.94])\n\tby stargate.chelsio.com (8.13.8/8.13.8) with ESMTP id w8O8SmFG027417; \n\tMon, 24 Sep 2018 01:28:48 -0700"
        ],
        "To": "dev@dpdk.org",
        "X-Mailer": "git-send-email 2.5.3",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "Date": "Mon, 24 Sep 2018 13:58:19 +0530",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "Delivered-To": "patchwork@dpdk.org",
        "In-Reply-To": [
            "<cover.1537776502.git.rahul.lakkireddy@chelsio.com>",
            "<cover.1537776502.git.rahul.lakkireddy@chelsio.com>"
        ],
        "Cc": "indranil@chelsio.com, nirranjan@chelsio.com",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Message-Id": "<8e2942b14f0cb2f2f24f3582b2b51173129501cf.1537776502.git.rahul.lakkireddy@chelsio.com>",
        "Return-Path": "<dev-bounces@dpdk.org>"
    },
    "content": "Query firmware for the new filter work request to offload flows with\nactions to modify IP and TCP/UDP port addresses. When available,\ntranslate IP and TCP/UDP port address modify actions to internal\nhardware specification and offload the flow to hardware.\n\nOriginal work by Shagun Agrawal\n\nSigned-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>\n---\nChanges since RFC v2:\n- Re-based to tip.\n- Updated all instances of fw_filter_wr to new fw_filter2_wr and removed\n  fw_filter_wr.\n- Ensure correct ULP type is set when offloading NAT actions.\n- Returning appropriate RTE_FLOW_ERROR_TYPE_ACTION error if a corresponding\n  valid flow pattern item for the header rewrite action is not found.\n- Updated release notes.\n\n doc/guides/rel_notes/release_18_11.rst  |   4 +-\n drivers/net/cxgbe/base/common.h         |   1 +\n drivers/net/cxgbe/base/t4_msg.h         |   1 +\n drivers/net/cxgbe/base/t4fw_interface.h |  23 ++-\n drivers/net/cxgbe/cxgbe_filter.c        |  37 +++--\n drivers/net/cxgbe/cxgbe_filter.h        |  23 +++\n drivers/net/cxgbe/cxgbe_flow.c          | 178 +++++++++++++++++++++++-\n drivers/net/cxgbe/cxgbe_main.c          |  10 ++\n 8 files changed, 265 insertions(+), 12 deletions(-)",
    "diff": "diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst\nindex 84b0a6a4b..04d5d26a4 100644\n--- a/doc/guides/rel_notes/release_18_11.rst\n+++ b/doc/guides/rel_notes/release_18_11.rst\n@@ -59,7 +59,9 @@ New Features\n   Flow API support has been enhanced for CXGBE Poll Mode Driver to offload:\n \n   * Match items: destination MAC address.\n-  * Action items: push/pop/rewrite vlan header.\n+  * Action items: push/pop/rewrite vlan header, rewrite IP addresses in\n+    outermost IPv4/IPv6 header, rewrite port numbers in outermost TCP/UDP\n+    header.\n \n * **Added support for SR-IOV in netvsc PMD.**\n \ndiff --git a/drivers/net/cxgbe/base/common.h b/drivers/net/cxgbe/base/common.h\nindex d9f74d995..fd2006682 100644\n--- a/drivers/net/cxgbe/base/common.h\n+++ b/drivers/net/cxgbe/base/common.h\n@@ -271,6 +271,7 @@ struct adapter_params {\n \n \tbool ulptx_memwrite_dsgl;          /* use of T5 DSGL allowed */\n \tu8 fw_caps_support;\t\t  /* 32-bit Port Capabilities */\n+\tu8 filter2_wr_support;            /* FW support for FILTER2_WR */\n };\n \n /* Firmware Port Capabilities types.\ndiff --git a/drivers/net/cxgbe/base/t4_msg.h b/drivers/net/cxgbe/base/t4_msg.h\nindex 2128da64f..6494f1827 100644\n--- a/drivers/net/cxgbe/base/t4_msg.h\n+++ b/drivers/net/cxgbe/base/t4_msg.h\n@@ -32,6 +32,7 @@ enum CPL_error {\n \n enum {\n \tULP_MODE_NONE          = 0,\n+\tULP_MODE_TCPDDP        = 5,\n };\n \n enum {\ndiff --git a/drivers/net/cxgbe/base/t4fw_interface.h b/drivers/net/cxgbe/base/t4fw_interface.h\nindex e2d2ee897..b4c95c588 100644\n--- a/drivers/net/cxgbe/base/t4fw_interface.h\n+++ b/drivers/net/cxgbe/base/t4fw_interface.h\n@@ -61,6 +61,7 @@ enum fw_wr_opcodes {\n \tFW_ETH_TX_PKTS_WR\t= 0x09,\n \tFW_ETH_TX_PKT_VM_WR\t= 0x11,\n \tFW_ETH_TX_PKTS_VM_WR\t= 0x12,\n+\tFW_FILTER2_WR\t\t= 0x77,\n \tFW_ETH_TX_PKTS2_WR      = 0x78,\n };\n \n@@ -165,7 +166,7 @@ enum fw_filter_wr_cookie {\n \tFW_FILTER_WR_EINVAL,\n };\n \n-struct fw_filter_wr {\n+struct fw_filter2_wr {\n \t__be32 op_pkd;\n \t__be32 len16_pkd;\n \t__be64 r3;\n@@ -195,6 +196,19 @@ struct fw_filter_wr {\n \t__be16 fpm;\n \t__be16 r7;\n \t__u8   sma[6];\n+\t__be16 r8;\n+\t__u8   filter_type_swapmac;\n+\t__u8   natmode_to_ulp_type;\n+\t__be16 newlport;\n+\t__be16 newfport;\n+\t__u8   newlip[16];\n+\t__u8   newfip[16];\n+\t__be32 natseqcheck;\n+\t__be32 r9;\n+\t__be64 r10;\n+\t__be64 r11;\n+\t__be64 r12;\n+\t__be64 r13;\n };\n \n #define S_FW_FILTER_WR_TID\t12\n@@ -300,6 +314,12 @@ struct fw_filter_wr {\n #define S_FW_FILTER_WR_MATCHTYPEM\t0\n #define V_FW_FILTER_WR_MATCHTYPEM(x)\t((x) << S_FW_FILTER_WR_MATCHTYPEM)\n \n+#define S_FW_FILTER2_WR_NATMODE\t\t5\n+#define V_FW_FILTER2_WR_NATMODE(x)\t((x) << S_FW_FILTER2_WR_NATMODE)\n+\n+#define S_FW_FILTER2_WR_ULP_TYPE\t0\n+#define V_FW_FILTER2_WR_ULP_TYPE(x)\t((x) << S_FW_FILTER2_WR_ULP_TYPE)\n+\n /******************************************************************************\n  *  C O M M A N D s\n  *********************/\n@@ -655,6 +675,7 @@ enum fw_params_param_dev {\n \tFW_PARAMS_PARAM_DEV_FWREV\t= 0x0B, /* fw version */\n \tFW_PARAMS_PARAM_DEV_TPREV\t= 0x0C, /* tp version */\n \tFW_PARAMS_PARAM_DEV_ULPTX_MEMWRITE_DSGL = 0x17,\n+\tFW_PARAMS_PARAM_DEV_FILTER2_WR\t= 0x1D,\n };\n \n /*\ndiff --git a/drivers/net/cxgbe/cxgbe_filter.c b/drivers/net/cxgbe/cxgbe_filter.c\nindex dcb1dd03e..b876abf43 100644\n--- a/drivers/net/cxgbe/cxgbe_filter.c\n+++ b/drivers/net/cxgbe/cxgbe_filter.c\n@@ -89,6 +89,9 @@ int validate_filter(struct adapter *adapter, struct ch_filter_specification *fs)\n \tif (fs->val.iport >= adapter->params.nports)\n \t\treturn -ERANGE;\n \n+\tif (!fs->cap && fs->nat_mode && !adapter->params.filter2_wr_support)\n+\t\treturn -EOPNOTSUPP;\n+\n \treturn 0;\n }\n \n@@ -627,6 +630,7 @@ void clear_filter(struct filter_entry *f)\n \n /**\n  * t4_mk_filtdelwr - create a delete filter WR\n+ * @adap: adapter context\n  * @ftid: the filter ID\n  * @wr: the filter work request to populate\n  * @qid: ingress queue to receive the delete notification\n@@ -634,10 +638,14 @@ void clear_filter(struct filter_entry *f)\n  * Creates a filter work request to delete the supplied filter.  If @qid is\n  * negative the delete notification is suppressed.\n  */\n-static void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid)\n+static void t4_mk_filtdelwr(struct adapter *adap, unsigned int ftid,\n+\t\t\t    struct fw_filter2_wr *wr, int qid)\n {\n \tmemset(wr, 0, sizeof(*wr));\n-\twr->op_pkd = cpu_to_be32(V_FW_WR_OP(FW_FILTER_WR));\n+\tif (adap->params.filter2_wr_support)\n+\t\twr->op_pkd = cpu_to_be32(V_FW_WR_OP(FW_FILTER2_WR));\n+\telse\n+\t\twr->op_pkd = cpu_to_be32(V_FW_WR_OP(FW_FILTER_WR));\n \twr->len16_pkd = cpu_to_be32(V_FW_WR_LEN16(sizeof(*wr) / 16));\n \twr->tid_to_iq = cpu_to_be32(V_FW_FILTER_WR_TID(ftid) |\n \t\t\t\t    V_FW_FILTER_WR_NOREPLY(qid < 0));\n@@ -655,7 +663,7 @@ static int del_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)\n \tstruct adapter *adapter = ethdev2adap(dev);\n \tstruct filter_entry *f = &adapter->tids.ftid_tab[fidx];\n \tstruct rte_mbuf *mbuf;\n-\tstruct fw_filter_wr *fwr;\n+\tstruct fw_filter2_wr *fwr;\n \tstruct sge_ctrl_txq *ctrlq;\n \tunsigned int port_id = ethdev2pinfo(dev)->port_id;\n \n@@ -667,8 +675,8 @@ static int del_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)\n \tmbuf->data_len = sizeof(*fwr);\n \tmbuf->pkt_len = mbuf->data_len;\n \n-\tfwr = rte_pktmbuf_mtod(mbuf, struct fw_filter_wr *);\n-\tt4_mk_filtdelwr(f->tid, fwr, adapter->sge.fw_evtq.abs_id);\n+\tfwr = rte_pktmbuf_mtod(mbuf, struct fw_filter2_wr *);\n+\tt4_mk_filtdelwr(adapter, f->tid, fwr, adapter->sge.fw_evtq.abs_id);\n \n \t/*\n \t * Mark the filter as \"pending\" and ship off the Filter Work Request.\n@@ -684,7 +692,7 @@ int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)\n \tstruct adapter *adapter = ethdev2adap(dev);\n \tstruct filter_entry *f = &adapter->tids.ftid_tab[fidx];\n \tstruct rte_mbuf *mbuf;\n-\tstruct fw_filter_wr *fwr;\n+\tstruct fw_filter2_wr *fwr;\n \tstruct sge_ctrl_txq *ctrlq;\n \tunsigned int port_id = ethdev2pinfo(dev)->port_id;\n \tint ret;\n@@ -712,13 +720,16 @@ int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)\n \tmbuf->data_len = sizeof(*fwr);\n \tmbuf->pkt_len = mbuf->data_len;\n \n-\tfwr = rte_pktmbuf_mtod(mbuf, struct fw_filter_wr *);\n+\tfwr = rte_pktmbuf_mtod(mbuf, struct fw_filter2_wr *);\n \tmemset(fwr, 0, sizeof(*fwr));\n \n \t/*\n \t * Construct the work request to set the filter.\n \t */\n-\tfwr->op_pkd = cpu_to_be32(V_FW_WR_OP(FW_FILTER_WR));\n+\tif (adapter->params.filter2_wr_support)\n+\t\tfwr->op_pkd = cpu_to_be32(V_FW_WR_OP(FW_FILTER2_WR));\n+\telse\n+\t\tfwr->op_pkd = cpu_to_be32(V_FW_WR_OP(FW_FILTER_WR));\n \tfwr->len16_pkd = cpu_to_be32(V_FW_WR_LEN16(sizeof(*fwr) / 16));\n \tfwr->tid_to_iq =\n \t\tcpu_to_be32(V_FW_FILTER_WR_TID(f->tid) |\n@@ -762,6 +773,16 @@ int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)\n \tfwr->fp = cpu_to_be16(f->fs.val.fport);\n \tfwr->fpm = cpu_to_be16(f->fs.mask.fport);\n \n+\tif (adapter->params.filter2_wr_support && f->fs.nat_mode) {\n+\t\tfwr->natmode_to_ulp_type =\n+\t\t\tV_FW_FILTER2_WR_ULP_TYPE(ULP_MODE_TCPDDP) |\n+\t\t\tV_FW_FILTER2_WR_NATMODE(f->fs.nat_mode);\n+\t\tmemcpy(fwr->newlip, f->fs.nat_lip, sizeof(fwr->newlip));\n+\t\tmemcpy(fwr->newfip, f->fs.nat_fip, sizeof(fwr->newfip));\n+\t\tfwr->newlport = cpu_to_be16(f->fs.nat_lport);\n+\t\tfwr->newfport = cpu_to_be16(f->fs.nat_fport);\n+\t}\n+\n \t/*\n \t * Mark the filter as \"pending\" and ship off the Filter Work Request.\n \t * When we get the Work Request Reply we'll clear the pending status.\ndiff --git a/drivers/net/cxgbe/cxgbe_filter.h b/drivers/net/cxgbe/cxgbe_filter.h\nindex 83d647de6..950fa0bca 100644\n--- a/drivers/net/cxgbe/cxgbe_filter.h\n+++ b/drivers/net/cxgbe/cxgbe_filter.h\n@@ -104,6 +104,18 @@ struct ch_filter_specification {\n \tuint8_t dmac[ETHER_ADDR_LEN];   /* new destination MAC address */\n \tuint16_t vlan;          /* VLAN Tag to insert */\n \n+\t/*\n+\t * Switch proxy/rewrite fields.  An ingress packet which matches a\n+\t * filter with \"switch\" set will be looped back out as an egress\n+\t * packet -- potentially with some header rewriting.\n+\t */\n+\tuint32_t nat_mode:3;\t/* specify NAT operation mode */\n+\n+\tuint8_t nat_lip[16];\t/* local IP to use after NAT'ing */\n+\tuint8_t nat_fip[16];\t/* foreign IP to use after NAT'ing */\n+\tuint16_t nat_lport;\t/* local port number to use after NAT'ing */\n+\tuint16_t nat_fport;\t/* foreign port number to use after NAT'ing */\n+\n \t/* Filter rule value/mask pairs. */\n \tstruct ch_filter_tuple val;\n \tstruct ch_filter_tuple mask;\n@@ -121,6 +133,17 @@ enum {\n \tVLAN_REWRITE\n };\n \n+enum {\n+\tNAT_MODE_NONE = 0,\t/* No NAT performed */\n+\tNAT_MODE_DIP,\t\t/* NAT on Dst IP */\n+\tNAT_MODE_DIP_DP,\t/* NAT on Dst IP, Dst Port */\n+\tNAT_MODE_DIP_DP_SIP,\t/* NAT on Dst IP, Dst Port and Src IP */\n+\tNAT_MODE_DIP_DP_SP,\t/* NAT on Dst IP, Dst Port and Src Port */\n+\tNAT_MODE_SIP_SP,\t/* NAT on Src IP and Src Port */\n+\tNAT_MODE_DIP_SIP_SP,\t/* NAT on Dst IP, Src IP and Src Port */\n+\tNAT_MODE_ALL\t\t/* NAT on entire 4-tuple */\n+};\n+\n enum filter_type {\n \tFILTER_TYPE_IPV4 = 0,\n \tFILTER_TYPE_IPV6,\ndiff --git a/drivers/net/cxgbe/cxgbe_flow.c b/drivers/net/cxgbe/cxgbe_flow.c\nindex bee3bd640..52cb3bdf4 100644\n--- a/drivers/net/cxgbe/cxgbe_flow.c\n+++ b/drivers/net/cxgbe/cxgbe_flow.c\n@@ -368,14 +368,77 @@ static int cxgbe_get_fidx(struct rte_flow *flow, unsigned int *fidx)\n \treturn 0;\n }\n \n+static int\n+cxgbe_get_flow_item_index(const struct rte_flow_item items[], u32 type)\n+{\n+\tconst struct rte_flow_item *i;\n+\tint j, index = -ENOENT;\n+\n+\tfor (i = items, j = 0; i->type != RTE_FLOW_ITEM_TYPE_END; i++, j++) {\n+\t\tif (i->type == type) {\n+\t\t\tindex = j;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\treturn index;\n+}\n+\n+static int\n+ch_rte_parse_nat(uint8_t nmode, struct ch_filter_specification *fs)\n+{\n+\t/* nmode:\n+\t * BIT_0 = [src_ip],   BIT_1 = [dst_ip]\n+\t * BIT_2 = [src_port], BIT_3 = [dst_port]\n+\t *\n+\t * Only below cases are supported as per our spec.\n+\t */\n+\tswitch (nmode) {\n+\tcase 0:  /* 0000b */\n+\t\tfs->nat_mode = NAT_MODE_NONE;\n+\t\tbreak;\n+\tcase 2:  /* 0010b */\n+\t\tfs->nat_mode = NAT_MODE_DIP;\n+\t\tbreak;\n+\tcase 5:  /* 0101b */\n+\t\tfs->nat_mode = NAT_MODE_SIP_SP;\n+\t\tbreak;\n+\tcase 7:  /* 0111b */\n+\t\tfs->nat_mode = NAT_MODE_DIP_SIP_SP;\n+\t\tbreak;\n+\tcase 10: /* 1010b */\n+\t\tfs->nat_mode = NAT_MODE_DIP_DP;\n+\t\tbreak;\n+\tcase 11: /* 1011b */\n+\t\tfs->nat_mode = NAT_MODE_DIP_DP_SIP;\n+\t\tbreak;\n+\tcase 14: /* 1110b */\n+\t\tfs->nat_mode = NAT_MODE_DIP_DP_SP;\n+\t\tbreak;\n+\tcase 15: /* 1111b */\n+\t\tfs->nat_mode = NAT_MODE_ALL;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n static int\n ch_rte_parse_atype_switch(const struct rte_flow_action *a,\n+\t\t\t  const struct rte_flow_item items[],\n+\t\t\t  uint8_t *nmode,\n \t\t\t  struct ch_filter_specification *fs,\n \t\t\t  struct rte_flow_error *e)\n {\n \tconst struct rte_flow_action_of_set_vlan_vid *vlanid;\n \tconst struct rte_flow_action_of_push_vlan *pushvlan;\n+\tconst struct rte_flow_action_set_ipv4 *ipv4;\n+\tconst struct rte_flow_action_set_ipv6 *ipv6;\n+\tconst struct rte_flow_action_set_tp *tp_port;\n \tconst struct rte_flow_action_phy_port *port;\n+\tint item_index;\n \n \tswitch (a->type) {\n \tcase RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:\n@@ -401,6 +464,94 @@ ch_rte_parse_atype_switch(const struct rte_flow_action *a,\n \t\tport = (const struct rte_flow_action_phy_port *)a->conf;\n \t\tfs->eport = port->index;\n \t\tbreak;\n+\tcase RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:\n+\t\titem_index = cxgbe_get_flow_item_index(items,\n+\t\t\t\t\t\t       RTE_FLOW_ITEM_TYPE_IPV4);\n+\t\tif (item_index < 0)\n+\t\t\treturn rte_flow_error_set(e, EINVAL,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, a,\n+\t\t\t\t\t\t  \"No RTE_FLOW_ITEM_TYPE_IPV4 \"\n+\t\t\t\t\t\t  \"found.\");\n+\n+\t\tipv4 = (const struct rte_flow_action_set_ipv4 *)a->conf;\n+\t\tmemcpy(fs->nat_fip, &ipv4->ipv4_addr, sizeof(ipv4->ipv4_addr));\n+\t\t*nmode |= 1 << 0;\n+\t\tbreak;\n+\tcase RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:\n+\t\titem_index = cxgbe_get_flow_item_index(items,\n+\t\t\t\t\t\t       RTE_FLOW_ITEM_TYPE_IPV4);\n+\t\tif (item_index < 0)\n+\t\t\treturn rte_flow_error_set(e, EINVAL,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, a,\n+\t\t\t\t\t\t  \"No RTE_FLOW_ITEM_TYPE_IPV4 \"\n+\t\t\t\t\t\t  \"found.\");\n+\n+\t\tipv4 = (const struct rte_flow_action_set_ipv4 *)a->conf;\n+\t\tmemcpy(fs->nat_lip, &ipv4->ipv4_addr, sizeof(ipv4->ipv4_addr));\n+\t\t*nmode |= 1 << 1;\n+\t\tbreak;\n+\tcase RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:\n+\t\titem_index = cxgbe_get_flow_item_index(items,\n+\t\t\t\t\t\t       RTE_FLOW_ITEM_TYPE_IPV6);\n+\t\tif (item_index < 0)\n+\t\t\treturn rte_flow_error_set(e, EINVAL,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, a,\n+\t\t\t\t\t\t  \"No RTE_FLOW_ITEM_TYPE_IPV6 \"\n+\t\t\t\t\t\t  \"found.\");\n+\n+\t\tipv6 = (const struct rte_flow_action_set_ipv6 *)a->conf;\n+\t\tmemcpy(fs->nat_fip, ipv6->ipv6_addr, sizeof(ipv6->ipv6_addr));\n+\t\t*nmode |= 1 << 0;\n+\t\tbreak;\n+\tcase RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:\n+\t\titem_index = cxgbe_get_flow_item_index(items,\n+\t\t\t\t\t\t       RTE_FLOW_ITEM_TYPE_IPV6);\n+\t\tif (item_index < 0)\n+\t\t\treturn rte_flow_error_set(e, EINVAL,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, a,\n+\t\t\t\t\t\t  \"No RTE_FLOW_ITEM_TYPE_IPV6 \"\n+\t\t\t\t\t\t  \"found.\");\n+\n+\t\tipv6 = (const struct rte_flow_action_set_ipv6 *)a->conf;\n+\t\tmemcpy(fs->nat_lip, ipv6->ipv6_addr, sizeof(ipv6->ipv6_addr));\n+\t\t*nmode |= 1 << 1;\n+\t\tbreak;\n+\tcase RTE_FLOW_ACTION_TYPE_SET_TP_SRC:\n+\t\titem_index = cxgbe_get_flow_item_index(items,\n+\t\t\t\t\t\t       RTE_FLOW_ITEM_TYPE_TCP);\n+\t\tif (item_index < 0) {\n+\t\t\titem_index =\n+\t\t\t\tcxgbe_get_flow_item_index(items,\n+\t\t\t\t\t\tRTE_FLOW_ITEM_TYPE_UDP);\n+\t\t\tif (item_index < 0)\n+\t\t\t\treturn rte_flow_error_set(e, EINVAL,\n+\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION, a,\n+\t\t\t\t\t\t\"No RTE_FLOW_ITEM_TYPE_TCP or \"\n+\t\t\t\t\t\t\"RTE_FLOW_ITEM_TYPE_UDP found\");\n+\t\t}\n+\n+\t\ttp_port = (const struct rte_flow_action_set_tp *)a->conf;\n+\t\tfs->nat_fport = be16_to_cpu(tp_port->port);\n+\t\t*nmode |= 1 << 2;\n+\t\tbreak;\n+\tcase RTE_FLOW_ACTION_TYPE_SET_TP_DST:\n+\t\titem_index = cxgbe_get_flow_item_index(items,\n+\t\t\t\t\t\t       RTE_FLOW_ITEM_TYPE_TCP);\n+\t\tif (item_index < 0) {\n+\t\t\titem_index =\n+\t\t\t\tcxgbe_get_flow_item_index(items,\n+\t\t\t\t\t\tRTE_FLOW_ITEM_TYPE_UDP);\n+\t\t\tif (item_index < 0)\n+\t\t\t\treturn rte_flow_error_set(e, EINVAL,\n+\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION, a,\n+\t\t\t\t\t\t\"No RTE_FLOW_ITEM_TYPE_TCP or \"\n+\t\t\t\t\t\t\"RTE_FLOW_ITEM_TYPE_UDP found\");\n+\t\t}\n+\n+\t\ttp_port = (const struct rte_flow_action_set_tp *)a->conf;\n+\t\tfs->nat_lport = be16_to_cpu(tp_port->port);\n+\t\t*nmode |= 1 << 3;\n+\t\tbreak;\n \tdefault:\n \t\t/* We are not supposed to come here */\n \t\treturn rte_flow_error_set(e, EINVAL,\n@@ -413,10 +564,12 @@ ch_rte_parse_atype_switch(const struct rte_flow_action *a,\n \n static int\n cxgbe_rtef_parse_actions(struct rte_flow *flow,\n+\t\t\t const struct rte_flow_item items[],\n \t\t\t const struct rte_flow_action action[],\n \t\t\t struct rte_flow_error *e)\n {\n \tstruct ch_filter_specification *fs = &flow->fs;\n+\tuint8_t nmode = 0, nat_ipv4 = 0, nat_ipv6 = 0;\n \tconst struct rte_flow_action_queue *q;\n \tconst struct rte_flow_action *a;\n \tchar abit = 0;\n@@ -458,6 +611,16 @@ cxgbe_rtef_parse_actions(struct rte_flow *flow,\n \t\tcase RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:\n \t\tcase RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:\n \t\tcase RTE_FLOW_ACTION_TYPE_PHY_PORT:\n+\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:\n+\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:\n+\t\t\tnat_ipv4++;\n+\t\t\tgoto action_switch;\n+\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:\n+\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:\n+\t\t\tnat_ipv6++;\n+\t\tcase RTE_FLOW_ACTION_TYPE_SET_TP_SRC:\n+\t\tcase RTE_FLOW_ACTION_TYPE_SET_TP_DST:\n+action_switch:\n \t\t\t/* We allow multiple switch actions, but switch is\n \t\t\t * not compatible with either queue or drop\n \t\t\t */\n@@ -465,7 +628,14 @@ cxgbe_rtef_parse_actions(struct rte_flow *flow,\n \t\t\t\treturn rte_flow_error_set(e, EINVAL,\n \t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION, a,\n \t\t\t\t\t\t\"overlapping action specified\");\n-\t\t\tret = ch_rte_parse_atype_switch(a, fs, e);\n+\t\t\tif (nat_ipv4 && nat_ipv6)\n+\t\t\t\treturn rte_flow_error_set(e, EINVAL,\n+\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION, a,\n+\t\t\t\t\t\"Can't have one address ipv4 and the\"\n+\t\t\t\t\t\" other ipv6\");\n+\n+\t\t\tret = ch_rte_parse_atype_switch(a, items, &nmode, fs,\n+\t\t\t\t\t\t\te);\n \t\t\tif (ret)\n \t\t\t\treturn ret;\n \t\t\tfs->action = FILTER_SWITCH;\n@@ -478,6 +648,10 @@ cxgbe_rtef_parse_actions(struct rte_flow *flow,\n \t\t}\n \t}\n \n+\tif (ch_rte_parse_nat(nmode, fs))\n+\t\treturn rte_flow_error_set(e, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, a,\n+\t\t\t\t\t  \"invalid settings for swich action\");\n \treturn 0;\n }\n \n@@ -586,7 +760,7 @@ cxgbe_flow_parse(struct rte_flow *flow,\n \tret = cxgbe_rtef_parse_items(flow, item, e);\n \tif (ret)\n \t\treturn ret;\n-\treturn cxgbe_rtef_parse_actions(flow, action, e);\n+\treturn cxgbe_rtef_parse_actions(flow, item, action, e);\n }\n \n static int __cxgbe_flow_create(struct rte_eth_dev *dev, struct rte_flow *flow)\ndiff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c\nindex 9c40f51b2..a135df9c7 100644\n--- a/drivers/net/cxgbe/cxgbe_main.c\n+++ b/drivers/net/cxgbe/cxgbe_main.c\n@@ -1180,6 +1180,16 @@ static int adap_init0(struct adapter *adap)\n \t\t\tgoto bye;\n \t}\n \n+\t/* See if FW supports FW_FILTER2 work request */\n+\tif (is_t4(adap->params.chip)) {\n+\t\tadap->params.filter2_wr_support = 0;\n+\t} else {\n+\t\tparams[0] = FW_PARAM_DEV(FILTER2_WR);\n+\t\tret = t4_query_params(adap, adap->mbox, adap->pf, 0,\n+\t\t\t\t      1, params, val);\n+\t\tadap->params.filter2_wr_support = (ret == 0 && val[0] != 0);\n+\t}\n+\n \t/* query tid-related parameters */\n \tparams[0] = FW_PARAM_DEV(NTID);\n \tret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1,\n",
    "prefixes": [
        "3/3"
    ]
}