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:
parent
8b7db46557
commit
1a7d3c055b
@ -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,
|
||||
|
82
tools/tools/netmap/bridge.8
Normal file
82
tools/tools/netmap/bridge.8
Normal 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.
|
@ -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);
|
||||
|
||||
|
@ -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 .
|
||||
|
Loading…
Reference in New Issue
Block a user