Add command line parameter:
--rxhdrs=eth,[eth-ipv4,eth-ipv4-udp]

Set the protocol_hdr of segments to scatter packets on receiving if
split feature is engaged. And the queues with BUFFER_SPLIT flag.

Add interactive mode command:
testpmd>set rxhdrs eth,eth-ipv4,eth-ipv4-udp
(protocol sequence should be valid)

The protocol split feature is off by default. To enable protocol split,
you need:
1. Start testpmd with multiple mempools. E.g. --mbuf-size=2048,2048
2. Configure Rx queue with rx_offload buffer split on.
3. Set the protocol type of buffer split. E.g. set rxhdrs eth,eth-ipv4
        (default protocols of testpmd : eth|eth-ipv4|eth-ipv6|
         eth-ipv4-tcp|eth-ipv6-tcp|eth-ipv4-udp|eth-ipv6-udp|
         eth-ipv4-sctp|eth-ipv6-sctp|grenat-eth|grenat-eth-ipv4|
         grenat-eth-ipv6|grenat-eth-ipv4-tcp|grenat-eth-ipv6-tcp|
         grenat-eth-ipv4-udp|grenat-eth-ipv6-udp|grenat-eth-ipv4-sctp|
         grenat-eth-ipv6-sctp)
Above protocols can be configured in testpmd. But the configuration can
only be applied when it is supported by specific pmd.

Signed-off-by: Yuan Wang <yuanx.w...@intel.com>
Signed-off-by: Xuan Ding <xuan.d...@intel.com>
Signed-off-by: Wenxuan Wu <wenxuanx...@intel.com>
---
 app/test-pmd/cmdline.c    | 146 +++++++++++++++++++++++++++++++++++++-
 app/test-pmd/config.c     |  88 +++++++++++++++++++++++
 app/test-pmd/parameters.c |  16 ++++-
 app/test-pmd/testpmd.c    |   2 +
 app/test-pmd/testpmd.h    |   6 ++
 5 files changed, 254 insertions(+), 4 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index ba749f588a..00c7d167ce 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -181,7 +181,7 @@ static void cmd_help_long_parsed(void *parsed_result,
                        "show (rxq|txq) info (port_id) (queue_id)\n"
                        "    Display information for configured RX/TX 
queue.\n\n"
 
-                       "show config (rxtx|cores|fwd|rxoffs|rxpkts|txpkts)\n"
+                       "show config 
(rxtx|cores|fwd|rxoffs|rxpkts|rxhdrs|txpkts)\n"
                        "    Display the given configuration.\n\n"
 
                        "read rxd (port_id) (queue_id) (rxd_id)\n"
@@ -305,6 +305,17 @@ static void cmd_help_long_parsed(void *parsed_result,
                        " Affects only the queues configured with split"
                        " offloads.\n\n"
 
+                       "set rxhdrs (eth[,eth-ipv4])*\n"
+                       "    Set the protocol hdr of each segment to scatter"
+                       " packets on receiving if split feature is engaged."
+                       " Affects only the queues configured with split"
+                       " offloads.\n"
+                       "    Supported values: 
eth|eth-ipv4|eth-ipv6|eth-ipv4-tcp|eth-ipv6-tcp|"
+                       "eth-ipv4-udp|eth-ipv6-udp|eth-ipv4-sctp|eth-ipv6-sctp|"
+                       
"grenat-eth|grenat-eth-ipv4|grenat-eth-ipv6|grenat-eth-ipv4-tcp|"
+                       
"grenat-eth-ipv6-tcp|grenat-eth-ipv4-udp|grenat-eth-ipv6-udp|"
+                       "grenat-eth-ipv4-sctp|grenat-eth-ipv6-sctp\n\n"
+
                        "set txpkts (x[,y]*)\n"
                        "    Set the length of each segment of TXONLY"
                        " and optionally CSUM packets.\n\n"
@@ -3366,6 +3377,88 @@ static cmdline_parse_inst_t cmd_stop = {
        },
 };
 
+static unsigned int
+get_ptype(char *value)
+{
+       uint32_t protocol;
+
+       if (!strcmp(value, "eth"))
+               protocol = RTE_PTYPE_L2_ETHER;
+       else if (!strcmp(value, "eth-ipv4"))
+               protocol = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN;
+       else if (!strcmp(value, "eth-ipv6"))
+               protocol = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN;
+       else if (!strcmp(value, "eth-ipv4-tcp"))
+               protocol = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 
RTE_PTYPE_L4_TCP;
+       else if (!strcmp(value, "eth-ipv6-tcp"))
+               protocol = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 
RTE_PTYPE_L4_TCP;
+       else if (!strcmp(value, "eth-ipv4-udp"))
+               protocol = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 
RTE_PTYPE_L4_UDP;
+       else if (!strcmp(value, "eth-ipv6-udp"))
+               protocol = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 
RTE_PTYPE_L4_UDP;
+       else if (!strcmp(value, "eth-ipv4-sctp"))
+               protocol = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 
RTE_PTYPE_L4_SCTP;
+       else if (!strcmp(value, "eth-ipv6-sctp"))
+               protocol = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 
RTE_PTYPE_L4_SCTP;
+       else if (!strcmp(value, "grenat-eth"))
+               protocol = RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER;
+       else if (!strcmp(value, "grenat-eth-ipv4"))
+               protocol = RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+                               RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN;
+       else if (!strcmp(value, "grenat-eth-ipv6"))
+               protocol = RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+                       RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN;
+       else if (!strcmp(value, "grenat-eth-ipv4-tcp"))
+               protocol = RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+                       RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 
RTE_PTYPE_INNER_L4_TCP;
+       else if (!strcmp(value, "grenat-eth-ipv6-tcp"))
+               protocol = RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+                       RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 
RTE_PTYPE_INNER_L4_TCP;
+       else if (!strcmp(value, "grenat-eth-ipv4-udp"))
+               protocol = RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+                       RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 
RTE_PTYPE_INNER_L4_UDP;
+       else if (!strcmp(value, "grenat-eth-ipv6-udp"))
+               protocol = RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+                       RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 
RTE_PTYPE_INNER_L4_UDP;
+       else if (!strcmp(value, "grenat-eth-ipv4-sctp"))
+               protocol = RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+                       RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 
RTE_PTYPE_INNER_L4_SCTP;
+       else if (!strcmp(value, "grenat-eth-ipv6-sctp"))
+               protocol = RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+                       RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 
RTE_PTYPE_INNER_L4_SCTP;
+       else {
+               fprintf(stderr, "Unsupported protocol: %s\n", value);
+               protocol = RTE_PTYPE_UNKNOWN;
+       }
+
+       return protocol;
+}
+/* *** SET RXHDRSLIST *** */
+
+unsigned int
+parse_hdrs_list(const char *str, const char *item_name, unsigned int max_items,
+                               unsigned int *parsed_items, int 
check_hdrs_sequence)
+{
+       unsigned int nb_item;
+       char *cur;
+       char *tmp;
+
+       nb_item = 0;
+       char *str2 = strdup(str);
+       cur = strtok_r(str2, ",", &tmp);
+       while (cur != NULL) {
+               parsed_items[nb_item] = get_ptype(cur);
+               cur = strtok_r(NULL, ",", &tmp);
+               nb_item++;
+       }
+       if (nb_item > max_items)
+               fprintf(stderr, "Number of %s = %u > %u (maximum items)\n",
+                       item_name, nb_item + 1, max_items);
+       free(str2);
+       if (!check_hdrs_sequence)
+               return nb_item;
+       return nb_item;
+}
 /* *** SET CORELIST and PORTLIST CONFIGURATION *** */
 
 unsigned int
@@ -3735,6 +3828,50 @@ static cmdline_parse_inst_t cmd_set_rxpkts = {
        },
 };
 
+/* *** SET SEGMENT HEADERS OF RX PACKETS SPLIT *** */
+struct cmd_set_rxhdrs_result {
+       cmdline_fixed_string_t set;
+       cmdline_fixed_string_t rxhdrs;
+       cmdline_fixed_string_t values;
+};
+
+static void
+cmd_set_rxhdrs_parsed(void *parsed_result,
+                     __rte_unused struct cmdline *cl,
+                     __rte_unused void *data)
+{
+       struct cmd_set_rxhdrs_result *res;
+       unsigned int seg_hdrs[MAX_SEGS_BUFFER_SPLIT];
+       unsigned int nb_segs;
+
+       res = parsed_result;
+       nb_segs = parse_hdrs_list(res->values, "segment hdrs",
+                                 MAX_SEGS_BUFFER_SPLIT, seg_hdrs, 0);
+       if (nb_segs > 0)
+               set_rx_pkt_hdrs(seg_hdrs, nb_segs);
+       cmd_reconfig_device_queue(RTE_PORT_ALL, 0, 1);
+}
+static cmdline_parse_token_string_t cmd_set_rxhdrs_set =
+       TOKEN_STRING_INITIALIZER(struct cmd_set_rxhdrs_result,
+                               set, "set");
+static cmdline_parse_token_string_t cmd_set_rxhdrs_rxhdrs =
+       TOKEN_STRING_INITIALIZER(struct cmd_set_rxhdrs_result,
+                               rxhdrs, "rxhdrs");
+static cmdline_parse_token_string_t cmd_set_rxhdrs_values =
+       TOKEN_STRING_INITIALIZER(struct cmd_set_rxhdrs_result,
+                               values, NULL);
+
+static cmdline_parse_inst_t cmd_set_rxhdrs = {
+       .f = cmd_set_rxhdrs_parsed,
+       .data = NULL,
+       .help_str = "set rxhdrs <eth[,eth-ipv4]*>",
+       .tokens = {
+               (void *)&cmd_set_rxhdrs_set,
+               (void *)&cmd_set_rxhdrs_rxhdrs,
+               (void *)&cmd_set_rxhdrs_values,
+               NULL,
+       },
+};
 /* *** SET SEGMENT LENGTHS OF TXONLY PACKETS *** */
 
 struct cmd_set_txpkts_result {
@@ -6487,6 +6624,8 @@ static void cmd_showcfg_parsed(void *parsed_result,
                show_rx_pkt_offsets();
        else if (!strcmp(res->what, "rxpkts"))
                show_rx_pkt_segments();
+       else if (!strcmp(res->what, "rxhdrs"))
+               show_rx_pkt_hdrs();
        else if (!strcmp(res->what, "txpkts"))
                show_tx_pkt_segments();
        else if (!strcmp(res->what, "txtimes"))
@@ -6499,12 +6638,12 @@ static cmdline_parse_token_string_t cmd_showcfg_port =
        TOKEN_STRING_INITIALIZER(struct cmd_showcfg_result, cfg, "config");
 static cmdline_parse_token_string_t cmd_showcfg_what =
        TOKEN_STRING_INITIALIZER(struct cmd_showcfg_result, what,
-                                "rxtx#cores#fwd#rxoffs#rxpkts#txpkts#txtimes");
+                                
"rxtx#cores#fwd#rxoffs#rxpkts#rxhdrs#txpkts#txtimes");
 
 static cmdline_parse_inst_t cmd_showcfg = {
        .f = cmd_showcfg_parsed,
        .data = NULL,
-       .help_str = "show config rxtx|cores|fwd|rxoffs|rxpkts|txpkts|txtimes",
+       .help_str = "show config 
rxtx|cores|fwd|rxoffs|rxpkts|rxhdrs|txpkts|txtimes",
        .tokens = {
                (void *)&cmd_showcfg_show,
                (void *)&cmd_showcfg_port,
@@ -12455,6 +12594,7 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
        (cmdline_parse_inst_t *)&cmd_set_log,
        (cmdline_parse_inst_t *)&cmd_set_rxoffs,
        (cmdline_parse_inst_t *)&cmd_set_rxpkts,
+       (cmdline_parse_inst_t *)&cmd_set_rxhdrs,
        (cmdline_parse_inst_t *)&cmd_set_txpkts,
        (cmdline_parse_inst_t *)&cmd_set_txsplit,
        (cmdline_parse_inst_t *)&cmd_set_txtimes,
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 568b0881d4..d3e95e40da 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -4746,6 +4746,94 @@ show_rx_pkt_segments(void)
        }
 }
 
+static const char *get_ptype_str(uint32_t ptype)
+{
+       switch (ptype) {
+       case RTE_PTYPE_L2_ETHER:
+               return "eth";
+       case RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN:
+               return "eth-ipv4";
+       case RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN:
+               return "eth-ipv6";
+       case RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 
RTE_PTYPE_L4_TCP:
+               return "eth-ipv4-tcp";
+       case RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 
RTE_PTYPE_L4_TCP:
+               return "eth-ipv6-tcp";
+       case RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 
RTE_PTYPE_L4_UDP:
+               return "eth-ipv4-udp";
+       case RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 
RTE_PTYPE_L4_UDP:
+               return "eth-ipv6-udp";
+       case RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 
RTE_PTYPE_L4_SCTP:
+               return "eth-ipv4-sctp";
+       case RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 
RTE_PTYPE_L4_SCTP:
+               return "eth-ipv6-sctp";
+       case RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER:
+               return "grenat-eth";
+       case 
RTE_PTYPE_TUNNEL_GRENAT|RTE_PTYPE_INNER_L2_ETHER|RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN:
+               return "grenat-eth-ipv4";
+       case 
RTE_PTYPE_TUNNEL_GRENAT|RTE_PTYPE_INNER_L2_ETHER|RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN:
+               return "grenat-eth-ipv6";
+       case RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+               RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP:
+               return "grenat-eth-ipv4-tcp";
+       case RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+               RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP:
+               return "grenat-eth-ipv6-tcp";
+       case RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+               RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP:
+               return "grenat-eth-ipv4-udp";
+       case RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+               RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP:
+               return "grenat-eth-ipv6-udp";
+       case RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+               RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP:
+               return "grenat-eth-ipv4-sctp";
+       case RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+               RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP:
+               return "grenat-eth-ipv6-sctp";
+       default:
+               return "unsupported";
+       }
+}
+
+void
+show_rx_pkt_hdrs(void)
+{
+       uint32_t i, n;
+
+       n = rx_pkt_nb_segs;
+       printf("Number of segments: %u\n", n);
+       if (n) {
+               printf("Packet segs: ");
+               for (i = 0; i < n - 1; i++)
+                       printf("%s, ", get_ptype_str(rx_pkt_hdr_protos[i]));
+               printf("payload\n");
+       }
+}
+
+void
+set_rx_pkt_hdrs(unsigned int *seg_hdrs, unsigned int nb_segs)
+{
+       unsigned int i;
+
+       if (nb_segs + 1 > MAX_SEGS_BUFFER_SPLIT) {
+               printf("nb segments per RX packets=%u > "
+                      "MAX_SEGS_BUFFER_SPLIT - ignored\n", nb_segs + 1);
+               return;
+       }
+
+       memset(rx_pkt_hdr_protos, 0, sizeof(rx_pkt_hdr_protos));
+
+       for (i = 0; i < nb_segs; i++)
+               rx_pkt_hdr_protos[i] = (uint32_t)seg_hdrs[i];
+       rx_pkt_hdr_protos[nb_segs] = RTE_PTYPE_ALL_MASK;
+       /*
+        * We calculate the number of hdrs, but payload is not included,
+        * so rx_pkt_nb_segs would increase 1.
+        */
+       rx_pkt_nb_segs = nb_segs + 1;
+}
+
 void
 set_rx_pkt_segments(unsigned int *seg_lengths, unsigned int nb_segs)
 {
diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 1024b5419c..5bf4219c46 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -152,6 +152,7 @@ usage(char* progname)
               " Used mainly with PCAP drivers.\n");
        printf("  --rxoffs=X[,Y]*: set RX segment offsets for split.\n");
        printf("  --rxpkts=X[,Y]*: set RX segment sizes to split.\n");
+       printf("  --rxhdrs=eth[,ipv4]*: set RX segment protocol to split.\n");
        printf("  --txpkts=X[,Y]*: set TX segment sizes"
                " or total packet length.\n");
        printf("  --txonly-multi-flow: generate multiple flows in txonly 
mode\n");
@@ -660,6 +661,7 @@ launch_args_parse(int argc, char** argv)
                { "flow-isolate-all",           0, 0, 0 },
                { "rxoffs",                     1, 0, 0 },
                { "rxpkts",                     1, 0, 0 },
+               { "rxhdrs",                     1, 0, 0 },
                { "txpkts",                     1, 0, 0 },
                { "txonly-multi-flow",          0, 0, 0 },
                { "rxq-share",                  2, 0, 0 },
@@ -1254,7 +1256,6 @@ launch_args_parse(int argc, char** argv)
                        if (!strcmp(lgopts[opt_idx].name, "rxpkts")) {
                                unsigned int seg_len[MAX_SEGS_BUFFER_SPLIT];
                                unsigned int nb_segs;
-
                                nb_segs = parse_item_list
                                                (optarg, "rxpkt segments",
                                                 MAX_SEGS_BUFFER_SPLIT,
@@ -1264,6 +1265,19 @@ launch_args_parse(int argc, char** argv)
                                else
                                        rte_exit(EXIT_FAILURE, "bad rxpkts\n");
                        }
+                       if (!strcmp(lgopts[opt_idx].name, "rxhdrs")) {
+                               unsigned int seg_hdrs[MAX_SEGS_BUFFER_SPLIT];
+                               unsigned int nb_segs;
+
+                               nb_segs = parse_hdrs_list
+                                               (optarg, "rxpkt segments",
+                                               MAX_SEGS_BUFFER_SPLIT,
+                                               seg_hdrs, 0);
+                               if (nb_segs > 0)
+                                       set_rx_pkt_hdrs(seg_hdrs, nb_segs);
+                               else
+                                       rte_exit(EXIT_FAILURE, "bad rxpkts\n");
+                       }
                        if (!strcmp(lgopts[opt_idx].name, "txpkts")) {
                                unsigned seg_lengths[RTE_MAX_SEGS_PER_PKT];
                                unsigned int nb_segs;
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index de6ad00138..bb2a969559 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -247,6 +247,7 @@ uint16_t rx_pkt_seg_lengths[MAX_SEGS_BUFFER_SPLIT];
 uint8_t  rx_pkt_nb_segs; /**< Number of segments to split */
 uint16_t rx_pkt_seg_offsets[MAX_SEGS_BUFFER_SPLIT];
 uint8_t  rx_pkt_nb_offs; /**< Number of specified offsets */
+uint32_t rx_pkt_hdr_protos[MAX_SEGS_BUFFER_SPLIT];
 
 /*
  * Configuration of packet segments used by the "txonly" processing engine.
@@ -2652,6 +2653,7 @@ rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,
                rx_seg->offset = i < rx_pkt_nb_offs ?
                                   rx_pkt_seg_offsets[i] : 0;
                rx_seg->mp = mpx ? mpx : mp;
+               rx_seg->proto_hdr = rx_pkt_hdr_protos[i];
        }
        rx_conf->rx_nseg = rx_pkt_nb_segs;
        rx_conf->rx_seg = rx_useg;
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 21c5632aec..0e5e94423a 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -554,6 +554,7 @@ extern uint32_t max_rx_pkt_len;
  * Configuration of packet segments used to scatter received packets
  * if some of split features is configured.
  */
+extern uint32_t rx_pkt_hdr_protos[MAX_SEGS_BUFFER_SPLIT];
 extern uint16_t rx_pkt_seg_lengths[MAX_SEGS_BUFFER_SPLIT];
 extern uint8_t  rx_pkt_nb_segs; /**< Number of segments to split */
 extern uint16_t rx_pkt_seg_offsets[MAX_SEGS_BUFFER_SPLIT];
@@ -825,6 +826,9 @@ inc_tx_burst_stats(struct fwd_stream *fs, uint16_t nb_tx)
 unsigned int parse_item_list(const char *str, const char *item_name,
                        unsigned int max_items,
                        unsigned int *parsed_items, int check_unique_values);
+unsigned int parse_hdrs_list(const char *str, const char *item_name,
+                       unsigned int max_item,
+                       unsigned int *parsed_items, int check_unique_values);
 void launch_args_parse(int argc, char** argv);
 void cmd_reconfig_device_queue(portid_t id, uint8_t dev, uint8_t queue);
 void cmdline_read_from_file(const char *filename);
@@ -974,6 +978,8 @@ void set_record_core_cycles(uint8_t on_off);
 void set_record_burst_stats(uint8_t on_off);
 void set_verbose_level(uint16_t vb_level);
 void set_rx_pkt_segments(unsigned int *seg_lengths, unsigned int nb_segs);
+void set_rx_pkt_hdrs(unsigned int *seg_protos, unsigned int nb_segs);
+void show_rx_pkt_hdrs(void);
 void show_rx_pkt_segments(void);
 void set_rx_pkt_offsets(unsigned int *seg_offsets, unsigned int nb_offs);
 void show_rx_pkt_offsets(void);
-- 
2.25.1

Reply via email to