@@ -885,6 +885,7 @@ Marcin Wojtas <mw@semihalf.com>
Marcin Zapolski <marcinx.a.zapolski@intel.com>
Marco Varlese <mvarlese@suse.de>
Marc Sune <marcdevel@gmail.com> <marc.sune@bisdn.de>
+Marek Pazdan <mpazdan@arista.com>
Maria Lingemark <maria.lingemark@ericsson.com>
Mario Carrillo <mario.alfredo.c.arevalo@intel.com>
Mário Kuka <kuka@cesnet.cz>
@@ -65,6 +65,7 @@
#include "cmdline_cman.h"
#include "cmdline_mtr.h"
#include "cmdline_tm.h"
+#include "cmdline_settings.h"
#include "bpf_cmd.h"
static struct cmdline *testpmd_cl;
@@ -255,6 +256,9 @@ static void cmd_help_long_parsed(void *parsed_result,
"show port (port_id) flow_ctrl"
" Show flow control info of a port.\n\n"
+ "show port (port_id) link settings"
+ " Show link settings of a port.\n\n"
+
"dump_physmem\n"
" Dumps all physical memory segment layouts\n\n"
@@ -661,6 +665,9 @@ static void cmd_help_long_parsed(void *parsed_result,
"(max_thresh) (prob_inv)]\n"
" Set congestion management configuration\n\n"
+ "set port (port_id) link settings advertising (bitmap_str)"
+ " Set link advertising settings of a port.\n\n"
+
, list_pkt_forwarding_modes()
);
}
@@ -13219,6 +13226,8 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
(cmdline_parse_inst_t *)&cmd_link_flow_control_set_macfwd,
(cmdline_parse_inst_t *)&cmd_link_flow_control_set_autoneg,
(cmdline_parse_inst_t *)&cmd_link_flow_control_show,
+ (cmdline_parse_inst_t *)&cmd_link_settings_show,
+ (cmdline_parse_inst_t *)&cmd_link_settings_set_advertising,
(cmdline_parse_inst_t *)&cmd_priority_flow_control_set,
(cmdline_parse_inst_t *)&cmd_queue_priority_flow_control_set,
(cmdline_parse_inst_t *)&cmd_config_dcb,
new file mode 100644
@@ -0,0 +1,516 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2024 Arista Networks, Inc. All rights reserved.
+ * Arista Networks, Inc. Confidential and Proprietary
+ */
+
+#include <stdio.h>
+#include <rte_ethdev.h>
+
+#include <cmdline_parse_string.h>
+#include <cmdline_parse_num.h>
+
+#include "testpmd.h"
+
+/* *** GET CURRENT ETHERNET LINK SETTINGS *** */
+struct cmd_link_settings_show {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t link;
+ cmdline_fixed_string_t settings;
+};
+
+cmdline_parse_token_string_t cmd_ls_show_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_settings_show,
+ show, "show");
+cmdline_parse_token_string_t cmd_ls_show_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_settings_show,
+ port, "port");
+cmdline_parse_token_num_t cmd_ls_show_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_link_settings_show,
+ port_id, RTE_UINT16);
+cmdline_parse_token_string_t cmd_ls_show_link =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_settings_show,
+ link, "link");
+cmdline_parse_token_string_t cmd_ls_show_settings =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_settings_show,
+ settings, "settings");
+
+/* Print link capability flags (supported, advertised or lp_advertised).
+ * Assumes that the corresponding SUPPORTED and ADVERTISED flags are equal.
+ */
+static void dump_link_caps(const char *prefix, const char *an_prefix,
+ const uint32_t *mask, int link_mode_only)
+{
+ static const struct {
+ int same_line; /* print on same line as previous */
+ unsigned int bit_index;
+ const char *name;
+ } mode_defs[] = {
+ { 0, RTE_LINK_MODE_10baseT_Half_BIT,
+ "10baseT/Half" },
+ { 1, RTE_LINK_MODE_10baseT_Full_BIT,
+ "10baseT/Full" },
+ { 0, RTE_LINK_MODE_100baseT_Half_BIT,
+ "100baseT/Half" },
+ { 1, RTE_LINK_MODE_100baseT_Full_BIT,
+ "100baseT/Full" },
+ { 0, RTE_LINK_MODE_100baseT1_Full_BIT,
+ "100baseT1/Full" },
+ { 0, RTE_LINK_MODE_1000baseT_Half_BIT,
+ "1000baseT/Half" },
+ { 1, RTE_LINK_MODE_1000baseT_Full_BIT,
+ "1000baseT/Full" },
+ { 0, RTE_LINK_MODE_1000baseT1_Full_BIT,
+ "1000baseT1/Full" },
+ { 0, RTE_LINK_MODE_1000baseKX_Full_BIT,
+ "1000baseKX/Full" },
+ { 0, RTE_LINK_MODE_2500baseX_Full_BIT,
+ "2500baseX/Full" },
+ { 0, RTE_LINK_MODE_10000baseT_Full_BIT,
+ "10000baseT/Full" },
+ { 0, RTE_LINK_MODE_10000baseKX4_Full_BIT,
+ "10000baseKX4/Full" },
+ { 0, RTE_LINK_MODE_10000baseKR_Full_BIT,
+ "10000baseKR/Full" },
+ { 0, RTE_LINK_MODE_10000baseR_FEC_BIT,
+ "10000baseR_FEC" },
+ { 0, RTE_LINK_MODE_20000baseMLD2_Full_BIT,
+ "20000baseMLD2/Full" },
+ { 0, RTE_LINK_MODE_20000baseKR2_Full_BIT,
+ "20000baseKR2/Full" },
+ { 0, RTE_LINK_MODE_40000baseKR4_Full_BIT,
+ "40000baseKR4/Full" },
+ { 0, RTE_LINK_MODE_40000baseCR4_Full_BIT,
+ "40000baseCR4/Full" },
+ { 0, RTE_LINK_MODE_40000baseSR4_Full_BIT,
+ "40000baseSR4/Full" },
+ { 0, RTE_LINK_MODE_40000baseLR4_Full_BIT,
+ "40000baseLR4/Full" },
+ { 0, RTE_LINK_MODE_56000baseKR4_Full_BIT,
+ "56000baseKR4/Full" },
+ { 0, RTE_LINK_MODE_56000baseCR4_Full_BIT,
+ "56000baseCR4/Full" },
+ { 0, RTE_LINK_MODE_56000baseSR4_Full_BIT,
+ "56000baseSR4/Full" },
+ { 0, RTE_LINK_MODE_56000baseLR4_Full_BIT,
+ "56000baseLR4/Full" },
+ { 0, RTE_LINK_MODE_25000baseCR_Full_BIT,
+ "25000baseCR/Full" },
+ { 0, RTE_LINK_MODE_25000baseKR_Full_BIT,
+ "25000baseKR/Full" },
+ { 0, RTE_LINK_MODE_25000baseSR_Full_BIT,
+ "25000baseSR/Full" },
+ { 0, RTE_LINK_MODE_50000baseCR2_Full_BIT,
+ "50000baseCR2/Full" },
+ { 0, RTE_LINK_MODE_50000baseKR2_Full_BIT,
+ "50000baseKR2/Full" },
+ { 0, RTE_LINK_MODE_100000baseKR4_Full_BIT,
+ "100000baseKR4/Full" },
+ { 0, RTE_LINK_MODE_100000baseSR4_Full_BIT,
+ "100000baseSR4/Full" },
+ { 0, RTE_LINK_MODE_100000baseCR4_Full_BIT,
+ "100000baseCR4/Full" },
+ { 0, RTE_LINK_MODE_100000baseLR4_ER4_Full_BIT,
+ "100000baseLR4_ER4/Full" },
+ { 0, RTE_LINK_MODE_50000baseSR2_Full_BIT,
+ "50000baseSR2/Full" },
+ { 0, RTE_LINK_MODE_1000baseX_Full_BIT,
+ "1000baseX/Full" },
+ { 0, RTE_LINK_MODE_10000baseCR_Full_BIT,
+ "10000baseCR/Full" },
+ { 0, RTE_LINK_MODE_10000baseSR_Full_BIT,
+ "10000baseSR/Full" },
+ { 0, RTE_LINK_MODE_10000baseLR_Full_BIT,
+ "10000baseLR/Full" },
+ { 0, RTE_LINK_MODE_10000baseLRM_Full_BIT,
+ "10000baseLRM/Full" },
+ { 0, RTE_LINK_MODE_10000baseER_Full_BIT,
+ "10000baseER/Full" },
+ { 0, RTE_LINK_MODE_2500baseT_Full_BIT,
+ "2500baseT/Full" },
+ { 0, RTE_LINK_MODE_5000baseT_Full_BIT,
+ "5000baseT/Full" },
+ { 0, RTE_LINK_MODE_50000baseKR_Full_BIT,
+ "50000baseKR/Full" },
+ { 0, RTE_LINK_MODE_50000baseSR_Full_BIT,
+ "50000baseSR/Full" },
+ { 0, RTE_LINK_MODE_50000baseCR_Full_BIT,
+ "50000baseCR/Full" },
+ { 0, RTE_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
+ "50000baseLR_ER_FR/Full" },
+ { 0, RTE_LINK_MODE_50000baseDR_Full_BIT,
+ "50000baseDR/Full" },
+ { 0, RTE_LINK_MODE_100000baseKR2_Full_BIT,
+ "100000baseKR2/Full" },
+ { 0, RTE_LINK_MODE_100000baseSR2_Full_BIT,
+ "100000baseSR2/Full" },
+ { 0, RTE_LINK_MODE_100000baseCR2_Full_BIT,
+ "100000baseCR2/Full" },
+ { 0, RTE_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
+ "100000baseLR2_ER2_FR2/Full" },
+ { 0, RTE_LINK_MODE_100000baseDR2_Full_BIT,
+ "100000baseDR2/Full" },
+ { 0, RTE_LINK_MODE_200000baseKR4_Full_BIT,
+ "200000baseKR4/Full" },
+ { 0, RTE_LINK_MODE_200000baseSR4_Full_BIT,
+ "200000baseSR4/Full" },
+ { 0, RTE_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT,
+ "200000baseLR4_ER4_FR4/Full" },
+ { 0, RTE_LINK_MODE_200000baseDR4_Full_BIT,
+ "200000baseDR4/Full" },
+ { 0, RTE_LINK_MODE_200000baseCR4_Full_BIT,
+ "200000baseCR4/Full" },
+ };
+ int indent;
+ int did1;
+ int new_line_pend;
+ int fecreported = 0;
+
+ /* Indent just like the separate functions used to */
+ indent = strlen(prefix) + 14;
+ if (indent < 24)
+ indent = 24;
+
+ fprintf(stdout, " %s link modes:%*s", prefix,
+ indent - (int)strlen(prefix) - 12, "");
+ did1 = 0;
+ new_line_pend = 0;
+ for (uint32_t i = 0; i < RTE_DIM(mode_defs); i++) {
+ if (did1 && !mode_defs[i].same_line)
+ new_line_pend = 1;
+ if (get_bit(mask, mode_defs[i].bit_index)) {
+ if (new_line_pend) {
+ fprintf(stdout, "\n");
+ fprintf(stdout, " %*s", indent, "");
+ new_line_pend = 0;
+ }
+ did1++;
+ fprintf(stdout, "%s ", mode_defs[i].name);
+ }
+ }
+ if (did1 == 0)
+ fprintf(stdout, "Not reported");
+ fprintf(stdout, "\n");
+
+ if (!link_mode_only) {
+ fprintf(stdout, " %s pause frame use: ", prefix);
+ if (get_bit(mask, RTE_LINK_MODE_Pause_BIT)) {
+ fprintf(stdout, "Symmetric");
+ if (get_bit(mask, RTE_LINK_MODE_Asym_Pause_BIT))
+ fprintf(stdout, " Receive-only");
+ fprintf(stdout, "\n");
+ } else {
+ if (get_bit(mask, RTE_LINK_MODE_Asym_Pause_BIT))
+ fprintf(stdout, "Transmit-only\n");
+ else
+ fprintf(stdout, "No\n");
+ }
+
+ fprintf(stdout, " %s auto-negotiation: ", an_prefix);
+ if (get_bit(mask, RTE_LINK_MODE_Autoneg_BIT))
+ fprintf(stdout, "Yes\n");
+ else
+ fprintf(stdout, "No\n");
+
+ fprintf(stdout, " %s FEC modes:", prefix);
+ if (get_bit(mask, RTE_LINK_MODE_FEC_NONE_BIT)) {
+ fprintf(stdout, " None");
+ fecreported = 1;
+ }
+ if (get_bit(mask, RTE_LINK_MODE_FEC_BASER_BIT)) {
+ fprintf(stdout, " BaseR");
+ fecreported = 1;
+ }
+ if (get_bit(mask, RTE_LINK_MODE_FEC_RS_BIT)) {
+ fprintf(stdout, " RS");
+ fecreported = 1;
+ }
+ if (!fecreported)
+ fprintf(stdout, " Not reported");
+ fprintf(stdout, "\n");
+ }
+}
+
+static void
+dump_supported(const struct rte_link_settings *link_settings)
+{
+ fprintf(stdout, " Supported ports: [ ");
+ if (get_bit(link_settings->link_modes.supported,
+ RTE_LINK_MODE_TP_BIT))
+ fprintf(stdout, "TP ");
+ if (get_bit(link_settings->link_modes.supported,
+ RTE_LINK_MODE_AUI_BIT))
+ fprintf(stdout, "AUI ");
+ if (get_bit(link_settings->link_modes.supported,
+ RTE_LINK_MODE_BNC_BIT))
+ fprintf(stdout, "BNC ");
+ if (get_bit(link_settings->link_modes.supported,
+ RTE_LINK_MODE_MII_BIT))
+ fprintf(stdout, "MII ");
+ if (get_bit(link_settings->link_modes.supported,
+ RTE_LINK_MODE_FIBRE_BIT))
+ fprintf(stdout, "FIBRE ");
+ if (get_bit(link_settings->link_modes.supported,
+ RTE_LINK_MODE_Backplane_BIT))
+ fprintf(stdout, "Backplane ");
+ fprintf(stdout, "]\n");
+
+ dump_link_caps("Supported", "Supports",
+ link_settings->link_modes.supported, 0);
+}
+
+
+
+static void
+cmd_link_settings_show_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_link_settings_show *res = parsed_result;
+ static const char *info_border = "*********************";
+ struct rte_link_settings link_settings;
+ int ret;
+
+ memset(&link_settings, 0x00, sizeof(link_settings));
+ ret = rte_eth_dev_get_link_settings(res->port_id, &link_settings);
+ if (ret != 0) {
+ fprintf(stderr,
+ "Failed to get current link settings: err = %d\n",
+ ret);
+ return;
+ }
+
+ printf("\n%s Link settings for port %-2d %s\n",
+ info_border, res->port_id, info_border);
+
+ dump_supported(&link_settings);
+ dump_link_caps("Advertised", "Advertised",
+ link_settings.link_modes.advertising, 0);
+
+ bool show_lp_advertising = false;
+ for (uint32_t idx = 0; idx < RTE_DIM(link_settings.link_modes.lp_advertising); idx++) {
+ if (link_settings.link_modes.lp_advertising[idx] != 0) {
+ show_lp_advertising = true;
+ break;
+ }
+ }
+
+ if (show_lp_advertising) {
+ dump_link_caps("Link partner advertised",
+ "Link partner advertised",
+ link_settings.link_modes.lp_advertising, 0);
+ }
+
+ fprintf(stdout, " Speed: ");
+ if (link_settings.base.link.link_speed == 0
+ || link_settings.base.link.link_speed == (uint16_t)(-1)
+ || link_settings.base.link.link_speed == (uint32_t)(-1))
+ fprintf(stdout, "Unknown!\n");
+ else
+ fprintf(stdout, "%uMb/s\n", link_settings.base.link.link_speed);
+
+ fprintf(stdout, " Duplex: ");
+ switch (link_settings.base.link.link_duplex) {
+ case RTE_ETH_LINK_HALF_DUPLEX:
+ fprintf(stdout, "Half\n");
+ break;
+ case RTE_ETH_LINK_FULL_DUPLEX:
+ fprintf(stdout, "Full\n");
+ break;
+ default:
+ fprintf(stdout, "Unknown! (%i)\n", link_settings.base.link.link_duplex);
+ break;
+ };
+
+ fprintf(stdout, " Port: ");
+ switch (link_settings.base.port) {
+ case RTE_PORT_TP:
+ fprintf(stdout, "Twisted Pair\n");
+ break;
+ case RTE_PORT_AUI:
+ fprintf(stdout, "AUI\n");
+ break;
+ case RTE_PORT_BNC:
+ fprintf(stdout, "BNC\n");
+ break;
+ case RTE_PORT_MII:
+ fprintf(stdout, "MII\n");
+ break;
+ case RTE_PORT_FIBRE:
+ fprintf(stdout, "FIBRE\n");
+ break;
+ case RTE_PORT_DA:
+ fprintf(stdout, "Direct Attach Copper\n");
+ break;
+ case RTE_PORT_NONE:
+ fprintf(stdout, "None\n");
+ break;
+ case RTE_PORT_OTHER:
+ fprintf(stdout, "Other\n");
+ break;
+ default:
+ fprintf(stdout, "Unknown! (%i)\n", link_settings.base.port);
+ break;
+ };
+
+ fprintf(stdout, " PHYAD: %d\n", link_settings.base.phy_address);
+
+ fprintf(stdout, " Auto-negotiation: %s\n",
+ (link_settings.base.link.link_autoneg == RTE_AUTONEG_DISABLE) ?
+ "off" : "on");
+
+ if (link_settings.base.port == RTE_PORT_TP) {
+ fprintf(stdout, " MDI-X: ");
+ if (link_settings.base.eth_tp_mdix_ctrl == RTE_TP_MDI) {
+ fprintf(stdout, "off (forced)\n");
+ } else if (link_settings.base.eth_tp_mdix_ctrl
+ == RTE_TP_MDI_X) {
+ fprintf(stdout, "on (forced)\n");
+ } else {
+ switch (link_settings.base.eth_tp_mdix) {
+ case RTE_TP_MDI:
+ fprintf(stdout, "off");
+ break;
+ case RTE_TP_MDI_X:
+ fprintf(stdout, "on");
+ break;
+ default:
+ fprintf(stdout, "Unknown");
+ break;
+ }
+ if (link_settings.base.eth_tp_mdix_ctrl
+ == RTE_TP_MDI_AUTO)
+ fprintf(stdout, " (auto)");
+ fprintf(stdout, "\n");
+ }
+ }
+}
+
+cmdline_parse_inst_t cmd_link_settings_show = {
+ .f = cmd_link_settings_show_parsed,
+ .data = NULL,
+ .help_str = "show port <port_id> link settings",
+ .tokens = {
+ (void *)&cmd_ls_show_show,
+ (void *)&cmd_ls_show_port,
+ (void *)&cmd_ls_show_portid,
+ (void *)&cmd_ls_show_link,
+ (void *)&cmd_ls_show_settings,
+ NULL,
+ },
+};
+
+static int parse_hex_u32_bitmap(const char *s,
+ unsigned int nbits, uint32_t *result)
+{
+ const unsigned int nwords = RTE_DIV_ROUND_UP(nbits, 32);
+ size_t slen = strlen(s);
+ size_t i;
+
+ /* ignore optional '0x' prefix */
+ if ((slen > 2) && (strncasecmp(s, "0x", 2) == 0)) {
+ slen -= 2;
+ s += 2;
+ }
+
+ if (slen > 8 * nwords) /* up to 2 digits per byte */
+ return -1;
+
+ memset(result, 0, 4 * nwords);
+ for (i = 0; i < slen; ++i) {
+ const unsigned int shift = (slen - 1 - i) * 4;
+ uint32_t *dest = &result[shift / 32];
+ uint32_t nibble;
+
+ if ('a' <= s[i] && s[i] <= 'f')
+ nibble = 0xa + (s[i] - 'a');
+ else if ('A' <= s[i] && s[i] <= 'F')
+ nibble = 0xa + (s[i] - 'A');
+ else if ('0' <= s[i] && s[i] <= '9')
+ nibble = (s[i] - '0');
+ else
+ return -1;
+
+ *dest |= (nibble << (shift % 32));
+ }
+
+ return 0;
+}
+
+/* *** SET ETHERNET LINK SETTINGS *** */
+struct cmd_link_settings_set {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t link;
+ cmdline_fixed_string_t settings;
+ cmdline_fixed_string_t advertising;
+ cmdline_multi_string_t bitmap_str;
+};
+
+cmdline_parse_token_string_t cmd_ls_set_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_settings_set,
+ set, "set");
+cmdline_parse_token_string_t cmd_ls_set_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_settings_set,
+ port, "port");
+cmdline_parse_token_num_t cmd_ls_set_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_link_settings_set,
+ port_id, RTE_UINT16);
+cmdline_parse_token_string_t cmd_ls_set_link =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_settings_set,
+ link, "link");
+cmdline_parse_token_string_t cmd_ls_set_settings =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_settings_set,
+ settings, "settings");
+cmdline_parse_token_string_t cmd_ls_set_advertising =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_settings_set,
+ advertising, "advertising");
+cmdline_parse_token_string_t cmd_ls_set_bitmap_str =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_settings_set,
+ bitmap_str, TOKEN_STRING_MULTI);
+
+static void
+cmd_link_settings_set_advertising_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_link_settings_set *res = parsed_result;
+ struct rte_link_settings link_settings;
+ int ret;
+
+ if (parse_hex_u32_bitmap(res->bitmap_str,
+ __RTE_LINK_MODE_MASK_NBITS,
+ link_settings.link_modes.advertising)) {
+ fprintf(stderr, "cannot parse bitmap_str\n");
+ return;
+
+ }
+
+ link_settings.base.link.link_autoneg = RTE_AUTONEG_ENABLE;
+
+ ret = rte_eth_dev_set_link_settings(res->port_id, &link_settings);
+ if (ret != 0) {
+ fprintf(stderr,
+ "Failed to set link settings: err = %d\n",
+ ret);
+ }
+}
+
+cmdline_parse_inst_t cmd_link_settings_set_advertising = {
+ .f = cmd_link_settings_set_advertising_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> link settings advertising <bitmap_str>"
+ " Bitmap_str - bitmap respresentation of advertising speeds",
+ .tokens = {
+ (void *)&cmd_ls_set_set,
+ (void *)&cmd_ls_set_port,
+ (void *)&cmd_ls_set_portid,
+ (void *)&cmd_ls_set_link,
+ (void *)&cmd_ls_set_settings,
+ (void *)&cmd_ls_set_advertising,
+ (void *)&cmd_ls_set_bitmap_str,
+ NULL,
+ },
+};
new file mode 100644
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2024 Arista Networks, Inc. All rights reserved.
+ * Arista Networks, Inc. Confidential and Proprietary
+ */
+
+#ifndef _CMDLINE_SETTINGS_H
+#define _CMDLINE_SETTINGS_H
+
+/* Link settings CLI */
+extern cmdline_parse_inst_t cmd_link_settings_show;
+extern cmdline_parse_inst_t cmd_link_settings_set_advertising;
+
+#endif /* _CMDLINE_SETTINGS_H */
+
@@ -11,6 +11,7 @@ sources = files(
'cmdline_flow.c',
'cmdline_mtr.c',
'cmdline_tm.c',
+ 'cmdline_settings.c',
'cmd_flex_item.c',
'config.c',
'csumonly.c',
@@ -1187,6 +1187,7 @@ void eth_set_allmulticast_mode(uint16_t port, int enable);
int eth_link_get_nowait_print_err(uint16_t port_id, struct rte_eth_link *link);
int eth_macaddr_get_print_err(uint16_t port_id,
struct rte_ether_addr *mac_addr);
+int get_bit(const uint32_t *ptr, uint32_t pos);
/* Functions to display the set of MAC addresses added to a port*/
void show_macs(portid_t port_id);
@@ -17,6 +17,8 @@
#define MAX_STRING_LEN 8192
+#define UINT_32_BIT_WIDTH (CHAR_BIT * sizeof(uint32_t))
+
#define MKDUMPSTR(buf, buf_size, cur_len, ...) \
do { \
if (cur_len >= buf_size) \
@@ -525,3 +527,11 @@ eth_macaddr_get_print_err(uint16_t port_id, struct rte_ether_addr *mac_addr)
return ret;
}
+
+int
+get_bit(const uint32_t *ptr, uint32_t pos)
+{
+ uint32_t byte_idx = pos / UINT_32_BIT_WIDTH;
+ uint32_t bit_idx = pos % UINT_32_BIT_WIDTH;
+ return (ptr[byte_idx] >> bit_idx) & 0x1;
+}
@@ -91,6 +91,8 @@
uint64_t igc_tx_timestamp_dynflag;
int igc_tx_timestamp_dynfield_offset = -1;
+#define IGC_32_BIT_WIDTH (CHAR_BIT * sizeof(uint32_t))
+
static const struct rte_eth_desc_lim rx_desc_lim = {
.nb_max = IGC_MAX_RXD,
.nb_min = IGC_MIN_RXD,
@@ -273,6 +275,10 @@ static int eth_igc_timesync_read_time(struct rte_eth_dev *dev,
static int eth_igc_timesync_write_time(struct rte_eth_dev *dev,
const struct timespec *timestamp);
static int eth_igc_read_clock(struct rte_eth_dev *dev, uint64_t *clock);
+static int eth_igc_get_link_settings(struct rte_eth_dev *dev,
+ struct rte_link_settings *link_settings);
+static int eth_igc_set_link_settings(struct rte_eth_dev *dev,
+ const struct rte_link_settings *link_settings);
static const struct eth_dev_ops eth_igc_ops = {
.dev_configure = eth_igc_configure,
@@ -334,6 +340,8 @@ static const struct eth_dev_ops eth_igc_ops = {
.timesync_read_time = eth_igc_timesync_read_time,
.timesync_write_time = eth_igc_timesync_write_time,
.read_clock = eth_igc_read_clock,
+ .get_link_settings = eth_igc_get_link_settings,
+ .set_link_settings = eth_igc_set_link_settings,
};
/*
@@ -532,8 +540,8 @@ eth_igc_link_update(struct rte_eth_dev *dev, int wait_to_complete)
}
}
} else {
- link.link_speed = 0;
- link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
+ link.link_speed = RTE_ETH_SPEED_NUM_UNKNOWN;
+ link.link_duplex = RTE_ETH_LINK_UNKNOWN_DUPLEX;
link.link_status = RTE_ETH_LINK_DOWN;
link.link_autoneg = RTE_ETH_LINK_FIXED;
}
@@ -2876,6 +2884,223 @@ eth_igc_read_clock(__rte_unused struct rte_eth_dev *dev, uint64_t *clock)
return 0;
}
+static inline void
+igc_set_bit(uint32_t *ptr, uint32_t pos)
+{
+ uint32_t byte_idx = pos / IGC_32_BIT_WIDTH;
+ uint32_t bit_idx = pos % IGC_32_BIT_WIDTH;
+ uint32_t tmp;
+
+ tmp = ptr[byte_idx];
+ tmp &= ~(RTE_BIT32(bit_idx));
+ tmp |= RTE_BIT32(bit_idx);
+ ptr[byte_idx] = tmp;
+}
+
+static inline uint8_t
+igc_get_bit(const uint32_t *ptr, uint32_t pos)
+{
+ uint32_t byte_idx = pos / IGC_32_BIT_WIDTH;
+ uint32_t bit_idx = pos % IGC_32_BIT_WIDTH;
+
+ return (ptr[byte_idx] >> bit_idx) & 0x1;
+}
+
+static int eth_igc_get_link_settings(struct rte_eth_dev *dev,
+ struct rte_link_settings *link_settings)
+{
+ s32 ret_val = IGC_SUCCESS;
+ s32 link_check = 0;
+ struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
+ uint32_t *supported = link_settings->link_modes.supported;
+ uint32_t *advertising = link_settings->link_modes.advertising;
+ uint32_t *lp_advertising = link_settings->link_modes.lp_advertising;
+
+ memset(supported, 0x00, __RTE_LINK_MODE_MASK_NU32 * sizeof(uint32_t));
+ memset(advertising, 0x00, __RTE_LINK_MODE_MASK_NU32 * sizeof(uint32_t));
+ memset(lp_advertising, 0x00, __RTE_LINK_MODE_MASK_NU32 * sizeof(uint32_t));
+
+ igc_set_bit(supported, RTE_LINK_MODE_10baseT_Half_BIT);
+ igc_set_bit(supported, RTE_LINK_MODE_10baseT_Full_BIT);
+ igc_set_bit(supported, RTE_LINK_MODE_100baseT_Half_BIT);
+ igc_set_bit(supported, RTE_LINK_MODE_100baseT_Full_BIT);
+ igc_set_bit(supported, RTE_LINK_MODE_1000baseT_Full_BIT);
+ igc_set_bit(supported, RTE_LINK_MODE_2500baseT_Full_BIT);
+
+ /* twisted pair */
+ link_settings->base.port = RTE_PORT_TP;
+ /* MDIO address of PHY (transceiver) */
+ link_settings->base.phy_address = hw->phy.addr;
+ igc_set_bit(supported, RTE_LINK_MODE_TP_BIT);
+ igc_set_bit(advertising, RTE_LINK_MODE_TP_BIT);
+
+ if (hw->phy.autoneg_advertised & ADVERTISE_10_HALF)
+ igc_set_bit(advertising, RTE_LINK_MODE_10baseT_Half_BIT);
+ if (hw->phy.autoneg_advertised & ADVERTISE_10_FULL)
+ igc_set_bit(advertising, RTE_LINK_MODE_10baseT_Full_BIT);
+ if (hw->phy.autoneg_advertised & ADVERTISE_100_HALF)
+ igc_set_bit(advertising, RTE_LINK_MODE_100baseT_Half_BIT);
+ if (hw->phy.autoneg_advertised & ADVERTISE_100_FULL)
+ igc_set_bit(advertising, RTE_LINK_MODE_100baseT_Full_BIT);
+ if (hw->phy.autoneg_advertised & ADVERTISE_1000_FULL)
+ igc_set_bit(advertising, RTE_LINK_MODE_1000baseT_Full_BIT);
+ if (hw->phy.autoneg_advertised & ADVERTISE_2500_FULL)
+ igc_set_bit(advertising, RTE_LINK_MODE_2500baseT_Full_BIT);
+
+ /* set autoneg settings */
+ if (hw->mac.autoneg == 1) {
+ igc_set_bit(supported, RTE_LINK_MODE_Autoneg_BIT);
+ igc_set_bit(advertising, RTE_LINK_MODE_Autoneg_BIT);
+ link_settings->base.link.link_autoneg = RTE_AUTONEG_ENABLE;
+ } else {
+ link_settings->base.link.link_autoneg = RTE_AUTONEG_DISABLE;
+ }
+
+ /* Set pause flow control settings */
+ igc_set_bit(supported, RTE_LINK_MODE_Pause_BIT);
+
+ switch (hw->fc.requested_mode) {
+ case igc_fc_full:
+ igc_set_bit(advertising, RTE_LINK_MODE_Pause_BIT);
+ break;
+ case igc_fc_rx_pause:
+ igc_set_bit(advertising, RTE_LINK_MODE_Pause_BIT);
+ igc_set_bit(advertising, RTE_LINK_MODE_Asym_Pause_BIT);
+ break;
+ case igc_fc_tx_pause:
+ igc_set_bit(advertising, RTE_LINK_MODE_Asym_Pause_BIT);
+ break;
+ default:
+ break;
+ }
+
+ hw->mac.get_link_status = 1;
+ /* Read the real link status */
+ switch (hw->phy.media_type) {
+ case igc_media_type_copper:
+ /* Do the work to read phy */
+ igc_check_for_link(hw);
+ link_check = !hw->mac.get_link_status;
+ break;
+ case igc_media_type_fiber:
+ igc_check_for_link(hw);
+ link_check = (IGC_READ_REG(hw, IGC_STATUS) &
+ IGC_STATUS_LU);
+ break;
+ case igc_media_type_internal_serdes:
+ igc_check_for_link(hw);
+ link_check = hw->mac.serdes_has_link;
+ break;
+ default:
+ break;
+ }
+
+ /* Now we check if a transition has happened */
+ if (link_check) {
+ uint16_t duplex, speed;
+ hw->mac.ops.get_link_up_info(hw, &speed, &duplex);
+ link_settings->base.link.link_duplex = (duplex == FULL_DUPLEX) ?
+ RTE_ETH_LINK_FULL_DUPLEX :
+ RTE_ETH_LINK_HALF_DUPLEX;
+ link_settings->base.link.link_speed = speed;
+ link_settings->base.link.link_status = RTE_ETH_LINK_UP;
+ link_settings->base.link.link_autoneg = !(dev->data->dev_conf.link_speeds &
+ RTE_ETH_LINK_SPEED_FIXED);
+ if (speed == SPEED_2500) {
+ uint32_t tipg = IGC_READ_REG(hw, IGC_TIPG);
+ if ((tipg & IGC_TIPG_IPGT_MASK) != 0x0b) {
+ tipg &= ~IGC_TIPG_IPGT_MASK;
+ tipg |= 0x0b;
+ IGC_WRITE_REG(hw, IGC_TIPG, tipg);
+ }
+ }
+ } else {
+ link_settings->base.link.link_speed = 0;
+ link_settings->base.link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
+ link_settings->base.link.link_status = RTE_ETH_LINK_DOWN;
+ link_settings->base.link.link_autoneg = RTE_ETH_LINK_FIXED;
+ }
+
+ /* MDI-X => 2; MDI =>1; Invalid =>0 */
+ if (hw->phy.media_type == igc_media_type_copper)
+ link_settings->base.eth_tp_mdix = hw->phy.is_mdix ? RTE_TP_MDI_X :
+ RTE_TP_MDI;
+ else
+ link_settings->base.eth_tp_mdix = RTE_TP_MDI_INVALID;
+
+ if (hw->phy.mdix == 0) /* AUTO_ALL_MODES */
+ link_settings->base.eth_tp_mdix_ctrl = RTE_TP_MDI_AUTO;
+ else
+ link_settings->base.eth_tp_mdix_ctrl = hw->phy.mdix;
+
+ return ret_val;
+}
+
+static int eth_igc_set_link_settings(struct rte_eth_dev *dev,
+ const struct rte_link_settings *link_settings)
+{
+ struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
+ struct igc_adapter *adapter = IGC_DEV_PRIVATE(dev);
+ const uint32_t *advertising = link_settings->link_modes.advertising;
+ int ret = IGC_SUCCESS;
+
+ if (igc_check_reset_block(hw)) {
+ PMD_DRV_LOG(ERR, "Cannot change link characteristics when reset is active\n");
+ return -EINVAL;
+ }
+
+ /* MDI setting is only allowed when autoneg enabled because
+ * some hardware doesn't allow MDI setting when speed or
+ * duplex is forced.
+ */
+ if (link_settings->base.eth_tp_mdix_ctrl) {
+ if (link_settings->base.eth_tp_mdix_ctrl != RTE_TP_MDI_AUTO &&
+ link_settings->base.link.link_autoneg != RTE_AUTONEG_ENABLE) {
+ PMD_DRV_LOG(ERR, "Forcing MDI/MDI-X state is not supported "
+ "when link speed and/or duplex are forced\n");
+ return -EINVAL;
+ }
+ }
+
+ /* All modes for igc but one fits into first byte of bitmask */
+ uint32_t igc_advertising = link_settings->link_modes.advertising[0];
+ /* Converting to u32 drops RTE_LINK_MODE_2500baseT_Full_BIT.
+ * We have to check this and convert it to ADVERTISE_2500_FULL
+ * (aka RTE_LINK_MODE_2500baseX_Full_BIT) explicitly.
+ */
+ if (igc_get_bit(advertising, RTE_LINK_MODE_2500baseT_Full_BIT))
+ igc_advertising |= ADVERTISE_2500_FULL;
+
+ if (link_settings->base.link.link_autoneg == RTE_AUTONEG_ENABLE) {
+ hw->mac.autoneg = 1;
+ hw->phy.autoneg_advertised = igc_advertising;
+ hw->fc.requested_mode = igc_fc_default;
+ } else {
+ PMD_DRV_LOG(INFO, "Force mode currently not supported\n");
+ }
+
+ /* MDI-X => 2; MDI => 1; Auto => 3 */
+ if (link_settings->base.eth_tp_mdix_ctrl) {
+ /* fix up the value for auto (3 => 0) as zero is mapped
+ * internally to auto
+ */
+ if (link_settings->base.eth_tp_mdix_ctrl == RTE_TP_MDI_AUTO)
+ hw->phy.mdix = 0; /* AUTO_ALL_MODES */
+ else
+ hw->phy.mdix = link_settings->base.eth_tp_mdix_ctrl;
+ }
+
+ /* reset the link */
+ if (!adapter->stopped) {
+ eth_igc_set_link_down(dev);
+ eth_igc_set_link_up(dev);
+ } else {
+ eth_igc_reset(dev);
+ }
+
+ return ret;
+}
+
static int
eth_igc_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
struct rte_pci_device *pci_dev)
@@ -125,6 +125,13 @@
/* SFP+ SFF-8472 Compliance */
#define IXGBE_SFF_SFF_8472_UNSUP 0x00
+#define IXGBE_SPEED_10000 10000
+
+/* Duplex, half or full. */
+#define IXGBE_DUPLEX_HALF 0x00
+#define IXGBE_DUPLEX_FULL 0x01
+#define IXGBE_DUPLEX_UNKNOWN 0xff
+
s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw);
bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr);
enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id);
@@ -94,6 +94,7 @@
#define IXGBE_4_BIT_MASK RTE_LEN2MASK(IXGBE_4_BIT_WIDTH, uint8_t)
#define IXGBE_8_BIT_WIDTH CHAR_BIT
#define IXGBE_8_BIT_MASK UINT8_MAX
+#define IXGBE_32_BIT_WIDTH (CHAR_BIT * sizeof(uint32_t))
#define IXGBEVF_PMD_NAME "rte_ixgbevf_pmd" /* PMD name */
@@ -130,6 +131,8 @@
#define IXGBE_DEVARG_FIBER_SDP3_NOT_TX_DISABLE "fiber_sdp3_no_tx_disable"
+#define IXGBE_ISBACKPLANE(type) ((type) == ixgbe_media_type_backplane)
+
static const char * const ixgbe_valid_arguments[] = {
IXGBE_DEVARG_FIBER_SDP3_NOT_TX_DISABLE,
NULL
@@ -353,6 +356,10 @@ static int ixgbe_dev_udp_tunnel_port_add(struct rte_eth_dev *dev,
struct rte_eth_udp_tunnel *udp_tunnel);
static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,
struct rte_eth_udp_tunnel *udp_tunnel);
+static int ixgbe_get_link_settings(struct rte_eth_dev *dev,
+ struct rte_link_settings *link_settings);
+static int ixgbe_set_link_settings(struct rte_eth_dev *dev,
+ const struct rte_link_settings *link_settings);
static int ixgbe_filter_restore(struct rte_eth_dev *dev);
static void ixgbe_l2_tunnel_conf(struct rte_eth_dev *dev);
static int ixgbe_wait_for_link_up(struct ixgbe_hw *hw);
@@ -564,6 +571,8 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
.tm_ops_get = ixgbe_tm_ops_get,
.tx_done_cleanup = ixgbe_dev_tx_done_cleanup,
.get_monitor_addr = ixgbe_get_monitor_addr,
+ .get_link_settings = ixgbe_get_link_settings,
+ .set_link_settings = ixgbe_set_link_settings,
};
/*
@@ -7791,6 +7800,392 @@ ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,
return ret;
}
+static inline void
+ixgbe_set_bit(uint32_t *ptr, uint32_t pos)
+{
+ uint32_t byte_idx = pos / IXGBE_32_BIT_WIDTH;
+ uint32_t bit_idx = pos % IXGBE_32_BIT_WIDTH;
+ uint32_t tmp;
+
+ tmp = ptr[byte_idx];
+ tmp &= ~(1 << bit_idx);
+ tmp |= 1 << bit_idx;
+ ptr[byte_idx] = tmp;
+}
+
+static inline uint8_t
+ixgbe_get_bit(const uint32_t *ptr, uint32_t pos)
+{
+ uint32_t byte_idx = pos / IXGBE_32_BIT_WIDTH;
+ uint32_t bit_idx = pos % IXGBE_32_BIT_WIDTH;
+
+ return (ptr[byte_idx] >> bit_idx) & 0x1;
+}
+
+
+static inline bool
+ixgbe_is_subset(const uint32_t *bitmap1, const uint32_t *bitmap2,
+ uint32_t nbits)
+{
+ uint32_t full_bytes_cnt = nbits / IXGBE_32_BIT_WIDTH;
+ uint32_t last_byte_bit_idx = nbits % IXGBE_32_BIT_WIDTH;
+
+ for (uint32_t idx = 0; idx < full_bytes_cnt; idx++) {
+ if (bitmap1[idx] & ~bitmap2[idx])
+ return false;
+ }
+
+ uint32_t last_chunk_mask = ((1ULL << last_byte_bit_idx) - 1) |
+ (1ULL << last_byte_bit_idx);
+ if ((bitmap1[full_bytes_cnt] & ~bitmap2[full_bytes_cnt]) & last_chunk_mask)
+ return false;
+
+ return true;
+}
+
+static void ixgbe_set_supported_10gtypes(struct ixgbe_hw *hw,
+ uint32_t *bitmap)
+{
+ if (!IXGBE_ISBACKPLANE(hw->phy.media_type)) {
+ ixgbe_set_bit(bitmap, RTE_LINK_MODE_10000baseT_Full_BIT);
+ return;
+ }
+
+ switch (hw->device_id) {
+ case IXGBE_DEV_ID_82598:
+ case IXGBE_DEV_ID_82599_KX4:
+ case IXGBE_DEV_ID_82599_KX4_MEZZ:
+ case IXGBE_DEV_ID_X550EM_X_KX4:
+ ixgbe_set_bit(bitmap, RTE_LINK_MODE_10000baseKX4_Full_BIT);
+ break;
+ case IXGBE_DEV_ID_82598_BX:
+ case IXGBE_DEV_ID_82599_KR:
+ case IXGBE_DEV_ID_X550EM_X_KR:
+ case IXGBE_DEV_ID_X550EM_X_XFI:
+ ixgbe_set_bit(bitmap, RTE_LINK_MODE_10000baseKR_Full_BIT);
+ break;
+ default:
+ ixgbe_set_bit(bitmap, RTE_LINK_MODE_10000baseKX4_Full_BIT);
+ ixgbe_set_bit(bitmap, RTE_LINK_MODE_10000baseKR_Full_BIT);
+ break;
+ }
+}
+
+static int ixgbe_get_link_settings(struct rte_eth_dev *dev,
+ struct rte_link_settings *link_settings)
+{
+ int ret_val = IXGBE_SUCCESS;
+ int wait = 1;
+ bool link_up;
+ bool autoneg;
+ uint32_t esdp_reg;
+ ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
+ struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct ixgbe_adapter *ad = dev->data->dev_private;
+ uint32_t *supported = link_settings->link_modes.supported;
+ uint32_t *advertising = link_settings->link_modes.advertising;
+ uint32_t *lp_advertising = link_settings->link_modes.lp_advertising;
+
+ memset(supported, 0x00, __RTE_LINK_MODE_MASK_NU32 * sizeof(uint32_t));
+ memset(advertising, 0x00, __RTE_LINK_MODE_MASK_NU32 * sizeof(uint32_t));
+ memset(lp_advertising, 0x00, __RTE_LINK_MODE_MASK_NU32 * sizeof(uint32_t));
+
+ /* Get supported speeds */
+ ret_val = ixgbe_get_link_capabilities(hw, &link_speed, &autoneg);
+ if (ret_val != IXGBE_SUCCESS)
+ return ret_val;
+
+ if (link_speed & IXGBE_LINK_SPEED_10GB_FULL) {
+ ixgbe_set_supported_10gtypes(hw, supported);
+ ixgbe_set_supported_10gtypes(hw, advertising);
+ }
+
+ if (link_speed & IXGBE_LINK_SPEED_5GB_FULL)
+ ixgbe_set_bit(supported, RTE_LINK_MODE_5000baseT_Full_BIT);
+
+ if (link_speed & IXGBE_LINK_SPEED_2_5GB_FULL)
+ ixgbe_set_bit(supported, RTE_LINK_MODE_2500baseT_Full_BIT);
+
+ if (link_speed & IXGBE_LINK_SPEED_1GB_FULL) {
+ if (IXGBE_ISBACKPLANE(hw->phy.media_type)) {
+ ixgbe_set_bit(supported, RTE_LINK_MODE_1000baseKX_Full_BIT);
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_1000baseKX_Full_BIT);
+ } else {
+ ixgbe_set_bit(supported, RTE_LINK_MODE_1000baseT_Full_BIT);
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_1000baseT_Full_BIT);
+ }
+ }
+ if (link_speed & IXGBE_LINK_SPEED_100_FULL) {
+ ixgbe_set_bit(supported, RTE_LINK_MODE_100baseT_Full_BIT);
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_100baseT_Full_BIT);
+ }
+ if (link_speed & IXGBE_LINK_SPEED_10_FULL) {
+ ixgbe_set_bit(supported, RTE_LINK_MODE_10baseT_Full_BIT);
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_10baseT_Full_BIT);
+ }
+
+ /* set the advertised speeds */
+ if (hw->phy.autoneg_advertised) {
+ if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10_FULL)
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_10baseT_Full_BIT);
+ if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL)
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_100baseT_Full_BIT);
+ if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
+ ixgbe_set_supported_10gtypes(hw, advertising);
+ if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) {
+ if (ixgbe_get_bit(supported, RTE_LINK_MODE_1000baseKX_Full_BIT))
+ ixgbe_set_bit(advertising,
+ RTE_LINK_MODE_1000baseKX_Full_BIT);
+ else
+ ixgbe_set_bit(advertising,
+ RTE_LINK_MODE_1000baseT_Full_BIT);
+ }
+ if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_5GB_FULL)
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_5000baseT_Full_BIT);
+ if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL)
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_2500baseT_Full_BIT);
+ } else {
+ if (hw->phy.multispeed_fiber && !autoneg) {
+ if (link_speed & IXGBE_LINK_SPEED_10GB_FULL)
+ ixgbe_set_bit(advertising,
+ RTE_LINK_MODE_10000baseT_Full_BIT);
+ }
+ }
+
+ if (autoneg) {
+ ixgbe_set_bit(supported, RTE_LINK_MODE_Autoneg_BIT);
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_Autoneg_BIT);
+ link_settings->base.link.link_autoneg = RTE_AUTONEG_ENABLE;
+ } else {
+ link_settings->base.link.link_autoneg = RTE_AUTONEG_DISABLE;
+ }
+
+ switch (hw->phy.type) {
+ case ixgbe_phy_tn:
+ case ixgbe_phy_aq:
+ case ixgbe_phy_x550em_ext_t:
+ case ixgbe_phy_fw:
+ case ixgbe_phy_cu_unknown:
+ ixgbe_set_bit(supported, RTE_LINK_MODE_TP_BIT);
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_TP_BIT);
+ link_settings->base.port = RTE_PORT_TP;
+ break;
+ case ixgbe_phy_qt:
+ ixgbe_set_bit(supported, RTE_LINK_MODE_FIBRE_BIT);
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_FIBRE_BIT);
+ link_settings->base.port = RTE_PORT_FIBRE;
+ break;
+ case ixgbe_phy_nl:
+ case ixgbe_phy_sfp_passive_tyco:
+ case ixgbe_phy_sfp_passive_unknown:
+ case ixgbe_phy_sfp_ftl:
+ case ixgbe_phy_sfp_avago:
+ case ixgbe_phy_sfp_intel:
+ case ixgbe_phy_sfp_unknown:
+ case ixgbe_phy_qsfp_passive_unknown:
+ case ixgbe_phy_qsfp_active_unknown:
+ case ixgbe_phy_qsfp_intel:
+ case ixgbe_phy_qsfp_unknown:
+ /* SFP+ devices, further checking needed */
+ switch (hw->phy.sfp_type) {
+ case ixgbe_sfp_type_da_cu:
+ case ixgbe_sfp_type_da_cu_core0:
+ case ixgbe_sfp_type_da_cu_core1:
+ ixgbe_set_bit(supported, RTE_LINK_MODE_FIBRE_BIT);
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_FIBRE_BIT);
+ link_settings->base.port = RTE_PORT_DA;
+ break;
+ case ixgbe_sfp_type_sr:
+ case ixgbe_sfp_type_lr:
+ case ixgbe_sfp_type_srlr_core0:
+ case ixgbe_sfp_type_srlr_core1:
+ case ixgbe_sfp_type_1g_sx_core0:
+ case ixgbe_sfp_type_1g_sx_core1:
+ case ixgbe_sfp_type_1g_lx_core0:
+ case ixgbe_sfp_type_1g_lx_core1:
+ ixgbe_set_bit(supported, RTE_LINK_MODE_FIBRE_BIT);
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_FIBRE_BIT);
+ link_settings->base.port = RTE_PORT_FIBRE;
+ break;
+ case ixgbe_sfp_type_not_present:
+ ixgbe_set_bit(supported, RTE_LINK_MODE_FIBRE_BIT);
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_FIBRE_BIT);
+ link_settings->base.port = RTE_PORT_NONE;
+ break;
+ case ixgbe_sfp_type_1g_cu_core0:
+ case ixgbe_sfp_type_1g_cu_core1:
+ ixgbe_set_bit(supported, RTE_LINK_MODE_TP_BIT);
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_TP_BIT);
+ link_settings->base.port = RTE_PORT_TP;
+ break;
+ case ixgbe_sfp_type_unknown:
+ default:
+ ixgbe_set_bit(supported, RTE_LINK_MODE_FIBRE_BIT);
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_FIBRE_BIT);
+ link_settings->base.port = RTE_PORT_OTHER;
+ break;
+ }
+ break;
+ case ixgbe_phy_xaui:
+ ixgbe_set_bit(supported, RTE_LINK_MODE_FIBRE_BIT);
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_FIBRE_BIT);
+ link_settings->base.port = RTE_PORT_NONE;
+ break;
+ case ixgbe_phy_unknown:
+ case ixgbe_phy_generic:
+ case ixgbe_phy_sfp_unsupported:
+ default:
+ ixgbe_set_bit(supported, RTE_LINK_MODE_FIBRE_BIT);
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_FIBRE_BIT);
+ link_settings->base.port = RTE_PORT_OTHER;
+ break;
+ }
+
+ /* Indicate pause support */
+ ixgbe_set_bit(supported, RTE_LINK_MODE_Pause_BIT);
+ switch (hw->fc.requested_mode) {
+ case ixgbe_fc_full:
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_Pause_BIT);
+ break;
+ case ixgbe_fc_rx_pause:
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_Pause_BIT);
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_Asym_Pause_BIT);
+ break;
+ case ixgbe_fc_tx_pause:
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_Asym_Pause_BIT);
+ break;
+ default:
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_Pause_BIT);
+ ixgbe_set_bit(advertising, RTE_LINK_MODE_Asym_Pause_BIT);
+ }
+
+ link_settings->base.link.link_status = RTE_ETH_LINK_DOWN;
+ link_settings->base.link.link_speed = RTE_ETH_SPEED_NUM_NONE;
+ link_settings->base.link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
+
+ hw->mac.get_link_status = true;
+ /* check if it needs to wait to complete, if lsc interrupt is enabled */
+ if (dev->data->dev_conf.intr_conf.lsc != 0)
+ wait = 0;
+
+ ret_val = ixgbe_check_link(hw, &link_speed, &link_up, wait);
+ if (ret_val != IXGBE_SUCCESS)
+ return ret_val;
+
+ if (ixgbe_get_media_type(hw) == ixgbe_media_type_fiber &&
+ !ad->sdp3_no_tx_disable) {
+ esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
+ if ((esdp_reg & IXGBE_ESDP_SDP3))
+ link_up = 0;
+ }
+
+ if (link_up) {
+ link_settings->base.link.link_status = RTE_ETH_LINK_UP;
+ link_settings->base.link.link_status = RTE_ETH_LINK_FULL_DUPLEX;
+ switch (link_speed) {
+ default:
+ case IXGBE_LINK_SPEED_UNKNOWN:
+ link_settings->base.link.link_speed = RTE_ETH_SPEED_NUM_UNKNOWN;
+ break;
+
+ case IXGBE_LINK_SPEED_10_FULL:
+ link_settings->base.link.link_speed = RTE_ETH_SPEED_NUM_10M;
+ break;
+
+ case IXGBE_LINK_SPEED_100_FULL:
+ link_settings->base.link.link_speed = RTE_ETH_SPEED_NUM_100M;
+ break;
+
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ link_settings->base.link.link_speed = RTE_ETH_SPEED_NUM_1G;
+ break;
+
+ case IXGBE_LINK_SPEED_2_5GB_FULL:
+ link_settings->base.link.link_speed = RTE_ETH_SPEED_NUM_2_5G;
+ break;
+
+ case IXGBE_LINK_SPEED_5GB_FULL:
+ link_settings->base.link.link_speed = RTE_ETH_SPEED_NUM_5G;
+ break;
+
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ link_settings->base.link.link_speed = RTE_ETH_SPEED_NUM_10G;
+ break;
+ }
+ }
+
+ return ret_val;
+}
+
+static int ixgbe_set_link_settings(struct rte_eth_dev *dev,
+ const struct rte_link_settings *link_settings)
+{
+ struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ const uint32_t *supported = link_settings->link_modes.supported;
+ const uint32_t *advertising = link_settings->link_modes.advertising;
+
+ u32 advertised, old;
+ int ret = 0;
+
+ if (hw->phy.media_type == ixgbe_media_type_copper ||
+ (IXGBE_ISBACKPLANE(hw->phy.media_type)) ||
+ hw->phy.multispeed_fiber) {
+ /*
+ * Check if advertising is subset of supported
+ */
+ if (!ixgbe_is_subset(advertising, supported,
+ __RTE_LINK_MODE_MASK_NBITS))
+ return -EINVAL;
+
+ /* only allow one speed at a time if no autoneg */
+ if (!link_settings->base.link.link_autoneg && hw->phy.multispeed_fiber) {
+ if (ixgbe_get_bit(advertising,
+ RTE_LINK_MODE_10000baseT_Full_BIT) &&
+ ixgbe_get_bit(advertising,
+ RTE_LINK_MODE_1000baseT_Full_BIT))
+ return -EINVAL;
+ }
+
+ old = hw->phy.autoneg_advertised;
+ advertised = 0;
+ if ((ixgbe_get_bit(advertising, RTE_LINK_MODE_10000baseT_Full_BIT)) ||
+ (ixgbe_get_bit(advertising, RTE_LINK_MODE_10000baseKR_Full_BIT)) ||
+ (ixgbe_get_bit(advertising, RTE_LINK_MODE_10000baseKX4_Full_BIT)))
+ advertised |= IXGBE_LINK_SPEED_10GB_FULL;
+ if (ixgbe_get_bit(advertising, RTE_LINK_MODE_5000baseT_Full_BIT))
+ advertised |= IXGBE_LINK_SPEED_5GB_FULL;
+ if (ixgbe_get_bit(advertising, RTE_LINK_MODE_2500baseT_Full_BIT))
+ advertised |= IXGBE_LINK_SPEED_2_5GB_FULL;
+ if ((ixgbe_get_bit(advertising, RTE_LINK_MODE_1000baseT_Full_BIT)) ||
+ (ixgbe_get_bit(advertising, RTE_LINK_MODE_1000baseKX_Full_BIT)))
+ advertised |= IXGBE_LINK_SPEED_1GB_FULL;
+ if (ixgbe_get_bit(advertising, RTE_LINK_MODE_100baseT_Full_BIT))
+ advertised |= IXGBE_LINK_SPEED_100_FULL;
+ if (ixgbe_get_bit(advertising, RTE_LINK_MODE_10baseT_Full_BIT))
+ advertised |= IXGBE_LINK_SPEED_10_FULL;
+ if (old == advertised)
+ return ret;
+
+ hw->mac.autotry_restart = true;
+ ret = hw->mac.ops.setup_link(hw, advertised, true);
+ if (ret) {
+ PMD_DRV_LOG(WARNING, "setup link failed with code %d\n", ret);
+ hw->mac.ops.setup_link(hw, old, true);
+ }
+ } else {
+ /* in this case we currently only support 10Gb/FULL */
+ u32 speed = link_settings->base.link.link_speed;
+
+ if (link_settings->base.link.link_autoneg == RTE_AUTONEG_ENABLE ||
+ (!ixgbe_get_bit(advertising, RTE_LINK_MODE_10000baseT_Full_BIT)) ||
+ (speed + link_settings->base.link.link_duplex !=
+ IXGBE_SPEED_10000 + IXGBE_DUPLEX_FULL))
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
static int
ixgbevf_dev_promiscuous_enable(struct rte_eth_dev *dev)
{
@@ -1119,6 +1119,34 @@ typedef const uint32_t *(*eth_buffer_split_supported_hdr_ptypes_get_t)(struct rt
*/
typedef int (*eth_dev_priv_dump_t)(struct rte_eth_dev *dev, FILE *file);
+/** @internal Retrieve physical link settings of a port.
+ *
+ * @param dev
+ * Port (ethdev) handle
+ *
+ * @param[out] settings
+ * Physical port link settings.
+ *
+ * @return
+ * Negative errno value on error, zero otherwise
+ */
+typedef int (*eth_get_link_settings_t)(struct rte_eth_dev *dev,
+ struct rte_link_settings *settings);
+
+/** @internal Configure physical link settings of a port.
+ *
+ * @param dev
+ * Port (ethdev) handle
+ *
+ * @param settings
+ * Physical port link settings.
+ *
+ * @return
+ * Negative errno value on error, zero otherwise
+ */
+typedef int (*eth_set_link_settings_t)(struct rte_eth_dev *dev,
+ const struct rte_link_settings *settings);
+
/**
* @internal Set Rx queue available descriptors threshold.
* @see rte_eth_rx_avail_thresh_set()
@@ -1474,6 +1502,11 @@ struct eth_dev_ops {
eth_count_aggr_ports_t count_aggr_ports;
/** Map a Tx queue with an aggregated port of the DPDK port */
eth_map_aggr_tx_affinity_t map_aggr_tx_affinity;
+
+ /** Retrieve physical link settings */
+ eth_get_link_settings_t get_link_settings;
+ /** Configure physical link settings */
+ eth_set_link_settings_t set_link_settings;
};
/**
@@ -6844,6 +6844,32 @@ rte_eth_dev_priv_dump(uint16_t port_id, FILE *file)
return eth_err(port_id, (*dev->dev_ops->eth_dev_priv_dump)(dev, file));
}
+int rte_eth_dev_get_link_settings(uint16_t port_id,
+ struct rte_link_settings *settings)
+{
+ struct rte_eth_dev *dev;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+ dev = &rte_eth_devices[port_id];
+
+ if (*dev->dev_ops->get_link_settings == NULL)
+ return -ENOTSUP;
+ return eth_err(port_id, (*dev->dev_ops->get_link_settings)(dev, settings));
+}
+
+int rte_eth_dev_set_link_settings(uint16_t port_id,
+ const struct rte_link_settings *settings)
+{
+ struct rte_eth_dev *dev;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+ dev = &rte_eth_devices[port_id];
+
+ if (*dev->dev_ops->set_link_settings == NULL)
+ return -ENOTSUP;
+ return eth_err(port_id, (*dev->dev_ops->set_link_settings)(dev, settings));
+}
+
int
rte_eth_rx_descriptor_dump(uint16_t port_id, uint16_t queue_id,
uint16_t offset, uint16_t num, FILE *file)
@@ -335,7 +335,7 @@ struct rte_eth_stats {
__extension__
struct __rte_aligned(8) rte_eth_link { /**< aligned for atomic64 read/write */
uint32_t link_speed; /**< RTE_ETH_SPEED_NUM_ */
- uint16_t link_duplex : 1; /**< RTE_ETH_LINK_[HALF/FULL]_DUPLEX */
+ uint16_t link_duplex : 2; /**< RTE_ETH_LINK_[HALF/FULL/UNKNOWN]_DUPLEX */
uint16_t link_autoneg : 1; /**< RTE_ETH_LINK_[AUTONEG/FIXED] */
uint16_t link_status : 1; /**< RTE_ETH_LINK_[DOWN/UP] */
};
@@ -343,13 +343,27 @@ struct __rte_aligned(8) rte_eth_link { /**< aligned for atomic64 read/write */
/**@{@name Link negotiation
* Constants used in link management.
*/
-#define RTE_ETH_LINK_HALF_DUPLEX 0 /**< Half-duplex connection (see link_duplex). */
-#define RTE_ETH_LINK_FULL_DUPLEX 1 /**< Full-duplex connection (see link_duplex). */
-#define RTE_ETH_LINK_DOWN 0 /**< Link is down (see link_status). */
-#define RTE_ETH_LINK_UP 1 /**< Link is up (see link_status). */
-#define RTE_ETH_LINK_FIXED 0 /**< No autonegotiation (see link_autoneg). */
-#define RTE_ETH_LINK_AUTONEG 1 /**< Autonegotiated (see link_autoneg). */
-#define RTE_ETH_LINK_MAX_STR_LEN 40 /**< Max length of default link string. */
+#define RTE_ETH_LINK_HALF_DUPLEX 0 /**< Half-duplex connection (see link_duplex). */
+#define RTE_ETH_LINK_FULL_DUPLEX 1 /**< Full-duplex connection (see link_duplex). */
+#define RTE_ETH_LINK_UNKNOWN_DUPLEX 2 /**</ Unknown-duplex (see link_duplex). */
+#define RTE_ETH_LINK_DOWN 0 /**< Link is down (see link_status). */
+#define RTE_ETH_LINK_UP 1 /**< Link is up (see link_status). */
+#define RTE_ETH_LINK_FIXED 0 /**< No autonegotiation (see link_autoneg). */
+#define RTE_ETH_LINK_AUTONEG 1 /**< Autonegotiated (see link_autoneg). */
+#define RTE_ETH_LINK_MAX_STR_LEN 40 /**< Max length of default link string. */
+/**@}*/
+
+/**@{@name Link negotiation
+ * Constants used in link management to specify connector port.
+ */
+#define RTE_PORT_TP 0x00
+#define RTE_PORT_AUI 0x01
+#define RTE_PORT_MII 0x02
+#define RTE_PORT_FIBRE 0x03
+#define RTE_PORT_BNC 0x04
+#define RTE_PORT_DA 0x05
+#define RTE_PORT_NONE 0xef
+#define RTE_PORT_OTHER 0xff
/**@}*/
/**
@@ -1433,6 +1447,147 @@ struct rte_eth_pfc_queue_conf {
} tx_pause; /* Valid when (mode == FC_TX_PAUSE || mode == FC_FULL) */
};
+/* Enable or disable autonegotiation. */
+#define RTE_AUTONEG_DISABLE 0x00
+#define RTE_AUTONEG_ENABLE 0x01
+
+/* MDI or MDI-X status/control - if MDI/MDI_X/AUTO is set then
+ * the driver is required to renegotiate link
+ */
+#define RTE_TP_MDI_INVALID 0x00 /* status: unknown; control: unsupported */
+#define RTE_TP_MDI 0x01 /* status: MDI; control: force MDI */
+#define RTE_TP_MDI_X 0x02 /* status: MDI-X; control: force MDI-X */
+#define RTE_TP_MDI_AUTO 0x03 /* control: auto-select */
+
+/* Link mode bit indices */
+enum rte_link_mode_bit_indices {
+ RTE_LINK_MODE_10baseT_Half_BIT = 0,
+ RTE_LINK_MODE_10baseT_Full_BIT = 1,
+ RTE_LINK_MODE_100baseT_Half_BIT = 2,
+ RTE_LINK_MODE_100baseT_Full_BIT = 3,
+ RTE_LINK_MODE_1000baseT_Half_BIT = 4,
+ RTE_LINK_MODE_1000baseT_Full_BIT = 5,
+ RTE_LINK_MODE_Autoneg_BIT = 6,
+ RTE_LINK_MODE_TP_BIT = 7,
+ RTE_LINK_MODE_AUI_BIT = 8,
+ RTE_LINK_MODE_MII_BIT = 9,
+ RTE_LINK_MODE_FIBRE_BIT = 10,
+ RTE_LINK_MODE_BNC_BIT = 11,
+ RTE_LINK_MODE_10000baseT_Full_BIT = 12,
+ RTE_LINK_MODE_Pause_BIT = 13,
+ RTE_LINK_MODE_Asym_Pause_BIT = 14,
+ RTE_LINK_MODE_2500baseX_Full_BIT = 15,
+ RTE_LINK_MODE_Backplane_BIT = 16,
+ RTE_LINK_MODE_1000baseKX_Full_BIT = 17,
+ RTE_LINK_MODE_10000baseKX4_Full_BIT = 18,
+ RTE_LINK_MODE_10000baseKR_Full_BIT = 19,
+ RTE_LINK_MODE_10000baseR_FEC_BIT = 20,
+ RTE_LINK_MODE_20000baseMLD2_Full_BIT = 21,
+ RTE_LINK_MODE_20000baseKR2_Full_BIT = 22,
+ RTE_LINK_MODE_40000baseKR4_Full_BIT = 23,
+ RTE_LINK_MODE_40000baseCR4_Full_BIT = 24,
+ RTE_LINK_MODE_40000baseSR4_Full_BIT = 25,
+ RTE_LINK_MODE_40000baseLR4_Full_BIT = 26,
+ RTE_LINK_MODE_56000baseKR4_Full_BIT = 27,
+ RTE_LINK_MODE_56000baseCR4_Full_BIT = 28,
+ RTE_LINK_MODE_56000baseSR4_Full_BIT = 29,
+ RTE_LINK_MODE_56000baseLR4_Full_BIT = 30,
+ RTE_LINK_MODE_25000baseCR_Full_BIT = 31,
+ RTE_LINK_MODE_25000baseKR_Full_BIT = 32,
+ RTE_LINK_MODE_25000baseSR_Full_BIT = 33,
+ RTE_LINK_MODE_50000baseCR2_Full_BIT = 34,
+ RTE_LINK_MODE_50000baseKR2_Full_BIT = 35,
+ RTE_LINK_MODE_100000baseKR4_Full_BIT = 36,
+ RTE_LINK_MODE_100000baseSR4_Full_BIT = 37,
+ RTE_LINK_MODE_100000baseCR4_Full_BIT = 38,
+ RTE_LINK_MODE_100000baseLR4_ER4_Full_BIT = 39,
+ RTE_LINK_MODE_50000baseSR2_Full_BIT = 40,
+ RTE_LINK_MODE_1000baseX_Full_BIT = 41,
+ RTE_LINK_MODE_10000baseCR_Full_BIT = 42,
+ RTE_LINK_MODE_10000baseSR_Full_BIT = 43,
+ RTE_LINK_MODE_10000baseLR_Full_BIT = 44,
+ RTE_LINK_MODE_10000baseLRM_Full_BIT = 45,
+ RTE_LINK_MODE_10000baseER_Full_BIT = 46,
+ RTE_LINK_MODE_2500baseT_Full_BIT = 47,
+ RTE_LINK_MODE_5000baseT_Full_BIT = 48,
+
+ RTE_LINK_MODE_FEC_NONE_BIT = 49,
+ RTE_LINK_MODE_FEC_RS_BIT = 50,
+ RTE_LINK_MODE_FEC_BASER_BIT = 51,
+ RTE_LINK_MODE_50000baseKR_Full_BIT = 52,
+ RTE_LINK_MODE_50000baseSR_Full_BIT = 53,
+ RTE_LINK_MODE_50000baseCR_Full_BIT = 54,
+ RTE_LINK_MODE_50000baseLR_ER_FR_Full_BIT = 55,
+ RTE_LINK_MODE_50000baseDR_Full_BIT = 56,
+ RTE_LINK_MODE_100000baseKR2_Full_BIT = 57,
+ RTE_LINK_MODE_100000baseSR2_Full_BIT = 58,
+ RTE_LINK_MODE_100000baseCR2_Full_BIT = 59,
+ RTE_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT = 60,
+ RTE_LINK_MODE_100000baseDR2_Full_BIT = 61,
+ RTE_LINK_MODE_200000baseKR4_Full_BIT = 62,
+ RTE_LINK_MODE_200000baseSR4_Full_BIT = 63,
+ RTE_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT = 64,
+ RTE_LINK_MODE_200000baseDR4_Full_BIT = 65,
+ RTE_LINK_MODE_200000baseCR4_Full_BIT = 66,
+ RTE_LINK_MODE_100baseT1_Full_BIT = 67,
+ RTE_LINK_MODE_1000baseT1_Full_BIT = 68,
+ RTE_LINK_MODE_400000baseKR8_Full_BIT = 69,
+ RTE_LINK_MODE_400000baseSR8_Full_BIT = 70,
+ RTE_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT = 71,
+ RTE_LINK_MODE_400000baseDR8_Full_BIT = 72,
+ RTE_LINK_MODE_400000baseCR8_Full_BIT = 73,
+ RTE_LINK_MODE_FEC_LLRS_BIT = 74,
+ RTE_LINK_MODE_100000baseKR_Full_BIT = 75,
+ RTE_LINK_MODE_100000baseSR_Full_BIT = 76,
+ RTE_LINK_MODE_100000baseLR_ER_FR_Full_BIT = 77,
+ RTE_LINK_MODE_100000baseCR_Full_BIT = 78,
+ RTE_LINK_MODE_100000baseDR_Full_BIT = 79,
+ RTE_LINK_MODE_200000baseKR2_Full_BIT = 80,
+ RTE_LINK_MODE_200000baseSR2_Full_BIT = 81,
+ RTE_LINK_MODE_200000baseLR2_ER2_FR2_Full_BIT = 82,
+ RTE_LINK_MODE_200000baseDR2_Full_BIT = 83,
+ RTE_LINK_MODE_200000baseCR2_Full_BIT = 84,
+ RTE_LINK_MODE_400000baseKR4_Full_BIT = 85,
+ RTE_LINK_MODE_400000baseSR4_Full_BIT = 86,
+ RTE_LINK_MODE_400000baseLR4_ER4_FR4_Full_BIT = 87,
+ RTE_LINK_MODE_400000baseDR4_Full_BIT = 88,
+ RTE_LINK_MODE_400000baseCR4_Full_BIT = 89,
+ RTE_LINK_MODE_100baseFX_Half_BIT = 90,
+ RTE_LINK_MODE_100baseFX_Full_BIT = 91,
+ /* must be last entry */
+ __RTE_LINK_MODE_MASK_NBITS
+};
+
+/* number of 32-bit words to store the user's link mode bitmaps */
+#define RTE_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+#define __RTE_LINK_MODE_MASK_NU32 \
+ RTE_DIV_ROUND_UP(__RTE_LINK_MODE_MASK_NBITS, 32)
+
+/**
+ * Link control and status
+ * @speed: Link speed (Mbps)
+ * @duplex: Duplex mode; one of %DUPLEX_*
+ * @port: Physical connector type; one of %PORT_*
+ * @autoneg: Enable/disable autonegotiation and auto-detection;
+ * either %AUTONEG_DISABLE or %AUTONEG_ENABLE
+ */
+struct rte_link_base_settings {
+ struct rte_eth_link link;
+ uint8_t port;
+ uint8_t phy_address;
+ uint8_t eth_tp_mdix;
+ uint8_t eth_tp_mdix_ctrl;
+};
+
+struct rte_link_settings {
+ struct rte_link_base_settings base;
+ struct {
+ uint32_t supported[__RTE_LINK_MODE_MASK_NU32];
+ uint32_t advertising[__RTE_LINK_MODE_MASK_NU32];
+ uint32_t lp_advertising[__RTE_LINK_MODE_MASK_NU32];
+ } link_modes;
+};
+
/**
* Tunnel type for device-specific classifier configuration.
* @see rte_eth_udp_tunnel
@@ -5936,6 +6091,50 @@ int rte_eth_cman_config_init(uint16_t port_id, struct rte_eth_cman_config *confi
__rte_experimental
int rte_eth_cman_config_set(uint16_t port_id, const struct rte_eth_cman_config *config);
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Retrieve link settings
+ *
+ * @param port_id
+ * The port identifier of the Ethernet device.
+ * @param settings
+ * A pointer to a structure of type *rte_link_settings* to retrieve
+ * link settings parameters for the given port.
+ *
+ * @return
+ * - (0) if successful.
+ * - (-ENOTSUP) if support for cman_config_get does not exist.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-EINVAL) if bad parameter.
+ */
+__rte_experimental
+int rte_eth_dev_get_link_settings(uint16_t port_id,
+ struct rte_link_settings *settings);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Configure link settings
+ *
+ * @param port_id
+ * The port identifier of the Ethernet device.
+ * @param settings
+ * A pointer to a structure of type *rte_link_settings* to configure
+ * link settings parameters for the given port.
+ *
+ * @return
+ * - (0) if successful.
+ * - (-ENOTSUP) if support for cman_config_get does not exist.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-EINVAL) if bad parameter.
+ */
+__rte_experimental
+int rte_eth_dev_set_link_settings(uint16_t port_id,
+ const struct rte_link_settings *settings);
+
/**
* @warning
* @b EXPERIMENTAL: this API may change, or be removed, without prior notice
@@ -325,6 +325,9 @@ EXPERIMENTAL {
rte_flow_template_table_resizable;
rte_flow_template_table_resize;
rte_flow_template_table_resize_complete;
+ rte_eth_dev_get_link_settings;
+ rte_eth_dev_set_link_settings;
+
};
INTERNAL {