From be13fd96ef22de100254ce5d819021def46d6214 Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Sun, 8 Jan 2017 11:20:53 +0200 Subject: mlx5 from dpdk16_11 Signed-off-by: Hanoh Haim --- src/dpdk/drivers/net/mlx5/mlx5_rxq.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) (limited to 'src/dpdk/drivers/net/mlx5/mlx5_rxq.c') diff --git a/src/dpdk/drivers/net/mlx5/mlx5_rxq.c b/src/dpdk/drivers/net/mlx5/mlx5_rxq.c index 6be01d39..28e93d3e 100644 --- a/src/dpdk/drivers/net/mlx5/mlx5_rxq.c +++ b/src/dpdk/drivers/net/mlx5/mlx5_rxq.c @@ -40,25 +40,25 @@ /* Verbs header. */ /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ #ifdef PEDANTIC -#pragma GCC diagnostic ignored "-pedantic" +#pragma GCC diagnostic ignored "-Wpedantic" #endif #include #include #include #ifdef PEDANTIC -#pragma GCC diagnostic error "-pedantic" +#pragma GCC diagnostic error "-Wpedantic" #endif /* DPDK headers don't like -pedantic. */ #ifdef PEDANTIC -#pragma GCC diagnostic ignored "-pedantic" +#pragma GCC diagnostic ignored "-Wpedantic" #endif #include #include #include #include #ifdef PEDANTIC -#pragma GCC diagnostic error "-pedantic" +#pragma GCC diagnostic error "-Wpedantic" #endif #include "mlx5.h" @@ -102,7 +102,7 @@ const struct hash_rxq_init hash_rxq_init[] = { ETH_RSS_FRAG_IPV4), .flow_priority = 1, .flow_spec.ipv4 = { - .type = IBV_EXP_FLOW_SPEC_IPV4_EXT, + .type = IBV_EXP_FLOW_SPEC_IPV4, .size = sizeof(hash_rxq_init[0].flow_spec.ipv4), }, .underlayer = &hash_rxq_init[HASH_RXQ_ETH], @@ -140,7 +140,7 @@ const struct hash_rxq_init hash_rxq_init[] = { ETH_RSS_FRAG_IPV6), .flow_priority = 1, .flow_spec.ipv6 = { - .type = IBV_EXP_FLOW_SPEC_IPV6_EXT, + .type = IBV_EXP_FLOW_SPEC_IPV6, .size = sizeof(hash_rxq_init[0].flow_spec.ipv6), }, .underlayer = &hash_rxq_init[HASH_RXQ_ETH], @@ -723,7 +723,7 @@ rxq_free_elts(struct rxq_ctrl *rxq_ctrl) if (rxq_ctrl->rxq.elts == NULL) return; - for (i = 0; (i != rxq_ctrl->rxq.elts_n); ++i) { + for (i = 0; (i != (1u << rxq_ctrl->rxq.elts_n)); ++i) { if ((*rxq_ctrl->rxq.elts)[i] != NULL) rte_pktmbuf_free_seg((*rxq_ctrl->rxq.elts)[i]); (*rxq_ctrl->rxq.elts)[i] = NULL; @@ -745,6 +745,8 @@ rxq_cleanup(struct rxq_ctrl *rxq_ctrl) DEBUG("cleaning up %p", (void *)rxq_ctrl); rxq_free_elts(rxq_ctrl); + if (rxq_ctrl->fdir_queue != NULL) + priv_fdir_queue_destroy(rxq_ctrl->priv, rxq_ctrl->fdir_queue); if (rxq_ctrl->if_wq != NULL) { assert(rxq_ctrl->priv != NULL); assert(rxq_ctrl->priv->ctx != NULL); @@ -805,7 +807,7 @@ rxq_cleanup(struct rxq_ctrl *rxq_ctrl) int rxq_rehash(struct rte_eth_dev *dev, struct rxq_ctrl *rxq_ctrl) { - unsigned int elts_n = rxq_ctrl->rxq.elts_n; + unsigned int elts_n = 1 << rxq_ctrl->rxq.elts_n; unsigned int i; struct ibv_exp_wq_attr mod; int err; @@ -868,7 +870,7 @@ rxq_setup(struct rxq_ctrl *tmpl) struct ibv_cq *ibcq = tmpl->cq; struct mlx5_cq *cq = to_mxxx(cq, cq); struct mlx5_rwq *rwq = container_of(tmpl->wq, struct mlx5_rwq, wq); - struct rte_mbuf *(*elts)[tmpl->rxq.elts_n] = + struct rte_mbuf *(*elts)[1 << tmpl->rxq.elts_n] = rte_calloc_socket("RXQ", 1, sizeof(*elts), 0, tmpl->socket); if (cq->cqe_sz != RTE_CACHE_LINE_SIZE) { @@ -879,7 +881,7 @@ rxq_setup(struct rxq_ctrl *tmpl) if (elts == NULL) return ENOMEM; tmpl->rxq.rq_db = rwq->rq.db; - tmpl->rxq.cqe_n = ibcq->cqe + 1; + tmpl->rxq.cqe_n = log2above(ibcq->cqe); tmpl->rxq.cq_ci = 0; tmpl->rxq.rq_ci = 0; tmpl->rxq.cq_db = cq->dbrec; @@ -922,8 +924,9 @@ rxq_ctrl_setup(struct rte_eth_dev *dev, struct rxq_ctrl *rxq_ctrl, .priv = priv, .socket = socket, .rxq = { - .elts_n = desc, + .elts_n = log2above(desc), .mp = mp, + .rss_hash = priv->rxqs_n > 1, }, }; struct ibv_exp_wq_attr mod; @@ -943,6 +946,11 @@ rxq_ctrl_setup(struct rte_eth_dev *dev, struct rxq_ctrl *rxq_ctrl, (void)conf; /* Thresholds configuration (ignored). */ /* Enable scattered packets support for this queue if necessary. */ assert(mb_len >= RTE_PKTMBUF_HEADROOM); + /* If smaller than MRU, multi-segment support must be enabled. */ + if (mb_len < (priv->mtu > dev->data->dev_conf.rxmode.max_rx_pkt_len ? + dev->data->dev_conf.rxmode.max_rx_pkt_len : + priv->mtu)) + dev->data->dev_conf.rxmode.jumbo_frame = 1; if ((dev->data->dev_conf.rxmode.jumbo_frame) && (dev->data->dev_conf.rxmode.max_rx_pkt_len > (mb_len - RTE_PKTMBUF_HEADROOM))) { @@ -1146,7 +1154,7 @@ rxq_ctrl_setup(struct rte_eth_dev *dev, struct rxq_ctrl *rxq_ctrl, } /* Reuse buffers from original queue if possible. */ if (rxq_ctrl->rxq.elts_n) { - assert(rxq_ctrl->rxq.elts_n == desc); + assert(1 << rxq_ctrl->rxq.elts_n == desc); assert(rxq_ctrl->rxq.elts != tmpl.rxq.elts); ret = rxq_alloc_elts(&tmpl, desc, rxq_ctrl->rxq.elts); } else @@ -1259,7 +1267,7 @@ mlx5_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, (void *)dev, (void *)rxq_ctrl); (*priv->rxqs)[idx] = &rxq_ctrl->rxq; /* Update receive callback. */ - dev->rx_pkt_burst = mlx5_rx_burst; + priv_select_rx_function(priv); } priv_unlock(priv); return -ret; -- cgit 1.2.3-korg From 79323b2d27bd2a3703a18594f1bb7fefd0d67514 Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Sun, 8 Jan 2017 11:59:16 +0200 Subject: patch the changes from 16.07 Signed-off-by: Hanoh Haim --- src/dpdk/drivers/net/mlx5/mlx5.c | 4 +- src/dpdk/drivers/net/mlx5/mlx5.h | 30 +++ src/dpdk/drivers/net/mlx5/mlx5_fdir.c | 91 +++++++-- src/dpdk/drivers/net/mlx5/mlx5_rxq.c | 4 +- src/dpdk/drivers/net/mlx5/mlx5_rxtx.h | 4 +- src/dpdk/drivers/net/mlx5/mlx5_stats.c | 327 +++++++++++++++++++++++++-------- 6 files changed, 365 insertions(+), 95 deletions(-) (limited to 'src/dpdk/drivers/net/mlx5/mlx5_rxq.c') diff --git a/src/dpdk/drivers/net/mlx5/mlx5.c b/src/dpdk/drivers/net/mlx5/mlx5.c index 7fc6ccf5..7c072391 100644 --- a/src/dpdk/drivers/net/mlx5/mlx5.c +++ b/src/dpdk/drivers/net/mlx5/mlx5.c @@ -181,6 +181,9 @@ mlx5_dev_close(struct rte_eth_dev *dev) } if (priv->reta_idx != NULL) rte_free(priv->reta_idx); + + mlx5_stats_free(dev); + priv_unlock(priv); memset(priv, 0, sizeof(*priv)); } @@ -1289,7 +1292,6 @@ rte_mlx5_pmd_init(void) * using this PMD, which is not supported in forked processes. */ setenv("RDMAV_HUGEPAGES_SAFE", "1", 1); - ibv_fork_init(); rte_eal_pci_register(&mlx5_driver.pci_drv); } diff --git a/src/dpdk/drivers/net/mlx5/mlx5.h b/src/dpdk/drivers/net/mlx5/mlx5.h index 79b7a600..83b29e18 100644 --- a/src/dpdk/drivers/net/mlx5/mlx5.h +++ b/src/dpdk/drivers/net/mlx5/mlx5.h @@ -84,6 +84,34 @@ enum { PCI_DEVICE_ID_MELLANOX_CONNECTX4LXVF = 0x1016, }; +struct mlx5_stats_priv { + + struct rte_eth_stats m_shadow; + uint32_t n_stats; /* number of counters */ + + void * et_stats ;/* point to ethtool counter struct ethtool_stats*/ + + /* index into ethtool */ + uint16_t inx_rx_vport_unicast_bytes; + uint16_t inx_rx_vport_multicast_bytes; + uint16_t inx_rx_vport_broadcast_bytes; + uint16_t inx_rx_vport_unicast_packets; + uint16_t inx_rx_vport_multicast_packets; + uint16_t inx_rx_vport_broadcast_packets; + uint16_t inx_tx_vport_unicast_bytes; + uint16_t inx_tx_vport_multicast_bytes; + uint16_t inx_tx_vport_broadcast_bytes; + uint16_t inx_tx_vport_unicast_packets; + uint16_t inx_tx_vport_multicast_packets; + uint16_t inx_tx_vport_broadcast_packets; + uint16_t inx_rx_wqe_err; + uint16_t inx_rx_crc_errors_phy; + uint16_t inx_rx_in_range_len_errors_phy; + uint16_t inx_rx_symbol_err_phy; + uint16_t inx_tx_errors_phy; +}; + + struct priv { struct rte_eth_dev *dev; /* Ethernet device. */ struct ibv_context *ctx; /* Verbs context. */ @@ -137,6 +165,7 @@ struct priv { struct fdir_queue *fdir_drop_queue; /* Flow director drop queue. */ uint32_t link_speed_capa; /* Link speed capabilities. */ rte_spinlock_t lock; /* Lock for control functions. */ + struct mlx5_stats_priv m_stats; }; /* Local storage for secondary process data. */ @@ -246,6 +275,7 @@ void mlx5_allmulticast_disable(struct rte_eth_dev *); void mlx5_stats_get(struct rte_eth_dev *, struct rte_eth_stats *); void mlx5_stats_reset(struct rte_eth_dev *); +void mlx5_stats_free(struct rte_eth_dev *dev); /* mlx5_vlan.c */ diff --git a/src/dpdk/drivers/net/mlx5/mlx5_fdir.c b/src/dpdk/drivers/net/mlx5/mlx5_fdir.c index 1acf6826..f03e95ef 100644 --- a/src/dpdk/drivers/net/mlx5/mlx5_fdir.c +++ b/src/dpdk/drivers/net/mlx5/mlx5_fdir.c @@ -37,12 +37,14 @@ #include #include +#define TREX_PATCH + /* Verbs header. */ /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ #ifdef PEDANTIC #pragma GCC diagnostic ignored "-Wpedantic" #endif -#include +#include #ifdef PEDANTIC #pragma GCC diagnostic error "-Wpedantic" #endif @@ -67,6 +69,9 @@ struct fdir_flow_desc { uint16_t src_port; uint32_t src_ip[4]; uint32_t dst_ip[4]; + uint8_t tos; + uint8_t ip_id; + uint8_t proto; uint8_t mac[6]; uint16_t vlan_tag; enum hash_rxq_type type; @@ -102,6 +107,7 @@ fdir_filter_to_flow_desc(const struct rte_eth_fdir_filter *fdir_filter, /* Set VLAN ID. */ desc->vlan_tag = fdir_filter->input.flow_ext.vlan_tci; +#ifndef TREX_PATCH /* Set MAC address. */ if (mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) { rte_memcpy(desc->mac, @@ -111,6 +117,14 @@ fdir_filter_to_flow_desc(const struct rte_eth_fdir_filter *fdir_filter, desc->type = HASH_RXQ_ETH; return; } +#else + if (fdir_filter->input.flow.ip4_flow.ip_id == 2) { + desc->type = HASH_RXQ_ETH; + desc->ip_id = fdir_filter->input.flow.ip4_flow.ip_id; + return; + } +#endif + /* Set mode */ switch (fdir_filter->input.flow_type) { @@ -145,6 +159,9 @@ fdir_filter_to_flow_desc(const struct rte_eth_fdir_filter *fdir_filter, case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: desc->src_ip[0] = fdir_filter->input.flow.ip4_flow.src_ip; desc->dst_ip[0] = fdir_filter->input.flow.ip4_flow.dst_ip; + desc->tos = fdir_filter->input.flow.ip4_flow.ttl; /* TTL is mapped to TOS TREX_PATCH */ + desc->ip_id = fdir_filter->input.flow.ip4_flow.ip_id; + desc->proto = fdir_filter->input.flow.ip4_flow.proto; break; case RTE_ETH_FLOW_NONFRAG_IPV6_UDP: case RTE_ETH_FLOW_NONFRAG_IPV6_TCP: @@ -158,6 +175,9 @@ fdir_filter_to_flow_desc(const struct rte_eth_fdir_filter *fdir_filter, rte_memcpy(desc->dst_ip, fdir_filter->input.flow.ipv6_flow.dst_ip, sizeof(desc->dst_ip)); + desc->tos = (uint8_t)fdir_filter->input.flow.ipv6_flow.hop_limits; /* TTL is mapped to TOS - TREX_PATCH */ + desc->ip_id = (uint8_t)fdir_filter->input.flow.ipv6_flow.flow_label; + desc->proto = fdir_filter->input.flow.ipv6_flow.proto; break; default: break; @@ -198,6 +218,11 @@ priv_fdir_overlap(const struct priv *priv, ((desc1->dst_port & mask->dst_port_mask) != (desc2->dst_port & mask->dst_port_mask))) return 0; + if ( (desc1->tos != desc2->tos) || + (desc1->ip_id != desc2->ip_id) || + (desc1->proto != desc2->proto) ) + return 0; + switch (desc1->type) { case HASH_RXQ_IPV4: case HASH_RXQ_UDPV4: @@ -252,8 +277,8 @@ priv_fdir_flow_add(struct priv *priv, struct ibv_exp_flow_attr *attr = &data->attr; uintptr_t spec_offset = (uintptr_t)&data->spec; struct ibv_exp_flow_spec_eth *spec_eth; - struct ibv_exp_flow_spec_ipv4 *spec_ipv4; - struct ibv_exp_flow_spec_ipv6 *spec_ipv6; + struct ibv_exp_flow_spec_ipv4_ext *spec_ipv4; + struct ibv_exp_flow_spec_ipv6_ext *spec_ipv6; struct ibv_exp_flow_spec_tcp_udp *spec_tcp_udp; struct mlx5_fdir_filter *iter_fdir_filter; unsigned int i; @@ -265,8 +290,10 @@ priv_fdir_flow_add(struct priv *priv, (iter_fdir_filter->flow != NULL) && (priv_fdir_overlap(priv, &mlx5_fdir_filter->desc, - &iter_fdir_filter->desc))) - return EEXIST; + &iter_fdir_filter->desc))){ + ERROR("overlap rules, please check your rules"); + return EEXIST; + } /* * No padding must be inserted by the compiler between attr and spec. @@ -289,6 +316,7 @@ priv_fdir_flow_add(struct priv *priv, /* Update priority */ attr->priority = 2; +#ifndef TREX_PATCH if (fdir_mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) { /* MAC Address */ for (i = 0; i != RTE_DIM(spec_eth->mask.dst_mac); ++i) { @@ -298,6 +326,14 @@ priv_fdir_flow_add(struct priv *priv, } goto create_flow; } +#else + // empty mask means "match everything". This rule will match all packets, no matter what is the ether type + if (desc->ip_id == 2) { + spec_eth->val.ether_type = 0x0806; + spec_eth->mask.ether_type = 0x0000; + goto create_flow; + } +#endif switch (desc->type) { case HASH_RXQ_IPV4: @@ -306,10 +342,10 @@ priv_fdir_flow_add(struct priv *priv, spec_offset += spec_eth->size; /* Set IP spec */ - spec_ipv4 = (struct ibv_exp_flow_spec_ipv4 *)spec_offset; + spec_ipv4 = (struct ibv_exp_flow_spec_ipv4_ext *)spec_offset; /* The second specification must be IP. */ - assert(spec_ipv4->type == IBV_EXP_FLOW_SPEC_IPV4); + assert(spec_ipv4->type == IBV_EXP_FLOW_SPEC_IPV4_EXT); assert(spec_ipv4->size == sizeof(*spec_ipv4)); spec_ipv4->val.src_ip = @@ -319,6 +355,21 @@ priv_fdir_flow_add(struct priv *priv, spec_ipv4->mask.src_ip = mask->ipv4_mask.src_ip; spec_ipv4->mask.dst_ip = mask->ipv4_mask.dst_ip; + /* PROTO */ + spec_ipv4->val.proto = desc->proto & mask->ipv4_mask.proto; + spec_ipv4->mask.proto = mask->ipv4_mask.proto; + +#ifdef TREX_PATCH + /* TOS */ + if (desc->ip_id == 1) { + spec_ipv4->mask.tos = 0x1; + spec_ipv4->val.tos = 0x1; + } else { + spec_ipv4->mask.tos = 0x0; + spec_ipv4->val.tos = 0x0; + } +#endif + /* Update priority */ attr->priority = 1; @@ -333,10 +384,10 @@ priv_fdir_flow_add(struct priv *priv, spec_offset += spec_eth->size; /* Set IP spec */ - spec_ipv6 = (struct ibv_exp_flow_spec_ipv6 *)spec_offset; + spec_ipv6 = (struct ibv_exp_flow_spec_ipv6_ext *)spec_offset; /* The second specification must be IP. */ - assert(spec_ipv6->type == IBV_EXP_FLOW_SPEC_IPV6); + assert(spec_ipv6->type == IBV_EXP_FLOW_SPEC_IPV6_EXT); assert(spec_ipv6->size == sizeof(*spec_ipv6)); for (i = 0; i != RTE_DIM(desc->src_ip); ++i) { @@ -352,6 +403,20 @@ priv_fdir_flow_add(struct priv *priv, mask->ipv6_mask.dst_ip, sizeof(spec_ipv6->mask.dst_ip)); + spec_ipv6->val.next_hdr = desc->proto & mask->ipv6_mask.proto; + spec_ipv6->mask.next_hdr = mask->ipv6_mask.proto; + +#ifdef TREX_PATCH + /* TOS */ + if (desc->ip_id == 1) { + spec_ipv6->mask.traffic_class = 0x1; + spec_ipv6->val.traffic_class = 0x1; + } else { + spec_ipv6->mask.traffic_class = 0; + spec_ipv6->val.traffic_class = 0; + } +#endif + /* Update priority */ attr->priority = 1; @@ -829,8 +894,10 @@ priv_fdir_filter_add(struct priv *priv, /* Duplicate filters are currently unsupported. */ mlx5_fdir_filter = priv_find_filter_in_list(priv, fdir_filter); if (mlx5_fdir_filter != NULL) { +#ifndef TREX_PATCH ERROR("filter already exists"); - return EINVAL; +#endif + return EEXIST; } /* Create new flow director filter. */ @@ -955,9 +1022,11 @@ priv_fdir_filter_delete(struct priv *priv, return 0; } +#ifndef TREX_PATCH ERROR("%p: flow director delete failed, cannot find filter", (void *)priv); - return EINVAL; +#endif + return ENOENT; } /** diff --git a/src/dpdk/drivers/net/mlx5/mlx5_rxq.c b/src/dpdk/drivers/net/mlx5/mlx5_rxq.c index 28e93d3e..c5746fa0 100644 --- a/src/dpdk/drivers/net/mlx5/mlx5_rxq.c +++ b/src/dpdk/drivers/net/mlx5/mlx5_rxq.c @@ -102,7 +102,7 @@ const struct hash_rxq_init hash_rxq_init[] = { ETH_RSS_FRAG_IPV4), .flow_priority = 1, .flow_spec.ipv4 = { - .type = IBV_EXP_FLOW_SPEC_IPV4, + .type = IBV_EXP_FLOW_SPEC_IPV4_EXT, .size = sizeof(hash_rxq_init[0].flow_spec.ipv4), }, .underlayer = &hash_rxq_init[HASH_RXQ_ETH], @@ -140,7 +140,7 @@ const struct hash_rxq_init hash_rxq_init[] = { ETH_RSS_FRAG_IPV6), .flow_priority = 1, .flow_spec.ipv6 = { - .type = IBV_EXP_FLOW_SPEC_IPV6, + .type = IBV_EXP_FLOW_SPEC_IPV6_EXT, .size = sizeof(hash_rxq_init[0].flow_spec.ipv6), }, .underlayer = &hash_rxq_init[HASH_RXQ_ETH], diff --git a/src/dpdk/drivers/net/mlx5/mlx5_rxtx.h b/src/dpdk/drivers/net/mlx5/mlx5_rxtx.h index 5579f89c..f45e3f51 100644 --- a/src/dpdk/drivers/net/mlx5/mlx5_rxtx.h +++ b/src/dpdk/drivers/net/mlx5/mlx5_rxtx.h @@ -178,8 +178,8 @@ struct hash_rxq_init { uint16_t size; } hdr; struct ibv_exp_flow_spec_tcp_udp tcp_udp; - struct ibv_exp_flow_spec_ipv4 ipv4; - struct ibv_exp_flow_spec_ipv6 ipv6; + struct ibv_exp_flow_spec_ipv4_ext ipv4; + struct ibv_exp_flow_spec_ipv6_ext ipv6; struct ibv_exp_flow_spec_eth eth; } flow_spec; /* Flow specification template. */ const struct hash_rxq_init *underlayer; /* Pointer to underlayer. */ diff --git a/src/dpdk/drivers/net/mlx5/mlx5_stats.c b/src/dpdk/drivers/net/mlx5/mlx5_stats.c index f2b5781a..c6087d4e 100644 --- a/src/dpdk/drivers/net/mlx5/mlx5_stats.c +++ b/src/dpdk/drivers/net/mlx5/mlx5_stats.c @@ -44,68 +44,243 @@ #include "mlx5_rxtx.h" #include "mlx5_defs.h" -/** - * DPDK callback to get device statistics. - * - * @param dev - * Pointer to Ethernet device structure. - * @param[out] stats - * Stats structure output buffer. - */ +#include +#include + +static void +mlx5_stats_read_hw(struct rte_eth_dev *dev, + struct rte_eth_stats *stats){ + struct priv *priv = mlx5_get_priv(dev); + struct mlx5_stats_priv * lps = &priv->m_stats; + unsigned int i; + + struct rte_eth_stats tmp = {0}; + struct ethtool_stats *et_stats = (struct ethtool_stats *)lps->et_stats; + struct ifreq ifr; + + et_stats->cmd = ETHTOOL_GSTATS; + et_stats->n_stats = lps->n_stats; + + ifr.ifr_data = (caddr_t) et_stats; + + if (priv_ifreq(priv, SIOCETHTOOL, &ifr) != 0) { + WARN("unable to get statistic values for mlnx5 "); + } + + tmp.ibytes += et_stats->data[lps->inx_rx_vport_unicast_bytes] + + et_stats->data[lps->inx_rx_vport_multicast_bytes] + + et_stats->data[lps->inx_rx_vport_broadcast_bytes]; + + tmp.ipackets += et_stats->data[lps->inx_rx_vport_unicast_packets] + + et_stats->data[lps->inx_rx_vport_multicast_packets] + + et_stats->data[lps->inx_rx_vport_broadcast_packets]; + + tmp.ierrors += (et_stats->data[lps->inx_rx_wqe_err] + + et_stats->data[lps->inx_rx_crc_errors_phy] + + et_stats->data[lps->inx_rx_in_range_len_errors_phy] + + et_stats->data[lps->inx_rx_symbol_err_phy]); + + tmp.obytes += et_stats->data[lps->inx_tx_vport_unicast_bytes] + + et_stats->data[lps->inx_tx_vport_multicast_bytes] + + et_stats->data[lps->inx_tx_vport_broadcast_bytes]; + + tmp.opackets += (et_stats->data[lps->inx_tx_vport_unicast_packets] + + et_stats->data[lps->inx_tx_vport_multicast_packets] + + et_stats->data[lps->inx_tx_vport_broadcast_packets]); + + tmp.oerrors += et_stats->data[lps->inx_tx_errors_phy]; + + /* SW Rx */ + for (i = 0; (i != priv->rxqs_n); ++i) { + struct rxq *rxq = (*priv->rxqs)[i]; + if (rxq) { + tmp.imissed += rxq->stats.idropped; + tmp.rx_nombuf += rxq->stats.rx_nombuf; + } + } + + /*SW Tx */ + for (i = 0; (i != priv->txqs_n); ++i) { + struct txq *txq = (*priv->txqs)[i]; + if (txq) { + tmp.oerrors += txq->stats.odropped; + } + } + + *stats =tmp; +} + +void +mlx5_stats_free(struct rte_eth_dev *dev) +{ + struct priv *priv = mlx5_get_priv(dev); + struct mlx5_stats_priv * lps = &priv->m_stats; + + if ( lps->et_stats ){ + free(lps->et_stats); + lps->et_stats=0; + } +} + + +static void +mlx5_stats_init(struct rte_eth_dev *dev) +{ + struct priv *priv = mlx5_get_priv(dev); + struct mlx5_stats_priv * lps = &priv->m_stats; + struct rte_eth_stats tmp = {0}; + + unsigned int i; + unsigned int idx; + char ifname[IF_NAMESIZE]; + struct ifreq ifr; + + struct ethtool_stats *et_stats = NULL; + struct ethtool_drvinfo drvinfo; + struct ethtool_gstrings *strings = NULL; + unsigned int n_stats, sz_str, sz_stats; + + if (priv_get_ifname(priv, &ifname)) { + WARN("unable to get interface name"); + return; + } + /* How many statistics are available ? */ + drvinfo.cmd = ETHTOOL_GDRVINFO; + ifr.ifr_data = (caddr_t) &drvinfo; + if (priv_ifreq(priv, SIOCETHTOOL, &ifr) != 0) { + WARN("unable to get driver info for %s", ifname); + return; + } + + n_stats = drvinfo.n_stats; + if (n_stats < 1) { + WARN("no statistics available for %s", ifname); + return; + } + lps->n_stats = n_stats; + + /* Allocate memory to grab stat names and values */ + sz_str = n_stats * ETH_GSTRING_LEN; + sz_stats = n_stats * sizeof(uint64_t); + strings = calloc(1, sz_str + sizeof(struct ethtool_gstrings)); + if (!strings) { + WARN("unable to allocate memory for strings"); + return; + } + + et_stats = calloc(1, sz_stats + sizeof(struct ethtool_stats)); + if (!et_stats) { + free(strings); + WARN("unable to allocate memory for stats"); + } + + strings->cmd = ETHTOOL_GSTRINGS; + strings->string_set = ETH_SS_STATS; + strings->len = n_stats; + ifr.ifr_data = (caddr_t) strings; + if (priv_ifreq(priv, SIOCETHTOOL, &ifr) != 0) { + WARN("unable to get statistic names for %s", ifname); + free(strings); + free(et_stats); + return; + } + + for (i = 0; (i != n_stats); ++i) { + + const char * curr_string = (const char*) &(strings->data[i * ETH_GSTRING_LEN]); + + if (!strcmp("rx_vport_unicast_bytes", curr_string)) lps->inx_rx_vport_unicast_bytes = i; + if (!strcmp("rx_vport_multicast_bytes", curr_string)) lps->inx_rx_vport_multicast_bytes = i; + if (!strcmp("rx_vport_broadcast_bytes", curr_string)) lps->inx_rx_vport_broadcast_bytes = i; + + if (!strcmp("rx_vport_unicast_packets", curr_string)) lps->inx_rx_vport_unicast_packets = i; + if (!strcmp("rx_vport_multicast_packets", curr_string)) lps->inx_rx_vport_multicast_packets = i; + if (!strcmp("rx_vport_broadcast_packets", curr_string)) lps->inx_rx_vport_broadcast_packets = i; + + if (!strcmp("tx_vport_unicast_bytes", curr_string)) lps->inx_tx_vport_unicast_bytes = i; + if (!strcmp("tx_vport_multicast_bytes", curr_string)) lps->inx_tx_vport_multicast_bytes = i; + if (!strcmp("tx_vport_broadcast_bytes", curr_string)) lps->inx_tx_vport_broadcast_bytes = i; + + if (!strcmp("tx_vport_unicast_packets", curr_string)) lps->inx_tx_vport_unicast_packets = i; + if (!strcmp("tx_vport_multicast_packets", curr_string)) lps->inx_tx_vport_multicast_packets = i; + if (!strcmp("tx_vport_broadcast_packets", curr_string)) lps->inx_tx_vport_broadcast_packets = i; + + if (!strcmp("rx_wqe_err", curr_string)) lps->inx_rx_wqe_err = i; + if (!strcmp("rx_crc_errors_phy", curr_string)) lps->inx_rx_crc_errors_phy = i; + if (!strcmp("rx_in_range_len_errors_phy", curr_string)) lps->inx_rx_in_range_len_errors_phy = i; + if (!strcmp("rx_symbol_err_phy", curr_string)) lps->inx_rx_symbol_err_phy = i; + + if (!strcmp("tx_errors_phy", curr_string)) lps->inx_tx_errors_phy = i; + } + + lps->et_stats =(void *)et_stats; + + if (!lps->inx_rx_vport_unicast_bytes || + !lps->inx_rx_vport_multicast_bytes || + !lps->inx_rx_vport_broadcast_bytes || + !lps->inx_rx_vport_unicast_packets || + !lps->inx_rx_vport_multicast_packets || + !lps->inx_rx_vport_broadcast_packets || + !lps->inx_tx_vport_unicast_bytes || + !lps->inx_tx_vport_multicast_bytes || + !lps->inx_tx_vport_broadcast_bytes || + !lps->inx_tx_vport_unicast_packets || + !lps->inx_tx_vport_multicast_packets || + !lps->inx_tx_vport_broadcast_packets || + !lps->inx_rx_wqe_err || + !lps->inx_rx_crc_errors_phy || + !lps->inx_rx_in_range_len_errors_phy) { + WARN("Counters are not recognized %s", ifname); + return; + } + + mlx5_stats_read_hw(dev,&tmp); + + /* copy yo shadow at first time */ + lps->m_shadow = tmp; + + free(strings); +} + + +static void +mlx5_stats_diff(struct rte_eth_stats *a, + struct rte_eth_stats *b, + struct rte_eth_stats *c){ + #define MLX5_DIFF(cnt) { a->cnt = (b->cnt - c->cnt); } + + MLX5_DIFF(ipackets); + MLX5_DIFF(opackets); + MLX5_DIFF(ibytes); + MLX5_DIFF(obytes); + MLX5_DIFF(imissed); + + MLX5_DIFF(ierrors); + MLX5_DIFF(oerrors); + MLX5_DIFF(rx_nombuf); +} + + + void mlx5_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { struct priv *priv = mlx5_get_priv(dev); - struct rte_eth_stats tmp = {0}; - unsigned int i; - unsigned int idx; - - priv_lock(priv); - /* Add software counters. */ - for (i = 0; (i != priv->rxqs_n); ++i) { - struct rxq *rxq = (*priv->rxqs)[i]; - - if (rxq == NULL) - continue; - idx = rxq->stats.idx; - if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) { -#ifdef MLX5_PMD_SOFT_COUNTERS - tmp.q_ipackets[idx] += rxq->stats.ipackets; - tmp.q_ibytes[idx] += rxq->stats.ibytes; -#endif - tmp.q_errors[idx] += (rxq->stats.idropped + - rxq->stats.rx_nombuf); - } -#ifdef MLX5_PMD_SOFT_COUNTERS - tmp.ipackets += rxq->stats.ipackets; - tmp.ibytes += rxq->stats.ibytes; -#endif - tmp.ierrors += rxq->stats.idropped; - tmp.rx_nombuf += rxq->stats.rx_nombuf; - } - for (i = 0; (i != priv->txqs_n); ++i) { - struct txq *txq = (*priv->txqs)[i]; - - if (txq == NULL) - continue; - idx = txq->stats.idx; - if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) { -#ifdef MLX5_PMD_SOFT_COUNTERS - tmp.q_opackets[idx] += txq->stats.opackets; - tmp.q_obytes[idx] += txq->stats.obytes; -#endif - tmp.q_errors[idx] += txq->stats.odropped; - } -#ifdef MLX5_PMD_SOFT_COUNTERS - tmp.opackets += txq->stats.opackets; - tmp.obytes += txq->stats.obytes; -#endif - tmp.oerrors += txq->stats.odropped; - } -#ifndef MLX5_PMD_SOFT_COUNTERS - /* FIXME: retrieve and add hardware counters. */ -#endif - *stats = tmp; + + struct mlx5_stats_priv * lps = &priv->m_stats; + priv_lock(priv); + + if (lps->et_stats == NULL) { + mlx5_stats_init(dev); + } + struct rte_eth_stats tmp = {0}; + + mlx5_stats_read_hw(dev,&tmp); + + mlx5_stats_diff(stats, + &tmp, + &lps->m_shadow); + priv_unlock(priv); } @@ -119,26 +294,20 @@ void mlx5_stats_reset(struct rte_eth_dev *dev) { struct priv *priv = dev->data->dev_private; - unsigned int i; - unsigned int idx; - - priv_lock(priv); - for (i = 0; (i != priv->rxqs_n); ++i) { - if ((*priv->rxqs)[i] == NULL) - continue; - idx = (*priv->rxqs)[i]->stats.idx; - (*priv->rxqs)[i]->stats = - (struct mlx5_rxq_stats){ .idx = idx }; - } - for (i = 0; (i != priv->txqs_n); ++i) { - if ((*priv->txqs)[i] == NULL) - continue; - idx = (*priv->txqs)[i]->stats.idx; - (*priv->txqs)[i]->stats = - (struct mlx5_txq_stats){ .idx = idx }; - } -#ifndef MLX5_PMD_SOFT_COUNTERS - /* FIXME: reset hardware counters. */ -#endif + struct mlx5_stats_priv * lps = &priv->m_stats; + + priv_lock(priv); + + if (lps->et_stats == NULL) { + mlx5_stats_init(dev); + } + struct rte_eth_stats tmp = {0}; + + + mlx5_stats_read_hw(dev,&tmp); + + /* copy to shadow */ + lps->m_shadow = tmp; + priv_unlock(priv); } -- cgit 1.2.3-korg