@@ -35,6 +35,8 @@ DIRS-y += librte_compat
DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal
DIRS-$(CONFIG_RTE_LIBRTE_RING) += librte_ring
DEPDIRS-librte_ring := librte_eal
+DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
+DEPDIRS-librte_metrics := librte_eal
DIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += librte_mempool
DEPDIRS-librte_mempool := librte_eal librte_ring
DIRS-$(CONFIG_RTE_LIBRTE_MBUF) += librte_mbuf
@@ -46,7 +48,7 @@ DEPDIRS-librte_cfgfile := librte_eal
DIRS-$(CONFIG_RTE_LIBRTE_CMDLINE) += librte_cmdline
DEPDIRS-librte_cmdline := librte_eal
DIRS-$(CONFIG_RTE_LIBRTE_ETHER) += librte_ether
-DEPDIRS-librte_ether := librte_net librte_eal librte_mempool librte_ring
+DEPDIRS-librte_ether := librte_net librte_eal librte_mempool librte_ring librte_metrics
DEPDIRS-librte_ether += librte_mbuf
DIRS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += librte_cryptodev
DEPDIRS-librte_cryptodev := librte_eal librte_mempool librte_ring librte_mbuf
@@ -70,8 +72,6 @@ DEPDIRS-librte_ip_frag := librte_eal librte_mempool librte_mbuf librte_ether
DEPDIRS-librte_ip_frag += librte_hash
DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += librte_jobstats
DEPDIRS-librte_jobstats := librte_eal
-DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
-DEPDIRS-librte_metrics := librte_eal
DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
DEPDIRS-librte_bitratestats := librte_eal librte_metrics librte_ether
DIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += librte_latencystats
@@ -40,7 +40,7 @@ INC += rte_string_fns.h rte_version.h
INC += rte_eal_memconfig.h rte_malloc_heap.h
INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_vdev.h
INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
-INC += rte_malloc.h rte_keepalive.h rte_time.h
+INC += rte_malloc.h rte_keepalive.h rte_time.h rte_clock.h
GENERIC_INC := rte_atomic.h rte_byteorder.h rte_cycles.h rte_prefetch.h
GENERIC_INC += rte_spinlock.h rte_memcpy.h rte_cpuflags.h rte_rwlock.h
new file mode 100644
@@ -0,0 +1,68 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2017-2018 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_CLOCK_H_
+#define _RTE_CLOCK_H_
+
+/**
+ * @file
+ *
+ * Retrieves the time of the monotonic clock.
+ */
+#include <time.h>
+
+struct rte_timespec {
+ time_t tv_sec; /* seconds */
+ long tv_nsec; /* nanoseconds */
+};
+
+/**
+ * Gets the time of the monotonic clock.
+ *
+ * @return
+ * The number of cycles
+ */
+static int
+rte_clock_monotonic_gettime(struct rte_timespec *time)
+{
+ if (time == NULL)
+ return -1;
+
+ struct timespec *sp = (struct timespec *)time;
+ if (clock_gettime(CLOCK_MONOTONIC, sp) != 0)
+ return -1;
+
+ return 0;
+}
+
+#endif /* _RTE_CLOCK_H_ */
@@ -64,6 +64,10 @@
#include <rte_errno.h>
#include <rte_spinlock.h>
#include <rte_string_fns.h>
+#include <rte_cycles.h>
+#include <rte_metrics.h>
+#include <rte_clock.h>
+#include <rte_time.h>
#include "rte_ether.h"
#include "rte_ethdev.h"
@@ -118,7 +122,8 @@ static const struct rte_eth_xstats_name_off rte_txq_stats_strings[] = {
#define RTE_NB_TXQ_STATS (sizeof(rte_txq_stats_strings) / \
sizeof(rte_txq_stats_strings[0]))
-
+#define RTE_MIB_ATTR_NAME_SIZE 32
+#define RTE_IF_TYPE_ETHERNETCSMACD 6
/**
* The user application callback description.
*
@@ -139,6 +144,11 @@ enum {
STAT_QMAP_RX
};
+enum {
+ OPER_STATUS_UP = 1,
+ OPER_STATUS_DOWN
+};
+
uint8_t
rte_eth_find_next(uint8_t port_id)
{
@@ -218,6 +228,7 @@ rte_eth_dev_allocate(const char *name)
{
uint8_t port_id;
struct rte_eth_dev *eth_dev;
+ struct rte_timespec tsp;
port_id = rte_eth_dev_find_free_port();
if (port_id == RTE_MAX_ETHPORTS) {
@@ -239,6 +250,13 @@ rte_eth_dev_allocate(const char *name)
snprintf(eth_dev->data->name, sizeof(eth_dev->data->name), "%s", name);
eth_dev->data->port_id = port_id;
eth_dev->data->mtu = ETHER_MTU;
+ if (rte_clock_monotonic_gettime(&tsp) != 0) {
+ RTE_PMD_DEBUG_TRACE("Failed to get monotonic clock time: "
+ "%s\n", __func__);
+ return NULL;
+ }
+ eth_dev->data->sys_up_time_start =
+ tsp.tv_sec * NSEC_PER_SEC + tsp.tv_nsec;
return eth_dev;
}
@@ -898,6 +916,7 @@ rte_eth_dev_start(uint8_t port_id)
{
struct rte_eth_dev *dev;
int diag;
+ struct rte_timespec tsp;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
@@ -923,6 +942,13 @@ rte_eth_dev_start(uint8_t port_id)
if (dev->data->dev_conf.intr_conf.lsc == 0) {
RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->link_update, -ENOTSUP);
(*dev->dev_ops->link_update)(dev, 0);
+ if (rte_clock_monotonic_gettime(&tsp) != 0) {
+ RTE_PMD_DEBUG_TRACE("Failed to get monotonic clock time"
+ ": %s\n", __func__);
+ return -1;
+ }
+ dev->data->if_last_change = tsp.tv_sec * NSEC_PER_SEC +
+ tsp.tv_nsec - dev->data->sys_up_time_start;
}
return 0;
}
@@ -1295,6 +1321,7 @@ void
rte_eth_link_get(uint8_t port_id, struct rte_eth_link *eth_link)
{
struct rte_eth_dev *dev;
+ struct rte_timespec tsp;
RTE_ETH_VALID_PORTID_OR_RET(port_id);
dev = &rte_eth_devices[port_id];
@@ -1305,6 +1332,12 @@ rte_eth_link_get(uint8_t port_id, struct rte_eth_link *eth_link)
RTE_FUNC_PTR_OR_RET(*dev->dev_ops->link_update);
(*dev->dev_ops->link_update)(dev, 1);
*eth_link = dev->data->dev_link;
+
+ if (rte_clock_monotonic_gettime(&tsp) != 0)
+ RTE_PMD_DEBUG_TRACE("Failed to get monotonic clock time"
+ ": %s\n", __func__);
+ dev->data->if_last_change = tsp.tv_sec * NSEC_PER_SEC +
+ tsp.tv_nsec - dev->data->sys_up_time_start;
}
}
@@ -1312,6 +1345,7 @@ void
rte_eth_link_get_nowait(uint8_t port_id, struct rte_eth_link *eth_link)
{
struct rte_eth_dev *dev;
+ struct rte_timespec tsp;
RTE_ETH_VALID_PORTID_OR_RET(port_id);
dev = &rte_eth_devices[port_id];
@@ -1322,6 +1356,14 @@ rte_eth_link_get_nowait(uint8_t port_id, struct rte_eth_link *eth_link)
RTE_FUNC_PTR_OR_RET(*dev->dev_ops->link_update);
(*dev->dev_ops->link_update)(dev, 0);
*eth_link = dev->data->dev_link;
+
+ if (rte_clock_monotonic_gettime(&tsp) != 0) {
+ RTE_PMD_DEBUG_TRACE("Failed to get monotonic clock time"
+ ": %s\n", __func__);
+ return -1;
+ }
+ dev->data->if_last_change = tsp.tv_sec * NSEC_PER_SEC +
+ tsp.tv_nsec - dev->data->sys_up_time_start;
}
}
@@ -1345,12 +1387,20 @@ void
rte_eth_stats_reset(uint8_t port_id)
{
struct rte_eth_dev *dev;
+ struct rte_timespec tsp;
RTE_ETH_VALID_PORTID_OR_RET(port_id);
dev = &rte_eth_devices[port_id];
RTE_FUNC_PTR_OR_RET(*dev->dev_ops->stats_reset);
(*dev->dev_ops->stats_reset)(dev);
+
+ if (rte_clock_monotonic_gettime(&tsp) != 0) {
+ RTE_PMD_DEBUG_TRACE("Failed to get monotonic clock time: "
+ "%s\n", __func__);
+ }
+ dev->data->if_cntr_disc_time = tsp.tv_sec * NSEC_PER_SEC + tsp.tv_nsec -
+ dev->data->sys_up_time_start;
dev->data->rx_mbuf_alloc_failed = 0;
}
@@ -1822,6 +1872,7 @@ void
rte_eth_xstats_reset(uint8_t port_id)
{
struct rte_eth_dev *dev;
+ struct rte_timespec tsp;
RTE_ETH_VALID_PORTID_OR_RET(port_id);
dev = &rte_eth_devices[port_id];
@@ -1829,6 +1880,13 @@ rte_eth_xstats_reset(uint8_t port_id)
/* implemented by the driver */
if (dev->dev_ops->xstats_reset != NULL) {
(*dev->dev_ops->xstats_reset)(dev);
+
+ if (rte_clock_monotonic_gettime(&tsp) != 0)
+ RTE_PMD_DEBUG_TRACE("Failed to get monotonic clock time: "
+ "%s\n", __func__);
+ dev->data->if_cntr_disc_time = tsp.tv_sec * NSEC_PER_SEC + tsp.tv_nsec -
+ dev->data->sys_up_time_start;
+
return;
}
@@ -3354,3 +3412,115 @@ rte_eth_dev_l2_tunnel_offload_set(uint8_t port_id,
-ENOTSUP);
return (*dev->dev_ops->l2_tunnel_offload_set)(dev, l2_tunnel, mask, en);
}
+
+/* IF-MIB attributes*/
+struct rte_if_mib_attrs {
+ uint64_t if_number; /* ifNumber */
+ uint64_t if_index; /* ifIndex */
+ uint64_t if_type; /* ifType */
+ uint64_t if_mtu; /* ifMtu */
+ uint64_t if_speed; /* ifSpeed */
+ uint64_t if_phys_address; /* ifPhysAddress */
+ uint64_t if_oper_status; /* ifOperStatus */
+ uint64_t if_last_change; /* ifLastChange */
+ uint64_t if_high_speed; /* ifHighSpeed */
+ uint64_t if_cnctr_present; /* ifConnectorPresent */
+ uint64_t if_cntr_disc_time; /* ifCounterDiscontinuityTime */
+};
+
+static struct rte_if_mib_attrs *if_mib_attrs;
+
+struct if_mib_attrs_nameoff {
+ char name[RTE_MIB_ATTR_NAME_SIZE];
+ unsigned int offset;
+};
+
+static const struct if_mib_attrs_nameoff if_mib_attrs_strings[] = {
+ {"ifNumber", offsetof(struct rte_if_mib_attrs, if_number)},
+ {"ifIndex", offsetof(struct rte_if_mib_attrs, if_index)},
+ {"ifType", offsetof(struct rte_if_mib_attrs, if_type)},
+ {"ifMtu", offsetof(struct rte_if_mib_attrs, if_mtu)},
+ {"ifSpeed", offsetof(struct rte_if_mib_attrs, if_speed)},
+ {"ifPhysAddress", offsetof(struct rte_if_mib_attrs, if_phys_address)},
+ {"ifOperStatus", offsetof(struct rte_if_mib_attrs, if_oper_status)},
+ {"ifLastChange", offsetof(struct rte_if_mib_attrs, if_last_change)},
+ {"ifHighSpeed", offsetof(struct rte_if_mib_attrs, if_high_speed)},
+ {"ifConnectorPresent", offsetof(struct rte_if_mib_attrs,
+ if_cnctr_present)},
+ {"ifCounterDiscontinuityTime", offsetof(struct rte_if_mib_attrs,
+ if_cntr_disc_time)},
+};
+
+#define NUM_IF_MIB_ATTRS (sizeof(if_mib_attrs_strings) / \
+ sizeof(if_mib_attrs_strings[0]))
+
+int
+rte_eth_ifmib_attr_init(void) {
+ if_mib_attrs = rte_zmalloc(NULL, sizeof(struct rte_if_mib_attrs),
+ RTE_CACHE_LINE_SIZE);
+
+ return 0;
+}
+
+int
+rte_eth_ifmib_attr_reg(uint8_t port_id) {
+
+ int idx;
+ unsigned int i;
+ uint64_t *attr_ptr = NULL;
+ const char *ptr_strings[NUM_IF_MIB_ATTRS] = {0};
+ struct rte_eth_dev *eth_dev;
+ struct rte_device *device;
+ struct rte_eth_dev_data *data;
+ uint64_t values[NUM_IF_MIB_ATTRS] = {0};
+
+ for (i = 0; i < NUM_IF_MIB_ATTRS; i++)
+ ptr_strings[i] = if_mib_attrs_strings[i].name;
+
+ /* register names with metrics library */
+ idx = rte_metrics_reg_names(ptr_strings, NUM_IF_MIB_ATTRS);
+
+ eth_dev = eth_dev_get(port_id);
+ data = eth_dev->data;
+ device = eth_dev->device;
+
+ /* implement if mib attributes */
+ if_mib_attrs->if_number = rte_eth_dev_count();
+
+ if_mib_attrs->if_index = data->port_id + 1;
+
+ if_mib_attrs->if_type = RTE_IF_TYPE_ETHERNETCSMACD;
+
+ if_mib_attrs->if_mtu = data->mtu;
+
+ if_mib_attrs->if_speed =
+ (data->dev_link.link_speed < (UINT32_MAX / 1000000)) ?
+ (data->dev_link.link_speed * 1000000) : UINT32_MAX;
+
+ if_mib_attrs->if_phys_address = 0;
+ ether_addr_copy(data->mac_addrs,
+ (struct ether_addr *)if_mib_attrs->if_phys_address);
+
+ if_mib_attrs->if_oper_status = data->dev_link.link_status ?
+ OPER_STATUS_UP : OPER_STATUS_DOWN;
+
+ if_mib_attrs->if_last_change = data->if_last_change;
+
+ if_mib_attrs->if_high_speed = data->dev_link.link_speed;
+
+ if_mib_attrs->if_cnctr_present =
+ (device->devargs->type == RTE_DEVTYPE_VIRTUAL) ?
+ OPER_STATUS_UP : OPER_STATUS_DOWN;
+
+ if_mib_attrs->if_cntr_disc_time = data->if_cntr_disc_time;
+
+ for (i = 0; i < NUM_IF_MIB_ATTRS; i++) {
+ attr_ptr = RTE_PTR_ADD(if_mib_attrs,
+ if_mib_attrs_strings[i].offset);
+ values[i] = *attr_ptr;
+ }
+ /* update values to metrics library */
+ rte_metrics_update_values(port_id, idx, values, NUM_IF_MIB_ATTRS);
+
+ return 0;
+}
@@ -1674,6 +1674,10 @@ struct rte_eth_dev_data {
uint32_t dev_flags; /**< Capabilities */
enum rte_kernel_driver kdrv; /**< Kernel driver passthrough */
int numa_node; /**< NUMA node connection */
+ /** IF-MIB attributes ifLastChange and ifCounterDiscontinuityTime */
+ uint64_t sys_up_time_start;
+ uint64_t if_cntr_disc_time;
+ uint64_t if_last_change;
};
/** Device supports hotplug detach */
@@ -4375,6 +4379,9 @@ rte_eth_dev_get_port_by_name(const char *name, uint8_t *port_id);
int
rte_eth_dev_get_name_by_port(uint8_t port_id, char *name);
+int rte_eth_ifmib_attr_init(void);
+int rte_eth_ifmib_attr_reg(uint8_t port_id);
+
#ifdef __cplusplus
}
#endif
@@ -37,6 +37,7 @@
#include <rte_malloc.h>
#include <rte_pci.h>
#include <rte_ethdev.h>
+#include <rte_cycles.h>
/**
* Copy pci device info to the Ethernet device data.
@@ -73,7 +73,6 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_ACL) += --whole-archive
_LDLIBS-$(CONFIG_RTE_LIBRTE_ACL) += -lrte_acl
_LDLIBS-$(CONFIG_RTE_LIBRTE_ACL) += --no-whole-archive
_LDLIBS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += -lrte_jobstats
-_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics
_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats
_LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += -lrte_latencystats
_LDLIBS-$(CONFIG_RTE_LIBRTE_POWER) += -lrte_power
@@ -95,6 +94,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EVENTDEV) += -lrte_eventdev
_LDLIBS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += -lrte_mempool
_LDLIBS-$(CONFIG_RTE_DRIVER_MEMPOOL_RING) += -lrte_mempool_ring
_LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring
+_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics
_LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal
_LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline
_LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER) += -lrte_reorder