2 * (C) 2011 Luigi Rizzo, Matteo Landi
6 * A netmap client to bridge two network interfaces
7 * (or one interface and the host stack).
17 char *version = "$Id$";
19 static int do_abort = 0;
24 (void)sig; /* UNUSED */
26 signal(SIGINT, SIG_DFL);
31 * move up to 'limit' pkts from rxring to txring swapping buffers.
34 process_rings(struct netmap_ring *rxring, struct netmap_ring *txring,
35 u_int limit, const char *msg)
39 /* print a warning if any of the ring flags is set (e.g. NM_REINIT) */
40 if (rxring->flags || txring->flags)
41 D("%s rxflags %x txflags %x",
42 msg, rxring->flags, txring->flags);
43 j = rxring->cur; /* RX */
44 k = txring->cur; /* TX */
45 if (rxring->avail < limit)
46 limit = rxring->avail;
47 if (txring->avail < limit)
48 limit = txring->avail;
51 struct netmap_slot *rs = &rxring->slot[j];
52 struct netmap_slot *ts = &txring->slot[k];
54 char *rxbuf = NETMAP_BUF(rxring, rs->buf_idx);
55 char *txbuf = NETMAP_BUF(txring, ts->buf_idx);
61 if (ts->buf_idx < 2 || rs->buf_idx < 2) {
62 D("wrong index rx[%d] = %d -> tx[%d] = %d",
63 j, rs->buf_idx, k, ts->buf_idx);
68 ts->buf_idx = rs->buf_idx;
71 /* copy the packet length. */
72 if (rs->len < 14 || rs->len > 2048)
73 D("wrong len %d rx[%d] -> tx[%d]", rs->len, j, k);
75 D("%s send len %d rx[%d] -> tx[%d]", msg, rs->len, j, k);
78 pkt_copy(rxbuf, txbuf, ts->len);
80 /* report the buffer change. */
81 ts->flags |= NS_BUF_CHANGED;
82 rs->flags |= NS_BUF_CHANGED;
84 j = NETMAP_RING_NEXT(rxring, j);
85 k = NETMAP_RING_NEXT(txring, k);
92 D("%s sent %d packets to %p", msg, m, txring);
97 /* move packts from src to destination */
99 move(struct my_ring *src, struct my_ring *dst, u_int limit)
101 struct netmap_ring *txring, *rxring;
102 u_int m = 0, si = src->begin, di = dst->begin;
103 const char *msg = (src->queueid & NETMAP_SW_RING) ?
104 "host->net" : "net->host";
106 while (si < src->end && di < dst->end) {
107 rxring = NETMAP_RXRING(src->nifp, si);
108 txring = NETMAP_TXRING(dst->nifp, di);
109 ND("txring %p rxring %p", txring, rxring);
110 if (rxring->avail == 0) {
114 if (txring->avail == 0) {
118 m += process_rings(rxring, txring, limit, msg);
125 * how many packets on this set of queues ?
128 pkt_queued(struct my_ring *me, int tx)
132 ND("me %p begin %d end %d", me, me->begin, me->end);
133 for (i = me->begin; i < me->end; i++) {
134 struct netmap_ring *ring = tx ?
135 NETMAP_TXRING(me->nifp, i) : NETMAP_RXRING(me->nifp, i);
138 if (0 && verbose && tot && !tx)
139 D("ring %s %s %s has %d avail at %d",
140 me->ifname, tx ? "tx": "rx",
141 me->end >= me->nifp->ni_tx_rings ? // XXX who comes first ?
143 tot, NETMAP_TXRING(me->nifp, me->begin)->cur);
151 "usage: bridge [-v] [-i ifa] [-i ifb] [-b burst] [-w wait_time] [iface]\n");
156 * bridge [-v] if1 [if2]
158 * If only one name, or the two interfaces are the same,
159 * bridges userland and the adapter. Otherwise bridge
163 main(int argc, char **argv)
165 struct pollfd pollfd[2];
167 u_int burst = 1024, wait_link = 4;
168 struct my_ring me[2];
169 char *ifa = NULL, *ifb = NULL;
171 fprintf(stderr, "%s %s built %s %s\n",
172 argv[0], version, __DATE__, __TIME__);
174 bzero(me, sizeof(me));
176 while ( (ch = getopt(argc, argv, "b:i:vw:")) != -1) {
179 D("bad option %c %s", ch, optarg);
182 case 'b': /* burst */
183 burst = atoi(optarg);
185 case 'i': /* interface */
188 else if (ifb == NULL)
191 D("%s ignored, already have 2 interfaces",
198 wait_link = atoi(optarg);
212 burst = atoi(argv[3]);
216 D("missing interface");
219 if (burst < 1 || burst > 8192) {
220 D("invalid burst %d, set to 1024", burst);
223 if (wait_link > 100) {
224 D("invalid wait_link %d, set to 4", wait_link);
227 /* setup netmap interface #1. */
230 if (!strcmp(ifa, ifb)) {
231 D("same interface, endpoint 0 goes to host");
234 /* two different interfaces. Take all rings on if1 */
235 i = 0; // all hw rings
237 if (netmap_open(me, i, 1))
239 me[1].mem = me[0].mem; /* copy the pointer, so only one mmap */
240 if (netmap_open(me+1, 0, 1))
243 /* setup poll(2) variables. */
244 memset(pollfd, 0, sizeof(pollfd));
245 for (i = 0; i < 2; i++) {
246 pollfd[i].fd = me[i].fd;
247 pollfd[i].events = (POLLIN);
250 D("Wait %d secs for link to come up...", wait_link);
252 D("Ready to go, %s 0x%x/%d <-> %s 0x%x/%d.",
253 me[0].ifname, me[0].queueid, me[0].nifp->ni_rx_rings,
254 me[1].ifname, me[1].queueid, me[1].nifp->ni_rx_rings);
257 signal(SIGINT, sigint_h);
260 pollfd[0].events = pollfd[1].events = 0;
261 pollfd[0].revents = pollfd[1].revents = 0;
262 n0 = pkt_queued(me, 0);
263 n1 = pkt_queued(me + 1, 0);
265 pollfd[1].events |= POLLOUT;
267 pollfd[0].events |= POLLIN;
269 pollfd[0].events |= POLLOUT;
271 pollfd[1].events |= POLLIN;
272 ret = poll(pollfd, 2, 2500);
273 if (ret <= 0 || verbose)
274 D("poll %s [0] ev %x %x rx %d@%d tx %d,"
275 " [1] ev %x %x rx %d@%d tx %d",
276 ret <= 0 ? "timeout" : "ok",
290 if (pollfd[0].revents & POLLERR) {
291 D("error on fd0, rxcur %d@%d",
292 me[0].rx->avail, me[0].rx->cur);
294 if (pollfd[1].revents & POLLERR) {
295 D("error on fd1, rxcur %d@%d",
296 me[1].rx->avail, me[1].rx->cur);
298 if (pollfd[0].revents & POLLOUT) {
299 move(me + 1, me, burst);
300 // XXX we don't need the ioctl */
301 // ioctl(me[0].fd, NIOCTXSYNC, NULL);
303 if (pollfd[1].revents & POLLOUT) {
304 move(me, me + 1, burst);
305 // XXX we don't need the ioctl */
306 // ioctl(me[1].fd, NIOCTXSYNC, NULL);
310 netmap_close(me + 1);
311 netmap_close(me + 0);