netmap: add man page for the bridge program

Added bridge(8).
Also, minor fixes to the netmap "bridge" application:
 - indentation fixes and code cleanup
 - better usage description
 - better processing of netmap flags

Reviewed by:	0mp
Approved by:	gnn (mentor)
MFC after:	3 days
Differential Revision:	https://reviews.freebsd.org/D17664
This commit is contained in:
Vincenzo Maffione 2018-10-23 15:34:43 +00:00
parent 8b7db46557
commit 1a7d3c055b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=339659
4 changed files with 149 additions and 44 deletions

View File

@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd March 2, 2017
.Dd October 23, 2018
.Dt NETMAP 4
.Os
.Sh NAME
@ -1073,6 +1073,9 @@ Other
clients attached to the same switch can now communicate
with the network card or the host.
.Sh SEE ALSO
.Xr pkt-gen 8 ,
.Xr bridge 8
.Pp
.Pa http://info.iet.unipi.it/~luigi/netmap/
.Pp
Luigi Rizzo, Revisiting network I/O APIs: the netmap framework,

View File

@ -0,0 +1,82 @@
.\" Copyright (c) 2016 Luigi Rizzo, Universita` di Pisa
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. 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.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
.\"
.\" $FreeBSD$
.\"
.Dd October 23, 2018
.Dt BRIDGE 8
.Os
.Sh NAME
.Nm bridge
.Nd netmap client to bridge two netmap ports
.Sh SYNOPSIS
.Bk -words
.Bl -tag -width "bridge"
.It Nm
.Op Fl i Ar port
.Op Fl b Ar batch size
.Op Fl w Ar wait-link
.Op Fl v
.Op Fl c
.El
.Ek
.Sh DESCRIPTION
.Nm
is a simple netmap application that bridges packets between two netmap ports.
If the two netmap ports use the same netmap memory region
.Nm
forwards packets without copying the packets payload (zero-copy mode), unless
explicitly prevented by the
.Fl c
flag.
.Bl -tag -width Ds
.It Fl i Ar port
Name of the netmap port.
It can be supplied up to two times to identify the ports that must be bridged.
Any netmap port type (physical interface, VALE switch, pipe, monitor port...)
can be used.
If the option is supplied only once, then it must be for a physical interface and, in that case,
.Nm
will bridge the port and the host stack.
.It Fl b Ar batch-size
Maximum number of packets to send in one operation.
.It Fl w Ar wait-link
indicates the number of seconds to wait before transmitting.
It defaults to 2, and may be useful when talking to physical
ports to let link negotiation complete before starting transmission.
.It Fl v
Enable verbose mode
.It Fl c
Disable zero-copy mode.
.El
.Sh SEE ALSO
.Xr netmap 4 ,
.Xr pkt-gen 8
.Sh AUTHORS
.An -nosplit
.Nm
has been written by
.An Luigi Rizzo
and
.An Matteo Landi
at the Universita` di Pisa, Italy.

View File

@ -34,18 +34,18 @@ sigint_h(int sig)
int
pkt_queued(struct nm_desc *d, int tx)
{
u_int i, tot = 0;
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));
}
}
return tot;
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));
}
}
return tot;
}
/*
@ -76,13 +76,13 @@ process_rings(struct netmap_ring *rxring, struct netmap_ring *txring,
/* swap packets */
if (ts->buf_idx < 2 || rs->buf_idx < 2) {
D("wrong index rx[%d] = %d -> tx[%d] = %d",
RD(5, "wrong index rx[%d] = %d -> tx[%d] = %d",
j, rs->buf_idx, k, ts->buf_idx);
sleep(2);
}
/* copy the packet length. */
if (rs->len > 2048) {
D("wrong len %d rx[%d] -> tx[%d]", rs->len, j, k);
if (rs->len > rxring->nr_buf_size) {
RD(5, "wrong len %d rx[%d] -> tx[%d]", 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);
@ -95,6 +95,8 @@ process_rings(struct netmap_ring *rxring, struct netmap_ring *txring,
/* report the buffer change. */
ts->flags |= NS_BUF_CHANGED;
rs->flags |= NS_BUF_CHANGED;
/* copy the NS_MOREFRAG */
rs->flags = (rs->flags & ~NS_MOREFRAG) | (ts->flags & NS_MOREFRAG);
} else {
char *rxbuf = NETMAP_BUF(rxring, rs->buf_idx);
char *txbuf = NETMAP_BUF(txring, ts->buf_idx);
@ -117,7 +119,7 @@ move(struct nm_desc *src, struct nm_desc *dst, u_int limit)
{
struct netmap_ring *txring, *rxring;
u_int m = 0, si = src->first_rx_ring, di = dst->first_tx_ring;
const char *msg = (src->req.nr_ringid & NETMAP_SW_RING) ?
const char *msg = (src->req.nr_flags == NR_REG_SW) ?
"host->net" : "net->host";
while (si <= src->last_rx_ring && di <= dst->last_tx_ring) {
@ -143,7 +145,20 @@ static void
usage(void)
{
fprintf(stderr,
"usage: bridge [-v] [-i ifa] [-i ifb] [-b burst] [-w wait_time] [ifa [ifb [burst]]]\n");
"netmap bridge program: forward packets between two "
"network interfaces\n"
" usage(1): bridge [-v] [-i ifa] [-i ifb] [-b burst] "
"[-w wait_time] [-L]\n"
" usage(2): bridge [-v] [-w wait_time] [-L] "
"[ifa [ifb [burst]]]\n"
"\n"
" ifa and ifb are specified using the nm_open() syntax.\n"
" When ifb is missing (or is equal to ifa), bridge will\n"
" forward between between ifa and the host stack if -L\n"
" is not specified, otherwise loopback traffic on ifa.\n"
"\n"
" example: bridge -w 10 -i netmap:eth3 -i netmap:eth1\n"
);
exit(1);
}
@ -163,14 +178,16 @@ main(int argc, char **argv)
struct nm_desc *pa = NULL, *pb = NULL;
char *ifa = NULL, *ifb = NULL;
char ifabuf[64] = { 0 };
int loopback = 0;
fprintf(stderr, "%s built %s %s\n",
argv[0], __DATE__, __TIME__);
fprintf(stderr, "%s built %s %s\n\n", argv[0], __DATE__, __TIME__);
while ( (ch = getopt(argc, argv, "b:ci:vw:")) != -1) {
while ((ch = getopt(argc, argv, "hb:ci:vw:L")) != -1) {
switch (ch) {
default:
D("bad option %c %s", ch, optarg);
/* fallthrough */
case 'h':
usage();
break;
case 'b': /* burst */
@ -194,6 +211,9 @@ main(int argc, char **argv)
case 'w':
wait_link = atoi(optarg);
break;
case 'L':
loopback = 1;
break;
}
}
@ -222,9 +242,13 @@ main(int argc, char **argv)
wait_link = 4;
}
if (!strcmp(ifa, ifb)) {
D("same interface, endpoint 0 goes to host");
snprintf(ifabuf, sizeof(ifabuf) - 1, "%s^", ifa);
ifa = ifabuf;
if (!loopback) {
D("same interface, endpoint 0 goes to host");
snprintf(ifabuf, sizeof(ifabuf) - 1, "%s^", ifa);
ifa = ifabuf;
} else {
D("same interface, loopbacking traffic");
}
} else {
/* two different interfaces. Take all rings on if1 */
}
@ -243,7 +267,7 @@ main(int argc, char **argv)
zerocopy = zerocopy && (pa->mem == pb->mem);
D("------- zerocopy %ssupported", zerocopy ? "" : "NOT ");
/* setup poll(2) variables. */
/* setup poll(2) array */
memset(pollfd, 0, sizeof(pollfd));
pollfd[0].fd = pa->fd;
pollfd[1].fd = pb->fd;
@ -263,18 +287,16 @@ main(int argc, char **argv)
n0 = pkt_queued(pa, 0);
n1 = pkt_queued(pb, 0);
#if defined(_WIN32) || defined(BUSYWAIT)
if (n0){
if (n0) {
ioctl(pollfd[1].fd, NIOCTXSYNC, NULL);
pollfd[1].revents = POLLOUT;
}
else {
} else {
ioctl(pollfd[0].fd, NIOCRXSYNC, NULL);
}
if (n1){
if (n1) {
ioctl(pollfd[0].fd, NIOCTXSYNC, NULL);
pollfd[0].revents = POLLOUT;
}
else {
} else {
ioctl(pollfd[1].fd, NIOCRXSYNC, NULL);
}
ret = 1;
@ -287,8 +309,10 @@ main(int argc, char **argv)
pollfd[0].events |= POLLOUT;
else
pollfd[1].events |= POLLIN;
/* poll() also cause kernel to txsync/rxsync the NICs */
ret = poll(pollfd, 2, 2500);
#endif //defined(_WIN32) || defined(BUSYWAIT)
#endif /* defined(_WIN32) || defined(BUSYWAIT) */
if (ret <= 0 || verbose)
D("poll %s [0] ev %x %x rx %d@%d tx %d,"
" [1] ev %x %x rx %d@%d tx %d",
@ -316,18 +340,15 @@ main(int argc, char **argv)
D("error on fd1, rx [%d,%d,%d)",
rx->head, rx->cur, rx->tail);
}
if (pollfd[0].revents & POLLOUT) {
if (pollfd[0].revents & POLLOUT)
move(pb, pa, burst);
// XXX we don't need the ioctl */
// ioctl(me[0].fd, NIOCTXSYNC, NULL);
}
if (pollfd[1].revents & POLLOUT) {
if (pollfd[1].revents & POLLOUT)
move(pa, pb, burst);
// XXX we don't need the ioctl */
// ioctl(me[1].fd, NIOCTXSYNC, NULL);
}
/* We don't need ioctl(NIOCTXSYNC) on the two file descriptors here,
* kernel will txsync on next poll(). */
}
D("exiting");
nm_close(pb);
nm_close(pa);

View File

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd May 1, 2016
.Dd October 23, 2018
.Dt PKT-GEN 8
.Os
.Sh NAME
@ -170,10 +170,9 @@ packets to be received by the target host.
.Dl
.Nm
-i netmap:ncxl0 -f tx -s 172.16.0.1:53 -d 172.16.1.3:53 -D 00:07:43:29:2a:e0
.Sh FILES
.Xr netmap 4
.Sh SEE ALSO
.Xr netmap 4
.Xr netmap 4 ,
.Xr bridge 8
.Sh AUTHORS
This manual page was written by
.An George V. Neville-Neil Aq gnn@FreeBSD.org .