From owner-freebsd-net@FreeBSD.ORG Mon Nov 3 19:34:26 2014 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 06B96931 for ; Mon, 3 Nov 2014 19:34:26 +0000 (UTC) Received: from mail-wi0-x233.google.com (mail-wi0-x233.google.com [IPv6:2a00:1450:400c:c05::233]) (using TLSv1 with cipher ECDHE-RSA-RC4-SHA (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority G2" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 85495EAA for ; Mon, 3 Nov 2014 19:34:25 +0000 (UTC) Received: by mail-wi0-f179.google.com with SMTP id h11so7383885wiw.0 for ; Mon, 03 Nov 2014 11:34:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:sender:in-reply-to:references:date:message-id:subject :from:to:cc:content-type; bh=GPb6mHV8Eces5KmeAm8nkoKH8Xitv3msomb7IJdt9r0=; b=hX4KUMIVikuISL/zsvkFKpWJZnsKIGMAD+HcX5d9oSHuh2puUdDqADZuXYI82vgjJL iw4Y+TmHgN923H0S5vpp1FC99bUzClNa5UUwClDpIQhIA619B7Id5JBiS6Y6mcj/2H4Y GTE6Mu/Lq1oOqMsYiEuxTf+UlGl6JzOYwy9JCp7OEuqQyPxccjoqPSjPTbNHa8RFlGsj AgHRK3ennvcitsd+SvHAszRUUzO1I3cgW5HOHmeN0j0PLPI7kUi9sjb8v+MEbODzCJeu hGDX7TD8TSUS0JgpnH5hdPB9EzUcYrloRlBWVSDwYM+IIZsxrPGB2/q5wepwjCcPzdAL NAxw== MIME-Version: 1.0 X-Received: by 10.194.61.208 with SMTP id s16mr5351738wjr.104.1415043263809; Mon, 03 Nov 2014 11:34:23 -0800 (PST) Sender: rizzo.unipi@gmail.com Received: by 10.194.19.9 with HTTP; Mon, 3 Nov 2014 11:34:23 -0800 (PST) In-Reply-To: References: Date: Mon, 3 Nov 2014 11:34:23 -0800 X-Google-Sender-Auth: TQxnKIVW-116Lx8XCES_-yd_hJQ Message-ID: Subject: Re: netmap: add extra interface on bridge From: Luigi Rizzo To: upyzl Content-Type: text/plain; charset=UTF-8 X-Content-Filtered-By: Mailman/MimeDel 2.1.18-1 Cc: "freebsd-net@freebsd.org" X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 03 Nov 2014 19:34:26 -0000 On Monday, November 3, 2014, upyzl 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@freebsd.org mailing list > http://lists.freebsd.org/mailman/listinfo/freebsd-net > To unsubscribe, send any mail to "freebsd-net-unsubscribe@freebsd.org > " > -- -----------------------------------------+------------------------------- Prof. Luigi RIZZO, rizzo@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) -----------------------------------------+-------------------------------