get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 106167,
    "url": "http://patches.dpdk.org/api/patches/106167/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20220121103122.2926856-7-ronan.randles@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": "<20220121103122.2926856-7-ronan.randles@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20220121103122.2926856-7-ronan.randles@intel.com",
    "date": "2022-01-21T10:31:13",
    "name": "[v2,06/15] gen: add parsing infrastructure and Ether protocol",
    "commit_ref": null,
    "pull_url": null,
    "state": "not-applicable",
    "archived": true,
    "hash": "a8dc81b0739b4a2d6fd8539afba8bc05d04ba71c",
    "submitter": {
        "id": 2439,
        "url": "http://patches.dpdk.org/api/people/2439/?format=api",
        "name": "Ronan Randles",
        "email": "ronan.randles@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20220121103122.2926856-7-ronan.randles@intel.com/mbox/",
    "series": [
        {
            "id": 21295,
            "url": "http://patches.dpdk.org/api/series/21295/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=21295",
            "date": "2022-01-21T10:31:07",
            "name": "add packet generator library and example app",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/21295/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/106167/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/106167/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 29CACA034E;\n\tFri, 21 Jan 2022 11:32:09 +0100 (CET)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id A908642769;\n\tFri, 21 Jan 2022 11:31:40 +0100 (CET)",
            "from mga01.intel.com (mga01.intel.com [192.55.52.88])\n by mails.dpdk.org (Postfix) with ESMTP id 069B842750\n for <dev@dpdk.org>; Fri, 21 Jan 2022 11:31:37 +0100 (CET)",
            "from orsmga008.jf.intel.com ([10.7.209.65])\n by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 21 Jan 2022 02:31:37 -0800",
            "from silpixa00401120.ir.intel.com ([10.55.128.255])\n by orsmga008.jf.intel.com with ESMTP; 21 Jan 2022 02:31:36 -0800"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n d=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n t=1642761098; x=1674297098;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=KE0FZUxIC5SRFTwuGuBQh2K25e6hNP4UWCCUUYxpKXo=;\n b=kdmo25cpRW3q6G3nlrS3FCWlh2ufkMZ5f2uBJhChQfNz5FlBOKmi17DJ\n o96DUjUOTakBhQpH+dIm0qCTlw1AryFBH27X0g7+9qv8zqwMk/sTjdkJ3\n pdltrEsUPh17ZELGYPhJ93CLJj7uI5MLKxuilZ4skEiscgK7O0+dCGRm3\n BVEg04sj4Tv3OGRi0jZ0u/2kj2FtYp0DYXtaJJlsMUBOUaEjgM2rAeo2V\n TJqyAis2CYu996uGCeLQb/bUogz9HKC/AjrDX4upJgNkebkSGQdYMR1Ub\n k/iAu0+HGUn8Z7jSn/cPk/xBX/XISwr2VxoLp5CIuHuIWfdd9IoW19xWi w==;",
        "X-IronPort-AV": [
            "E=McAfee;i=\"6200,9189,10233\"; a=\"270045103\"",
            "E=Sophos;i=\"5.88,304,1635231600\"; d=\"scan'208\";a=\"270045103\"",
            "E=Sophos;i=\"5.88,304,1635231600\"; d=\"scan'208\";a=\"533222749\""
        ],
        "X-ExtLoop1": "1",
        "From": "Ronan Randles <ronan.randles@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "Harry van Haaren <harry.van.haaren@intel.com>",
        "Subject": "[PATCH v2 06/15] gen: add parsing infrastructure and Ether protocol",
        "Date": "Fri, 21 Jan 2022 10:31:13 +0000",
        "Message-Id": "<20220121103122.2926856-7-ronan.randles@intel.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20220121103122.2926856-1-ronan.randles@intel.com>",
        "References": "<20211214141242.3383831-1-ronan.randles@intel.com>\n <20220121103122.2926856-1-ronan.randles@intel.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "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"
    },
    "content": "From: Harry van Haaren <harry.van.haaren@intel.com>\n\nThis commit adds parsing infrastructure and support\nfor Ether parsing. Appropriate unit tests are also added\n\nSigned-off-by: Harry van Haaren <harry.van.haaren@intel.com>\n---\n app/test/test_gen.c |  29 +++++\n lib/gen/meson.build |   2 +-\n lib/gen/rte_gen.c   | 299 ++++++++++++++++++++++++++++++++++++++++++++\n lib/gen/rte_gen.h   |  12 ++\n lib/gen/version.map |   1 +\n 5 files changed, 342 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/app/test/test_gen.c b/app/test/test_gen.c\nindex b60ceaef8a..324582d0a5 100644\n--- a/app/test/test_gen.c\n+++ b/app/test/test_gen.c\n@@ -112,6 +112,34 @@ test_gen_packet_set_raw(void)\n \treturn 0;\n }\n \n+static int\n+test_gen_packet_parse_string(void)\n+{\n+\tstruct rte_gen *gen = rte_gen_create(mp);\n+\tTEST_ASSERT_FAIL(gen, \"Expected valid pointer after create()\");\n+\n+\tstruct str_parse_t {\n+\t\tconst char *str;\n+\t} pkt_strings[] = {\n+\t\t{ .str = \"Ether()\"},\n+\t\t{ .str = \"Ether()/\"},\n+\t\t{ .str = \"/Ether()\"},\n+\t\t{ .str = \"/Ether()/\"}\n+\t};\n+\n+\tuint32_t i;\n+\tfor (i = 0; i < RTE_DIM(pkt_strings); i++) {\n+\t\tconst char *pkt_str = pkt_strings[i].str;\n+\t\tint32_t err = rte_gen_packet_parse_string(gen, pkt_str, NULL);\n+\t\tTEST_ASSERT_EQUAL(err, 0, \"Expected string %s to parse.\",\n+\t\t\t\tpkt_str);\n+\t}\n+\n+\trte_gen_destroy(gen);\n+\treturn 0;\n+}\n+\n+\n static struct unit_test_suite gen_suite  = {\n \t.suite_name = \"gen: packet generator unit test suite\",\n \t.setup = testsuite_setup,\n@@ -121,6 +149,7 @@ static struct unit_test_suite gen_suite  = {\n \t\tTEST_CASE_ST(NULL, NULL, test_gen_basic_rxtx),\n \t\tTEST_CASE_ST(NULL, NULL, test_gen_loop_rxtx),\n \t\tTEST_CASE_ST(NULL, NULL, test_gen_packet_set_raw),\n+\t\tTEST_CASE_ST(NULL, NULL, test_gen_packet_parse_string),\n \t\tTEST_CASES_END() /**< NULL terminate unit test array */\n \t}\n };\ndiff --git a/lib/gen/meson.build b/lib/gen/meson.build\nindex 753984cbba..b3a55564f4 100644\n--- a/lib/gen/meson.build\n+++ b/lib/gen/meson.build\n@@ -3,4 +3,4 @@\n \n sources = files('rte_gen.c')\n headers = files('rte_gen.h')\n-deps += ['mempool', 'mbuf']\n+deps += ['mempool', 'mbuf', 'net']\ndiff --git a/lib/gen/rte_gen.c b/lib/gen/rte_gen.c\nindex 8a54c4bcdb..4d3fe4017f 100644\n--- a/lib/gen/rte_gen.c\n+++ b/lib/gen/rte_gen.c\n@@ -9,12 +9,18 @@\n #include <rte_hexdump.h>\n #include <rte_log.h>\n \n+#include <rte_ether.h>\n+\n RTE_LOG_REGISTER(gen_logtype, lib.gen, NOTICE);\n \n #define GEN_LOG(level, fmt, args...)\t\t\t\t\\\n \trte_log(RTE_LOG_ ## level, gen_logtype, \"%s(): \" fmt,\t\\\n \t\t__func__, ## args)\n \n+/* Don't prefix with function name, breaks the Scapy style formatting. */\n+#define GEN_LOG_PROTOCOL(level, fmt, args...)\t\t\t\\\n+\trte_log(RTE_LOG_ ## level, gen_logtype, fmt, ## args)\n+\n #define GEN_MAX_BURST 32\n #define GEN_INIT_PKT_SIZE 64\n \n@@ -126,3 +132,296 @@ rte_gen_tx_burst(struct rte_gen *gen,\n \n \treturn nb_pkts;\n }\n+\n+enum GEN_PROTO {\n+\tGEN_PROTO_INVALID,\n+\tGEN_PROTO_ETHER,\n+\n+\t/* Must be last. */\n+\tGEN_PROTO_COUNT,\n+};\n+\n+typedef void (*gen_log_func)(void *data, const char *indent);\n+\n+/* Structure for holding offset and function pointers for protocol. */\n+struct protocol_meta {\n+\t/* Byte offset into packet where this protocol starts. */\n+\tuint32_t offset;\n+\t/* Function to call to log the packet's information. */\n+\tgen_log_func log_func;\n+};\n+\n+/* Allow up to 32 nexted '/' characters in the protocol string. */\n+#define GEN_PROTO_PARSE_MAX 16\n+\n+/* Structure to hold state required while parsing. */\n+struct gen_parser {\n+\t/* Mbuf the parsed data is being put into. */\n+\tstruct rte_mbuf *mbuf;\n+\tuint8_t *mbuf_data;\n+\n+\t/* Offset into the packet data to parse to next. */\n+\tuint32_t buf_write_offset;\n+\n+\t/* Parsing state. */\n+\tuint8_t parse_iter;\n+\tchar indent_str[(GEN_PROTO_PARSE_MAX * 2) + 1];\n+\n+\t/* String being parsed. */\n+\tchar *parse_string;\n+\tchar *parse_strtok_save_ptr;\n+\n+\t/* Store metadata for parse/display of protocols.  */\n+\tstruct protocol_meta proto_meta[GEN_PROTO_PARSE_MAX];\n+\n+\t/* Per protocol hit counters. */\n+\tuint32_t proto_hit_counters[GEN_PROTO_COUNT];\n+};\n+\n+/* Forward declaration of recursive parsing function.\n+ * @param inner reports back the inner protocol that was handled. This is often\n+ * required for the outer protocol to indicate what the inner protocol is.\n+ */\n+static int32_t\n+gen_parser_parse_next(struct gen_parser *parser, enum GEN_PROTO *inner);\n+\n+/* Return void pointer to the position in the data buffer to parse into. */\n+static inline void *\n+gen_parser_get_data_ptr(struct gen_parser *parser)\n+{\n+\treturn &parser->mbuf_data[parser->buf_write_offset];\n+}\n+\n+/* Initialize a parser structure. */\n+static int32_t\n+gen_parser_init(struct gen_parser *parser, struct rte_gen *gen,\n+\t\tconst char *pkt_string)\n+{\n+\t/* Initialize own memory to zero. */\n+\tmemset(parser, 0, sizeof(*parser));\n+\n+\t/* Duplicate string for tokenizing string. */\n+\tparser->parse_string = strdup(pkt_string);\n+\tif (!parser->parse_string)\n+\t\tgoto error;\n+\n+\t/* Allocate mbuf to parse packet into. */\n+\tparser->mbuf = rte_pktmbuf_alloc(gen->mp);\n+\tif (!parser->mbuf)\n+\t\tgoto error;\n+\n+\tparser->mbuf_data = rte_pktmbuf_mtod(parser->mbuf, uint8_t *);\n+\n+\treturn 0;\n+\n+error:\n+\tfree(parser->parse_string);\n+\treturn -ENOMEM;\n+}\n+\n+static void\n+gen_log_ether(void *data, const char *indent)\n+{\n+\tstruct rte_ether_hdr *eth = data;\n+\tchar src[64];\n+\tchar dst[64];\n+\n+\trte_ether_format_addr(src, 64, &eth->src_addr);\n+\trte_ether_format_addr(dst, 64, &eth->dst_addr);\n+\tconst char *type_str;\n+\tswitch (rte_be_to_cpu_16(eth->ether_type)) {\n+\tcase RTE_ETHER_TYPE_IPV4:\n+\t\ttype_str = \"IPv4\";\n+\t\tbreak;\n+\tdefault:\n+\t\ttype_str = \"0x9000\";\n+\t\tbreak;\n+\t};\n+\tGEN_LOG_PROTOCOL(DEBUG,\n+\t\t\"###[ Ethernet ]###\\n%sdst= %s\\n%ssrc= %s\\n%stype= %s\\n\",\n+\t\tindent, dst, indent, src, indent, type_str);\n+}\n+\n+/* Ether(...) string detected, supports parameters:\n+ * - dst : Destination MAC in 00:11:22:33:44:55 or 0011:2233:4455 forms.\n+ * - src : Source MAC in the same forms.\n+ * Note:\n+ * - type is set based on the next header\n+ */\n+static int32_t\n+gen_parse_ether(struct gen_parser *parser, char *protocol_str)\n+{\n+\tstruct rte_ether_hdr *eth = gen_parser_get_data_ptr(parser);\n+\n+\tchar *dst_ptr = strstr(protocol_str, \"dst=\");\n+\tif (dst_ptr) {\n+\t\tchar *dup = strdup(dst_ptr);\n+\t\trte_ether_unformat_addr(&dup[4], &eth->dst_addr);\n+\t\tfree(dup);\n+\t} else\n+\t\trte_ether_unformat_addr(\"ff:ff:ff:ff:ff:ff\", &eth->dst_addr);\n+\n+\tchar *src_ptr = strstr(protocol_str, \"src=\");\n+\tif (src_ptr)\n+\t\trte_ether_unformat_addr(&src_ptr[4], &eth->src_addr);\n+\telse\n+\t\trte_ether_unformat_addr(\"00:00:00:00:00:00\", &eth->src_addr);\n+\n+\t/* Move up write pointer in packet. */\n+\tparser->buf_write_offset += sizeof(*eth);\n+\n+\t/* Recurse and handle inner protocol. */\n+\tenum GEN_PROTO inner;\n+\tint32_t err = gen_parser_parse_next(parser, &inner);\n+\tif (err) {\n+\t\tGEN_LOG(ERR, \"parser parse next() error %d\\n\", err);\n+\t\treturn err;\n+\t}\n+\n+\tswitch (inner) {\n+\tdefault:\n+\t\teth->ether_type = rte_cpu_to_be_16(0x9000);\n+\t\tbreak;\n+\t};\n+\treturn 0;\n+}\n+\n+/* (Name, Function-pointer) pairs for supported parse types */\n+typedef int32_t (*gen_parse_func)(struct gen_parser *parser,\n+\t\t\t\tchar *protocol_str);\n+\n+struct gen_parse_func_t {\n+\tconst char *name;\n+\tenum GEN_PROTO proto;\n+\tgen_parse_func parse_func;\n+\tgen_log_func log_func;\n+};\n+\n+/* Mapping from string to function to parse that protocol. */\n+static struct gen_parse_func_t gen_protocols[] = {\n+\t{\n+\t\t.name = \"Ether(\",\n+\t\t.proto = GEN_PROTO_ETHER,\n+\t\t.parse_func = gen_parse_ether,\n+\t\t.log_func = gen_log_ether,\n+\t}\n+};\n+\n+/* Function to tokenize and parse each segment of a string.\n+ * @param outer indicates the protocol before this one.\n+ * @param inner returns the protocol that is parsed here/now.\n+ */\n+static int32_t\n+gen_parser_parse_next(struct gen_parser *parser,\n+\t\t\tenum GEN_PROTO *inner_proto)\n+{\n+\t/* Tokenize the input string based on '/' character. */\n+\tchar *tok_str = (parser->parse_iter == 0) ?\n+\t\t\t\t\tparser->parse_string : NULL;\n+\tparser->parse_string = strtok_r(tok_str, \"/\",\n+\t\t\t\t\t&parser->parse_strtok_save_ptr);\n+\n+\t/* End protocol parsing recursion when parse_string is NULL, or max\n+\t * protocol recursion depth is reached.\n+\t */\n+\tif (!parser->parse_string ||\n+\t\t\tparser->parse_iter >= GEN_PROTO_PARSE_MAX) {\n+\t\tstruct rte_mbuf *mbuf = parser->mbuf;\n+\t\tmbuf->data_len = parser->buf_write_offset;\n+\t\tmbuf->pkt_len = parser->buf_write_offset;\n+\t\tGEN_LOG(DEBUG, \"packet length %d\\n\", mbuf->pkt_len);\n+\t\treturn 0;\n+\t}\n+\n+\tuint32_t i;\n+\t/* Loop over protocols, and identify the parse function to call. */\n+\tfor (i = 0; i < RTE_DIM(gen_protocols); i++) {\n+\t\tconst char *proto = gen_protocols[i].name;\n+\t\tuint32_t proto_len = strlen(proto);\n+\t\tif (strncmp(proto, parser->parse_string, proto_len))\n+\t\t\tcontinue;\n+\n+\t\t/* Store the log function pointer to output later. */\n+\t\tuint32_t iter = parser->parse_iter;\n+\t\tparser->proto_hit_counters[i]++;\n+\t\tstruct protocol_meta *meta = &parser->proto_meta[iter];\n+\n+\t\tif (gen_protocols[i].log_func == NULL) {\n+\t\t\tGEN_LOG(ERR, \"Missing log function, failed to log %s\\n\",\n+\t\t\t\t\t\t\t\t\tproto);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tmeta->log_func = gen_protocols[i].log_func;\n+\t\tmeta->offset = parser->buf_write_offset;\n+\n+\t\tif (gen_protocols[i].parse_func == NULL) {\n+\t\t\tGEN_LOG(ERR, \"Missing parse function, failed to parse %s\\n\"\n+\t\t\t\t\t\t\t\t, proto);\n+\t\t\treturn -1;\n+\t\t}\n+\t\t/* Handle protocol recursively. */\n+\t\tparser->parse_iter++;\n+\t\tint err = gen_protocols[i].parse_func(parser,\n+\t\t\t\t\t\t\tparser->parse_string);\n+\t\t*inner_proto = gen_protocols[i].proto;\n+\n+\t\treturn err;\n+\t}\n+\n+\tGEN_LOG(ERR, \"parser does not understand protocol %s\\n\",\n+\t\tparser->parse_string);\n+\treturn -1;\n+}\n+\n+int32_t\n+rte_gen_packet_parse_string(struct rte_gen *gen,\n+\t\t\t    const char *pkt_string,\n+\t\t\t    struct rte_mbuf **old_mbuf_to_user)\n+{\n+\tstruct gen_parser parser;\n+\tint32_t err = gen_parser_init(&parser, gen, pkt_string);\n+\tif (err) {\n+\t\tGEN_LOG(ERR, \"error with parser_init(), %d\\n\", err);\n+\t\treturn -1;\n+\t};\n+\n+\t/* Recursively parse each protocol. */\n+\tenum GEN_PROTO inner;\n+\terr = gen_parser_parse_next(&parser, &inner);\n+\tif (err) {\n+\t\tGEN_LOG(ERR, \"Error in parsing packet string. \"\n+\t\t\t\"Set \\\"gen\\\" log level to debug for more info.\\n\");\n+\t\trte_pktmbuf_free(parser.mbuf);\n+\t\treturn -1;\n+\t}\n+\n+\tuint32_t i;\n+\t/* Iterate the per protocol stored metadata to log output. */\n+\tfor (i = 0; i < parser.parse_iter; i++) {\n+\t\tsnprintf(parser.indent_str, 2 + i * 2,\n+\t\t\t\"                               \" /* 32 spaces. */);\n+\n+\t\tif (gen_protocols[i].log_func == NULL) {\n+\t\t\tGEN_LOG(ERR, \"Missing log function\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tvoid *buf_off = parser.mbuf_data + parser.proto_meta[i].offset;\n+\t\tparser.proto_meta[i].log_func(buf_off, parser.indent_str);\n+\t}\n+\n+\tif (inner != GEN_PROTO_ETHER) {\n+\t\tGEN_LOG(WARNING,\n+\t\t\t\"Outer protocol of frame is not Ethernet.\\n\");\n+\t}\n+\n+\t/* Free the currently in use mbuf. */\n+\tif (old_mbuf_to_user)\n+\t\t*old_mbuf_to_user = gen->base_pkt;\n+\telse\n+\t\trte_pktmbuf_free(gen->base_pkt);\n+\n+\t/* TODO: HVH design race-condition above vs rx/tx*/\n+\tgen->base_pkt = parser.mbuf;\n+\treturn 0;\n+}\ndiff --git a/lib/gen/rte_gen.h b/lib/gen/rte_gen.h\nindex 9119331673..93b3346436 100644\n--- a/lib/gen/rte_gen.h\n+++ b/lib/gen/rte_gen.h\n@@ -95,6 +95,18 @@ rte_gen_packet_set_raw(struct rte_gen *gen,\n \t\t       const uint8_t *raw_data,\n \t\t       uint32_t raw_data_size);\n \n+/* Parse a string description of a packet.\n+ *\n+ * The optional out parameter supplies the previously being sent mbuf to\n+ * the user to be freed later. If this argument is not provided, then the\n+ * mbuf is freed by this function.\n+ */\n+__rte_experimental\n+int32_t\n+rte_gen_packet_parse_string(struct rte_gen *gen,\n+\t\t\t    const char *pkt_string,\n+\t\t\t    struct rte_mbuf **old_mbuf_to_user);\n+\n #ifdef __cplusplus\n }\n #endif\ndiff --git a/lib/gen/version.map b/lib/gen/version.map\nindex d75e0b4bac..e335c608ee 100644\n--- a/lib/gen/version.map\n+++ b/lib/gen/version.map\n@@ -6,4 +6,5 @@ EXPERIMENTAL {\n \trte_gen_rx_burst;\n \trte_gen_tx_burst;\n \trte_gen_packet_set_raw;\n+\trte_gen_packet_parse_string;\n };\n",
    "prefixes": [
        "v2",
        "06/15"
    ]
}