Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/29676/?format=api
https://patches.dpdk.org/api/patches/29676/?format=api", "web_url": "https://patches.dpdk.org/project/dpdk/patch/1507201331-228465-6-git-send-email-mark.b.kavanagh@intel.com/", "project": { "id": 1, "url": "https://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": "<1507201331-228465-6-git-send-email-mark.b.kavanagh@intel.com>", "list_archive_url": "https://inbox.dpdk.org/dev/1507201331-228465-6-git-send-email-mark.b.kavanagh@intel.com", "date": "2017-10-05T11:02:10", "name": "[dpdk-dev,v7,5/6] app/testpmd: enable TCP/IPv4, VxLAN and GRE GSO", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": true, "hash": "5ee13a53ca564e2904f38d2922b27c24329c9a02", "submitter": { "id": 133, "url": "https://patches.dpdk.org/api/people/133/?format=api", "name": "Mark Kavanagh", "email": "mark.b.kavanagh@intel.com" }, "delegate": null, "mbox": "https://patches.dpdk.org/project/dpdk/patch/1507201331-228465-6-git-send-email-mark.b.kavanagh@intel.com/mbox/", "series": [], "comments": "https://patches.dpdk.org/api/patches/29676/comments/", "check": "fail", "checks": "https://patches.dpdk.org/api/patches/29676/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 5A7161B1AB;\n\tThu, 5 Oct 2017 13:02:35 +0200 (CEST)", "from mga11.intel.com (mga11.intel.com [192.55.52.93])\n\tby dpdk.org (Postfix) with ESMTP id F37927D4E\n\tfor <dev@dpdk.org>; Thu, 5 Oct 2017 13:02:28 +0200 (CEST)", "from fmsmga005.fm.intel.com ([10.253.24.32])\n\tby fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t05 Oct 2017 04:02:28 -0700", "from silpixa00380299.ir.intel.com ([10.237.222.17])\n\tby fmsmga005.fm.intel.com with ESMTP; 05 Oct 2017 04:02:26 -0700" ], "X-ExtLoop1": "1", "X-IronPort-AV": "E=Sophos;i=\"5.42,481,1500966000\"; d=\"scan'208\";a=\"159160367\"", "From": "Mark Kavanagh <mark.b.kavanagh@intel.com>", "To": "dev@dpdk.org", "Cc": "jiayu.hu@intel.com, jianfeng.tan@intel.com, konstantin.ananyev@intel.com,\n\tferruh.yigit@intel.com, thomas@monjalon.net,\n\tMark Kavanagh <mark.b.kavanagh@intel.com>", "Date": "Thu, 5 Oct 2017 12:02:10 +0100", "Message-Id": "<1507201331-228465-6-git-send-email-mark.b.kavanagh@intel.com>", "X-Mailer": "git-send-email 1.9.3", "In-Reply-To": "<1507201331-228465-1-git-send-email-mark.b.kavanagh@intel.com>", "References": "<1506962749-106779-1-git-send-email-mark.b.kavanagh@intel.com>\n\t<1507201331-228465-1-git-send-email-mark.b.kavanagh@intel.com>", "Subject": "[dpdk-dev] [PATCH v7 5/6] app/testpmd: enable TCP/IPv4,\n\tVxLAN and GRE GSO", "X-BeenThere": "dev@dpdk.org", "X-Mailman-Version": "2.1.15", "Precedence": "list", "List-Id": "DPDK patches and discussions <dev.dpdk.org>", "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>", "List-Archive": "<http://dpdk.org/ml/archives/dev/>", "List-Post": "<mailto:dev@dpdk.org>", "List-Help": "<mailto:dev-request@dpdk.org?subject=help>", "List-Subscribe": "<http://dpdk.org/ml/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: Jiayu Hu <jiayu.hu@intel.com>\n\nThis patch adds GSO support to the csum forwarding engine. Oversized\npackets transmitted over a GSO-enabled port will undergo segmentation\n(with the exception of packet-types unsupported by the GSO library).\nGSO support is disabled by default.\n\nGSO support may be toggled on a per-port basis, using the command:\n\n \"set port <port_id> gso on|off\"\n\nThe maximum packet length (including the packet header and payload) for\nGSO segments may be set with the command:\n\n \"set gso segsz <length>\"\n\nShow GSO configuration for a given port with the command:\n\n\t\"show port <port_id> gso\"\n\nSigned-off-by: Jiayu Hu <jiayu.hu@intel.com>\nSigned-off-by: Mark Kavanagh <mark.b.kavanagh@intel.com>\n---\n app/test-pmd/cmdline.c | 179 ++++++++++++++++++++++++++++\n app/test-pmd/config.c | 24 ++++\n app/test-pmd/csumonly.c | 43 ++++++-\n app/test-pmd/testpmd.c | 13 ++\n app/test-pmd/testpmd.h | 10 ++\n doc/guides/testpmd_app_ug/testpmd_funcs.rst | 46 +++++++\n 6 files changed, 311 insertions(+), 4 deletions(-)", "diff": "diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c\nindex ccdf239..92e6171 100644\n--- a/app/test-pmd/cmdline.c\n+++ b/app/test-pmd/cmdline.c\n@@ -431,6 +431,17 @@ static void cmd_help_long_parsed(void *parsed_result,\n \t\t\t\" Set max flow number and max packet number per-flow\"\n \t\t\t\" for GRO.\\n\\n\"\n \n+\t\t\t\"set port (port_id) gso (on|off)\"\n+\t\t\t\" Enable or disable Generic Segmentation Offload in\"\n+\t\t\t\" csum forwarding engine.\\n\\n\"\n+\n+\t\t\t\"set gso segsz (length)\\n\"\n+\t\t\t\" Set max packet length for output GSO segments,\"\n+\t\t\t\" including packet header and payload.\\n\\n\"\n+\n+\t\t\t\"show port (port_id) gso\\n\"\n+\t\t\t\" Show GSO configuration.\\n\\n\"\n+\n \t\t\t\"set fwd (%s)\\n\"\n \t\t\t\" Set packet forwarding mode.\\n\\n\"\n \n@@ -3967,6 +3978,171 @@ struct cmd_gro_set_result {\n \t},\n };\n \n+/* *** ENABLE/DISABLE GSO *** */\n+struct cmd_gso_enable_result {\n+\tcmdline_fixed_string_t cmd_set;\n+\tcmdline_fixed_string_t cmd_port;\n+\tcmdline_fixed_string_t cmd_keyword;\n+\tcmdline_fixed_string_t cmd_mode;\n+\tuint8_t cmd_pid;\n+};\n+\n+static void\n+cmd_gso_enable_parsed(void *parsed_result,\n+\t\t__attribute__((unused)) struct cmdline *cl,\n+\t\t__attribute__((unused)) void *data)\n+{\n+\tstruct cmd_gso_enable_result *res;\n+\n+\tres = parsed_result;\n+\tif (!strcmp(res->cmd_keyword, \"gso\"))\n+\t\tsetup_gso(res->cmd_mode, res->cmd_pid);\n+}\n+\n+cmdline_parse_token_string_t cmd_gso_enable_set =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_gso_enable_result,\n+\t\t\tcmd_set, \"set\");\n+cmdline_parse_token_string_t cmd_gso_enable_port =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_gso_enable_result,\n+\t\t\tcmd_port, \"port\");\n+cmdline_parse_token_string_t cmd_gso_enable_keyword =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_gso_enable_result,\n+\t\t\tcmd_keyword, \"gso\");\n+cmdline_parse_token_string_t cmd_gso_enable_mode =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_gso_enable_result,\n+\t\t\tcmd_mode, \"on#off\");\n+cmdline_parse_token_num_t cmd_gso_enable_pid =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_gso_enable_result,\n+\t\t\tcmd_pid, UINT8);\n+\n+cmdline_parse_inst_t cmd_gso_enable = {\n+\t.f = cmd_gso_enable_parsed,\n+\t.data = NULL,\n+\t.help_str = \"set port <port_id> gso on|off\",\n+\t.tokens = {\n+\t\t(void *)&cmd_gso_enable_set,\n+\t\t(void *)&cmd_gso_enable_port,\n+\t\t(void *)&cmd_gso_enable_pid,\n+\t\t(void *)&cmd_gso_enable_keyword,\n+\t\t(void *)&cmd_gso_enable_mode,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** SET MAX PACKET LENGTH FOR GSO SEGMENTS *** */\n+struct cmd_gso_size_result {\n+\tcmdline_fixed_string_t cmd_set;\n+\tcmdline_fixed_string_t cmd_keyword;\n+\tcmdline_fixed_string_t cmd_segsz;\n+\tuint16_t cmd_size;\n+};\n+\n+static void\n+cmd_gso_size_parsed(void *parsed_result,\n+\t\t __attribute__((unused)) struct cmdline *cl,\n+\t\t __attribute__((unused)) void *data)\n+{\n+\tstruct cmd_gso_size_result *res = parsed_result;\n+\n+\tif (test_done == 0) {\n+\t\tprintf(\"Before setting GSO segsz, please first stop fowarding\\n\");\n+\t\treturn;\n+\t}\n+\n+\tif (!strcmp(res->cmd_keyword, \"gso\") &&\n+\t\t\t!strcmp(res->cmd_segsz, \"segsz\")) {\n+\t\tif (res->cmd_size < RTE_GSO_SEG_SIZE_MIN)\n+\t\t\tprintf(\"gso_size should be larger than %lu.\"\n+\t\t\t\t\t\" Please input a legal value\\n\",\n+\t\t\t\t\tRTE_GSO_SEG_SIZE_MIN);\n+\t\telse\n+\t\t\tgso_max_segment_size = res->cmd_size;\n+\t}\n+}\n+\n+cmdline_parse_token_string_t cmd_gso_size_set =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_gso_size_result,\n+\t\t\t\tcmd_set, \"set\");\n+cmdline_parse_token_string_t cmd_gso_size_keyword =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_gso_size_result,\n+\t\t\t\tcmd_keyword, \"gso\");\n+cmdline_parse_token_string_t cmd_gso_size_segsz =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_gso_size_result,\n+\t\t\t\tcmd_segsz, \"segsz\");\n+cmdline_parse_token_num_t cmd_gso_size_size =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_gso_size_result,\n+\t\t\t\tcmd_size, UINT16);\n+\n+cmdline_parse_inst_t cmd_gso_size = {\n+\t.f = cmd_gso_size_parsed,\n+\t.data = NULL,\n+\t.help_str = \"set gso segsz <length>\",\n+\t.tokens = {\n+\t\t(void *)&cmd_gso_size_set,\n+\t\t(void *)&cmd_gso_size_keyword,\n+\t\t(void *)&cmd_gso_size_segsz,\n+\t\t(void *)&cmd_gso_size_size,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** SHOW GSO CONFIGURATION *** */\n+struct cmd_gso_show_result {\n+\tcmdline_fixed_string_t cmd_show;\n+\tcmdline_fixed_string_t cmd_port;\n+\tcmdline_fixed_string_t cmd_keyword;\n+\tuint8_t cmd_pid;\n+};\n+\n+static void\n+cmd_gso_show_parsed(void *parsed_result,\n+\t\t __attribute__((unused)) struct cmdline *cl,\n+\t\t __attribute__((unused)) void *data)\n+{\n+\tstruct cmd_gso_show_result *res = parsed_result;\n+\n+\tif (!rte_eth_dev_is_valid_port(res->cmd_pid)) {\n+\t\tprintf(\"invalid port id %u\\n\", res->cmd_pid);\n+\t\treturn;\n+\t}\n+\tif (!strcmp(res->cmd_keyword, \"gso\")) {\n+\t\tif (gso_ports[res->cmd_pid].enable) {\n+\t\t\tprintf(\"Max GSO'd packet size: %uB\\n\"\n+\t\t\t\t\t\"Supported GSO types: TCP/IPv4, \"\n+\t\t\t\t\t\"VxLAN with inner TCP/IPv4 packet, \"\n+\t\t\t\t\t\"GRE with inner TCP/IPv4 packet\\n\",\n+\t\t\t\t\tgso_max_segment_size);\n+\t\t} else\n+\t\t\tprintf(\"GSO is not enabled on Port %u\\n\", res->cmd_pid);\n+\t}\n+}\n+\n+cmdline_parse_token_string_t cmd_gso_show_show =\n+TOKEN_STRING_INITIALIZER(struct cmd_gso_show_result,\n+\t\tcmd_show, \"show\");\n+cmdline_parse_token_string_t cmd_gso_show_port =\n+TOKEN_STRING_INITIALIZER(struct cmd_gso_show_result,\n+\t\tcmd_port, \"port\");\n+cmdline_parse_token_string_t cmd_gso_show_keyword =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_gso_show_result,\n+\t\t\t\tcmd_keyword, \"gso\");\n+cmdline_parse_token_num_t cmd_gso_show_pid =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_gso_show_result,\n+\t\t\t\tcmd_pid, UINT8);\n+\n+cmdline_parse_inst_t cmd_gso_show = {\n+\t.f = cmd_gso_show_parsed,\n+\t.data = NULL,\n+\t.help_str = \"show port <port_id> gso\",\n+\t.tokens = {\n+\t\t(void *)&cmd_gso_show_show,\n+\t\t(void *)&cmd_gso_show_port,\n+\t\t(void *)&cmd_gso_show_pid,\n+\t\t(void *)&cmd_gso_show_keyword,\n+\t\tNULL,\n+\t},\n+};\n+\n /* *** ENABLE/DISABLE FLUSH ON RX STREAMS *** */\n struct cmd_set_flush_rx {\n \tcmdline_fixed_string_t set;\n@@ -14255,6 +14431,9 @@ struct cmd_cmdfile_result {\n \t(cmdline_parse_inst_t *)&cmd_tunnel_tso_show,\n \t(cmdline_parse_inst_t *)&cmd_enable_gro,\n \t(cmdline_parse_inst_t *)&cmd_gro_set,\n+\t(cmdline_parse_inst_t *)&cmd_gso_enable,\n+\t(cmdline_parse_inst_t *)&cmd_gso_size,\n+\t(cmdline_parse_inst_t *)&cmd_gso_show,\n \t(cmdline_parse_inst_t *)&cmd_link_flow_control_set,\n \t(cmdline_parse_inst_t *)&cmd_link_flow_control_set_rx,\n \t(cmdline_parse_inst_t *)&cmd_link_flow_control_set_tx,\ndiff --git a/app/test-pmd/config.c b/app/test-pmd/config.c\nindex 3ae3e1c..88d09d0 100644\n--- a/app/test-pmd/config.c\n+++ b/app/test-pmd/config.c\n@@ -2454,6 +2454,30 @@ struct igb_ring_desc_16_bytes {\n \t}\n }\n \n+void\n+setup_gso(const char *mode, uint8_t port_id)\n+{\n+\tif (!rte_eth_dev_is_valid_port(port_id)) {\n+\t\tprintf(\"invalid port id %u\\n\", port_id);\n+\t\treturn;\n+\t}\n+\tif (strcmp(mode, \"on\") == 0) {\n+\t\tif (test_done == 0) {\n+\t\t\tprintf(\"before enabling GSO,\"\n+\t\t\t\t\t\" please stop forwarding first\\n\");\n+\t\t\treturn;\n+\t\t}\n+\t\tgso_ports[port_id].enable = 1;\n+\t} else if (strcmp(mode, \"off\") == 0) {\n+\t\tif (test_done == 0) {\n+\t\t\tprintf(\"before disabling GSO,\"\n+\t\t\t\t\t\" please stop forwarding first\\n\");\n+\t\t\treturn;\n+\t\t}\n+\t\tgso_ports[port_id].enable = 0;\n+\t}\n+}\n+\n char*\n list_pkt_forwarding_modes(void)\n {\ndiff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c\nindex 90c8119..81a631c 100644\n--- a/app/test-pmd/csumonly.c\n+++ b/app/test-pmd/csumonly.c\n@@ -70,6 +70,8 @@\n #include <rte_string_fns.h>\n #include <rte_flow.h>\n #include <rte_gro.h>\n+#include <rte_gso.h>\n+\n #include \"testpmd.h\"\n \n #define IP_DEFTTL 64 /* from RFC 1340. */\n@@ -91,6 +93,7 @@\n /* structure that caches offload info for the current packet */\n struct testpmd_offload_info {\n \tuint16_t ethertype;\n+\tuint8_t gso_enable;\n \tuint16_t l2_len;\n \tuint16_t l3_len;\n \tuint16_t l4_len;\n@@ -381,6 +384,8 @@ struct simple_gre_hdr {\n \t\t\t\tget_udptcp_checksum(l3_hdr, tcp_hdr,\n \t\t\t\t\tinfo->ethertype);\n \t\t}\n+\t\tif (info->gso_enable)\n+\t\t\tol_flags |= PKT_TX_TCP_SEG;\n \t} else if (info->l4_proto == IPPROTO_SCTP) {\n \t\tsctp_hdr = (struct sctp_hdr *)((char *)l3_hdr + info->l3_len);\n \t\tsctp_hdr->cksum = 0;\n@@ -627,6 +632,9 @@ struct simple_gre_hdr {\n pkt_burst_checksum_forward(struct fwd_stream *fs)\n {\n \tstruct rte_mbuf *pkts_burst[MAX_PKT_BURST];\n+\tstruct rte_mbuf *gso_segments[GSO_MAX_PKT_BURST];\n+\tstruct rte_gso_ctx *gso_ctx;\n+\tstruct rte_mbuf **tx_pkts_burst;\n \tstruct rte_port *txp;\n \tstruct rte_mbuf *m, *p;\n \tstruct ether_hdr *eth_hdr;\n@@ -641,6 +649,8 @@ struct simple_gre_hdr {\n \tuint32_t rx_bad_ip_csum;\n \tuint32_t rx_bad_l4_csum;\n \tstruct testpmd_offload_info info;\n+\tuint16_t nb_segments = 0;\n+\tint ret;\n \n #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES\n \tuint64_t start_tsc;\n@@ -674,6 +684,8 @@ struct simple_gre_hdr {\n \tmemset(&info, 0, sizeof(info));\n \tinfo.tso_segsz = txp->tso_segsz;\n \tinfo.tunnel_tso_segsz = txp->tunnel_tso_segsz;\n+\tif (gso_ports[fs->tx_port].enable)\n+\t\tinfo.gso_enable = 1;\n \n \tfor (i = 0; i < nb_rx; i++) {\n \t\tif (likely(i < nb_rx - 1))\n@@ -851,13 +863,35 @@ struct simple_gre_hdr {\n \t\t}\n \t}\n \n+\tif (gso_ports[fs->tx_port].enable == 0)\n+\t\ttx_pkts_burst = pkts_burst;\n+\telse {\n+\t\tgso_ctx = &(current_fwd_lcore()->gso_ctx);\n+\t\tgso_ctx->gso_size = gso_max_segment_size;\n+\t\tfor (i = 0; i < nb_rx; i++) {\n+\t\t\tret = rte_gso_segment(pkts_burst[i], gso_ctx,\n+\t\t\t\t\t&gso_segments[nb_segments],\n+\t\t\t\t\tRTE_DIM(gso_segments) - nb_segments);\n+\t\t\tif (ret < 0) {\n+\t\t\t\tRTE_LOG(DEBUG, USER1,\n+\t\t\t\t\t\t\"Unable to segment \\\n+\t\t\t\t\t\tpacket %d of %d\", i, nb_rx);\n+\t\t\t\trte_pktmbuf_free(pkts_burst[i]);\n+\t\t\t} else\n+\t\t\t\tnb_segments += ret;\n+\t\t}\n+\n+\t\ttx_pkts_burst = gso_segments;\n+\t\tnb_rx = nb_segments;\n+\t}\n+\n \tnb_prep = rte_eth_tx_prepare(fs->tx_port, fs->tx_queue,\n-\t\t\tpkts_burst, nb_rx);\n+\t\t\ttx_pkts_burst, nb_rx);\n \tif (nb_prep != nb_rx)\n \t\tprintf(\"Preparing packet burst to transmit failed: %s\\n\",\n \t\t\t\trte_strerror(rte_errno));\n \n-\tnb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst,\n+\tnb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, tx_pkts_burst,\n \t\t\tnb_prep);\n \n \t/*\n@@ -868,7 +902,7 @@ struct simple_gre_hdr {\n \t\twhile (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {\n \t\t\trte_delay_us(burst_tx_delay_time);\n \t\t\tnb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,\n-\t\t\t\t\t&pkts_burst[nb_tx], nb_rx - nb_tx);\n+\t\t\t\t\t&tx_pkts_burst[nb_tx], nb_rx - nb_tx);\n \t\t}\n \t}\n \tfs->tx_packets += nb_tx;\n@@ -881,9 +915,10 @@ struct simple_gre_hdr {\n \tif (unlikely(nb_tx < nb_rx)) {\n \t\tfs->fwd_dropped += (nb_rx - nb_tx);\n \t\tdo {\n-\t\t\trte_pktmbuf_free(pkts_burst[nb_tx]);\n+\t\t\trte_pktmbuf_free(tx_pkts_burst[nb_tx]);\n \t\t} while (++nb_tx < nb_rx);\n \t}\n+\n #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES\n \tend_tsc = rte_rdtsc();\n \tcore_cycles = (end_tsc - start_tsc);\ndiff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c\nindex e097ee0..b9ee77c 100644\n--- a/app/test-pmd/testpmd.c\n+++ b/app/test-pmd/testpmd.c\n@@ -400,6 +400,9 @@ static int eth_event_callback(uint8_t port_id,\n */\n static int all_ports_started(void);\n \n+struct gso_status gso_ports[RTE_MAX_ETHPORTS];\n+uint16_t gso_max_segment_size = ETHER_MAX_LEN - ETHER_CRC_LEN;\n+\n /*\n * Helper function to check if socket is already discovered.\n * If yes, return positive value. If not, return zero.\n@@ -570,6 +573,7 @@ static int eth_event_callback(uint8_t port_id,\n \tunsigned int nb_mbuf_per_pool;\n \tlcoreid_t lc_id;\n \tuint8_t port_per_socket[RTE_MAX_NUMA_NODES];\n+\tuint32_t gso_types = 0;\n \n \tmemset(port_per_socket,0,RTE_MAX_NUMA_NODES);\n \n@@ -654,6 +658,8 @@ static int eth_event_callback(uint8_t port_id,\n \n \tinit_port_config();\n \n+\tgso_types = DEV_TX_OFFLOAD_TCP_TSO | DEV_TX_OFFLOAD_VXLAN_TNL_TSO |\n+\t\tDEV_TX_OFFLOAD_GRE_TNL_TSO;\n \t/*\n \t * Records which Mbuf pool to use by each logical core, if needed.\n \t */\n@@ -664,6 +670,13 @@ static int eth_event_callback(uint8_t port_id,\n \t\tif (mbp == NULL)\n \t\t\tmbp = mbuf_pool_find(0);\n \t\tfwd_lcores[lc_id]->mbp = mbp;\n+\t\t/* initialize GSO context */\n+\t\tfwd_lcores[lc_id]->gso_ctx.direct_pool = mbp;\n+\t\tfwd_lcores[lc_id]->gso_ctx.indirect_pool = mbp;\n+\t\tfwd_lcores[lc_id]->gso_ctx.gso_types = gso_types;\n+\t\tfwd_lcores[lc_id]->gso_ctx.gso_size = ETHER_MAX_LEN -\n+\t\t\tETHER_CRC_LEN;\n+\t\tfwd_lcores[lc_id]->gso_ctx.flag = 0;\n \t}\n \n \t/* Configuration of packet forwarding streams. */\ndiff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h\nindex 1d1ee75..ff842a1 100644\n--- a/app/test-pmd/testpmd.h\n+++ b/app/test-pmd/testpmd.h\n@@ -36,6 +36,7 @@\n \n #include <rte_pci.h>\n #include <rte_gro.h>\n+#include <rte_gso.h>\n \n #define RTE_PORT_ALL (~(portid_t)0x0)\n \n@@ -205,6 +206,7 @@ struct rte_port {\n * CPU id. configuration table.\n */\n struct fwd_lcore {\n+\tstruct rte_gso_ctx gso_ctx; /**< GSO context */\n \tstruct rte_mempool *mbp; /**< The mbuf pool to use by this core */\n \tstreamid_t stream_idx; /**< index of 1st stream in \"fwd_streams\" */\n \tstreamid_t stream_nb; /**< number of streams in \"fwd_streams\" */\n@@ -442,6 +444,13 @@ struct gro_status {\n };\n extern struct gro_status gro_ports[RTE_MAX_ETHPORTS];\n \n+#define GSO_MAX_PKT_BURST 2048\n+struct gso_status {\n+\tuint8_t enable;\n+};\n+extern struct gso_status gso_ports[RTE_MAX_ETHPORTS];\n+extern uint16_t gso_max_segment_size;\n+\n static inline unsigned int\n lcore_num(void)\n {\n@@ -642,6 +651,7 @@ void port_rss_hash_key_update(portid_t port_id, char rss_type[],\n int rx_queue_id_is_invalid(queueid_t rxq_id);\n int tx_queue_id_is_invalid(queueid_t txq_id);\n void setup_gro(const char *mode, uint8_t port_id);\n+void setup_gso(const char *mode, uint8_t port_id);\n \n /* Functions to manage the set of filtered Multicast MAC addresses */\n void mcast_addr_add(uint8_t port_id, struct ether_addr *mc_addr);\ndiff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst\nindex 2ed62f5..f9b5bda 100644\n--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst\n+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst\n@@ -932,6 +932,52 @@ number of packets a GRO table can store.\n If current packet number is greater than or equal to the max value, GRO\n will stop processing incoming packets.\n \n+set port - gso\n+~~~~~~~~~~~~~~\n+\n+Toggle per-port GSO support in ``csum`` forwarding engine::\n+\n+ testpmd> set port <port_id> gso on|off\n+\n+If enabled, the csum forwarding engine will perform GSO on supported IPv4\n+packets, transmitted on the given port.\n+\n+If disabled, packets transmitted on the given port will not undergo GSO.\n+By default, GSO is disabled for all ports.\n+\n+.. note::\n+\n+ When GSO is enabled on a port, supported IPv4 packets transmitted on that\n+ port undergo GSO. Afterwards, the segmented packets are represented by\n+ multi-segment mbufs; however, the csum forwarding engine doesn't calculation\n+ of checksums for GSO'd segments in SW. As a result, if users want correct\n+ checksums in GSO segments, they should enable HW checksum calculation for\n+ GSO-enabled ports.\n+\n+ For example, HW checksum calculation for VxLAN GSO'd packets may be enabled\n+ by setting the following options in the csum forwarding engine:\n+\n+ testpmd> csum set outer_ip hw <port_id>\n+\n+ testpmd> csum set ip hw <port_id>\n+\n+ testpmd> csum set tcp hw <port_id>\n+\n+set gso segsz\n+~~~~~~~~~~~~~\n+\n+Set the maximum GSO segment size (measured in bytes), which includes the\n+packet header and the packet payload for GSO-enabled ports (global)::\n+\n+ testpmd> set gso segsz <length>\n+\n+show port - gso\n+~~~~~~~~~~~~~~~\n+\n+Display the status of Generic Segmentation Offload for a given port::\n+\n+ testpmd> show port <port_id> gso\n+\n mac_addr add\n ~~~~~~~~~~~~\n \n", "prefixes": [ "dpdk-dev", "v7", "5/6" ] }{ "id": 29676, "url": "