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 4 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
72 changes: 60 additions & 12 deletions dp-core/vr_interface.c
Expand Up @@ -1806,12 +1806,14 @@ 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, short core)
{
unsigned int i;
struct vr_interface_stats *stats;
struct vr_interface_settings settings;
short 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 +1862,50 @@ 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_iftxrngenqpkts = 0;
req->vifr_iftxrngenqdrops = 0;
req->vifr_ifdeqpkts = 0;
req->vifr_ifdeqdrops = 0;
req->vifr_ifrxenqpkts = 0;
req->vifr_ifrxenqdrops = 0;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to vifr_ifrxrng as you suggested.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


if (req->vifr_core == 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 += stats->vis_ifenqpkts;
req->vifr_ifenqdrops += stats->vis_ifenqdrops;
req->vifr_iftxrngenqpkts += stats->vis_iftxrngenqpkts;
req->vifr_iftxrngenqdrops += stats->vis_iftxrngenqdrops;
req->vifr_ifdeqpkts += stats->vis_ifdeqpkts;
req->vifr_ifdeqdrops += stats->vis_ifdeqdrops;
req->vifr_ifrxenqpkts += stats->vis_ifrxenqpkts;
req->vifr_ifrxenqdrops += stats->vis_ifrxenqdrops;
}
} else if (req->vifr_core > 0) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be safe, also check for vifr_core <= MAX.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can get to vr_interface_make_req() either from vr_interface_get() or vr_interface_dump(). They both perform validation for vifr_core not to exceed maximum value. vr_interface_make_req() itself checks only if we want summed up stats or per-core. The vifr_core value is always sane there.

real_core = req->vifr_core - 1;
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_iftxrngenqpkts += stats->vis_iftxrngenqpkts;
req->vifr_iftxrngenqdrops += stats->vis_iftxrngenqdrops;
req->vifr_ifdeqpkts += stats->vis_ifdeqpkts;
req->vifr_ifdeqdrops += stats->vis_ifdeqdrops;
req->vifr_ifrxenqpkts += stats->vis_ifrxenqpkts;
req->vifr_ifrxenqdrops += stats->vis_ifrxenqdrops;
}

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

if (req->vifr_core <= vr_num_cpus)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also check for vifr_core > 0

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

core = req->vifr_core;
else
core = 0;


router = vrouter_get(req->vifr_rid);
if (!router) {
Expand All @@ -1954,7 +1998,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 +2018,12 @@ vr_interface_dump(vr_interface_req *r)
vr_interface_req *resp = NULL;
struct vr_interface *vif;
struct vrouter *router = vrouter_get(r->vifr_vrf);
short core = r->vifr_core;
struct vr_message_dumper *dumper = NULL;

if ((unsigned int)core > vr_num_cpus)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be conststeny, change to "if ((core < 0) || (core > vr_num_cpus))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did it like this: if (r->vifr_core > 0 && r->vifr_core <= (int)vr_num_cpus) => sane; else => core = 0; The same in vr_interface_get().

goto generate_response;

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

Expand All @@ -1998,7 +2046,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
52 changes: 52 additions & 0 deletions dpdk/vr_dpdk_interface.c
Expand Up @@ -22,6 +22,10 @@
#include <rte_errno.h>
#include <rte_ethdev.h>
#include <rte_ip.h>
#include <rte_port_ring.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.
Expand Down Expand Up @@ -830,6 +834,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 +860,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 +937,34 @@ dpdk_if_tx(struct vr_interface *vif, struct vr_packet *pkt)
rte_pktmbuf_dump(stdout, m, 0x60);
#endif

vr_stats = vif_get_stats(tx_queue->q_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);

/**
* Update counters for:
* - packets enqueued to the interface successfully.
* - packets which have been dropped when .f_tx() could not send.
* If we write to ring instead of NIC's queue, count it as a ring
* enqueue.
*/
if (likely(tx_queue->txq_ops.f_stats != NULL)) {
tx_queue->txq_ops.f_stats(tx_queue->q_queue_h, &port_stats, 0);

if (tx_queue->txq_ops.f_tx == rte_port_ring_writer_ops.f_tx) {
vr_stats->vis_iftxrngenqpkts = port_stats.n_pkts_in;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

n_pkts_out would be better (instead of n_pkts_in), but it looks like this is what the DPDK patch has...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, currently n_pkts_in is in both reader and writer stats structures.

vr_stats->vis_iftxrngenqdrops = port_stats.n_pkts_drop;
} else {
vr_stats->vis_ifenqpkts = port_stats.n_pkts_in;
vr_stats->vis_ifenqdrops = port_stats.n_pkts_drop;
}
}
} 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 +982,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 +1012,30 @@ dpdk_if_rx(struct vr_interface *vif, struct vr_packet *pkt)
rte_pktmbuf_dump(stdout, m, 0x60);
#endif

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

/**
* Update counters for:
* - packets enqueued to the interface successfully.
* - packets which have been dropped when .f_tx() could not send.
*/
if (likely(tx_queue->txq_ops.f_stats != NULL)) {
tx_queue->txq_ops.f_stats(tx_queue->q_queue_h, &port_stats, 0);

if (tx_queue->txq_ops.f_tx == rte_port_ring_writer_ops.f_tx) {
vr_stats->vis_iftxrngenqpkts = port_stats.n_pkts_in;
vr_stats->vis_iftxrngenqdrops = port_stats.n_pkts_drop;
} else {
vr_stats->vis_ifenqpkts = port_stats.n_pkts_in;
vr_stats->vis_ifenqdrops = port_stats.n_pkts_drop;
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MIght be good to put the above code in an inline function as it is called in multiple places.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Two functions: one to work with rte_port_out_stats, the other with rte_port_in_stats. Put them in vr_dpdk.h (not sure if good place).

} 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