netmap: add extra interface on bridge

Luigi Rizzo rizzo at iet.unipi.it
Mon Nov 3 19:34:26 UTC 2014


On Monday, November 3, 2014, upyzl <zj262144 at gmail.com> wrote:

> Hi there,
>
> I'm study on developing a simple openflow-based datapath module
>
> I know and tried successfully by "bridge -i em0 -i em1"
>
> Now I need bridge em0 em1 em2, but I find using vale-ctl is very difficult
> for me, as I need develop extract, match packets (packets from IN_PORT) and
> do actions from flow table (for simple, the flow table is static).


You are much batter off rewriting the whole thing yoirself. bridge.c is
hardwired for transparent interconnection of two interfaces,  so the
patches you show below cannot possibly work.

Here is a suggestion.

Try to design (pen and paper) a simple handler that grabs packets from one
interface, classifies them using your custom floe table and queues to the
various output interfaces.

Write a second handler that takes packets from an output queue and pushes
them to a port.

 Ignore performance, for simplicity; thingd are already hard enough. Ignore
the fact you are using netmap, that is just a detail, you can design your
pseudo code as something that reads one packet at a time and writes one
packet at a time.

In the process, define what is your policy for dealing with a full output
queue, also consider the broadcast case (you either drop, or block but with
a timeout to avoid stalling the world because of a single port being down).

Then you can write your event loop registering all input fds that are not
blocked (see previous point), all output fds that have traffic queued, a
timeout handler.

This will be single threaded do you do not have to worry about locking.

Once this works you can look at performance.
For that, there is a ton of solutions (heavily commented) you can find in
netmap_vale.c part of the netmap sources.

Cheers
Luigi

>
> I try like this, but only em0 & em1 are connect, without em2...
>
>  --- "a/bridge.c"
> +++ "b/bridge.c"
> @@ -162,11 +162,11 @@ usage(void)
>  int
>  main(int argc, char **argv)
>  {
> -    struct pollfd pollfd[2];
> +    struct pollfd pollfd[3];
>      int i, ch;
>      u_int burst = 1024, wait_link = 4;
> -    struct my_ring me[2];
> -    char *ifa = NULL, *ifb = NULL;
> +    struct my_ring me[3];
> +    char *ifa = NULL, *ifb = NULL, *ifc = NULL;
>
>      fprintf(stderr, "%s %s built %s %s\n",
>          argv[0], version, __DATE__, __TIME__);
> @@ -187,6 +187,8 @@ main(int argc, char **argv)
>                  ifa = optarg;
>              else if (ifb == NULL)
>                  ifb = optarg;
> +            else if (ifc == NULL)
> +                ifc = optarg;
>              else
>                  D("%s ignored, already have 2 interfaces",
>                      optarg);
> @@ -209,6 +211,8 @@ main(int argc, char **argv)
>      if (argc > 2)
>          ifb = argv[2];
>      if (argc > 3)
> +        ifc = argv[3];
> +    if (argc > 4)
>          burst = atoi(argv[3]);
>      if (!ifb)
>          ifb = ifa;
> @@ -227,6 +231,7 @@ main(int argc, char **argv)
>      /* setup netmap interface #1. */
>      me[0].ifname = ifa;
>      me[1].ifname = ifb;
> +  me[2].ifname = ifc;
>      if (!strcmp(ifa, ifb)) {
>          D("same interface, endpoint 0 goes to host");
>          i = NETMAP_SW_RING;
> @@ -236,13 +241,15 @@ main(int argc, char **argv)
>      }
>      if (netmap_open(me, i, 1))
>          return (1);
> -    me[1].mem = me[0].mem; /* copy the pointer, so only one mmap */
> +    me[2].mem = me[1].mem = me[0].mem; /* copy the pointer, so only one
> mmap */
>      if (netmap_open(me+1, 0, 1))
>          return (1);
> +    if (netmap_open(me+2, 0, 1))
> +        return (1);
>
>      /* setup poll(2) variables. */
>      memset(pollfd, 0, sizeof(pollfd));
> -    for (i = 0; i < 2; i++) {
> +    for (i = 0; i < 3; i++) {
>          pollfd[i].fd = me[i].fd;
>          pollfd[i].events = (POLLIN);
>      }
> @@ -256,20 +263,31 @@ main(int argc, char **argv)
>      /* 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;
> +        int n0, n1, n2, ret;
> +        pollfd[0].events = pollfd[1].events = pollfd[2].events = 0;
> +        pollfd[0].revents = pollfd[1].revents = pollfd[2].revents = 0;
>          n0 = pkt_queued(me, 0);
>          n1 = pkt_queued(me + 1, 0);
> -        if (n0)
> +        n2 = pkt_queued(me + 2, 0);
> +        if (n0) {
>              pollfd[1].events |= POLLOUT;
> +            pollfd[2].events |= POLLOUT;
> +        }
>          else
>              pollfd[0].events |= POLLIN;
> -        if (n1)
> +        if (n1) {
>              pollfd[0].events |= POLLOUT;
> +            pollfd[2].events |= POLLOUT;
> +        }
>          else
>              pollfd[1].events |= POLLIN;
> -        ret = poll(pollfd, 2, 2500);
> +        if (n2) {
> +            pollfd[0].events |= POLLOUT;
> +            pollfd[1].events |= POLLOUT;
> +        }
> +        else
> +            pollfd[2].events |= POLLIN;
> +        ret = poll(pollfd, 3, 2500);
>          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",
> @@ -297,16 +315,25 @@ main(int argc, char **argv)
>          }
>          if (pollfd[0].revents & POLLOUT) {
>              move(me + 1, me, burst);
> +            move(me + 2, me, burst);
>              // XXX we don't need the ioctl */
>              // ioctl(me[0].fd, NIOCTXSYNC, NULL);
>          }
>          if (pollfd[1].revents & POLLOUT) {
>              move(me, me + 1, burst);
> +            move(me + 2, me + 1, burst);
>              // XXX we don't need the ioctl */
>              // ioctl(me[1].fd, NIOCTXSYNC, NULL);
>          }
> +        if (pollfd[2].revents & POLLOUT) {
> +            move(me, me + 2, burst);
> +            move(me + 1, me + 2, burst);
> +            // XXX we don't need the ioctl */
> +            // ioctl(me[2].fd, NIOCTXSYNC, NULL);
> +        }
>      }
>      D("exiting");
> +    netmap_close(me + 2);
>      netmap_close(me + 1);
>      netmap_close(me + 0);
>
>
> for last, use ioctl instead of move is failed either...
>
> any advices or relative documents for devel are welcome :)
>
> Regards
> _______________________________________________
> freebsd-net at freebsd.org <javascript:;> mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-net
> To unsubscribe, send any mail to "freebsd-net-unsubscribe at freebsd.org
> <javascript:;>"
>


-- 
-----------------------------------------+-------------------------------
 Prof. Luigi RIZZO, rizzo at iet.unipi.it  . Dip. di Ing. dell'Informazione
 http://www.iet.unipi.it/~luigi/        . Universita` di Pisa
 TEL      +39-050-2211611               . via Diotisalvi 2
 Mobile   +39-338-6809875               . 56122 PISA (Italy)
-----------------------------------------+-------------------------------


More information about the freebsd-net mailing list