get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 59477,
    "url": "http://patches.dpdk.org/api/patches/59477/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20190920102246.44945-1-alvinx.zhang@intel.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": "<20190920102246.44945-1-alvinx.zhang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20190920102246.44945-1-alvinx.zhang@intel.com",
    "date": "2019-09-20T10:22:46",
    "name": "[v7] net/i40e: limit the number of VF messages",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "3afdcc6d0a47caea88e35f9c1147a7f907477b8b",
    "submitter": {
        "id": 1398,
        "url": "http://patches.dpdk.org/api/people/1398/?format=api",
        "name": "Alvin Zhang",
        "email": "alvinx.zhang@intel.com"
    },
    "delegate": null,
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20190920102246.44945-1-alvinx.zhang@intel.com/mbox/",
    "series": [
        {
            "id": 6464,
            "url": "http://patches.dpdk.org/api/series/6464/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=6464",
            "date": "2019-09-20T10:22:46",
            "name": "[v7] net/i40e: limit the number of VF messages",
            "version": 7,
            "mbox": "http://patches.dpdk.org/series/6464/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/59477/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/59477/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 4C2D11F1C9;\n\tFri, 20 Sep 2019 03:36:36 +0200 (CEST)",
            "from mga07.intel.com (mga07.intel.com [134.134.136.100])\n\tby dpdk.org (Postfix) with ESMTP id 11AA91F1C8\n\tfor <dev@dpdk.org>; Fri, 20 Sep 2019 03:36:34 +0200 (CEST)",
            "from fmsmga002.fm.intel.com ([10.253.24.26])\n\tby orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t19 Sep 2019 18:36:33 -0700",
            "from unknown (HELO localhost.localdomain) ([10.240.176.181])\n\tby fmsmga002.fm.intel.com with ESMTP; 19 Sep 2019 18:36:32 -0700"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.64,526,1559545200\"; d=\"scan'208\";a=\"217499336\"",
        "From": "alvinx.zhang@intel.com",
        "To": "qi.z.zhang@intel.com",
        "Cc": "dev@dpdk.org,\n\tAlvin Zhang <alvinx.zhang@intel.com>",
        "Date": "Fri, 20 Sep 2019 18:22:46 +0800",
        "Message-Id": "<20190920102246.44945-1-alvinx.zhang@intel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20190918210349.67635-1-alvinx.zhang@intel.com>",
        "References": "<20190918210349.67635-1-alvinx.zhang@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v7] net/i40e: limit the number of VF messages",
        "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\t<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\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Alvin Zhang <alvinx.zhang@intel.com>\n\nPF driver supportes counting VF adminQ messages. If any VF driver\nsending much more adminQ messages to it's PF driver in a period of\ntime, it will trigger the PF's message limiting, then in the\nnext certain amount of seconds the PF driver will ignore any new\nadminQ message from that VF.\n\nSigned-off-by: Alvin Zhang <alvinx.zhang@intel.com>\n---\n\nv7: modify codes according to the comments.\nv6: combine valid/invalid/unsupported messages to one.\nv5: add validating the \"valid\" message, scheme redesigned.\nv4: change the instruction file \"i40e.rst\".\nv3: resolve the compile issue on ubuntu 32-bit system.\nv2: modify codes according to the comments.\n---\n doc/guides/nics/i40e.rst       | 10 ++++++\n drivers/net/i40e/i40e_ethdev.c | 72 ++++++++++++++++++++++++++++++++++++++++++\n drivers/net/i40e/i40e_ethdev.h | 32 +++++++++++++++++++\n drivers/net/i40e/i40e_pf.c     | 71 +++++++++++++++++++++++++++++++++++++++--\n 4 files changed, 183 insertions(+), 2 deletions(-)",
    "diff": "diff --git a/doc/guides/nics/i40e.rst b/doc/guides/nics/i40e.rst\nindex 0884e15..38acf59 100644\n--- a/doc/guides/nics/i40e.rst\n+++ b/doc/guides/nics/i40e.rst\n@@ -185,6 +185,16 @@ Runtime Config Options\n \n   -w 84:00.0,use-latest-supported-vec=1\n \n+- ``Enable validation for VF message`` (default ``not enabled``)\n+\n+  The PF counts messages from each VF. If in any period of seconds the message\n+  statistic from a VF exceeds maximal limitation, the PF will ignore any new message\n+  from that VF for some seconds.\n+  Format -- \"maximal-message@period-seconds:ignore-seconds\"\n+  For example::\n+\n+  -w 84:00.0,vf_msg_cfg=80@120:180\n+\n Vector RX Pre-conditions\n ~~~~~~~~~~~~~~~~~~~~~~~~\n For Vector RX it is assumed that the number of descriptor rings will be a power\ndiff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c\nindex 4e40b7a..4e2c488 100644\n--- a/drivers/net/i40e/i40e_ethdev.c\n+++ b/drivers/net/i40e/i40e_ethdev.c\n@@ -44,6 +44,7 @@\n #define ETH_I40E_SUPPORT_MULTI_DRIVER\t\"support-multi-driver\"\n #define ETH_I40E_QUEUE_NUM_PER_VF_ARG\t\"queue-num-per-vf\"\n #define ETH_I40E_USE_LATEST_VEC\t\"use-latest-supported-vec\"\n+#define ETH_I40E_VF_MSG_CFG\t\t\"vf_msg_cfg\"\n \n #define I40E_CLEAR_PXE_WAIT_MS     200\n \n@@ -406,6 +407,7 @@ static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,\n \tETH_I40E_SUPPORT_MULTI_DRIVER,\n \tETH_I40E_QUEUE_NUM_PER_VF_ARG,\n \tETH_I40E_USE_LATEST_VEC,\n+\tETH_I40E_VF_MSG_CFG,\n \tNULL};\n \n static const struct rte_pci_id pci_id_i40e_map[] = {\n@@ -1256,6 +1258,74 @@ static inline void i40e_config_automask(struct i40e_pf *pf)\n \treturn 0;\n }\n \n+static int\n+read_vf_msg_config(__rte_unused const char *key,\n+\t\t\t       const char *value,\n+\t\t\t       void *opaque)\n+{\n+\tstruct i40e_vf_msg_cfg cfg;\n+\n+\tmemset(&cfg, 0, sizeof(cfg));\n+\tif (sscanf(value, \"%u@%u:%u\", &cfg.max_msg, &cfg.period,\n+\t\t\t&cfg.ignore_second) != 3) {\n+\t\tPMD_DRV_LOG(ERR, \"format error! example: \"\n+\t\t\t\t\"%s=60@120:180\", ETH_I40E_VF_MSG_CFG);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/*\n+\t * If the message validation function been enabled, the 'period'\n+\t * and 'ignore_second' must greater than 0.\n+\t */\n+\tif (cfg.max_msg && (!cfg.period || !cfg.ignore_second)) {\n+\t\tPMD_DRV_LOG(ERR, \"%s error! the second and third\"\n+\t\t\t\t\" number must be greater than 0!\",\n+\t\t\t\tETH_I40E_VF_MSG_CFG);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tmemcpy(opaque, &cfg, sizeof(cfg));\n+\treturn 0;\n+}\n+\n+static int\n+i40e_parse_vf_msg_config(struct rte_eth_dev *dev,\n+\t\tstruct i40e_vf_msg_cfg *msg_cfg)\n+{\n+\tstruct rte_kvargs *kvlist;\n+\tint kvargs_count;\n+\tint ret = 0;\n+\n+\t/* reset all to zero */\n+\tmemset(msg_cfg, 0, sizeof(*msg_cfg));\n+\n+\tif (!dev->device->devargs)\n+\t\treturn ret;\n+\n+\tkvlist = rte_kvargs_parse(dev->device->devargs->args, valid_keys);\n+\tif (!kvlist)\n+\t\treturn -EINVAL;\n+\n+\tkvargs_count = rte_kvargs_count(kvlist, ETH_I40E_VF_MSG_CFG);\n+\tif (!kvargs_count)\n+\t\tgoto free_end;\n+\n+\tif (kvargs_count > 1) {\n+\t\tPMD_DRV_LOG(ERR, \"More than one argument \\\"%s\\\"!\",\n+\t\t\t\tETH_I40E_VF_MSG_CFG);\n+\t\tret = -EINVAL;\n+\t\tgoto free_end;\n+\t}\n+\n+\tif (rte_kvargs_process(kvlist, ETH_I40E_VF_MSG_CFG,\n+\t\t\tread_vf_msg_config, msg_cfg) < 0)\n+\t\tret = -EINVAL;\n+\n+free_end:\n+\trte_kvargs_free(kvlist);\n+\treturn ret;\n+}\n+\n #define I40E_ALARM_INTERVAL 50000 /* us */\n \n static int\n@@ -1328,6 +1398,8 @@ static inline void i40e_config_automask(struct i40e_pf *pf)\n \t\treturn -EIO;\n \t}\n \n+\t/* read VF message configuration */\n+\ti40e_parse_vf_msg_config(dev, &pf->vf_msg_cfg);\n \t/* Check if need to support multi-driver */\n \ti40e_support_multi_driver(dev);\n \t/* Check if users want the latest supported vec path */\ndiff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h\nindex 38ac3ea..261954b 100644\n--- a/drivers/net/i40e/i40e_ethdev.h\n+++ b/drivers/net/i40e/i40e_ethdev.h\n@@ -426,6 +426,22 @@ struct i40e_pf_vf {\n \t/* version of the virtchnl from VF */\n \tstruct virtchnl_version_info version;\n \tuint32_t request_caps; /* offload caps requested from VF */\n+\n+\t/*\n+\t * Variables for store the arrival timestamp of VF messages.\n+\t * If the timestamp of latest message stored at\n+\t * `msg_timestamps[index % max]` then the timestamp of\n+\t * earliest message stored at `msg_time[(index + 1) % max]`.\n+\t * When a new message come, the timestamp of this message\n+\t * will be stored at `msg_timestamps[(index + 1) % max]` and the\n+\t * earliest message timestamp is at\n+\t * `msg_timestamps[(index + 2) % max]` now...\n+\t */\n+\tuint32_t msg_index;\n+\tuint64_t *msg_timestamps;\n+\n+\t/* cycle of stop ignoring VF message */\n+\tuint64_t ignore_end_cycle;\n };\n \n /*\n@@ -900,6 +916,20 @@ struct i40e_rte_flow_rss_conf {\n \tuint16_t queue[I40E_MAX_Q_PER_TC]; /**< Queues indices to use. */\n };\n \n+struct i40e_vf_msg_cfg {\n+\t/* maximal VF message during a statistic period */\n+\tuint32_t max_msg;\n+\n+\t/* statistic period, in second */\n+\tuint32_t period;\n+\t/*\n+\t * If message statistics from a VF exceed the maximal limitation,\n+\t * the PF will ignore any new message from that VF for\n+\t * 'ignor_second' time.\n+\t */\n+\tuint32_t ignore_second;\n+};\n+\n /*\n  * Structure to store private data specific for PF instance.\n  */\n@@ -975,6 +1005,8 @@ struct i40e_pf {\n \tstruct i40e_customized_pctype customized_pctype[I40E_CUSTOMIZED_MAX];\n \t/* Switch Domain Id */\n \tuint16_t switch_domain_id;\n+\n+\tstruct i40e_vf_msg_cfg vf_msg_cfg;\n };\n \n enum pending_msg {\ndiff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c\nindex b28d02e..9ee2be6 100644\n--- a/drivers/net/i40e/i40e_pf.c\n+++ b/drivers/net/i40e/i40e_pf.c\n@@ -1297,6 +1297,8 @@\n \t/* AdminQ will pass absolute VF id, transfer to internal vf id */\n \tuint16_t vf_id = abs_vf_id - hw->func_caps.vf_base_id;\n \tstruct rte_pmd_i40e_mb_event_param ret_param;\n+\tuint64_t first_cycle, cur_cycle;\n+\tuint32_t next, limit;\n \tbool b_op = TRUE;\n \tint ret;\n \n@@ -1306,11 +1308,19 @@\n \t}\n \n \tvf = &pf->vfs[vf_id];\n+\n+\t/* read current cycle */\n+\tcur_cycle = rte_get_timer_cycles();\n+\n+\t/* if the VF being blocked, ignore the message and return */\n+\tif (cur_cycle < vf->ignore_end_cycle)\n+\t\treturn;\n+\n \tif (!vf->vsi) {\n \t\tPMD_DRV_LOG(ERR, \"NO VSI associated with VF found\");\n \t\ti40e_pf_host_send_msg_to_vf(vf, opcode,\n \t\t\tI40E_ERR_NO_AVAILABLE_VSI, NULL, 0);\n-\t\treturn;\n+\t\tgoto check;\n \t}\n \n \t/* perform basic checks on the msg */\n@@ -1334,7 +1344,7 @@\n \t\t\t    vf_id, opcode, msglen);\n \t\ti40e_pf_host_send_msg_to_vf(vf, opcode,\n \t\t\t\t\t    I40E_ERR_PARAM, NULL, 0);\n-\t\treturn;\n+\t\tgoto check;\n \t}\n \n \t/**\n@@ -1456,6 +1466,41 @@\n \t\t\t\t\t\t\t\tNULL, 0);\n \t\tbreak;\n \t}\n+\n+check:\n+\t/* if message validation not enabled */\n+\tif (!pf->vf_msg_cfg.max_msg)\n+\t\treturn;\n+\n+\t/* store current cycle to next place */\n+\tlimit = pf->vf_msg_cfg.max_msg - 1;\n+\tnext = vf->msg_index;\n+\tnext = (next >= limit) ? 0 : (next + 1);\n+\tvf->msg_index = next;\n+\tvf->msg_timestamps[next] = cur_cycle;\n+\n+\t/* read the timestamp of earliest message */\n+\tnext = (next >= limit) ? 0 : (next + 1);\n+\tfirst_cycle = vf->msg_timestamps[next];\n+\n+\t/*\n+\t * If the time span from the arrival time of first message to\n+\t * the arrival time of current message smaller than `period`,\n+\t * that mean too much message in this statistic period.\n+\t */\n+\tif (first_cycle && cur_cycle < first_cycle +\n+\t\t\t(uint64_t)pf->vf_msg_cfg.period * rte_get_timer_hz()) {\n+\t\tPMD_DRV_LOG(ERR, \"VF %u too much messages(%u in %u\"\n+\t\t\t\t\" seconds),\\n\\tany new message from which\"\n+\t\t\t\t\" will be ignored during next %u seconds!\",\n+\t\t\t\tvf_id, limit + 1,\n+\t\t\t\t(uint32_t)((cur_cycle - first_cycle +\n+\t\t\t\trte_get_timer_hz() - 1) / rte_get_timer_hz()),\n+\t\t\t\tpf->vf_msg_cfg.ignore_second);\n+\t\tvf->ignore_end_cycle = rte_get_timer_cycles() +\n+\t\t\t\tpf->vf_msg_cfg.ignore_second *\n+\t\t\t\trte_get_timer_hz();\n+\t}\n }\n \n int\n@@ -1463,6 +1508,7 @@\n {\n \tstruct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);\n \tstruct i40e_hw *hw = I40E_PF_TO_HW(pf);\n+\tsize_t size;\n \tint ret, i;\n \tuint32_t val;\n \n@@ -1489,10 +1535,22 @@\n \tI40E_WRITE_REG(hw, I40E_PFGEN_PORTMDIO_NUM, val);\n \tI40E_WRITE_FLUSH(hw);\n \n+\t/* calculate the memory size for storing timestamp of messages */\n+\tsize = pf->vf_msg_cfg.max_msg * sizeof(uint64_t);\n+\n \tfor (i = 0; i < pf->vf_num; i++) {\n \t\tpf->vfs[i].pf = pf;\n \t\tpf->vfs[i].state = I40E_VF_INACTIVE;\n \t\tpf->vfs[i].vf_idx = i;\n+\n+\t\tif (size) {\n+\t\t\t/* allocate memory for store timestamp of messages */\n+\t\t\tpf->vfs[i].msg_timestamps = (uint64_t *)\n+\t\t\t\t\trte_zmalloc(\"i40e_pf_vf\", size, 0);\n+\t\t\tif (pf->vfs[i].msg_timestamps == NULL)\n+\t\t\t\tgoto fail;\n+\t\t}\n+\n \t\tret = i40e_pf_host_vf_reset(&pf->vfs[i], 0);\n \t\tif (ret != I40E_SUCCESS)\n \t\t\tgoto fail;\n@@ -1505,6 +1563,9 @@\n \treturn I40E_SUCCESS;\n \n fail:\n+\tfor (; i >= 0; i--)\n+\t\tif (pf->vfs[i].msg_timestamps)\n+\t\t\trte_free(pf->vfs[i].msg_timestamps);\n \trte_free(pf->vfs);\n \ti40e_pf_enable_irq0(hw);\n \n@@ -1517,6 +1578,7 @@\n \tstruct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);\n \tstruct i40e_hw *hw = I40E_PF_TO_HW(pf);\n \tuint32_t val;\n+\tint i;\n \n \tPMD_INIT_FUNC_TRACE();\n \n@@ -1529,6 +1591,11 @@\n \t\t(pf->vf_nb_qps == 0))\n \t\treturn I40E_SUCCESS;\n \n+\t/* free memory for store timestamp of messages */\n+\tfor (i = 0; i < pf->vf_num; i++)\n+\t\tif (pf->vfs[i].msg_timestamps)\n+\t\t\trte_free(pf->vfs[i].msg_timestamps);\n+\n \t/* free memory to store VF structure */\n \trte_free(pf->vfs);\n \tpf->vfs = NULL;\n",
    "prefixes": [
        "v7"
    ]
}