Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev dpdk new counters #82

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
114 changes: 102 additions & 12 deletions dp-core/vr_interface.c
Expand Up @@ -1806,12 +1806,15 @@ vr_interface_add(vr_interface_req *req, bool need_response)
}

static void
vr_interface_make_req(vr_interface_req *req, struct vr_interface *intf)
vr_interface_make_req(vr_interface_req *req, struct vr_interface *intf,
unsigned int core)
{
unsigned int i;
struct vr_interface_stats *stats;
struct vr_interface_settings settings;
int real_core;

req->vifr_core = core;
req->vifr_type = intf->vif_type;
req->vifr_flags = intf->vif_flags;
req->vifr_vrf = intf->vif_vrf;
Expand Down Expand Up @@ -1860,15 +1863,79 @@ vr_interface_make_req(vr_interface_req *req, struct vr_interface *intf)
req->vifr_obytes = 0;
req->vifr_opackets = 0;
req->vifr_oerrors = 0;

for (i = 0; i < vr_num_cpus; i++) {
stats = vif_get_stats(intf, i);
req->vifr_ibytes += stats->vis_ibytes;
req->vifr_ipackets += stats->vis_ipackets;
req->vifr_ierrors += stats->vis_ierrors;
req->vifr_obytes += stats->vis_obytes;
req->vifr_opackets += stats->vis_opackets;
req->vifr_oerrors += stats->vis_oerrors;
req->vifr_ifenqpkts = 0;
req->vifr_ifenqdrops = 0;
req->vifr_ifdeqpkts = 0;
req->vifr_ifdeqdrops = 0;
req->vifr_iftxrngenqpkts = 0;
req->vifr_iftxrngenqdrops = 0;
req->vifr_ifrxrngenqpkts = 0;
req->vifr_ifrxrngenqdrops = 0;

/**
* Implementation of getting per-core vif statistics is based on this
* little trick to avoid making changes in how agent makes requests for
* statistics. From vRouter's and agent's point of view, request for stats
* for 0th core means a request for stats summed up for all the cores.
* So cores are enumerated starting with 1.
* Meanwhile, from user's point of view they are enumerated starting with 0
* (e.g. vif --list --core 0 means 'vif stats for the very first (0th)
* core'). This is how Linux enumerates CPUs, so it should be more
* intuitive for the user.
*
* Agent is not aware of possibility of asking for per-core stats. Its
* requests have vifr_core implicitly set to 0. So we need to make a
* conversion between those enumerating systems. The vif utility increments
* by 1 the core number user asked for. Then this modified requests comes
* here. See the comment below.
*/
if (req->vifr_core == 0) { /* user or agent wants summed up stats */
for (i = 0; i < vr_num_cpus; i++) {
stats = vif_get_stats(intf, i);
req->vifr_ibytes += stats->vis_ibytes;
req->vifr_ipackets += stats->vis_ipackets;
req->vifr_ierrors += stats->vis_ierrors;
req->vifr_obytes += stats->vis_obytes;
req->vifr_opackets += stats->vis_opackets;
req->vifr_oerrors += stats->vis_oerrors;
req->vifr_ifenqpkts += stats->vis_ifenqpkts;
req->vifr_ifdeqpkts += stats->vis_ifdeqpkts;
req->vifr_ifdeqdrops += stats->vis_ifdeqdrops;
req->vifr_ifenqdrops += stats->vis_ifenqdrops;
req->vifr_iftxrngenqpkts += stats->vis_iftxrngenqpkts;
req->vifr_iftxrngenqdrops += stats->vis_iftxrngenqdrops;
req->vifr_ifrxrngenqpkts += stats->vis_ifrxrngenqpkts;
req->vifr_ifrxrngenqdrops += stats->vis_ifrxrngenqdrops;
}
/* user wants stats for a specific core */
} else if (req->vifr_core > 0 && req->vifr_core <= vr_num_cpus) {
/**
* real_core is what user really asks for.
* If a request came for stats for 1st core, it means user
* asked for 0th core. If request was made for 2nd, user wanted
* the 1st, and so on.
*
* TODO: This would be much simplier if agent could explicitly ask
* for stats for 'minus 1st' core, meaning 'all the cores'.
*/
real_core = req->vifr_core;
real_core--;
stats = vif_get_stats(intf, real_core);

req->vifr_ibytes = stats->vis_ibytes;
req->vifr_ipackets = stats->vis_ipackets;
req->vifr_ierrors = stats->vis_ierrors;
req->vifr_obytes = stats->vis_obytes;
req->vifr_opackets = stats->vis_opackets;
req->vifr_oerrors = stats->vis_oerrors;
req->vifr_ifenqpkts = stats->vis_ifenqpkts;
req->vifr_ifenqdrops = stats->vis_ifenqdrops;
req->vifr_ifdeqpkts = stats->vis_ifdeqpkts;
req->vifr_ifdeqdrops = stats->vis_ifdeqdrops;
req->vifr_iftxrngenqpkts = stats->vis_iftxrngenqpkts;
req->vifr_iftxrngenqdrops = stats->vis_iftxrngenqdrops;
req->vifr_ifrxrngenqpkts = stats->vis_ifrxrngenqpkts;
req->vifr_ifrxrngenqdrops = stats->vis_ifrxrngenqdrops;
}

req->vifr_speed = -1;
Expand Down Expand Up @@ -1935,6 +2002,18 @@ vr_interface_get(vr_interface_req *req)
struct vr_interface *vif = NULL;
struct vrouter *router;
vr_interface_req *resp = NULL;
unsigned int core;

/**
* Check if requested core number is sane. If not, let's assume the
* request was made for summed up stats for all the cores.
*/
if (req->vifr_core > 0 && req->vifr_core <= vr_num_cpus) {
core = req->vifr_core;
} else {
core = 0;
}


router = vrouter_get(req->vifr_rid);
if (!router) {
Expand All @@ -1954,7 +2033,7 @@ vr_interface_get(vr_interface_req *req)
goto generate_response;
}

vr_interface_make_req(resp, vif);
vr_interface_make_req(resp, vif, core);
} else
ret = -ENOENT;

Expand All @@ -1974,8 +2053,19 @@ vr_interface_dump(vr_interface_req *r)
vr_interface_req *resp = NULL;
struct vr_interface *vif;
struct vrouter *router = vrouter_get(r->vifr_vrf);
unsigned int core;
struct vr_message_dumper *dumper = NULL;

/**
* Check if requested core number is sane. If not, let's assume the
* request was made for summed up stats for all the cores.
*/
if (r->vifr_core > 0 && r->vifr_core <= vr_num_cpus) {
core = r->vifr_core;
} else {
core = 0;
}

if (!router && (ret = -ENODEV))
goto generate_response;

Expand All @@ -1998,7 +2088,7 @@ vr_interface_dump(vr_interface_req *r)
i < router->vr_max_interfaces; i++) {
vif = router->vr_interfaces[i];
if (vif) {
vr_interface_make_req(resp, vif);
vr_interface_make_req(resp, vif, core);
ret = vr_message_dump_object(dumper, VR_INTERFACE_OBJECT_ID, resp);
if (ret <= 0)
break;
Expand Down
19 changes: 19 additions & 0 deletions dpdk/vr_dpdk_interface.c
Expand Up @@ -23,6 +23,9 @@
#include <rte_ethdev.h>
#include <rte_ip.h>

extern struct vr_interface_stats *vif_get_stats(struct vr_interface *,
unsigned short);

/*
* dpdk_virtual_if_add - add a virtual (virtio) interface to vrouter.
* Returns 0 on success, < 0 otherwise.
Expand Down Expand Up @@ -830,6 +833,8 @@ dpdk_if_tx(struct vr_interface *vif, struct vr_packet *pkt)
struct vr_dpdk_queue *tx_queue = &lcore->lcore_tx_queues[vif_idx];
struct vr_dpdk_queue *monitoring_tx_queue;
struct vr_packet *p_clone;
struct rte_port_out_stats port_stats;
struct vr_interface_stats *vr_stats;
int ret;

RTE_LOG(DEBUG, VROUTER,"%s: TX packet to interface %s\n", __func__,
Expand All @@ -854,10 +859,14 @@ dpdk_if_tx(struct vr_interface *vif, struct vr_packet *pkt)

if (unlikely(vif->vif_type == VIF_TYPE_AGENT)) {
ret = rte_ring_mp_enqueue(vr_dpdk.packet_ring, m);
vr_stats = vif_get_stats(vif, lcore_id);
if (ret != 0) {
/* TODO: a separate counter for this drop */
vif_drop_pkt(vif, vr_dpdk_mbuf_to_pkt(m), 0);
vr_stats->vis_iftxrngenqdrops++;
return -1;
} else {
vr_stats->vis_iftxrngenqpkts++;
}
#ifdef VR_DPDK_TX_PKT_DUMP
#ifdef VR_DPDK_PKT_DUMP_VIF_FILTER
Expand Down Expand Up @@ -927,13 +936,17 @@ dpdk_if_tx(struct vr_interface *vif, struct vr_packet *pkt)
rte_pktmbuf_dump(stdout, m, 0x60);
#endif

vr_stats = vif_get_stats(vif, lcore_id);
if (likely(tx_queue->txq_ops.f_tx != NULL)) {
tx_queue->txq_ops.f_tx(tx_queue->q_queue_h, m);
if (lcore_id == VR_DPDK_PACKET_LCORE_ID)
tx_queue->txq_ops.f_flush(tx_queue->q_queue_h);

dpdk_port_out_stats_update(tx_queue, &port_stats, vr_stats);
} else {
RTE_LOG(DEBUG, VROUTER,"%s: error TXing to interface %s: no queue for lcore %u\n",
__func__, vif->vif_name, lcore_id);
vr_stats->vis_ifenqdrops++;
vif_drop_pkt(vif, vr_dpdk_mbuf_to_pkt(m), 0);
return -1;
}
Expand All @@ -951,6 +964,8 @@ dpdk_if_rx(struct vr_interface *vif, struct vr_packet *pkt)
struct vr_dpdk_queue *tx_queue = &lcore->lcore_tx_queues[vif_idx];
struct vr_dpdk_queue *monitoring_tx_queue;
struct vr_packet *p_clone;
struct rte_port_out_stats port_stats;
struct vr_interface_stats *vr_stats;

RTE_LOG(DEBUG, VROUTER,"%s: TX packet to interface %s\n", __func__,
vif->vif_name);
Expand Down Expand Up @@ -979,11 +994,15 @@ dpdk_if_rx(struct vr_interface *vif, struct vr_packet *pkt)
rte_pktmbuf_dump(stdout, m, 0x60);
#endif

vr_stats = vif_get_stats(vif, lcore_id);
if (likely(tx_queue->txq_ops.f_tx != NULL)) {
tx_queue->txq_ops.f_tx(tx_queue->q_queue_h, m);

dpdk_port_out_stats_update(tx_queue, &port_stats, vr_stats);
} else {
RTE_LOG(DEBUG, VROUTER,"%s: error TXing to interface %s: no queue for lcore %u\n",
__func__, vif->vif_name, lcore_id);
vr_stats->vis_ifenqdrops++;
vif_drop_pkt(vif, vr_dpdk_mbuf_to_pkt(m), 0);
return -1;
}
Expand Down
74 changes: 73 additions & 1 deletion dpdk/vr_dpdk_knidev.c
Expand Up @@ -23,7 +23,23 @@
/*
* KNI Reader
*/
#if DPDK_KNIDEV_READER_STATS_COLLECT == 1

#define DPDK_KNIDEV_READER_STATS_PKTS_IN_ADD(port, val) \
port->stats.n_pkts_in += val
#define DPDK_KNIDEV_READER_STATS_PKTS_DROP_ADD(port, val) \
port->stats.n_pkts_drop += val

#else

#define DPDK_KNIDEV_READER_STATS_PKTS_IN_ADD(port, val)
#define DPDK_KNIDEV_READER_STATS_PKTS_DROP_ADD(port, val)

#endif

struct dpdk_knidev_reader {
struct rte_port_in_stats stats;

struct rte_kni *kni;
};

Expand Down Expand Up @@ -64,8 +80,12 @@ dpdk_knidev_reader_rx(void *port, struct rte_mbuf **pkts, uint32_t n_pkts)
{
struct dpdk_knidev_reader *p =
(struct dpdk_knidev_reader *) port;
uint32_t nb_rx;

return rte_kni_rx_burst(p->kni, pkts, n_pkts);
nb_rx = rte_kni_rx_burst(p->kni, pkts, n_pkts);
DPDK_KNIDEV_READER_STATS_PKTS_IN_ADD(p, nb_rx);

return nb_rx;
}

static int
Expand All @@ -81,10 +101,42 @@ dpdk_knidev_reader_free(void *port)
return 0;
}

static int
dpdk_knidev_reader_stats_read(void *port,
struct rte_port_in_stats *stats, int clear)
{
struct dpdk_knidev_reader *p =
(struct dpdk_knidev_reader *) port;

if (stats != NULL)
memcpy(stats, &p->stats, sizeof(p->stats));

if (clear)
memset(&p->stats, 0, sizeof(p->stats));

return 0;
}

/*
* KNI Writer
*/
#if DPDK_KNIDEV_WRITER_STATS_COLLECT == 1

#define DPDK_KNIDEV_WRITER_STATS_PKTS_IN_ADD(port, val) \
port->stats.n_pkts_in += val
#define DPDK_KNIDEV_WRITER_STATS_PKTS_DROP_ADD(port, val) \
port->stats.n_pkts_drop += val

#else

#define DPDK_KNIDEV_WRITER_STATS_PKTS_IN_ADD(port, val)
#define DPDK_KNIDEV_WRITER_STATS_PKTS_DROP_ADD(port, val)

#endif

struct dpdk_knidev_writer {
struct rte_port_out_stats stats;

struct rte_mbuf *tx_buf[2 * RTE_PORT_IN_BURST_SIZE_MAX];
uint32_t tx_burst_sz;
uint16_t tx_buf_count;
Expand Down Expand Up @@ -139,6 +191,7 @@ send_burst(struct dpdk_knidev_writer *p)

nb_tx = rte_kni_tx_burst(p->kni, p->tx_buf, p->tx_buf_count);

DPDK_KNIDEV_WRITER_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - nb_tx);
for ( ; nb_tx < p->tx_buf_count; nb_tx++)
/* TODO: a separate counter for this drop */
vr_dpdk_pfree(p->tx_buf[nb_tx], VP_DROP_INTERFACE_DROP);
Expand All @@ -152,6 +205,7 @@ dpdk_knidev_writer_tx(void *port, struct rte_mbuf *pkt)
struct dpdk_knidev_writer *p = (struct dpdk_knidev_writer *) port;

p->tx_buf[p->tx_buf_count++] = pkt;
DPDK_KNIDEV_WRITER_STATS_PKTS_IN_ADD(p, 1);
if (p->tx_buf_count >= p->tx_burst_sz)
send_burst(p);

Expand Down Expand Up @@ -183,13 +237,30 @@ dpdk_knidev_writer_free(void *port)
return 0;
}

static int
dpdk_knidev_writer_stats_read(void *port,
struct rte_port_out_stats *stats, int clear)
{
struct dpdk_knidev_writer *p =
(struct dpdk_knidev_writer *) port;

if (stats != NULL)
memcpy(stats, &p->stats, sizeof(p->stats));

if (clear)
memset(&p->stats, 0, sizeof(p->stats));

return 0;
}

/*
* Summary of KNI operations
*/
struct rte_port_in_ops dpdk_knidev_reader_ops = {
.f_create = dpdk_knidev_reader_create,
.f_free = dpdk_knidev_reader_free,
.f_rx = dpdk_knidev_reader_rx,
.f_stats = dpdk_knidev_reader_stats_read,
};

struct rte_port_out_ops dpdk_knidev_writer_ops = {
Expand All @@ -198,6 +269,7 @@ struct rte_port_out_ops dpdk_knidev_writer_ops = {
.f_tx = dpdk_knidev_writer_tx,
.f_tx_bulk = NULL, /* TODO: not implemented */
.f_flush = dpdk_knidev_writer_flush,
.f_stats = dpdk_knidev_writer_stats_read,
};

/* Release KNI RX queue */
Expand Down