diff options
Diffstat (limited to 'platform/linux-generic/pktio')
-rw-r--r-- | platform/linux-generic/pktio/dpdk.c | 60 | ||||
-rw-r--r-- | platform/linux-generic/pktio/ipc.c | 31 | ||||
-rw-r--r-- | platform/linux-generic/pktio/loop.c | 20 | ||||
-rw-r--r-- | platform/linux-generic/pktio/netmap.c | 26 | ||||
-rw-r--r-- | platform/linux-generic/pktio/null.c | 22 | ||||
-rw-r--r-- | platform/linux-generic/pktio/pcap.c | 22 | ||||
-rw-r--r-- | platform/linux-generic/pktio/socket.c | 6 | ||||
-rw-r--r-- | platform/linux-generic/pktio/socket_common.c | 139 | ||||
-rw-r--r-- | platform/linux-generic/pktio/socket_mmap.c | 6 | ||||
-rw-r--r-- | platform/linux-generic/pktio/tap.c | 6 |
10 files changed, 330 insertions, 8 deletions
diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c index 18f583a65..7aee73dc1 100644 --- a/platform/linux-generic/pktio/dpdk.c +++ b/platform/linux-generic/pktio/dpdk.c @@ -1,5 +1,5 @@ /* Copyright (c) 2016-2018, Linaro Limited - * Copyright (c) 2019, Nokia + * Copyright (c) 2019-2020, Nokia * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -2056,8 +2056,63 @@ static int dpdk_link_status(pktio_entry_t *pktio_entry) memset(&link, 0, sizeof(struct rte_eth_link)); rte_eth_link_get_nowait(pkt_priv(pktio_entry)->port_id, &link); + if (link.link_status) + return ODP_PKTIO_LINK_STATUS_UP; + return ODP_PKTIO_LINK_STATUS_DOWN; +} + +static int dpdk_link_info(pktio_entry_t *pktio_entry, odp_pktio_link_info_t *info) +{ + struct rte_eth_link link; + struct rte_eth_fc_conf fc_conf; + uint16_t port_id = pkt_priv(pktio_entry)->port_id; + int ret; - return link.link_status; + memset(&fc_conf, 0, sizeof(struct rte_eth_fc_conf)); + memset(&link, 0, sizeof(struct rte_eth_link)); + + ret = rte_eth_dev_flow_ctrl_get(port_id, &fc_conf); + if (ret && ret != -ENOTSUP) { + ODP_ERR("rte_eth_dev_flow_ctrl_get() failed\n"); + return -1; + } + + memset(info, 0, sizeof(odp_pktio_link_info_t)); + info->pause_rx = ODP_PKTIO_LINK_PAUSE_OFF; + info->pause_tx = ODP_PKTIO_LINK_PAUSE_OFF; + if (fc_conf.mode == RTE_FC_RX_PAUSE) { + info->pause_rx = ODP_PKTIO_LINK_PAUSE_ON; + } else if (fc_conf.mode == RTE_FC_TX_PAUSE) { + info->pause_tx = ODP_PKTIO_LINK_PAUSE_ON; + } else if (fc_conf.mode == RTE_FC_FULL) { + info->pause_rx = ODP_PKTIO_LINK_PAUSE_ON; + info->pause_tx = ODP_PKTIO_LINK_PAUSE_ON; + } + + rte_eth_link_get_nowait(port_id, &link); + if (link.link_autoneg == ETH_LINK_AUTONEG) + info->autoneg = ODP_PKTIO_LINK_AUTONEG_ON; + else + info->autoneg = ODP_PKTIO_LINK_AUTONEG_OFF; + + if (link.link_duplex == ETH_LINK_FULL_DUPLEX) + info->duplex = ODP_PKTIO_LINK_DUPLEX_FULL; + else + info->duplex = ODP_PKTIO_LINK_DUPLEX_HALF; + + if (link.link_speed == ETH_SPEED_NUM_NONE) + info->speed = ODP_PKTIO_LINK_SPEED_UNKNOWN; + else + info->speed = link.link_speed; + + if (link.link_status == ETH_LINK_UP) + info->status = ODP_PKTIO_LINK_STATUS_UP; + else + info->status = ODP_PKTIO_LINK_STATUS_DOWN; + + info->media = "unknown"; + + return 0; } static void stats_convert(const struct rte_eth_stats *rte_stats, @@ -2106,6 +2161,7 @@ const pktio_if_ops_t dpdk_pktio_ops = { .recv = dpdk_recv, .send = dpdk_send, .link_status = dpdk_link_status, + .link_info = dpdk_link_info, .mtu_get = dpdk_frame_maxlen, .promisc_mode_set = dpdk_promisc_mode_set, .promisc_mode_get = dpdk_promisc_mode_get, diff --git a/platform/linux-generic/pktio/ipc.c b/platform/linux-generic/pktio/ipc.c index d63a77b74..34b32ae2c 100644 --- a/platform/linux-generic/pktio/ipc.c +++ b/platform/linux-generic/pktio/ipc.c @@ -900,6 +900,35 @@ static int ipc_stop(pktio_entry_t *pktio_entry) return 0; } +static int ipc_link_status(pktio_entry_t *pktio_entry) +{ + pkt_ipc_t *pktio_ipc = pkt_priv(pktio_entry); + + if (odp_atomic_load_u32(&pktio_ipc->ready)) + return ODP_PKTIO_LINK_STATUS_UP; + return ODP_PKTIO_LINK_STATUS_DOWN; +} + +static int ipc_link_info(pktio_entry_t *pktio_entry, odp_pktio_link_info_t *info) +{ + pkt_ipc_t *pktio_ipc = pkt_priv(pktio_entry); + + memset(info, 0, sizeof(odp_pktio_link_info_t)); + + info->autoneg = ODP_PKTIO_LINK_AUTONEG_OFF; + info->duplex = ODP_PKTIO_LINK_DUPLEX_FULL; + info->media = "virtual"; + info->pause_rx = ODP_PKTIO_LINK_PAUSE_OFF; + info->pause_tx = ODP_PKTIO_LINK_PAUSE_OFF; + info->speed = ODP_PKTIO_LINK_SPEED_UNKNOWN; + if (odp_atomic_load_u32(&pktio_ipc->ready)) + info->status = ODP_PKTIO_LINK_STATUS_UP; + else + info->status = ODP_PKTIO_LINK_STATUS_DOWN; + + return 0; +} + static int ipc_close(pktio_entry_t *pktio_entry) { pkt_ipc_t *pktio_ipc = pkt_priv(pktio_entry); @@ -947,6 +976,8 @@ const pktio_if_ops_t ipc_pktio_ops = { .send = ipc_pktio_send, .start = ipc_start, .stop = ipc_stop, + .link_status = ipc_link_status, + .link_info = ipc_link_info, .mtu_get = ipc_mtu_get, .promisc_mode_set = NULL, .promisc_mode_get = NULL, diff --git a/platform/linux-generic/pktio/loop.c b/platform/linux-generic/pktio/loop.c index e6d004d43..3de096139 100644 --- a/platform/linux-generic/pktio/loop.c +++ b/platform/linux-generic/pktio/loop.c @@ -1,5 +1,5 @@ /* Copyright (c) 2013-2018, Linaro Limited - * Copyright (c) 2013, Nokia Solutions and Networks + * Copyright (c) 2013-2020, Nokia Solutions and Networks * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -367,7 +367,22 @@ static int loopback_mac_addr_get(pktio_entry_t *pktio_entry ODP_UNUSED, static int loopback_link_status(pktio_entry_t *pktio_entry ODP_UNUSED) { /* loopback interfaces are always up */ - return 1; + return ODP_PKTIO_LINK_STATUS_UP; +} + +static int loopback_link_info(pktio_entry_t *pktio_entry ODP_UNUSED, odp_pktio_link_info_t *info) +{ + memset(info, 0, sizeof(odp_pktio_link_info_t)); + + info->autoneg = ODP_PKTIO_LINK_AUTONEG_OFF; + info->duplex = ODP_PKTIO_LINK_DUPLEX_FULL; + info->media = "virtual"; + info->pause_rx = ODP_PKTIO_LINK_PAUSE_OFF; + info->pause_tx = ODP_PKTIO_LINK_PAUSE_OFF; + info->speed = ODP_PKTIO_LINK_SPEED_UNKNOWN; + info->status = ODP_PKTIO_LINK_STATUS_UP; + + return 0; } static int loopback_init_capability(pktio_entry_t *pktio_entry) @@ -467,6 +482,7 @@ const pktio_if_ops_t loopback_pktio_ops = { .mac_get = loopback_mac_addr_get, .mac_set = NULL, .link_status = loopback_link_status, + .link_info = loopback_link_info, .capability = loopback_capability, .pktin_ts_res = NULL, .pktin_ts_from_ns = NULL, diff --git a/platform/linux-generic/pktio/netmap.c b/platform/linux-generic/pktio/netmap.c index e1a5da773..0f608c6f6 100644 --- a/platform/linux-generic/pktio/netmap.c +++ b/platform/linux-generic/pktio/netmap.c @@ -1,5 +1,5 @@ /* Copyright (c) 2015-2018, Linaro Limited - * Copyright (c) 2019, Nokia + * Copyright (c) 2019-2020, Nokia * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -355,12 +355,33 @@ static int netmap_close(pktio_entry_t *pktio_entry) static int netmap_link_status(pktio_entry_t *pktio_entry) { if (pkt_priv(pktio_entry)->is_virtual) - return 1; + return ODP_PKTIO_LINK_STATUS_UP; return link_status_fd(pkt_priv(pktio_entry)->sockfd, pkt_priv(pktio_entry)->if_name); } +static int netmap_link_info(pktio_entry_t *pktio_entry, odp_pktio_link_info_t *info) +{ + pkt_netmap_t *pkt_nm = pkt_priv(pktio_entry); + + if (pkt_nm->is_virtual) { + memset(info, 0, sizeof(odp_pktio_link_info_t)); + + info->autoneg = ODP_PKTIO_LINK_AUTONEG_OFF; + info->duplex = ODP_PKTIO_LINK_DUPLEX_FULL; + info->media = "virtual"; + info->pause_rx = ODP_PKTIO_LINK_PAUSE_OFF; + info->pause_tx = ODP_PKTIO_LINK_PAUSE_OFF; + info->speed = ODP_PKTIO_LINK_SPEED_UNKNOWN; + info->status = ODP_PKTIO_LINK_STATUS_UP; + + return 0; + } + + return link_info_fd(pkt_nm->sockfd, pkt_nm->if_name, info); +} + /** * Wait for netmap link to come up * @@ -1225,6 +1246,7 @@ const pktio_if_ops_t netmap_pktio_ops = { .start = netmap_start, .stop = netmap_stop, .link_status = netmap_link_status, + .link_info = netmap_link_info, .stats = netmap_stats, .stats_reset = netmap_stats_reset, .mtu_get = netmap_mtu_get, diff --git a/platform/linux-generic/pktio/null.c b/platform/linux-generic/pktio/null.c index bb7f85c9b..d739ccafe 100644 --- a/platform/linux-generic/pktio/null.c +++ b/platform/linux-generic/pktio/null.c @@ -154,6 +154,26 @@ static int null_init_global(void) return 0; } +static int null_link_status(pktio_entry_t *pktio_entry ODP_UNUSED) +{ + return ODP_PKTIO_LINK_STATUS_UP; +} + +static int null_link_info(pktio_entry_t *pktio_entry ODP_UNUSED, odp_pktio_link_info_t *info) +{ + memset(info, 0, sizeof(odp_pktio_link_info_t)); + + info->autoneg = ODP_PKTIO_LINK_AUTONEG_OFF; + info->duplex = ODP_PKTIO_LINK_DUPLEX_FULL; + info->media = "virtual"; + info->pause_rx = ODP_PKTIO_LINK_PAUSE_OFF; + info->pause_tx = ODP_PKTIO_LINK_PAUSE_OFF; + info->speed = ODP_PKTIO_LINK_SPEED_UNKNOWN; + info->status = ODP_PKTIO_LINK_STATUS_UP; + + return 0; +} + const pktio_if_ops_t null_pktio_ops = { .name = "null", .print = NULL, @@ -179,4 +199,6 @@ const pktio_if_ops_t null_pktio_ops = { .config = NULL, .input_queues_config = null_inqueues_config, .output_queues_config = null_outqueues_config, + .link_status = null_link_status, + .link_info = null_link_info }; diff --git a/platform/linux-generic/pktio/pcap.c b/platform/linux-generic/pktio/pcap.c index 6ef998717..262528abc 100644 --- a/platform/linux-generic/pktio/pcap.c +++ b/platform/linux-generic/pktio/pcap.c @@ -444,6 +444,26 @@ static int pcapif_init_global(void) return 0; } +static int pcapif_link_status(pktio_entry_t *pktio_entry ODP_UNUSED) +{ + return ODP_PKTIO_LINK_STATUS_UP; +} + +static int pcapif_link_info(pktio_entry_t *pktio_entry ODP_UNUSED, odp_pktio_link_info_t *info) +{ + memset(info, 0, sizeof(odp_pktio_link_info_t)); + + info->autoneg = ODP_PKTIO_LINK_AUTONEG_OFF; + info->duplex = ODP_PKTIO_LINK_DUPLEX_FULL; + info->media = "virtual"; + info->pause_rx = ODP_PKTIO_LINK_PAUSE_OFF; + info->pause_tx = ODP_PKTIO_LINK_PAUSE_OFF; + info->speed = ODP_PKTIO_LINK_SPEED_UNKNOWN; + info->status = ODP_PKTIO_LINK_STATUS_UP; + + return 0; +} + const pktio_if_ops_t pcap_pktio_ops = { .name = "pcap", .print = NULL, @@ -466,4 +486,6 @@ const pktio_if_ops_t pcap_pktio_ops = { .config = NULL, .input_queues_config = NULL, .output_queues_config = NULL, + .link_status = pcapif_link_status, + .link_info = pcapif_link_info }; diff --git a/platform/linux-generic/pktio/socket.c b/platform/linux-generic/pktio/socket.c index d148edf03..4776b83f9 100644 --- a/platform/linux-generic/pktio/socket.c +++ b/platform/linux-generic/pktio/socket.c @@ -493,6 +493,11 @@ static int sock_link_status(pktio_entry_t *pktio_entry) pktio_entry->s.name); } +static int sock_link_info(pktio_entry_t *pktio_entry, odp_pktio_link_info_t *info) +{ + return link_info_fd(pkt_priv(pktio_entry)->sockfd, pktio_entry->s.name, info); +} + static int sock_capability(pktio_entry_t *pktio_entry ODP_UNUSED, odp_pktio_capability_t *capa) { @@ -566,6 +571,7 @@ const pktio_if_ops_t sock_mmsg_pktio_ops = { .mac_get = sock_mac_addr_get, .mac_set = NULL, .link_status = sock_link_status, + .link_info = sock_link_info, .capability = sock_capability, .pktin_ts_res = NULL, .pktin_ts_from_ns = NULL, diff --git a/platform/linux-generic/pktio/socket_common.c b/platform/linux-generic/pktio/socket_common.c index 4fbf2f041..2eb3b4001 100644 --- a/platform/linux-generic/pktio/socket_common.c +++ b/platform/linux-generic/pktio/socket_common.c @@ -1,5 +1,5 @@ /* Copyright (c) 2018, Linaro Limited - * Copyright (c) 2019, Nokia + * Copyright (c) 2019-2020, Nokia * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -14,7 +14,9 @@ #include <sys/types.h> #include <sys/ioctl.h> #include <net/if.h> +#include <linux/ethtool.h> #include <linux/if_packet.h> +#include <linux/sockios.h> #include <errno.h> #include <odp_debug_internal.h> #include <odp_errno_define.h> @@ -155,8 +157,141 @@ int link_status_fd(int fd, const char *name) __odp_errno = errno; ODP_DBG("ioctl(SIOCGIFFLAGS): %s: \"%s\".\n", strerror(errno), ifr.ifr_name); + return ODP_PKTIO_LINK_STATUS_UNKNOWN; + } + + if (ifr.ifr_flags & IFF_RUNNING) + return ODP_PKTIO_LINK_STATUS_UP; + return ODP_PKTIO_LINK_STATUS_DOWN; +} + +int link_info_fd(int fd, const char *name, odp_pktio_link_info_t *info) +{ + struct ethtool_link_settings hcmd = {.cmd = ETHTOOL_GLINKSETTINGS}; + struct ethtool_link_settings *ecmd; + struct ethtool_pauseparam pcmd = {.cmd = ETHTOOL_GPAUSEPARAM}; + struct ifreq ifr; + int status; + + status = link_status_fd(fd, name); + if (status < 0) + return -1; + + snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", name); + + /* Link pause status */ + ifr.ifr_data = (void *)&pcmd; + if (ioctl(fd, SIOCETHTOOL, &ifr) && errno != EOPNOTSUPP) { + __odp_errno = errno; + ODP_ERR("ioctl(SIOCETHTOOL): %s: \"%s\".\n", strerror(errno), + ifr.ifr_name); + return -1; + } + + /* Try to perform handshake and fall back to old API if failed */ + ifr.ifr_data = (void *)&hcmd; + if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) { + struct ethtool_cmd ecmd_old = {.cmd = ETHTOOL_GSET}; + + ifr.ifr_data = (void *)&ecmd_old; + if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) { + __odp_errno = errno; + ODP_ERR("ioctl(SIOCETHTOOL): %s: \"%s\".\n", strerror(errno), ifr.ifr_name); + return -1; + } + + memset(info, 0, sizeof(odp_pktio_link_info_t)); + info->speed = ethtool_cmd_speed(&ecmd_old); + if (info->speed == (uint32_t)SPEED_UNKNOWN) + info->speed = ODP_PKTIO_LINK_SPEED_UNKNOWN; + + if (ecmd_old.autoneg == AUTONEG_ENABLE) + info->autoneg = ODP_PKTIO_LINK_AUTONEG_ON; + else if (ecmd_old.autoneg == AUTONEG_DISABLE) + info->autoneg = ODP_PKTIO_LINK_AUTONEG_OFF; + else + info->autoneg = ODP_PKTIO_LINK_AUTONEG_UNKNOWN; + + if (ecmd_old.duplex == DUPLEX_HALF) + info->duplex = ODP_PKTIO_LINK_DUPLEX_HALF; + else if (ecmd_old.duplex == DUPLEX_FULL) + info->duplex = ODP_PKTIO_LINK_DUPLEX_FULL; + else + info->duplex = ODP_PKTIO_LINK_DUPLEX_UNKNOWN; + + info->pause_rx = pcmd.rx_pause ? ODP_PKTIO_LINK_PAUSE_ON : ODP_PKTIO_LINK_PAUSE_OFF; + info->pause_tx = pcmd.tx_pause ? ODP_PKTIO_LINK_PAUSE_ON : ODP_PKTIO_LINK_PAUSE_OFF; + + if (ecmd_old.port == PORT_TP) + info->media = "copper"; + else if (ecmd_old.port == PORT_FIBRE) + info->media = "fiber"; + else if (ecmd_old.port == PORT_OTHER) + info->media = "other"; + else + info->media = "unknown"; + + info->status = status; + + return 0; + } + + if (hcmd.link_mode_masks_nwords >= 0 || hcmd.cmd != ETHTOOL_GLINKSETTINGS) { + ODP_ERR("ETHTOOL_GLINKSETTINGS handshake failed\n"); + return -1; + } + /* Absolute value indicates kernel recommended 'link_mode_masks_nwords' value. */ + hcmd.link_mode_masks_nwords = -hcmd.link_mode_masks_nwords; + + /* Reserve space for the three bitmasks (map_supported, map_advertising, map_lp_advertising) + * at the end of struct ethtool_link_settings. 'link_mode_masks_nwords' defines the bitmask + * length in 32-bit words. */ + uint8_t ODP_ALIGNED_CACHE data[offsetof(struct ethtool_link_settings, link_mode_masks) + + (3 * sizeof(uint32_t) * hcmd.link_mode_masks_nwords)]; + + ecmd = (void *)data; + *ecmd = hcmd; + ifr.ifr_data = (void *)ecmd; + if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) { + __odp_errno = errno; + ODP_ERR("ioctl(SIOCETHTOOL): %s: \"%s\".\n", strerror(errno), + ifr.ifr_name); return -1; } - return !!(ifr.ifr_flags & IFF_RUNNING); + memset(info, 0, sizeof(odp_pktio_link_info_t)); + if (ecmd->speed == (uint32_t)SPEED_UNKNOWN) + info->speed = ODP_PKTIO_LINK_SPEED_UNKNOWN; + else + info->speed = ecmd->speed; + + if (ecmd->autoneg == AUTONEG_ENABLE) + info->autoneg = ODP_PKTIO_LINK_AUTONEG_ON; + else if (ecmd->autoneg == AUTONEG_DISABLE) + info->autoneg = ODP_PKTIO_LINK_AUTONEG_OFF; + else + info->autoneg = ODP_PKTIO_LINK_AUTONEG_UNKNOWN; + + if (ecmd->duplex == DUPLEX_HALF) + info->duplex = ODP_PKTIO_LINK_DUPLEX_HALF; + else if (ecmd->duplex == DUPLEX_FULL) + info->duplex = ODP_PKTIO_LINK_DUPLEX_FULL; + else + info->duplex = ODP_PKTIO_LINK_DUPLEX_UNKNOWN; + + info->pause_rx = pcmd.rx_pause ? ODP_PKTIO_LINK_PAUSE_ON : ODP_PKTIO_LINK_PAUSE_OFF; + info->pause_tx = pcmd.tx_pause ? ODP_PKTIO_LINK_PAUSE_ON : ODP_PKTIO_LINK_PAUSE_OFF; + + if (ecmd->port == PORT_TP) + info->media = "copper"; + else if (ecmd->port == PORT_FIBRE) + info->media = "fiber"; + else if (ecmd->port == PORT_OTHER) + info->media = "other"; + else + info->media = "unknown"; + + info->status = status; + + return 0; } diff --git a/platform/linux-generic/pktio/socket_mmap.c b/platform/linux-generic/pktio/socket_mmap.c index bf1cbad81..d0d37636d 100644 --- a/platform/linux-generic/pktio/socket_mmap.c +++ b/platform/linux-generic/pktio/socket_mmap.c @@ -784,6 +784,11 @@ static int sock_mmap_link_status(pktio_entry_t *pktio_entry) pktio_entry->s.name); } +static int sock_mmap_link_info(pktio_entry_t *pktio_entry, odp_pktio_link_info_t *info) +{ + return link_info_fd(pkt_priv(pktio_entry)->sockfd, pktio_entry->s.name, info); +} + static int sock_mmap_capability(pktio_entry_t *pktio_entry ODP_UNUSED, odp_pktio_capability_t *capa) { @@ -860,6 +865,7 @@ const pktio_if_ops_t sock_mmap_pktio_ops = { .mac_get = sock_mmap_mac_addr_get, .mac_set = NULL, .link_status = sock_mmap_link_status, + .link_info = sock_mmap_link_info, .capability = sock_mmap_capability, .pktin_ts_res = NULL, .pktin_ts_from_ns = NULL, diff --git a/platform/linux-generic/pktio/tap.c b/platform/linux-generic/pktio/tap.c index db5c701b2..13a9feaf8 100644 --- a/platform/linux-generic/pktio/tap.c +++ b/platform/linux-generic/pktio/tap.c @@ -467,6 +467,11 @@ static int tap_link_status(pktio_entry_t *pktio_entry) pktio_entry->s.name + 4); } +static int tap_link_info(pktio_entry_t *pktio_entry, odp_pktio_link_info_t *info) +{ + return link_info_fd(pkt_priv(pktio_entry)->skfd, pktio_entry->s.name + 4, info); +} + static int tap_capability(pktio_entry_t *pktio_entry ODP_UNUSED, odp_pktio_capability_t *capa) { @@ -501,6 +506,7 @@ const pktio_if_ops_t tap_pktio_ops = { .mac_get = tap_mac_addr_get, .mac_set = tap_mac_addr_set, .link_status = tap_link_status, + .link_info = tap_link_info, .capability = tap_capability, .pktin_ts_res = NULL, .pktin_ts_from_ns = NULL, |