List comments

GET /api/patches/74491/comments/
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "id": 116309,
        "web_url": "https://patches.dpdk.org/comment/116309/",
        "msgid": "<20200720130816.GB726@bricha3-MOBL.ger.corp.intel.com>",
        "date": "2020-07-20T13:08:16",
        "subject": "Re: [dpdk-dev] [PATCH v6 2/3] test/test_telemetry_data: add unit\n tests for data to JSON",
        "submitter": {
            "id": 20,
            "url": "https://patches.dpdk.org/api/people/20/",
            "name": "Bruce Richardson",
            "email": "bruce.richardson@intel.com"
        },
        "content": "On Mon, Jul 20, 2020 at 12:19:06PM +0100, Ciara Power wrote:\n> From: Louise Kilheeney <louise.kilheeney@intel.com>\n> \n> This patch adds tests for verifying telemetry data structures are\n> converted to JSON as expected. Both flat and recursive data structures\n> are tested, for all possible value types.\n> \n> The app connects to the telemetry socket as a client, and registers one\n> command with a corresponding callback function. Each time the callback\n> function is called, it copies a global data variable to the data pointer\n> passed in by telemetry.\n> When a test case is run, the test case function builds up the global\n> data variable with the relevant data types, and the expected json string\n> output which should be generated from that. The 'test_output()' function\n> is used to trigger the callback and ensure the actual output matches\n> that expected.\n> \n> Signed-off-by: Louise Kilheeney <louise.kilheeney@intel.com>\n> Signed-off-by: Ciara Power <ciara.power@intel.com>\n> \n> ---\n> v6:\n>   - Fixed FreeBSD build error.\n>   - Added comments and expanded commit log.\n>   - Add loop to call test cases stored in a list.\n> ---\n\nThanks, this is a good improvement. Apologies but a few more comments below\nthat I missed in the previous version.\n\n/Bruce\n\n>  app/test/Makefile              |   1 +\n>  app/test/meson.build           |   5 +-\n>  app/test/test_telemetry_data.c | 375 +++++++++++++++++++++++++++++++++\n>  3 files changed, 379 insertions(+), 2 deletions(-)\n>  create mode 100644 app/test/test_telemetry_data.c\n> \n> diff --git a/app/test/Makefile b/app/test/Makefile\n> index f4065271e..1cb64089c 100644\n> --- a/app/test/Makefile\n> +++ b/app/test/Makefile\n> @@ -145,6 +145,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm6.c\n>  SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm6_perf.c\n>  \n>  SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += test_telemetry_json.c\n> +SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += test_telemetry_data.c\n>  \n>  SRCS-y += test_debug.c\n>  SRCS-y += test_errno.c\n> diff --git a/app/test/meson.build b/app/test/meson.build\n> index 786a21397..4a72fe5b6 100644\n> --- a/app/test/meson.build\n> +++ b/app/test/meson.build\n> @@ -170,6 +170,7 @@ test_deps = ['acl',\n>  \t'ring',\n>  \t'security',\n>  \t'stack',\n> +\t'telemetry',\n>  \t'timer'\n>  ]\n>  \n> @@ -345,8 +346,8 @@ if dpdk_conf.has('RTE_LIBRTE_SKELETON_EVENTDEV_PMD')\n>  \ttest_deps += 'pmd_skeleton_event'\n>  endif\n>  if dpdk_conf.has('RTE_LIBRTE_TELEMETRY')\n> -\ttest_sources += 'test_telemetry_json.c'\n> -\tfast_tests += [['telemetry_json_autotest', true]]\n> +\ttest_sources += ['test_telemetry_json.c', 'test_telemetry_data.c']\n> +\tfast_tests += [['telemetry_json_autotest', true], ['telemetry_data_autotest', true]]\n>  endif\n>  \n>  # The following linkages of drivers are required because\n> diff --git a/app/test/test_telemetry_data.c b/app/test/test_telemetry_data.c\n> new file mode 100644\n> index 000000000..f95054433\n> --- /dev/null\n> +++ b/app/test/test_telemetry_data.c\n> @@ -0,0 +1,375 @@\n> +/* SPDX-License-Identifier: BSD-3-Clause\n> + * Copyright 2020 Intel Corporation\n> + */\n> +\n> +#include <glob.h>\n\nWhile the python script for testing telemetry does use glob to find the\nsocket, in this case I think it's unnecessary since we know we are in the\nprocess that created the listening socket, so we can just connect straight\nto it.\n\n> +#include <string.h>\n> +#include <sys/socket.h>\n> +#include <sys/un.h>\n> +#include <unistd.h>\n> +#include <limits.h>\n> +\n> +#include <rte_eal.h>\n> +#include <rte_common.h>\n> +#include <rte_telemetry.h>\n> +#include <rte_string_fns.h>\n> +\n> +#include \"test.h\"\n> +#include \"telemetry_data.h\"\n> +\n> +#define TELEMETRY_VERSION \"v2\"\n> +#define REQUEST_CMD \"/test\"\n> +#define BUF_SIZE 1024\n> +#define TEST_OUTPUT(exp) test_output(__func__, exp)\n> +\n> +static struct rte_tel_data response_data;\n> +static int sock;\n> +\n> +/*\n> + * This function is the callback registered with Telemetry to be used when\n> + * the /test command is requested. This callback returns the global data built\n> + * up by the individual test cases.\n> + */\n> +static int\n> +test_cb(const char *cmd __rte_unused, const char *params __rte_unused,\n> +\t\tstruct rte_tel_data *d)\n> +{\n> +\t*d = response_data;\n> +\treturn 0;\n> +}\n> +\n> +/*\n> + * This function is called by each test case function. It communicates with\n> + * the telemetry socket by requesting the /test command, and reading the\n> + * response. The expected response is passed in by the test case function,\n> + * and is compared to the actual response received from Telemetry.\n> + */\n> +static int\n> +test_output(const char *func_name, const char *expected)\n> +{\n> +\tint bytes;\n> +\tchar buf[BUF_SIZE * 16];\n> +\tif (write(sock, REQUEST_CMD, strlen(REQUEST_CMD)) < 0) {\n> +\t\tprintf(\"%s: Error with socket write - %s\\n\", __func__,\n> +\t\t\t\tstrerror(errno));\n> +\t\treturn -1;\n> +\t}\n> +\tbytes = read(sock, buf, sizeof(buf));\n> +\tif (bytes < 0) {\n> +\t\tprintf(\"%s: Error with socket read - %s\\n\", __func__,\n> +\t\t\t\tstrerror(errno));\n> +\t\treturn -1;\n> +\t}\n> +\tbuf[bytes] = '\\0';\n\nNeed to check here for overflow. If bytes == BUF_SIZE * 16, you'll\noverflow.\n\n> +\tprintf(\"%s: buf = '%s', expected = '%s'\\n\", func_name, buf, expected);\n> +\treturn strncmp(expected, buf, sizeof(buf));\n> +}\n> +\n> +static int\n> +test_dict_with_array_int_values(void)\n> +{\n> +\tint i;\n> +\n> +\tstruct rte_tel_data *child_data = rte_tel_data_alloc();\n> +\trte_tel_data_start_array(child_data, RTE_TEL_INT_VAL);\n> +\n> +\tstruct rte_tel_data *child_data2 = rte_tel_data_alloc();\n> +\trte_tel_data_start_array(child_data2, RTE_TEL_INT_VAL);\n> +\n> +\tmemset(&response_data, 0, sizeof(response_data));\n> +\trte_tel_data_start_dict(&response_data);\n> +\n> +\tfor (i = 0; i < 5; i++) {\n> +\t\trte_tel_data_add_array_int(child_data, i);\n> +\t\trte_tel_data_add_array_int(child_data2, i);\n> +\t}\n> +\n> +\trte_tel_data_add_dict_container(&response_data, \"dict_0\",\n> +\t child_data, 0);\n> +\trte_tel_data_add_dict_container(&response_data, \"dict_1\",\n> +\t child_data2, 0);\n> +\n> +\treturn TEST_OUTPUT(\"{\\\"/test\\\":{\\\"dict_0\\\":[0,1,2,3,4],\\\"dict_1\\\":[0,1,2,3,4]}}\");\n> +}\n> +\n> +static int\n> +test_array_with_array_int_values(void)\n> +{\n> +\tint i;\n> +\n> +\tstruct rte_tel_data *child_data = rte_tel_data_alloc();\n> +\trte_tel_data_start_array(child_data, RTE_TEL_INT_VAL);\n> +\n> +\tstruct rte_tel_data *child_data2 = rte_tel_data_alloc();\n> +\trte_tel_data_start_array(child_data2, RTE_TEL_INT_VAL);\n> +\n> +\tmemset(&response_data, 0, sizeof(response_data));\n> +\trte_tel_data_start_array(&response_data, RTE_TEL_CONTAINER);\n> +\n> +\tfor (i = 0; i < 5; i++) {\n> +\t\trte_tel_data_add_array_int(child_data, i);\n> +\t\trte_tel_data_add_array_int(child_data2, i);\n> +\t}\n> +\trte_tel_data_add_array_container(&response_data, child_data, 0);\n> +\trte_tel_data_add_array_container(&response_data, child_data2, 0);\n> +\n> +\treturn TEST_OUTPUT(\"{\\\"/test\\\":[[0,1,2,3,4],[0,1,2,3,4]]}\");\n> +}\n> +\n> +static int\n> +test_case_array_int(void)\n> +{\n> +\tint i;\n> +\tmemset(&response_data, 0, sizeof(response_data));\n> +\trte_tel_data_start_array(&response_data, RTE_TEL_INT_VAL);\n> +\tfor (i = 0; i < 5; i++)\n> +\t\trte_tel_data_add_array_int(&response_data, i);\n> +\treturn TEST_OUTPUT(\"{\\\"/test\\\":[0,1,2,3,4]}\");\n> +}\n> +\n> +static int\n> +test_case_add_dict_int(void)\n> +{\n> +\tint i = 0;\n> +\tchar name_of_value[8];\n> +\n> +\tmemset(&response_data, 0, sizeof(response_data));\n> +\trte_tel_data_start_dict(&response_data);\n> +\n> +\tfor (i = 0; i < 5; i++) {\n> +\t\tsprintf(name_of_value, \"dict_%d\", i);\n> +\t\trte_tel_data_add_dict_int(&response_data, name_of_value, i);\n> +\t}\n> +\n> +\treturn TEST_OUTPUT(\"{\\\"/test\\\":{\\\"dict_0\\\":0,\\\"dict_1\\\":1,\\\"dict_2\\\":2,\\\"dict_3\\\":3,\\\"dict_4\\\":4}}\");\n> +}\n> +\n> +static int\n> +test_case_array_string(void)\n> +{\n> +\tmemset(&response_data, 0, sizeof(response_data));\n> +\trte_tel_data_start_array(&response_data, RTE_TEL_STRING_VAL);\n> +\trte_tel_data_add_array_string(&response_data, \"aaaa\");\n> +\trte_tel_data_add_array_string(&response_data, \"bbbb\");\n> +\trte_tel_data_add_array_string(&response_data, \"cccc\");\n> +\trte_tel_data_add_array_string(&response_data, \"dddd\");\n> +\trte_tel_data_add_array_string(&response_data, \"eeee\");\n> +\n> +\treturn TEST_OUTPUT(\"{\\\"/test\\\":[\\\"aaaa\\\",\\\"bbbb\\\",\\\"cccc\\\",\\\"dddd\\\",\\\"eeee\\\"]}\");\n> +}\n> +\n> +static int\n> +test_case_add_dict_string(void)\n> +{\n> +\tmemset(&response_data, 0, sizeof(response_data));\n> +\trte_tel_data_start_dict(&response_data);\n> +\n> +\trte_tel_data_add_dict_string(&response_data, \"dict_0\", \"aaaa\");\n> +\trte_tel_data_add_dict_string(&response_data, \"dict_1\", \"bbbb\");\n> +\trte_tel_data_add_dict_string(&response_data, \"dict_2\", \"cccc\");\n> +\trte_tel_data_add_dict_string(&response_data, \"dict_3\", \"dddd\");\n> +\n> +\treturn TEST_OUTPUT(\"{\\\"/test\\\":{\\\"dict_0\\\":\\\"aaaa\\\",\\\"dict_1\\\":\\\"bbbb\\\",\\\"dict_2\\\":\\\"cccc\\\",\\\"dict_3\\\":\\\"dddd\\\"}}\");\n> +}\n\nAlthough these are single strings, they are not user output, and so you can\nsplit them across lines to limit line length.\n\n> +\n> +\n> +static int\n> +test_dict_with_array_string_values(void)\n> +{\n> +\tstruct rte_tel_data *child_data = rte_tel_data_alloc();\n> +\trte_tel_data_start_array(child_data, RTE_TEL_STRING_VAL);\n> +\n> +\tstruct rte_tel_data *child_data2 = rte_tel_data_alloc();\n> +\trte_tel_data_start_array(child_data2, RTE_TEL_STRING_VAL);\n> +\n> +\tmemset(&response_data, 0, sizeof(response_data));\n> +\trte_tel_data_start_dict(&response_data);\n> +\n> +\trte_tel_data_add_array_string(child_data, \"aaaa\");\n> +\trte_tel_data_add_array_string(child_data2, \"bbbb\");\n> +\n> +\trte_tel_data_add_dict_container(&response_data, \"dict_0\",\n> +\t child_data, 0);\n> +\trte_tel_data_add_dict_container(&response_data, \"dict_1\",\n> +\t child_data2, 0);\n> +\n> +\treturn TEST_OUTPUT(\"{\\\"/test\\\":{\\\"dict_0\\\":[\\\"aaaa\\\"],\\\"dict_1\\\":[\\\"bbbb\\\"]}}\");\n> +}\n> +\n> +static int\n> +test_array_with_array_string_values(void)\n> +{\n> +\tstruct rte_tel_data *child_data = rte_tel_data_alloc();\n> +\trte_tel_data_start_array(child_data, RTE_TEL_STRING_VAL);\n> +\n> +\tstruct rte_tel_data *child_data2 = rte_tel_data_alloc();\n> +\trte_tel_data_start_array(child_data2, RTE_TEL_STRING_VAL);\n> +\n> +\tmemset(&response_data, 0, sizeof(response_data));\n> +\trte_tel_data_start_array(&response_data, RTE_TEL_CONTAINER);\n> +\n> +\trte_tel_data_add_array_string(child_data, \"aaaa\");\n> +\trte_tel_data_add_array_string(child_data2, \"bbbb\");\n> +\n> +\trte_tel_data_add_array_container(&response_data, child_data, 0);\n> +\trte_tel_data_add_array_container(&response_data, child_data2, 0);\n> +\n> +\treturn TEST_OUTPUT(\"{\\\"/test\\\":[[\\\"aaaa\\\"],[\\\"bbbb\\\"]]}\");\n> +}\n> +\n> +static int\n> +test_case_array_u64(void)\n> +{\n> +\tint i;\n> +\tmemset(&response_data, 0, sizeof(response_data));\n> +\trte_tel_data_start_array(&response_data, RTE_TEL_U64_VAL);\n> +\tfor (i = 0; i < 5; i++)\n> +\t\trte_tel_data_add_array_u64(&response_data, i);\n> +\treturn TEST_OUTPUT(\"{\\\"/test\\\":[0,1,2,3,4]}\");\n> +}\n> +\n> +static int\n> +test_case_add_dict_u64(void)\n> +{\n> +\tint i = 0;\n> +\tchar name_of_value[8];\n> +\n> +\tmemset(&response_data, 0, sizeof(response_data));\n> +\trte_tel_data_start_dict(&response_data);\n> +\n> +\tfor (i = 0; i < 5; i++) {\n> +\t\tsprintf(name_of_value, \"dict_%d\", i);\n> +\t\trte_tel_data_add_dict_u64(&response_data, name_of_value, i);\n> +\t}\n> +\treturn TEST_OUTPUT(\"{\\\"/test\\\":{\\\"dict_0\\\":0,\\\"dict_1\\\":1,\\\"dict_2\\\":2,\\\"dict_3\\\":3,\\\"dict_4\\\":4}}\");\n> +}\n> +\n> +static int\n> +test_dict_with_array_u64_values(void)\n> +{\n> +\tint i;\n> +\n> +\tstruct rte_tel_data *child_data = rte_tel_data_alloc();\n> +\trte_tel_data_start_array(child_data, RTE_TEL_U64_VAL);\n> +\n> +\tstruct rte_tel_data *child_data2 = rte_tel_data_alloc();\n> +\trte_tel_data_start_array(child_data2, RTE_TEL_U64_VAL);\n> +\n> +\tmemset(&response_data, 0, sizeof(response_data));\n> +\trte_tel_data_start_dict(&response_data);\n> +\n> +\tfor (i = 0; i < 10; i++) {\n> +\t\trte_tel_data_add_array_u64(child_data, i);\n> +\t\trte_tel_data_add_array_u64(child_data2, i);\n> +\t}\n> +\n> +\trte_tel_data_add_dict_container(&response_data, \"dict_0\",\n> +\t child_data, 0);\n> +\trte_tel_data_add_dict_container(&response_data, \"dict_1\",\n> +\t child_data2, 0);\n> +\n> +\treturn TEST_OUTPUT(\"{\\\"/test\\\":{\\\"dict_0\\\":[0,1,2,3,4,5,6,7,8,9],\\\"dict_1\\\":[0,1,2,3,4,5,6,7,8,9]}}\");\n> +}\n> +\n> +static int\n> +test_array_with_array_u64_values(void)\n> +{\n> +\tint i;\n> +\n> +\tstruct rte_tel_data *child_data = rte_tel_data_alloc();\n> +\trte_tel_data_start_array(child_data, RTE_TEL_U64_VAL);\n> +\n> +\tstruct rte_tel_data *child_data2 = rte_tel_data_alloc();\n> +\trte_tel_data_start_array(child_data2, RTE_TEL_U64_VAL);\n> +\n> +\tmemset(&response_data, 0, sizeof(response_data));\n> +\trte_tel_data_start_array(&response_data, RTE_TEL_CONTAINER);\n> +\n> +\tfor (i = 0; i < 5; i++) {\n> +\t\trte_tel_data_add_array_u64(child_data, i);\n> +\t\trte_tel_data_add_array_u64(child_data2, i);\n> +\t}\n> +\trte_tel_data_add_array_container(&response_data, child_data, 0);\n> +\trte_tel_data_add_array_container(&response_data, child_data2, 0);\n> +\n> +\treturn TEST_OUTPUT(\"{\\\"/test\\\":[[0,1,2,3,4],[0,1,2,3,4]]}\");\n> +}\n> +\n> +static int\n> +connect_to_socket(void)\n> +{\n> +\tchar file_pattern[PATH_MAX];\n> +\tchar buf[BUF_SIZE];\n> +\tglob_t globbuf;\n> +\tint sock, bytes;\n> +\tstruct sockaddr_un telem_addr;\n> +\n> +\tsnprintf(file_pattern, sizeof(file_pattern),\n> +\t\t\t\"%s/dpdk_telemetry.%s\",\trte_eal_get_runtime_dir(),\n> +\t\t\tTELEMETRY_VERSION);\n> +\tif (glob(file_pattern, 0, NULL, &globbuf) != 0) {\n> +\t\tprintf(\"\\n%s: Error finding socket file path: %s\\n\", __func__,\n> +\t\t\t\tstrerror(errno));\n> +\t\tglobfree(&globbuf);\n> +\t\treturn -1;\n> +\t}\n> +\n\nThe path you create here should be the exact path that you need, no\nglobbing should be necessary, which I think should simplify the code a bit.\n\n> +\tsock = socket(AF_UNIX, SOCK_SEQPACKET, 0);\n> +\tif (sock < 0) {\n> +\t\tprintf(\"\\n%s: Error creating socket: %s\\n\", __func__,\n> +\t\t\t\tstrerror(errno));\n> +\t\treturn -1;\n> +\t}\n> +\ttelem_addr.sun_family = AF_UNIX;\n> +\tstrlcpy(telem_addr.sun_path, globbuf.gl_pathv[0],\n> +\t\t\tsizeof(telem_addr.sun_path));\n> +\tif (connect(sock, (struct sockaddr *) &telem_addr,\n> +\t\t\tsizeof(telem_addr)) < 0)\n> +\t\tprintf(\"\\n%s: Error connecting to socket: %s\\n\", __func__,\n> +\t\t\t\tstrerror(errno));\n> +\n> +\tbytes = read(sock, buf, sizeof(buf));\n> +\tif (bytes < 0) {\n> +\t\tprintf(\"%s: Error with socket read - %s\\n\", __func__,\n> +\t\t\t\tstrerror(errno));\n> +\t\treturn -1;\n> +\t}\n> +\tbuf[bytes] = '\\0';\n\nAgain, watch for overflow when you hit the exact output limit.\n\n> +\tprintf(\"\\n%s: %s\\n\", __func__, buf);\n> +\tglobfree(&globbuf);\n> +\treturn sock;\n> +}\n> +\n> +static int\n> +test_telemetry_data(void)\n> +{\n> +\ttypedef int (*test_case)(void);\n> +\tunsigned int i = 0;\n> +\n> +\tsock = connect_to_socket();\n> +\tif (sock <= 0)\n> +\t\treturn -1;\n> +\n> +\ttest_case test_cases[] = {test_case_array_string,\n> +\t\t\ttest_case_array_int, test_case_array_u64,\n> +\t\t\ttest_case_add_dict_int, test_case_add_dict_u64,\n> +\t\t\ttest_case_add_dict_string,\n> +\t\t\ttest_dict_with_array_int_values,\n> +\t\t\ttest_dict_with_array_u64_values,\n> +\t\t\ttest_dict_with_array_string_values,\n> +\t\t\ttest_array_with_array_int_values,\n> +\t\t\ttest_array_with_array_u64_values,\n> +\t\t\ttest_array_with_array_string_values };\n> +\n> +\trte_telemetry_register_cmd(REQUEST_CMD, test_cb, \"Test\");\n> +\tfor (i = 0; i < RTE_DIM(test_cases); i++) {\n> +\t\tif (test_cases[i]() != 0) {\n> +\t\t\tclose(sock);\n> +\t\t\treturn -1;\n> +\t\t}\n> +\t}\n\nThanks, this is much more readable than the previous version.\n\n> +\tclose(sock);\n> +\treturn 0;\n> +}\n> +\n> +REGISTER_TEST_COMMAND(telemetry_data_autotest, test_telemetry_data);\n> -- \n> 2.17.1\n>",
        "headers": {
            "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
            "Content-Disposition": "inline",
            "X-IronPort-AV": [
                "E=McAfee;i=\"6000,8403,9687\"; a=\"211448404\"",
                "E=Sophos;i=\"5.75,375,1589266800\"; d=\"scan'208\";a=\"211448404\"",
                "E=Sophos;i=\"5.75,375,1589266800\"; d=\"scan'208\";a=\"461684426\""
            ],
            "IronPort-SDR": [
                "\n M1rCWfhfd0J+QyPOM3ZSqGbumrjeSeGzpJCX/v223FwycxsT0Ct7hYWZP3IFUpwuPXnheLHB42\n 24XIFBKOvBxA==",
                "\n 3akDlpX0NGv6JDVObZwOaoNfYAK+BL5J1IFZJcFkgPk5tXgl9LBxLBYOh9HHuLOQTGiTPWRlir\n OSv9v+A6WUfw=="
            ],
            "X-Amp-File-Uploaded": "False",
            "Precedence": "list",
            "X-Mailman-Version": "2.1.15",
            "X-Original-To": "patchwork@inbox.dpdk.org",
            "List-Post": "<mailto:dev@dpdk.org>",
            "MIME-Version": "1.0",
            "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
            "X-BeenThere": "dev@dpdk.org",
            "References": "<20200612105344.15383-1-ciara.power@intel.com>\n <20200720111907.30717-1-ciara.power@intel.com>\n <20200720111907.30717-3-ciara.power@intel.com>",
            "Subject": "Re: [dpdk-dev] [PATCH v6 2/3] test/test_telemetry_data: add unit\n tests for data to JSON",
            "Content-Type": "text/plain; charset=us-ascii",
            "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 CD99DA0540;\n\tMon, 20 Jul 2020 15:08:28 +0200 (CEST)",
                "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 235A41DBB;\n\tMon, 20 Jul 2020 15:08:27 +0200 (CEST)",
                "from mga06.intel.com (mga06.intel.com [134.134.136.31])\n by dpdk.org (Postfix) with ESMTP id 24B121023\n for <dev@dpdk.org>; Mon, 20 Jul 2020 15:08:23 +0200 (CEST)",
                "from orsmga005.jf.intel.com ([10.7.209.41])\n by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 20 Jul 2020 06:08:22 -0700",
                "from bricha3-mobl.ger.corp.intel.com ([10.252.33.168])\n by orsmga005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-SHA;\n 20 Jul 2020 06:08:20 -0700"
            ],
            "X-Amp-Result": "SKIPPED(no attachment in message)",
            "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
            "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
            "Message-ID": "<20200720130816.GB726@bricha3-MOBL.ger.corp.intel.com>",
            "Date": "Mon, 20 Jul 2020 14:08:16 +0100",
            "Sender": "\"dev\" <dev-bounces@dpdk.org>",
            "To": "Ciara Power <ciara.power@intel.com>",
            "From": "Bruce Richardson <bruce.richardson@intel.com>",
            "In-Reply-To": "<20200720111907.30717-3-ciara.power@intel.com>",
            "Cc": "kevin.laatz@intel.com, thomas@monjalon.net, ferruh.yigit@intel.com,\n arybchenko@solarflare.com, dev@dpdk.org, keith.wiles@intel.com,\n Louise Kilheeney <louise.kilheeney@intel.com>",
            "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
            "Errors-To": "dev-bounces@dpdk.org",
            "Return-Path": "<dev-bounces@dpdk.org>"
        }
    }
]