netmap: bridge: improve readability

Multiple cosmetic changes, plus a fix to a verbose print
(indicating wrong net->host/host->net direction).

MFC after:	3 days
This commit is contained in:
Vincenzo Maffione 2020-11-22 13:39:21 +00:00
parent 9fd3f663da
commit 7ebc0ac4c9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=367936

View file

@ -3,19 +3,19 @@
*
* BSD license
*
* A netmap client to bridge two network interfaces
* (or one interface and the host stack).
* A netmap application to bridge two network interfaces,
* or one interface and the host stack.
*
* $FreeBSD$
*/
#include <libnetmap.h>
#include <signal.h>
#include <stdio.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <libnetmap.h>
static int verbose = 0;
@ -32,30 +32,39 @@ sigint_h(int sig)
/*
* how many packets on this set of queues ?
* How many slots do we (user application) have on this
* set of queues ?
*/
static int
pkt_queued(struct nmport_d *d, int tx)
rx_slots_avail(struct nmport_d *d)
{
u_int i, tot = 0;
if (tx) {
for (i = d->first_tx_ring; i <= d->last_tx_ring; i++) {
tot += nm_ring_space(NETMAP_TXRING(d->nifp, i));
}
} else {
for (i = d->first_rx_ring; i <= d->last_rx_ring; i++) {
tot += nm_ring_space(NETMAP_RXRING(d->nifp, i));
}
for (i = d->first_rx_ring; i <= d->last_rx_ring; i++) {
tot += nm_ring_space(NETMAP_RXRING(d->nifp, i));
}
return tot;
}
static int
tx_slots_avail(struct nmport_d *d)
{
u_int i, tot = 0;
for (i = d->first_tx_ring; i <= d->last_tx_ring; i++) {
tot += nm_ring_space(NETMAP_TXRING(d->nifp, i));
}
return tot;
}
/*
* move up to 'limit' pkts from rxring to txring swapping buffers.
* Move up to 'limit' pkts from rxring to txring, swapping buffers
* if zerocopy is possible. Otherwise fall back on packet copying.
*/
static int
process_rings(struct netmap_ring *rxring, struct netmap_ring *txring,
rings_move(struct netmap_ring *rxring, struct netmap_ring *txring,
u_int limit, const char *msg)
{
u_int j, k, m = 0;
@ -63,7 +72,7 @@ process_rings(struct netmap_ring *rxring, struct netmap_ring *txring,
/* print a warning if any of the ring flags is set (e.g. NM_REINIT) */
if (rxring->flags || txring->flags)
D("%s rxflags %x txflags %x",
msg, rxring->flags, txring->flags);
msg, rxring->flags, txring->flags);
j = rxring->head; /* RX */
k = txring->head; /* TX */
m = nm_ring_space(rxring);
@ -79,16 +88,18 @@ process_rings(struct netmap_ring *rxring, struct netmap_ring *txring,
/* swap packets */
if (ts->buf_idx < 2 || rs->buf_idx < 2) {
RD(5, "wrong index rx[%d] = %d -> tx[%d] = %d",
j, rs->buf_idx, k, ts->buf_idx);
RD(2, "wrong index rxr[%d] = %d -> txr[%d] = %d",
j, rs->buf_idx, k, ts->buf_idx);
sleep(2);
}
/* copy the packet length. */
if (rs->len > rxring->nr_buf_size) {
RD(5, "wrong len %d rx[%d] -> tx[%d]", rs->len, j, k);
RD(2, "%s: invalid len %u, rxr[%d] -> txr[%d]",
msg, rs->len, j, k);
rs->len = 0;
} else if (verbose > 1) {
D("%s send len %d rx[%d] -> tx[%d]", msg, rs->len, j, k);
D("%s: fwd len %u, rx[%d] -> tx[%d]",
msg, rs->len, j, k);
}
ts->len = rs->len;
if (zerocopy) {
@ -111,24 +122,23 @@ process_rings(struct netmap_ring *rxring, struct netmap_ring *txring,
rxring->head = rxring->cur = j;
txring->head = txring->cur = k;
if (verbose && m > 0)
D("%s sent %d packets to %p", msg, m, txring);
D("%s fwd %d packets: rxring %u --> txring %u",
msg, m, rxring->ringid, txring->ringid);
return (m);
}
/* move packts from src to destination */
/* Move packets from source port to destination port. */
static int
move(struct nmport_d *src, struct nmport_d *dst, u_int limit)
ports_move(struct nmport_d *src, struct nmport_d *dst, u_int limit,
const char *msg)
{
struct netmap_ring *txring, *rxring;
u_int m = 0, si = src->first_rx_ring, di = dst->first_tx_ring;
const char *msg = (src->reg.nr_flags == NR_REG_SW) ?
"host->net" : "net->host";
while (si <= src->last_rx_ring && di <= dst->last_tx_ring) {
rxring = NETMAP_RXRING(src->nifp, si);
txring = NETMAP_TXRING(dst->nifp, di);
ND("txring %p rxring %p", txring, rxring);
if (nm_ring_empty(rxring)) {
si++;
continue;
@ -137,7 +147,7 @@ move(struct nmport_d *src, struct nmport_d *dst, u_int limit)
di++;
continue;
}
m += process_rings(rxring, txring, limit, msg);
m += rings_move(rxring, txring, limit, msg);
}
return (m);
@ -149,7 +159,7 @@ usage(void)
{
fprintf(stderr,
"netmap bridge program: forward packets between two "
"network interfaces\n"
"netmap ports\n"
" usage(1): bridge [-v] [-i ifa] [-i ifb] [-b burst] "
"[-w wait_time] [-L]\n"
" usage(2): bridge [-v] [-w wait_time] [-L] "
@ -161,6 +171,11 @@ usage(void)
" is not specified, otherwise loopback traffic on ifa.\n"
"\n"
" example: bridge -w 10 -i netmap:eth3 -i netmap:eth1\n"
"\n"
" If ifa and ifb are two interfaces, they must be in\n"
" promiscuous mode. Otherwise, if bridging with the \n"
" host stack, the interface must have the offloads \n"
" disabled.\n"
);
exit(1);
}
@ -175,13 +190,15 @@ usage(void)
int
main(int argc, char **argv)
{
char msg_a2b[128], msg_b2a[128];
struct pollfd pollfd[2];
int ch;
u_int burst = 1024, wait_link = 4;
struct nmport_d *pa = NULL, *pb = NULL;
char *ifa = NULL, *ifb = NULL;
char ifabuf[64] = { 0 };
int pa_sw_rings, pb_sw_rings;
int loopback = 0;
int ch;
fprintf(stderr, "%s built %s %s\n\n", argv[0], __DATE__, __TIME__);
@ -281,14 +298,27 @@ main(int argc, char **argv)
pa->hdr.nr_name, pa->first_rx_ring, pa->reg.nr_rx_rings,
pb->hdr.nr_name, pb->first_rx_ring, pb->reg.nr_rx_rings);
pa_sw_rings = (pa->reg.nr_mode == NR_REG_SW ||
pa->reg.nr_mode == NR_REG_ONE_SW);
pb_sw_rings = (pb->reg.nr_mode == NR_REG_SW ||
pb->reg.nr_mode == NR_REG_ONE_SW);
snprintf(msg_a2b, sizeof(msg_a2b), "%s:%s --> %s:%s",
pa->hdr.nr_name, pa_sw_rings ? "host" : "nic",
pb->hdr.nr_name, pb_sw_rings ? "host" : "nic");
snprintf(msg_b2a, sizeof(msg_b2a), "%s:%s --> %s:%s",
pb->hdr.nr_name, pb_sw_rings ? "host" : "nic",
pa->hdr.nr_name, pa_sw_rings ? "host" : "nic");
/* main loop */
signal(SIGINT, sigint_h);
while (!do_abort) {
int n0, n1, ret;
pollfd[0].events = pollfd[1].events = 0;
pollfd[0].revents = pollfd[1].revents = 0;
n0 = pkt_queued(pa, 0);
n1 = pkt_queued(pb, 0);
n0 = rx_slots_avail(pa);
n1 = rx_slots_avail(pb);
#if defined(_WIN32) || defined(BUSYWAIT)
if (n0) {
ioctl(pollfd[1].fd, NIOCTXSYNC, NULL);
@ -322,35 +352,37 @@ main(int argc, char **argv)
ret <= 0 ? "timeout" : "ok",
pollfd[0].events,
pollfd[0].revents,
pkt_queued(pa, 0),
rx_slots_avail(pa),
NETMAP_RXRING(pa->nifp, pa->cur_rx_ring)->head,
pkt_queued(pa, 1),
tx_slots_avail(pa),
pollfd[1].events,
pollfd[1].revents,
pkt_queued(pb, 0),
rx_slots_avail(pb),
NETMAP_RXRING(pb->nifp, pb->cur_rx_ring)->head,
pkt_queued(pb, 1)
tx_slots_avail(pb)
);
if (ret < 0)
continue;
if (pollfd[0].revents & POLLERR) {
struct netmap_ring *rx = NETMAP_RXRING(pa->nifp, pa->cur_rx_ring);
D("error on fd0, rx [%d,%d,%d)",
rx->head, rx->cur, rx->tail);
rx->head, rx->cur, rx->tail);
}
if (pollfd[1].revents & POLLERR) {
struct netmap_ring *rx = NETMAP_RXRING(pb->nifp, pb->cur_rx_ring);
D("error on fd1, rx [%d,%d,%d)",
rx->head, rx->cur, rx->tail);
rx->head, rx->cur, rx->tail);
}
if (pollfd[0].revents & POLLOUT)
move(pb, pa, burst);
ports_move(pb, pa, burst, msg_b2a);
if (pollfd[1].revents & POLLOUT)
move(pa, pb, burst);
ports_move(pa, pb, burst, msg_a2b);
/* We don't need ioctl(NIOCTXSYNC) on the two file descriptors here,
* kernel will txsync on next poll(). */
/*
* We don't need ioctl(NIOCTXSYNC) on the two file descriptors.
* here. The kernel will txsync on next poll().
*/
}
nmport_close(pb);
nmport_close(pa);