get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 83957,
    "url": "http://patches.dpdk.org/api/patches/83957/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20201111064936.768604-16-jiawenwu@trustnetic.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "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",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20201111064936.768604-16-jiawenwu@trustnetic.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20201111064936.768604-16-jiawenwu@trustnetic.com",
    "date": "2020-11-11T06:49:14",
    "name": "[v2,15/37] net/txgbe: support FDIR add and delete operations",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "b93863e4954f394d52dc4e3475c35d6a85b058ff",
    "submitter": {
        "id": 1932,
        "url": "http://patches.dpdk.org/api/people/1932/?format=api",
        "name": "Jiawen Wu",
        "email": "jiawenwu@trustnetic.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20201111064936.768604-16-jiawenwu@trustnetic.com/mbox/",
    "series": [
        {
            "id": 13798,
            "url": "http://patches.dpdk.org/api/series/13798/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=13798",
            "date": "2020-11-11T06:49:00",
            "name": "net: add txgbe PMD part 2",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/13798/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/83957/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/83957/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 03237A09D2;\n\tWed, 11 Nov 2020 07:52:39 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 8212ABC66;\n\tWed, 11 Nov 2020 07:47:56 +0100 (CET)",
            "from smtpbgeu1.qq.com (smtpbgeu1.qq.com [52.59.177.22])\n by dpdk.org (Postfix) with ESMTP id 9A1936947\n for <dev@dpdk.org>; Wed, 11 Nov 2020 07:47:45 +0100 (CET)",
            "from localhost.localdomain.com (unknown [183.129.236.74])\n by esmtp10.qq.com (ESMTP) with\n id ; Wed, 11 Nov 2020 14:47:39 +0800 (CST)"
        ],
        "X-QQ-mid": "bizesmtp27t1605077260t37v2g24",
        "X-QQ-SSF": "01400000000000C0C000B00A0000000",
        "X-QQ-FEAT": "mJep2VbaKxYjU00PrJ4XjeluoURoSIKYIizf2URkGTaw3zujzpymGV38PeC2m\n DBYR6JGUciS5A0vh2eu5FbAJUgjS7H4xIUG03xiONaa6G2LW4C8X4E6kYQ9QuQqv1J6fIsB\n wTb3kxajLjY/WpMXr7qtCG9kF1WoAncKQKeuBv5olh8sKkI2t3omKaYFS1t+YpFLRSp52gP\n StsinVIzrHhM5XxMbWZW8X1m9Zocmp6spujcXpb9I+IzicKormFJ/j/kId2SwPpAkvt9m91\n 9IB/njrQVfL3sANxZ9od1gzuGdpxsdHIfDYOhiO2Y50WaSaqjj5OY2VfDZMeqQOZ5CHVMr8\n gyiLunG5GJx1ZzDHrcUhVxBkXnIBw==",
        "X-QQ-GoodBg": "2",
        "From": "Jiawen Wu <jiawenwu@trustnetic.com>",
        "To": "dev@dpdk.org",
        "Cc": "Jiawen Wu <jiawenwu@trustnetic.com>",
        "Date": "Wed, 11 Nov 2020 14:49:14 +0800",
        "Message-Id": "<20201111064936.768604-16-jiawenwu@trustnetic.com>",
        "X-Mailer": "git-send-email 2.18.4",
        "In-Reply-To": "<20201111064936.768604-1-jiawenwu@trustnetic.com>",
        "References": "<20201111064936.768604-1-jiawenwu@trustnetic.com>",
        "X-QQ-SENDSIZE": "520",
        "Feedback-ID": "bizesmtp:trustnetic.com:qybgforeign:qybgforeign7",
        "X-QQ-Bgrelay": "1",
        "Subject": "[dpdk-dev] [PATCH v2 15/37] net/txgbe: support FDIR add and delete\n\toperations",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Support add and delete operations on flow director.\n\nSigned-off-by: Jiawen Wu <jiawenwu@trustnetic.com>\n---\n drivers/net/txgbe/base/txgbe_type.h |  11 +\n drivers/net/txgbe/txgbe_ethdev.h    |  16 +\n drivers/net/txgbe/txgbe_fdir.c      | 472 +++++++++++++++++++++++++++-\n 3 files changed, 498 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h\nindex 633692cd7..160d5253a 100644\n--- a/drivers/net/txgbe/base/txgbe_type.h\n+++ b/drivers/net/txgbe/base/txgbe_type.h\n@@ -22,6 +22,7 @@\n #define TXGBE_MAX_UTA\t\t128\n \n #define TXGBE_FDIR_INIT_DONE_POLL\t\t10\n+#define TXGBE_FDIRCMD_CMD_POLL\t\t\t10\n \n #define TXGBE_ALIGN\t\t128 /* as intel did */\n \n@@ -71,7 +72,17 @@ enum {\n #define TXGBE_ATR_BUCKET_HASH_KEY\t\t0x3DAD14E2\n #define TXGBE_ATR_SIGNATURE_HASH_KEY\t\t0x174D3614\n \n+/* Software ATR input stream values and masks */\n #define TXGBE_ATR_HASH_MASK\t\t\t0x7fff\n+#define TXGBE_ATR_L3TYPE_MASK\t\t\t0x4\n+#define TXGBE_ATR_L3TYPE_IPV4\t\t\t0x0\n+#define TXGBE_ATR_L3TYPE_IPV6\t\t\t0x4\n+#define TXGBE_ATR_L4TYPE_MASK\t\t\t0x3\n+#define TXGBE_ATR_L4TYPE_UDP\t\t\t0x1\n+#define TXGBE_ATR_L4TYPE_TCP\t\t\t0x2\n+#define TXGBE_ATR_L4TYPE_SCTP\t\t\t0x3\n+#define TXGBE_ATR_TUNNEL_MASK\t\t\t0x10\n+#define TXGBE_ATR_TUNNEL_ANY\t\t\t0x10\n \n /* Flow Director ATR input struct. */\n struct txgbe_atr_input {\ndiff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h\nindex cd24efeea..ad72e1750 100644\n--- a/drivers/net/txgbe/txgbe_ethdev.h\n+++ b/drivers/net/txgbe/txgbe_ethdev.h\n@@ -91,6 +91,18 @@ struct txgbe_fdir_filter {\n /* list of fdir filters */\n TAILQ_HEAD(txgbe_fdir_filter_list, txgbe_fdir_filter);\n \n+struct txgbe_fdir_rule {\n+\tstruct txgbe_hw_fdir_mask mask;\n+\tstruct txgbe_atr_input input; /* key of fdir filter */\n+\tbool b_spec; /* If TRUE, input, fdirflags, queue have meaning. */\n+\tbool b_mask; /* If TRUE, mask has meaning. */\n+\tenum rte_fdir_mode mode; /* IP, MAC VLAN, Tunnel */\n+\tuint32_t fdirflags; /* drop or forward */\n+\tuint32_t soft_id; /* an unique value for this rule */\n+\tuint8_t queue; /* assigned rx queue */\n+\tuint8_t flex_bytes_offset;\n+};\n+\n struct txgbe_hw_fdir_info {\n \tstruct txgbe_hw_fdir_mask mask;\n \tuint8_t     flex_bytes_offset;\n@@ -436,6 +448,10 @@ void txgbe_set_ivar_map(struct txgbe_hw *hw, int8_t direction,\n  */\n int txgbe_fdir_configure(struct rte_eth_dev *dev);\n int txgbe_fdir_set_input_mask(struct rte_eth_dev *dev);\n+int txgbe_fdir_filter_program(struct rte_eth_dev *dev,\n+\t\t\t      struct txgbe_fdir_rule *rule,\n+\t\t\t      bool del, bool update);\n+\n void txgbe_configure_pb(struct rte_eth_dev *dev);\n void txgbe_configure_port(struct rte_eth_dev *dev);\n void txgbe_configure_dcb(struct rte_eth_dev *dev);\ndiff --git a/drivers/net/txgbe/txgbe_fdir.c b/drivers/net/txgbe/txgbe_fdir.c\nindex df6125d4a..d38e21e9e 100644\n--- a/drivers/net/txgbe/txgbe_fdir.c\n+++ b/drivers/net/txgbe/txgbe_fdir.c\n@@ -7,7 +7,7 @@\n #include <stdarg.h>\n #include <errno.h>\n #include <sys/queue.h>\n-\n+#include <rte_malloc.h>\n \n #include \"txgbe_logs.h\"\n #include \"base/txgbe.h\"\n@@ -15,6 +15,7 @@\n \n #define TXGBE_DEFAULT_FLEXBYTES_OFFSET  12 /*default flexbytes offset in bytes*/\n #define TXGBE_MAX_FLX_SOURCE_OFF        62\n+#define TXGBE_FDIRCMD_CMD_INTERVAL_US   10\n \n #define IPV6_ADDR_TO_MASK(ipaddr, ipv6m) do { \\\n \tuint8_t ipv6_addr[16]; \\\n@@ -405,3 +406,472 @@ txgbe_fdir_configure(struct rte_eth_dev *dev)\n \treturn 0;\n }\n \n+/*\n+ * Note that the bkt_hash field in the txgbe_atr_input structure is also never\n+ * set.\n+ *\n+ * Compute the hashes for SW ATR\n+ *  @stream: input bitstream to compute the hash on\n+ *  @key: 32-bit hash key\n+ **/\n+static uint32_t\n+txgbe_atr_compute_hash(struct txgbe_atr_input *atr_input,\n+\t\t\t\t uint32_t key)\n+{\n+\t/*\n+\t * The algorithm is as follows:\n+\t *    Hash[15:0] = Sum { S[n] x K[n+16] }, n = 0...350\n+\t *    where Sum {A[n]}, n = 0...n is bitwise XOR of A[0], A[1]...A[n]\n+\t *    and A[n] x B[n] is bitwise AND between same length strings\n+\t *\n+\t *    K[n] is 16 bits, defined as:\n+\t *       for n modulo 32 >= 15, K[n] = K[n % 32 : (n % 32) - 15]\n+\t *       for n modulo 32 < 15, K[n] =\n+\t *             K[(n % 32:0) | (31:31 - (14 - (n % 32)))]\n+\t *\n+\t *    S[n] is 16 bits, defined as:\n+\t *       for n >= 15, S[n] = S[n:n - 15]\n+\t *       for n < 15, S[n] = S[(n:0) | (350:350 - (14 - n))]\n+\t *\n+\t *    To simplify for programming, the algorithm is implemented\n+\t *    in software this way:\n+\t *\n+\t *    key[31:0], hi_hash_dword[31:0], lo_hash_dword[31:0], hash[15:0]\n+\t *\n+\t *    for (i = 0; i < 352; i+=32)\n+\t *        hi_hash_dword[31:0] ^= Stream[(i+31):i];\n+\t *\n+\t *    lo_hash_dword[15:0]  ^= Stream[15:0];\n+\t *    lo_hash_dword[15:0]  ^= hi_hash_dword[31:16];\n+\t *    lo_hash_dword[31:16] ^= hi_hash_dword[15:0];\n+\t *\n+\t *    hi_hash_dword[31:0]  ^= Stream[351:320];\n+\t *\n+\t *    if (key[0])\n+\t *        hash[15:0] ^= Stream[15:0];\n+\t *\n+\t *    for (i = 0; i < 16; i++) {\n+\t *        if (key[i])\n+\t *            hash[15:0] ^= lo_hash_dword[(i+15):i];\n+\t *        if (key[i + 16])\n+\t *            hash[15:0] ^= hi_hash_dword[(i+15):i];\n+\t *    }\n+\t *\n+\t */\n+\t__be32 *dword_stream = (__be32 *)atr_input;\n+\t__be32 common_hash_dword = 0;\n+\tu32 hi_hash_dword, lo_hash_dword, flow_pool_ptid;\n+\tu32 hash_result = 0;\n+\tu8 i;\n+\n+\t/* record the flow_vm_vlan bits as they are a key part to the hash */\n+\tflow_pool_ptid = be_to_cpu32(dword_stream[0]);\n+\n+\t/* generate common hash dword */\n+\tfor (i = 1; i <= 10; i++)\n+\t\tcommon_hash_dword ^= dword_stream[i];\n+\n+\thi_hash_dword = be_to_cpu32(common_hash_dword);\n+\n+\t/* low dword is word swapped version of common */\n+\tlo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);\n+\n+\t/* apply (Flow ID/VM Pool/Packet Type) bits to hash words */\n+\thi_hash_dword ^= flow_pool_ptid ^ (flow_pool_ptid >> 16);\n+\n+\t/* Process bits 0 and 16 */\n+\tif (key & 0x0001)\n+\t\thash_result ^= lo_hash_dword;\n+\tif (key & 0x00010000)\n+\t\thash_result ^= hi_hash_dword;\n+\n+\t/*\n+\t * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to\n+\t * delay this because bit 0 of the stream should not be processed\n+\t * so we do not add the vlan until after bit 0 was processed\n+\t */\n+\tlo_hash_dword ^= flow_pool_ptid ^ (flow_pool_ptid << 16);\n+\n+\t/* process the remaining 30 bits in the key 2 bits at a time */\n+\tfor (i = 15; i; i--) {\n+\t\tif (key & (0x0001 << i))\n+\t\t\thash_result ^= lo_hash_dword >> i;\n+\t\tif (key & (0x00010000 << i))\n+\t\t\thash_result ^= hi_hash_dword >> i;\n+\t}\n+\n+\treturn hash_result;\n+}\n+\n+static uint32_t\n+atr_compute_perfect_hash(struct txgbe_atr_input *input,\n+\t\tenum rte_fdir_pballoc_type pballoc)\n+{\n+\tuint32_t bucket_hash;\n+\n+\tbucket_hash = txgbe_atr_compute_hash(input,\n+\t\t\t\tTXGBE_ATR_BUCKET_HASH_KEY);\n+\tif (pballoc == RTE_FDIR_PBALLOC_256K)\n+\t\tbucket_hash &= PERFECT_BUCKET_256KB_HASH_MASK;\n+\telse if (pballoc == RTE_FDIR_PBALLOC_128K)\n+\t\tbucket_hash &= PERFECT_BUCKET_128KB_HASH_MASK;\n+\telse\n+\t\tbucket_hash &= PERFECT_BUCKET_64KB_HASH_MASK;\n+\n+\treturn TXGBE_FDIRPIHASH_BKT(bucket_hash);\n+}\n+\n+/**\n+ * txgbe_fdir_check_cmd_complete - poll to check whether FDIRPICMD is complete\n+ * @hw: pointer to hardware structure\n+ */\n+static inline int\n+txgbe_fdir_check_cmd_complete(struct txgbe_hw *hw, uint32_t *fdircmd)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < TXGBE_FDIRCMD_CMD_POLL; i++) {\n+\t\t*fdircmd = rd32(hw, TXGBE_FDIRPICMD);\n+\t\tif (!(*fdircmd & TXGBE_FDIRPICMD_OP_MASK))\n+\t\t\treturn 0;\n+\t\trte_delay_us(TXGBE_FDIRCMD_CMD_INTERVAL_US);\n+\t}\n+\n+\treturn -ETIMEDOUT;\n+}\n+\n+/*\n+ * Calculate the hash value needed for signature-match filters. In the FreeBSD\n+ * driver, this is done by the optimised function\n+ * txgbe_atr_compute_sig_hash_raptor(). However that can't be used here as it\n+ * doesn't support calculating a hash for an IPv6 filter.\n+ */\n+static uint32_t\n+atr_compute_signature_hash(struct txgbe_atr_input *input,\n+\t\tenum rte_fdir_pballoc_type pballoc)\n+{\n+\tuint32_t bucket_hash, sig_hash;\n+\n+\tbucket_hash = txgbe_atr_compute_hash(input,\n+\t\t\t\tTXGBE_ATR_BUCKET_HASH_KEY);\n+\tif (pballoc == RTE_FDIR_PBALLOC_256K)\n+\t\tbucket_hash &= SIG_BUCKET_256KB_HASH_MASK;\n+\telse if (pballoc == RTE_FDIR_PBALLOC_128K)\n+\t\tbucket_hash &= SIG_BUCKET_128KB_HASH_MASK;\n+\telse\n+\t\tbucket_hash &= SIG_BUCKET_64KB_HASH_MASK;\n+\n+\tsig_hash = txgbe_atr_compute_hash(input,\n+\t\t\t\tTXGBE_ATR_SIGNATURE_HASH_KEY);\n+\n+\treturn TXGBE_FDIRPIHASH_SIG(sig_hash) |\n+\t       TXGBE_FDIRPIHASH_BKT(bucket_hash);\n+}\n+\n+/**\n+ * With the ability to set extra flags in FDIRPICMD register\n+ * added, and IPv6 support also added. The hash value is also pre-calculated\n+ * as the pballoc value is needed to do it.\n+ */\n+static int\n+fdir_write_perfect_filter(struct txgbe_hw *hw,\n+\t\t\tstruct txgbe_atr_input *input, uint8_t queue,\n+\t\t\tuint32_t fdircmd, uint32_t fdirhash,\n+\t\t\tenum rte_fdir_mode mode)\n+{\n+\tuint32_t fdirport, fdirflex;\n+\tint err = 0;\n+\n+\tUNREFERENCED_PARAMETER(mode);\n+\n+\t/* record the IPv4 address (little-endian)\n+\t * can not use wr32.\n+\t */\n+\twr32(hw, TXGBE_FDIRPISIP4, be_to_le32(input->src_ip[0]));\n+\twr32(hw, TXGBE_FDIRPIDIP4, be_to_le32(input->dst_ip[0]));\n+\n+\t/* record source and destination port (little-endian)*/\n+\tfdirport = TXGBE_FDIRPIPORT_DST(be_to_le16(input->dst_port));\n+\tfdirport |= TXGBE_FDIRPIPORT_SRC(be_to_le16(input->src_port));\n+\twr32(hw, TXGBE_FDIRPIPORT, fdirport);\n+\n+\t/* record pkt_type (little-endian) and flex_bytes(big-endian) */\n+\tfdirflex = TXGBE_FDIRPIFLEX_FLEX(be_to_npu16(input->flex_bytes));\n+\tfdirflex |= TXGBE_FDIRPIFLEX_PTYPE(be_to_le16(input->pkt_type));\n+\twr32(hw, TXGBE_FDIRPIFLEX, fdirflex);\n+\n+\t/* configure FDIRHASH register */\n+\tfdirhash |= TXGBE_FDIRPIHASH_VLD;\n+\twr32(hw, TXGBE_FDIRPIHASH, fdirhash);\n+\n+\t/*\n+\t * flush all previous writes to make certain registers are\n+\t * programmed prior to issuing the command\n+\t */\n+\ttxgbe_flush(hw);\n+\n+\t/* configure FDIRPICMD register */\n+\tfdircmd |= TXGBE_FDIRPICMD_OP_ADD |\n+\t\t   TXGBE_FDIRPICMD_UPD |\n+\t\t   TXGBE_FDIRPICMD_LAST |\n+\t\t   TXGBE_FDIRPICMD_QPENA;\n+\tfdircmd |= TXGBE_FDIRPICMD_FT(input->flow_type);\n+\tfdircmd |= TXGBE_FDIRPICMD_QP(queue);\n+\tfdircmd |= TXGBE_FDIRPICMD_POOL(input->vm_pool);\n+\n+\twr32(hw, TXGBE_FDIRPICMD, fdircmd);\n+\n+\tPMD_DRV_LOG(DEBUG, \"Rx Queue=%x hash=%x\", queue, fdirhash);\n+\n+\terr = txgbe_fdir_check_cmd_complete(hw, &fdircmd);\n+\tif (err < 0)\n+\t\tPMD_DRV_LOG(ERR, \"Timeout writing flow director filter.\");\n+\n+\treturn err;\n+}\n+\n+/**\n+ * This function supports setting extra fields in the FDIRPICMD register, and\n+ * removes the code that was verifying the flow_type field. According to the\n+ * documentation, a flow type of 00 (i.e. not TCP, UDP, or SCTP) is not\n+ * supported, however it appears to work ok...\n+ *  Adds a signature hash filter\n+ *  @hw: pointer to hardware structure\n+ *  @input: unique input dword\n+ *  @queue: queue index to direct traffic to\n+ *  @fdircmd: any extra flags to set in fdircmd register\n+ *  @fdirhash: pre-calculated hash value for the filter\n+ **/\n+static int\n+fdir_add_signature_filter(struct txgbe_hw *hw,\n+\t\tstruct txgbe_atr_input *input, uint8_t queue, uint32_t fdircmd,\n+\t\tuint32_t fdirhash)\n+{\n+\tint err = 0;\n+\n+\tPMD_INIT_FUNC_TRACE();\n+\n+\t/* configure FDIRPICMD register */\n+\tfdircmd |= TXGBE_FDIRPICMD_OP_ADD |\n+\t\t   TXGBE_FDIRPICMD_UPD |\n+\t\t   TXGBE_FDIRPICMD_LAST |\n+\t\t   TXGBE_FDIRPICMD_QPENA;\n+\tfdircmd |= TXGBE_FDIRPICMD_FT(input->flow_type);\n+\tfdircmd |= TXGBE_FDIRPICMD_QP(queue);\n+\n+\tfdirhash |= TXGBE_FDIRPIHASH_VLD;\n+\twr32(hw, TXGBE_FDIRPIHASH, fdirhash);\n+\twr32(hw, TXGBE_FDIRPICMD, fdircmd);\n+\n+\tPMD_DRV_LOG(DEBUG, \"Rx Queue=%x hash=%x\", queue, fdirhash);\n+\n+\terr = txgbe_fdir_check_cmd_complete(hw, &fdircmd);\n+\tif (err < 0)\n+\t\tPMD_DRV_LOG(ERR, \"Timeout writing flow director filter.\");\n+\n+\treturn err;\n+}\n+\n+/*\n+ * This is modified to take in the hash as a parameter so that\n+ * it can be used for removing signature and perfect filters.\n+ */\n+static int\n+fdir_erase_filter_raptor(struct txgbe_hw *hw, uint32_t fdirhash)\n+{\n+\tuint32_t fdircmd = 0;\n+\tint err = 0;\n+\n+\twr32(hw, TXGBE_FDIRPIHASH, fdirhash);\n+\n+\t/* flush hash to HW */\n+\ttxgbe_flush(hw);\n+\n+\t/* Query if filter is present */\n+\twr32(hw, TXGBE_FDIRPICMD, TXGBE_FDIRPICMD_OP_QRY);\n+\n+\terr = txgbe_fdir_check_cmd_complete(hw, &fdircmd);\n+\tif (err < 0) {\n+\t\tPMD_INIT_LOG(ERR, \"Timeout querying for flow director filter.\");\n+\t\treturn err;\n+\t}\n+\n+\t/* if filter exists in hardware then remove it */\n+\tif (fdircmd & TXGBE_FDIRPICMD_VLD) {\n+\t\twr32(hw, TXGBE_FDIRPIHASH, fdirhash);\n+\t\ttxgbe_flush(hw);\n+\t\twr32(hw, TXGBE_FDIRPICMD, TXGBE_FDIRPICMD_OP_REM);\n+\t}\n+\n+\terr = txgbe_fdir_check_cmd_complete(hw, &fdircmd);\n+\tif (err < 0)\n+\t\tPMD_INIT_LOG(ERR, \"Timeout erasing flow director filter.\");\n+\n+\treturn err;\n+}\n+\n+static inline struct txgbe_fdir_filter *\n+txgbe_fdir_filter_lookup(struct txgbe_hw_fdir_info *fdir_info,\n+\t\t\t struct txgbe_atr_input *input)\n+{\n+\tint ret;\n+\n+\tret = rte_hash_lookup(fdir_info->hash_handle, (const void *)input);\n+\tif (ret < 0)\n+\t\treturn NULL;\n+\n+\treturn fdir_info->hash_map[ret];\n+}\n+\n+static inline int\n+txgbe_insert_fdir_filter(struct txgbe_hw_fdir_info *fdir_info,\n+\t\t\t struct txgbe_fdir_filter *fdir_filter)\n+{\n+\tint ret;\n+\n+\tret = rte_hash_add_key(fdir_info->hash_handle, &fdir_filter->input);\n+\tif (ret < 0) {\n+\t\tPMD_DRV_LOG(ERR,\n+\t\t\t    \"Failed to insert fdir filter to hash table %d!\",\n+\t\t\t    ret);\n+\t\treturn ret;\n+\t}\n+\n+\tfdir_info->hash_map[ret] = fdir_filter;\n+\n+\tTAILQ_INSERT_TAIL(&fdir_info->fdir_list, fdir_filter, entries);\n+\n+\treturn 0;\n+}\n+\n+static inline int\n+txgbe_remove_fdir_filter(struct txgbe_hw_fdir_info *fdir_info,\n+\t\t\t struct txgbe_atr_input *input)\n+{\n+\tint ret;\n+\tstruct txgbe_fdir_filter *fdir_filter;\n+\n+\tret = rte_hash_del_key(fdir_info->hash_handle, input);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tfdir_filter = fdir_info->hash_map[ret];\n+\tfdir_info->hash_map[ret] = NULL;\n+\n+\tTAILQ_REMOVE(&fdir_info->fdir_list, fdir_filter, entries);\n+\trte_free(fdir_filter);\n+\n+\treturn 0;\n+}\n+\n+int\n+txgbe_fdir_filter_program(struct rte_eth_dev *dev,\n+\t\t\t  struct txgbe_fdir_rule *rule,\n+\t\t\t  bool del,\n+\t\t\t  bool update)\n+{\n+\tstruct txgbe_hw *hw = TXGBE_DEV_HW(dev);\n+\tuint32_t fdirhash;\n+\tuint8_t queue;\n+\tbool is_perfect = FALSE;\n+\tint err;\n+\tstruct txgbe_hw_fdir_info *info = TXGBE_DEV_FDIR(dev);\n+\tenum rte_fdir_mode fdir_mode = dev->data->dev_conf.fdir_conf.mode;\n+\tstruct txgbe_fdir_filter *node;\n+\n+\tif (fdir_mode == RTE_FDIR_MODE_NONE ||\n+\t    fdir_mode != rule->mode)\n+\t\treturn -ENOTSUP;\n+\n+\tif (fdir_mode >= RTE_FDIR_MODE_PERFECT)\n+\t\tis_perfect = TRUE;\n+\n+\tif (is_perfect) {\n+\t\tif (rule->input.flow_type & TXGBE_ATR_L3TYPE_IPV6) {\n+\t\t\tPMD_DRV_LOG(ERR, \"IPv6 is not supported in\"\n+\t\t\t\t    \" perfect mode!\");\n+\t\t\treturn -ENOTSUP;\n+\t\t}\n+\t\tfdirhash = atr_compute_perfect_hash(&rule->input,\n+\t\t\t\tdev->data->dev_conf.fdir_conf.pballoc);\n+\t\tfdirhash |= TXGBE_FDIRPIHASH_IDX(rule->soft_id);\n+\t} else {\n+\t\tfdirhash = atr_compute_signature_hash(&rule->input,\n+\t\t\t\tdev->data->dev_conf.fdir_conf.pballoc);\n+\t}\n+\n+\tif (del) {\n+\t\terr = txgbe_remove_fdir_filter(info, &rule->input);\n+\t\tif (err < 0) {\n+\t\t\tPMD_DRV_LOG(ERR,\n+\t\t\t\t\"No such fdir filter to delete %d!\", err);\n+\t\t\treturn err;\n+\t\t}\n+\n+\t\terr = fdir_erase_filter_raptor(hw, fdirhash);\n+\t\tif (err < 0)\n+\t\t\tPMD_DRV_LOG(ERR, \"Fail to delete FDIR filter!\");\n+\t\telse\n+\t\t\tPMD_DRV_LOG(DEBUG, \"Success to delete FDIR filter!\");\n+\t\treturn err;\n+\t}\n+\n+\t/* add or update an fdir filter*/\n+\tif (rule->fdirflags & TXGBE_FDIRPICMD_DROP) {\n+\t\tif (!is_perfect) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Drop option is not supported in\"\n+\t\t\t\t    \" signature mode.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tqueue = dev->data->dev_conf.fdir_conf.drop_queue;\n+\t} else if (rule->queue < TXGBE_MAX_RX_QUEUE_NUM) {\n+\t\tqueue = rule->queue;\n+\t} else {\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tnode = txgbe_fdir_filter_lookup(info, &rule->input);\n+\tif (node) {\n+\t\tif (!update) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Conflict with existing fdir filter!\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tnode->fdirflags = rule->fdirflags;\n+\t\tnode->fdirhash = fdirhash;\n+\t\tnode->queue = queue;\n+\t} else {\n+\t\tnode = rte_zmalloc(\"txgbe_fdir\",\n+\t\t\t\t   sizeof(struct txgbe_fdir_filter), 0);\n+\t\tif (!node)\n+\t\t\treturn -ENOMEM;\n+\t\trte_memcpy(&node->input, &rule->input,\n+\t\t\t   sizeof(struct txgbe_atr_input));\n+\t\tnode->fdirflags = rule->fdirflags;\n+\t\tnode->fdirhash = fdirhash;\n+\t\tnode->queue = queue;\n+\n+\t\terr = txgbe_insert_fdir_filter(info, node);\n+\t\tif (err < 0) {\n+\t\t\trte_free(node);\n+\t\t\treturn err;\n+\t\t}\n+\t}\n+\n+\tif (is_perfect)\n+\t\terr = fdir_write_perfect_filter(hw, &node->input,\n+\t\t\t\t\t\tnode->queue, node->fdirflags,\n+\t\t\t\t\t\tnode->fdirhash, fdir_mode);\n+\telse\n+\t\terr = fdir_add_signature_filter(hw, &node->input,\n+\t\t\t\t\t\tnode->queue, node->fdirflags,\n+\t\t\t\t\t\tnode->fdirhash);\n+\tif (err < 0) {\n+\t\tPMD_DRV_LOG(ERR, \"Fail to add FDIR filter!\");\n+\t\ttxgbe_remove_fdir_filter(info, &rule->input);\n+\t} else {\n+\t\tPMD_DRV_LOG(DEBUG, \"Success to add FDIR filter\");\n+\t}\n+\n+\treturn err;\n+}\n+\n",
    "prefixes": [
        "v2",
        "15/37"
    ]
}