get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 98297,
    "url": "http://patches.dpdk.org/api/patches/98297/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20210908083758.312055-18-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": "<20210908083758.312055-18-jiawenwu@trustnetic.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210908083758.312055-18-jiawenwu@trustnetic.com",
    "date": "2021-09-08T08:37:43",
    "name": "[17/32] net/ngbe: support RSS hash",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "210f729740d0b638fcfc2135d9d2758b7f4ccd26",
    "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/20210908083758.312055-18-jiawenwu@trustnetic.com/mbox/",
    "series": [
        {
            "id": 18760,
            "url": "http://patches.dpdk.org/api/series/18760/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=18760",
            "date": "2021-09-08T08:37:26",
            "name": "net/ngbe: add many features",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/18760/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/98297/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/98297/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 mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 8C0A5A0C56;\n\tWed,  8 Sep 2021 10:38:10 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 143CC41174;\n\tWed,  8 Sep 2021 10:36:59 +0200 (CEST)",
            "from smtpbguseast2.qq.com (smtpbguseast2.qq.com [54.204.34.130])\n by mails.dpdk.org (Postfix) with ESMTP id C52E0411DA\n for <dev@dpdk.org>; Wed,  8 Sep 2021 10:36:56 +0200 (CEST)",
            "from wxdbg.localdomain.com (unknown [183.129.236.74])\n by esmtp6.qq.com (ESMTP) with\n id ; Wed, 08 Sep 2021 16:36:51 +0800 (CST)"
        ],
        "X-QQ-mid": "bizesmtp47t1631090212t9i5fak1",
        "X-QQ-SSF": "01400000002000E0G000B00A0000000",
        "X-QQ-FEAT": "hJ5650VbgwAlYPvWfE0aZbXGWdMA8DwCKZQiGfa4sFUOcBavi5rg0ytAuvMh3\n fpJISDzgx7h5/k+UVkVmIdhO0D705/4GrvII/D4EeWqAB25lrAwfQqzEZ31l8Lk4ksY73UK\n BECh6lPqnry1If8PoSNs1Hmz3kjvW6hUTOwd8uDNNw8AjVfFiS7KmyXUBXj7eGmSkHlJsve\n Hglu4iwcoTARcEULoG1MYJudTAL0krQyHGWJON2AbwXyiJp72f4tSHSOj+ArK/JYIitNtbj\n vGEemVN3VBbgcKL6yBe13VvdDz/cXcEGCovLlbk48vvlEFyPkstJCwyKffAZhQ2wRj0dWF6\n 2d6xuExm3OUTLtVda3WOi33jk5rU94d4q30WDHO",
        "X-QQ-GoodBg": "2",
        "From": "Jiawen Wu <jiawenwu@trustnetic.com>",
        "To": "dev@dpdk.org",
        "Cc": "Jiawen Wu <jiawenwu@trustnetic.com>",
        "Date": "Wed,  8 Sep 2021 16:37:43 +0800",
        "Message-Id": "<20210908083758.312055-18-jiawenwu@trustnetic.com>",
        "X-Mailer": "git-send-email 2.27.0",
        "In-Reply-To": "<20210908083758.312055-1-jiawenwu@trustnetic.com>",
        "References": "<20210908083758.312055-1-jiawenwu@trustnetic.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-QQ-SENDSIZE": "520",
        "Feedback-ID": "bizesmtp:trustnetic.com:qybgforeign:qybgforeign7",
        "X-QQ-Bgrelay": "1",
        "Subject": "[dpdk-dev] [PATCH 17/32] net/ngbe: support RSS hash",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "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 RSS hashing on Rx, and configuration of RSS hash computation.\n\nSigned-off-by: Jiawen Wu <jiawenwu@trustnetic.com>\n---\n doc/guides/nics/features/ngbe.ini |   3 +\n doc/guides/nics/ngbe.rst          |   2 +\n drivers/net/ngbe/meson.build      |   2 +\n drivers/net/ngbe/ngbe_ethdev.c    |  99 +++++++++++++\n drivers/net/ngbe/ngbe_ethdev.h    |  27 ++++\n drivers/net/ngbe/ngbe_rxtx.c      | 235 ++++++++++++++++++++++++++++++\n 6 files changed, 368 insertions(+)",
    "diff": "diff --git a/doc/guides/nics/features/ngbe.ini b/doc/guides/nics/features/ngbe.ini\nindex 265edba361..70d731a695 100644\n--- a/doc/guides/nics/features/ngbe.ini\n+++ b/doc/guides/nics/features/ngbe.ini\n@@ -17,6 +17,9 @@ Promiscuous mode     = Y\n Allmulticast mode    = Y\n Unicast MAC filter   = Y\n Multicast MAC filter = Y\n+RSS hash             = Y\n+RSS key update       = Y\n+RSS reta update      = Y\n VLAN filter          = Y\n CRC offload          = P\n VLAN offload         = P\ndiff --git a/doc/guides/nics/ngbe.rst b/doc/guides/nics/ngbe.rst\nindex 3683862fd1..ce160e832c 100644\n--- a/doc/guides/nics/ngbe.rst\n+++ b/doc/guides/nics/ngbe.rst\n@@ -11,6 +11,8 @@ for Wangxun 1 Gigabit Ethernet NICs.\n Features\n --------\n \n+- Multiple queues for Tx and Rx\n+- Receiver Side Scaling (RSS)\n - MAC/VLAN filtering\n - Packet type information\n - Checksum offload\ndiff --git a/drivers/net/ngbe/meson.build b/drivers/net/ngbe/meson.build\nindex 05f94fe7d6..c55e6c20e8 100644\n--- a/drivers/net/ngbe/meson.build\n+++ b/drivers/net/ngbe/meson.build\n@@ -16,4 +16,6 @@ sources = files(\n         'ngbe_rxtx.c',\n )\n \n+deps += ['hash']\n+\n includes += include_directories('base')\ndiff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c\nindex acc018c811..0bc1400aea 100644\n--- a/drivers/net/ngbe/ngbe_ethdev.c\n+++ b/drivers/net/ngbe/ngbe_ethdev.c\n@@ -856,6 +856,9 @@ ngbe_dev_configure(struct rte_eth_dev *dev)\n \n \tPMD_INIT_FUNC_TRACE();\n \n+\tif (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG)\n+\t\tdev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;\n+\n \t/* set flag to update link status after init */\n \tintr->flags |= NGBE_FLAG_NEED_LINK_UPDATE;\n \n@@ -1082,6 +1085,7 @@ static int\n ngbe_dev_stop(struct rte_eth_dev *dev)\n {\n \tstruct rte_eth_link link;\n+\tstruct ngbe_adapter *adapter = ngbe_dev_adapter(dev);\n \tstruct ngbe_hw *hw = ngbe_dev_hw(dev);\n \tstruct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);\n \tstruct rte_intr_handle *intr_handle = &pci_dev->intr_handle;\n@@ -1129,6 +1133,8 @@ ngbe_dev_stop(struct rte_eth_dev *dev)\n \t\tintr_handle->intr_vec = NULL;\n \t}\n \n+\tadapter->rss_reta_updated = 0;\n+\n \thw->adapter_stopped = true;\n \tdev->data->dev_started = 0;\n \n@@ -1718,6 +1724,10 @@ ngbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)\n \tdev_info->rx_desc_lim = rx_desc_lim;\n \tdev_info->tx_desc_lim = tx_desc_lim;\n \n+\tdev_info->hash_key_size = NGBE_HKEY_MAX_INDEX * sizeof(uint32_t);\n+\tdev_info->reta_size = ETH_RSS_RETA_SIZE_128;\n+\tdev_info->flow_type_rss_offloads = NGBE_RSS_OFFLOAD_ALL;\n+\n \tdev_info->speed_capa = ETH_LINK_SPEED_1G | ETH_LINK_SPEED_100M |\n \t\t\t\tETH_LINK_SPEED_10M;\n \n@@ -2184,6 +2194,91 @@ ngbe_dev_interrupt_handler(void *param)\n \tngbe_dev_interrupt_action(dev);\n }\n \n+int\n+ngbe_dev_rss_reta_update(struct rte_eth_dev *dev,\n+\t\t\t  struct rte_eth_rss_reta_entry64 *reta_conf,\n+\t\t\t  uint16_t reta_size)\n+{\n+\tuint8_t i, j, mask;\n+\tuint32_t reta;\n+\tuint16_t idx, shift;\n+\tstruct ngbe_adapter *adapter = ngbe_dev_adapter(dev);\n+\tstruct ngbe_hw *hw = ngbe_dev_hw(dev);\n+\n+\tPMD_INIT_FUNC_TRACE();\n+\n+\tif (!hw->is_pf) {\n+\t\tPMD_DRV_LOG(ERR, \"RSS reta update is not supported on this \"\n+\t\t\t\"NIC.\");\n+\t\treturn -ENOTSUP;\n+\t}\n+\n+\tif (reta_size != ETH_RSS_RETA_SIZE_128) {\n+\t\tPMD_DRV_LOG(ERR, \"The size of hash lookup table configured \"\n+\t\t\t\"(%d) doesn't match the number hardware can supported \"\n+\t\t\t\"(%d)\", reta_size, ETH_RSS_RETA_SIZE_128);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tfor (i = 0; i < reta_size; i += 4) {\n+\t\tidx = i / RTE_RETA_GROUP_SIZE;\n+\t\tshift = i % RTE_RETA_GROUP_SIZE;\n+\t\tmask = (uint8_t)RS64(reta_conf[idx].mask, shift, 0xF);\n+\t\tif (!mask)\n+\t\t\tcontinue;\n+\n+\t\treta = rd32a(hw, NGBE_REG_RSSTBL, i >> 2);\n+\t\tfor (j = 0; j < 4; j++) {\n+\t\t\tif (RS8(mask, j, 0x1)) {\n+\t\t\t\treta  &= ~(MS32(8 * j, 0xFF));\n+\t\t\t\treta |= LS32(reta_conf[idx].reta[shift + j],\n+\t\t\t\t\t\t8 * j, 0xFF);\n+\t\t\t}\n+\t\t}\n+\t\twr32a(hw, NGBE_REG_RSSTBL, i >> 2, reta);\n+\t}\n+\tadapter->rss_reta_updated = 1;\n+\n+\treturn 0;\n+}\n+\n+int\n+ngbe_dev_rss_reta_query(struct rte_eth_dev *dev,\n+\t\t\t struct rte_eth_rss_reta_entry64 *reta_conf,\n+\t\t\t uint16_t reta_size)\n+{\n+\tstruct ngbe_hw *hw = ngbe_dev_hw(dev);\n+\tuint8_t i, j, mask;\n+\tuint32_t reta;\n+\tuint16_t idx, shift;\n+\n+\tPMD_INIT_FUNC_TRACE();\n+\n+\tif (reta_size != ETH_RSS_RETA_SIZE_128) {\n+\t\tPMD_DRV_LOG(ERR, \"The size of hash lookup table configured \"\n+\t\t\t\"(%d) doesn't match the number hardware can supported \"\n+\t\t\t\"(%d)\", reta_size, ETH_RSS_RETA_SIZE_128);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tfor (i = 0; i < reta_size; i += 4) {\n+\t\tidx = i / RTE_RETA_GROUP_SIZE;\n+\t\tshift = i % RTE_RETA_GROUP_SIZE;\n+\t\tmask = (uint8_t)RS64(reta_conf[idx].mask, shift, 0xF);\n+\t\tif (!mask)\n+\t\t\tcontinue;\n+\n+\t\treta = rd32a(hw, NGBE_REG_RSSTBL, i >> 2);\n+\t\tfor (j = 0; j < 4; j++) {\n+\t\t\tif (RS8(mask, j, 0x1))\n+\t\t\t\treta_conf[idx].reta[shift + j] =\n+\t\t\t\t\t(uint16_t)RS32(reta, 8 * j, 0xFF);\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n static int\n ngbe_add_rar(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,\n \t\t\t\tuint32_t index, uint32_t pool)\n@@ -2555,6 +2650,10 @@ static const struct eth_dev_ops ngbe_eth_dev_ops = {\n \t.mac_addr_set               = ngbe_set_default_mac_addr,\n \t.uc_hash_table_set          = ngbe_uc_hash_table_set,\n \t.uc_all_hash_table_set      = ngbe_uc_all_hash_table_set,\n+\t.reta_update                = ngbe_dev_rss_reta_update,\n+\t.reta_query                 = ngbe_dev_rss_reta_query,\n+\t.rss_hash_update            = ngbe_dev_rss_hash_update,\n+\t.rss_hash_conf_get          = ngbe_dev_rss_hash_conf_get,\n \t.set_mc_addr_list           = ngbe_dev_set_mc_addr_list,\n };\n \ndiff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h\nindex 65dad4a72b..083db6080b 100644\n--- a/drivers/net/ngbe/ngbe_ethdev.h\n+++ b/drivers/net/ngbe/ngbe_ethdev.h\n@@ -17,6 +17,7 @@\n \n #define NGBE_VFTA_SIZE 128\n #define NGBE_VLAN_TAG_SIZE 4\n+#define NGBE_HKEY_MAX_INDEX 10\n /*Default value of Max Rx Queue*/\n #define NGBE_MAX_RX_QUEUE_NUM\t8\n \n@@ -28,6 +29,17 @@\n \n #define NGBE_QUEUE_ITR_INTERVAL_DEFAULT\t500 /* 500us */\n \n+#define NGBE_RSS_OFFLOAD_ALL ( \\\n+\tETH_RSS_IPV4 | \\\n+\tETH_RSS_NONFRAG_IPV4_TCP | \\\n+\tETH_RSS_NONFRAG_IPV4_UDP | \\\n+\tETH_RSS_IPV6 | \\\n+\tETH_RSS_NONFRAG_IPV6_TCP | \\\n+\tETH_RSS_NONFRAG_IPV6_UDP | \\\n+\tETH_RSS_IPV6_EX | \\\n+\tETH_RSS_IPV6_TCP_EX | \\\n+\tETH_RSS_IPV6_UDP_EX)\n+\n #define NGBE_MISC_VEC_ID               RTE_INTR_VEC_ZERO_OFFSET\n #define NGBE_RX_VEC_START              RTE_INTR_VEC_RXTX_OFFSET\n \n@@ -75,6 +87,9 @@ struct ngbe_adapter {\n \tstruct ngbe_hwstrip        hwstrip;\n \tstruct ngbe_uta_info       uta_info;\n \tbool                       rx_bulk_alloc_allowed;\n+\n+\t/* For RSS reta table update */\n+\tuint8_t rss_reta_updated;\n };\n \n static inline struct ngbe_adapter *\n@@ -177,6 +192,12 @@ uint16_t ngbe_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts,\n uint16_t ngbe_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,\n \t\tuint16_t nb_pkts);\n \n+int ngbe_dev_rss_hash_update(struct rte_eth_dev *dev,\n+\t\t\t      struct rte_eth_rss_conf *rss_conf);\n+\n+int ngbe_dev_rss_hash_conf_get(struct rte_eth_dev *dev,\n+\t\t\t\tstruct rte_eth_rss_conf *rss_conf);\n+\n void ngbe_set_ivar_map(struct ngbe_hw *hw, int8_t direction,\n \t\t\t       uint8_t queue, uint8_t msix_vector);\n \n@@ -222,6 +243,12 @@ const uint32_t *ngbe_dev_supported_ptypes_get(struct rte_eth_dev *dev);\n int ngbe_dev_set_mc_addr_list(struct rte_eth_dev *dev,\n \t\t\t\t      struct rte_ether_addr *mc_addr_set,\n \t\t\t\t      uint32_t nb_mc_addr);\n+int ngbe_dev_rss_reta_update(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_eth_rss_reta_entry64 *reta_conf,\n+\t\t\tuint16_t reta_size);\n+int ngbe_dev_rss_reta_query(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_eth_rss_reta_entry64 *reta_conf,\n+\t\t\tuint16_t reta_size);\n void ngbe_vlan_hw_strip_bitmap_set(struct rte_eth_dev *dev,\n \t\tuint16_t queue, bool on);\n void ngbe_config_vlan_strip_on_all_queues(struct rte_eth_dev *dev,\ndiff --git a/drivers/net/ngbe/ngbe_rxtx.c b/drivers/net/ngbe/ngbe_rxtx.c\nindex 22693c144a..04abc2bb47 100644\n--- a/drivers/net/ngbe/ngbe_rxtx.c\n+++ b/drivers/net/ngbe/ngbe_rxtx.c\n@@ -897,6 +897,18 @@ ngbe_rxd_pkt_info_to_pkt_type(uint32_t pkt_info, uint16_t ptid_mask)\n \treturn ngbe_decode_ptype(ptid);\n }\n \n+static inline uint64_t\n+ngbe_rxd_pkt_info_to_pkt_flags(uint32_t pkt_info)\n+{\n+\tstatic uint64_t ip_rss_types_map[16] __rte_cache_aligned = {\n+\t\t0, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH,\n+\t\t0, PKT_RX_RSS_HASH, 0, PKT_RX_RSS_HASH,\n+\t\tPKT_RX_RSS_HASH, 0, 0, 0,\n+\t\t0, 0, 0,  PKT_RX_FDIR,\n+\t};\n+\treturn ip_rss_types_map[NGBE_RXD_RSSTYPE(pkt_info)];\n+}\n+\n static inline uint64_t\n rx_desc_status_to_pkt_flags(uint32_t rx_status, uint64_t vlan_flags)\n {\n@@ -1008,10 +1020,16 @@ ngbe_rx_scan_hw_ring(struct ngbe_rx_queue *rxq)\n \t\t\tpkt_flags = rx_desc_status_to_pkt_flags(s[j],\n \t\t\t\t\trxq->vlan_flags);\n \t\t\tpkt_flags |= rx_desc_error_to_pkt_flags(s[j]);\n+\t\t\tpkt_flags |=\n+\t\t\t\tngbe_rxd_pkt_info_to_pkt_flags(pkt_info[j]);\n \t\t\tmb->ol_flags = pkt_flags;\n \t\t\tmb->packet_type =\n \t\t\t\tngbe_rxd_pkt_info_to_pkt_type(pkt_info[j],\n \t\t\t\trxq->pkt_type_mask);\n+\n+\t\t\tif (likely(pkt_flags & PKT_RX_RSS_HASH))\n+\t\t\t\tmb->hash.rss =\n+\t\t\t\t\trte_le_to_cpu_32(rxdp[j].qw0.dw1);\n \t\t}\n \n \t\t/* Move mbuf pointers from the S/W ring to the stage */\n@@ -1302,6 +1320,7 @@ ngbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,\n \t\t *    - packet length,\n \t\t *    - Rx port identifier.\n \t\t * 2) integrate hardware offload data, if any:\n+\t\t *    - RSS flag & hash,\n \t\t *    - IP checksum flag,\n \t\t *    - VLAN TCI, if any,\n \t\t *    - error flags.\n@@ -1323,10 +1342,14 @@ ngbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,\n \t\tpkt_flags = rx_desc_status_to_pkt_flags(staterr,\n \t\t\t\t\trxq->vlan_flags);\n \t\tpkt_flags |= rx_desc_error_to_pkt_flags(staterr);\n+\t\tpkt_flags |= ngbe_rxd_pkt_info_to_pkt_flags(pkt_info);\n \t\trxm->ol_flags = pkt_flags;\n \t\trxm->packet_type = ngbe_rxd_pkt_info_to_pkt_type(pkt_info,\n \t\t\t\t\t\t       rxq->pkt_type_mask);\n \n+\t\tif (likely(pkt_flags & PKT_RX_RSS_HASH))\n+\t\t\trxm->hash.rss = rte_le_to_cpu_32(rxd.qw0.dw1);\n+\n \t\t/*\n \t\t * Store the mbuf address into the next entry of the array\n \t\t * of returned packets.\n@@ -1366,6 +1389,7 @@ ngbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,\n  * Fill the following info in the HEAD buffer of the Rx cluster:\n  *    - RX port identifier\n  *    - hardware offload data, if any:\n+ *      - RSS flag & hash\n  *      - IP checksum flag\n  *      - VLAN TCI, if any\n  *      - error flags\n@@ -1389,9 +1413,13 @@ ngbe_fill_cluster_head_buf(struct rte_mbuf *head, struct ngbe_rx_desc *desc,\n \tpkt_info = rte_le_to_cpu_32(desc->qw0.dw0);\n \tpkt_flags = rx_desc_status_to_pkt_flags(staterr, rxq->vlan_flags);\n \tpkt_flags |= rx_desc_error_to_pkt_flags(staterr);\n+\tpkt_flags |= ngbe_rxd_pkt_info_to_pkt_flags(pkt_info);\n \thead->ol_flags = pkt_flags;\n \thead->packet_type = ngbe_rxd_pkt_info_to_pkt_type(pkt_info,\n \t\t\t\t\t\trxq->pkt_type_mask);\n+\n+\tif (likely(pkt_flags & PKT_RX_RSS_HASH))\n+\t\thead->hash.rss = rte_le_to_cpu_32(desc->qw0.dw1);\n }\n \n /**\n@@ -2249,6 +2277,188 @@ ngbe_dev_free_queues(struct rte_eth_dev *dev)\n \tdev->data->nb_tx_queues = 0;\n }\n \n+/**\n+ * Receive Side Scaling (RSS)\n+ *\n+ * Principles:\n+ * The source and destination IP addresses of the IP header and the source\n+ * and destination ports of TCP/UDP headers, if any, of received packets are\n+ * hashed against a configurable random key to compute a 32-bit RSS hash result.\n+ * The seven (7) LSBs of the 32-bit hash result are used as an index into a\n+ * 128-entry redirection table (RETA).  Each entry of the RETA provides a 3-bit\n+ * RSS output index which is used as the Rx queue index where to store the\n+ * received packets.\n+ * The following output is supplied in the Rx write-back descriptor:\n+ *     - 32-bit result of the Microsoft RSS hash function,\n+ *     - 4-bit RSS type field.\n+ */\n+\n+/*\n+ * Used as the default key.\n+ */\n+static uint8_t rss_intel_key[40] = {\n+\t0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2,\n+\t0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0,\n+\t0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,\n+\t0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C,\n+\t0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA,\n+};\n+\n+static void\n+ngbe_rss_disable(struct rte_eth_dev *dev)\n+{\n+\tstruct ngbe_hw *hw = ngbe_dev_hw(dev);\n+\n+\twr32m(hw, NGBE_RACTL, NGBE_RACTL_RSSENA, 0);\n+}\n+\n+int\n+ngbe_dev_rss_hash_update(struct rte_eth_dev *dev,\n+\t\t\t  struct rte_eth_rss_conf *rss_conf)\n+{\n+\tstruct ngbe_hw *hw = ngbe_dev_hw(dev);\n+\tuint8_t  *hash_key;\n+\tuint32_t mrqc;\n+\tuint32_t rss_key;\n+\tuint64_t rss_hf;\n+\tuint16_t i;\n+\n+\tif (!hw->is_pf) {\n+\t\tPMD_DRV_LOG(ERR, \"RSS hash update is not supported on this \"\n+\t\t\t\"NIC.\");\n+\t\treturn -ENOTSUP;\n+\t}\n+\n+\thash_key = rss_conf->rss_key;\n+\tif (hash_key) {\n+\t\t/* Fill in RSS hash key */\n+\t\tfor (i = 0; i < 10; i++) {\n+\t\t\trss_key  = LS32(hash_key[(i * 4) + 0], 0, 0xFF);\n+\t\t\trss_key |= LS32(hash_key[(i * 4) + 1], 8, 0xFF);\n+\t\t\trss_key |= LS32(hash_key[(i * 4) + 2], 16, 0xFF);\n+\t\t\trss_key |= LS32(hash_key[(i * 4) + 3], 24, 0xFF);\n+\t\t\twr32a(hw, NGBE_REG_RSSKEY, i, rss_key);\n+\t\t}\n+\t}\n+\n+\t/* Set configured hashing protocols */\n+\trss_hf = rss_conf->rss_hf & NGBE_RSS_OFFLOAD_ALL;\n+\n+\tmrqc = rd32(hw, NGBE_RACTL);\n+\tmrqc &= ~NGBE_RACTL_RSSMASK;\n+\tif (rss_hf & ETH_RSS_IPV4)\n+\t\tmrqc |= NGBE_RACTL_RSSIPV4;\n+\tif (rss_hf & ETH_RSS_NONFRAG_IPV4_TCP)\n+\t\tmrqc |= NGBE_RACTL_RSSIPV4TCP;\n+\tif (rss_hf & ETH_RSS_IPV6 ||\n+\t    rss_hf & ETH_RSS_IPV6_EX)\n+\t\tmrqc |= NGBE_RACTL_RSSIPV6;\n+\tif (rss_hf & ETH_RSS_NONFRAG_IPV6_TCP ||\n+\t    rss_hf & ETH_RSS_IPV6_TCP_EX)\n+\t\tmrqc |= NGBE_RACTL_RSSIPV6TCP;\n+\tif (rss_hf & ETH_RSS_NONFRAG_IPV4_UDP)\n+\t\tmrqc |= NGBE_RACTL_RSSIPV4UDP;\n+\tif (rss_hf & ETH_RSS_NONFRAG_IPV6_UDP ||\n+\t    rss_hf & ETH_RSS_IPV6_UDP_EX)\n+\t\tmrqc |= NGBE_RACTL_RSSIPV6UDP;\n+\n+\tif (rss_hf)\n+\t\tmrqc |= NGBE_RACTL_RSSENA;\n+\telse\n+\t\tmrqc &= ~NGBE_RACTL_RSSENA;\n+\n+\twr32(hw, NGBE_RACTL, mrqc);\n+\n+\treturn 0;\n+}\n+\n+int\n+ngbe_dev_rss_hash_conf_get(struct rte_eth_dev *dev,\n+\t\t\t    struct rte_eth_rss_conf *rss_conf)\n+{\n+\tstruct ngbe_hw *hw = ngbe_dev_hw(dev);\n+\tuint8_t *hash_key;\n+\tuint32_t mrqc;\n+\tuint32_t rss_key;\n+\tuint64_t rss_hf;\n+\tuint16_t i;\n+\n+\thash_key = rss_conf->rss_key;\n+\tif (hash_key) {\n+\t\t/* Return RSS hash key */\n+\t\tfor (i = 0; i < 10; i++) {\n+\t\t\trss_key = rd32a(hw, NGBE_REG_RSSKEY, i);\n+\t\t\thash_key[(i * 4) + 0] = RS32(rss_key, 0, 0xFF);\n+\t\t\thash_key[(i * 4) + 1] = RS32(rss_key, 8, 0xFF);\n+\t\t\thash_key[(i * 4) + 2] = RS32(rss_key, 16, 0xFF);\n+\t\t\thash_key[(i * 4) + 3] = RS32(rss_key, 24, 0xFF);\n+\t\t}\n+\t}\n+\n+\trss_hf = 0;\n+\n+\tmrqc = rd32(hw, NGBE_RACTL);\n+\tif (mrqc & NGBE_RACTL_RSSIPV4)\n+\t\trss_hf |= ETH_RSS_IPV4;\n+\tif (mrqc & NGBE_RACTL_RSSIPV4TCP)\n+\t\trss_hf |= ETH_RSS_NONFRAG_IPV4_TCP;\n+\tif (mrqc & NGBE_RACTL_RSSIPV6)\n+\t\trss_hf |= ETH_RSS_IPV6 |\n+\t\t\t  ETH_RSS_IPV6_EX;\n+\tif (mrqc & NGBE_RACTL_RSSIPV6TCP)\n+\t\trss_hf |= ETH_RSS_NONFRAG_IPV6_TCP |\n+\t\t\t  ETH_RSS_IPV6_TCP_EX;\n+\tif (mrqc & NGBE_RACTL_RSSIPV4UDP)\n+\t\trss_hf |= ETH_RSS_NONFRAG_IPV4_UDP;\n+\tif (mrqc & NGBE_RACTL_RSSIPV6UDP)\n+\t\trss_hf |= ETH_RSS_NONFRAG_IPV6_UDP |\n+\t\t\t  ETH_RSS_IPV6_UDP_EX;\n+\tif (!(mrqc & NGBE_RACTL_RSSENA))\n+\t\trss_hf = 0;\n+\n+\trss_hf &= NGBE_RSS_OFFLOAD_ALL;\n+\n+\trss_conf->rss_hf = rss_hf;\n+\treturn 0;\n+}\n+\n+static void\n+ngbe_rss_configure(struct rte_eth_dev *dev)\n+{\n+\tstruct rte_eth_rss_conf rss_conf;\n+\tstruct ngbe_adapter *adapter = ngbe_dev_adapter(dev);\n+\tstruct ngbe_hw *hw = ngbe_dev_hw(dev);\n+\tuint32_t reta;\n+\tuint16_t i;\n+\tuint16_t j;\n+\n+\tPMD_INIT_FUNC_TRACE();\n+\n+\t/*\n+\t * Fill in redirection table\n+\t * The byte-swap is needed because NIC registers are in\n+\t * little-endian order.\n+\t */\n+\tif (adapter->rss_reta_updated == 0) {\n+\t\treta = 0;\n+\t\tfor (i = 0, j = 0; i < ETH_RSS_RETA_SIZE_128; i++, j++) {\n+\t\t\tif (j == dev->data->nb_rx_queues)\n+\t\t\t\tj = 0;\n+\t\t\treta = (reta >> 8) | LS32(j, 24, 0xFF);\n+\t\t\tif ((i & 3) == 3)\n+\t\t\t\twr32a(hw, NGBE_REG_RSSTBL, i >> 2, reta);\n+\t\t}\n+\t}\n+\t/*\n+\t * Configure the RSS key and the RSS protocols used to compute\n+\t * the RSS hash of input packets.\n+\t */\n+\trss_conf = dev->data->dev_conf.rx_adv_conf.rss_conf;\n+\tif (rss_conf.rss_key == NULL)\n+\t\trss_conf.rss_key = rss_intel_key; /* Default hash key */\n+\tngbe_dev_rss_hash_update(dev, &rss_conf);\n+}\n+\n void ngbe_configure_port(struct rte_eth_dev *dev)\n {\n \tstruct ngbe_hw *hw = ngbe_dev_hw(dev);\n@@ -2317,6 +2527,24 @@ ngbe_alloc_rx_queue_mbufs(struct ngbe_rx_queue *rxq)\n \treturn 0;\n }\n \n+static int\n+ngbe_dev_mq_rx_configure(struct rte_eth_dev *dev)\n+{\n+\tswitch (dev->data->dev_conf.rxmode.mq_mode) {\n+\tcase ETH_MQ_RX_RSS:\n+\t\tngbe_rss_configure(dev);\n+\t\tbreak;\n+\n+\tcase ETH_MQ_RX_NONE:\n+\tdefault:\n+\t\t/* if mq_mode is none, disable rss mode.*/\n+\t\tngbe_rss_disable(dev);\n+\t\tbreak;\n+\t}\n+\n+\treturn 0;\n+}\n+\n void\n ngbe_set_rx_function(struct rte_eth_dev *dev)\n {\n@@ -2488,8 +2716,15 @@ ngbe_dev_rx_init(struct rte_eth_dev *dev)\n \n \tif (rx_conf->offloads & DEV_RX_OFFLOAD_SCATTER)\n \t\tdev->data->scattered_rx = 1;\n+\n+\t/*\n+\t * Device configured with multiple RX queues.\n+\t */\n+\tngbe_dev_mq_rx_configure(dev);\n+\n \t/*\n \t * Setup the Checksum Register.\n+\t * Disable Full-Packet Checksum which is mutually exclusive with RSS.\n \t * Enable IP/L4 checksum computation by hardware if requested to do so.\n \t */\n \trxcsum = rd32(hw, NGBE_PSRCTL);\n",
    "prefixes": [
        "17/32"
    ]
}