Revision: 569
          http://sourceforge.net/p/vde/svn/569
Author:   rd235
Date:     2014-01-30 10:32:16 +0000 (Thu, 30 Jan 2014)
Log Message:
-----------
vde_vxlan initial release

Modified Paths:
--------------
    trunk/vde-2/.gitignore
    trunk/vde-2/configure.ac
    trunk/vde-2/man/Makefile.am
    trunk/vde-2/src/Makefile.am

Added Paths:
-----------
    trunk/vde-2/man/vde_vxlan.1
    trunk/vde-2/src/vde_vxlan/
    trunk/vde-2/src/vde_vxlan/Makefile.am
    trunk/vde-2/src/vde_vxlan/log.c
    trunk/vde-2/src/vde_vxlan/log.h
    trunk/vde-2/src/vde_vxlan/plug.c
    trunk/vde-2/src/vde_vxlan/plug.h
    trunk/vde-2/src/vde_vxlan/vde_vxlan.c
    trunk/vde-2/src/vde_vxlan/vxlan.c
    trunk/vde-2/src/vde_vxlan/vxlan.h
    trunk/vde-2/src/vde_vxlan/vxlan_hash.c
    trunk/vde-2/src/vde_vxlan/vxlan_hash.h

Modified: trunk/vde-2/.gitignore
===================================================================
--- trunk/vde-2/.gitignore      2014-01-15 11:18:47 UTC (rev 568)
+++ trunk/vde-2/.gitignore      2014-01-30 10:32:16 UTC (rev 569)
@@ -42,6 +42,7 @@
 src/vde_cryptcab/vde_cryptcab
 src/vde_l3/vde_l3
 src/vde_over_ns/vde_over_ns
+src/vde_vxlan/vde_vxlan
 src/vde_pcapplug
 src/vde_plug
 src/vde_plug2tap

Modified: trunk/vde-2/configure.ac
===================================================================
--- trunk/vde-2/configure.ac    2014-01-15 11:18:47 UTC (rev 568)
+++ trunk/vde-2/configure.ac    2014-01-30 10:32:16 UTC (rev 569)
@@ -146,6 +146,13 @@
     [Disable libpthread-dependent vde_router compilation]),
   [if test $enableval = "no" ; then enable_router=no ; warn_router=no ; fi])
 
+enable_vxlan=yes
+# Disable vde_vxlan?
+AC_ARG_ENABLE([vxlan],
+  AS_HELP_STRING([--disable-vxlan],
+    [Disable vde_vxlan compilation]),
+  [if test $enableval = "no" ; then enable_vxlan=no ; warn_vxlan=no ; fi])
+
 # Check of tuntap device
 AC_ARG_ENABLE([tuntap],
   AS_HELP_STRING([--disable-tuntap], [Disable tuntap compilation]), [:],
@@ -236,6 +243,7 @@
 AM_CONDITIONAL(ENABLE_CRYPTCAB, test "$add_cryptcab_support" = yes)
 AM_CONDITIONAL(ENABLE_VDE_OVER_NS, test "$add_over_ns_support" = yes)
 AM_CONDITIONAL(ENABLE_ROUTER, test "$enable_router" = yes)
+AM_CONDITIONAL(ENABLE_VXLAN, test "$enable_vxlan" = yes)
 AM_CONDITIONAL(ENABLE_PYTHON, test "$enable_python" = yes)
 AM_CONDITIONAL(ENABLE_PCAP, test "$add_pcap" = yes)
 AM_CONDITIONAL(CAN_MAKE_LIBVDETAP, test "$can_make_libvdetap" = yes)
@@ -269,6 +277,7 @@
   [src/vde_l3/Makefile]
   [src/vde_cryptcab/Makefile]
   [src/vde_router/Makefile]
+  [src/vde_vxlan/Makefile]
   [src/slirpvde/Makefile]
   [src/vde_switch/plugins/Makefile]
 )
@@ -291,6 +300,12 @@
   AS_ECHO " - VDE Router.............. disabled"
 fi
 
+if test x$enable_vxlan = "xyes" ; then
+  AS_ECHO " + VDE VXLAN............... enabled"
+else
+  AS_ECHO " - VDE VXLAN............... disabled"
+fi
+
 if test x$enable_python = "xyes" ; then
   AS_ECHO " + Python Libraries........ enabled"
 else
@@ -354,6 +369,13 @@
   fi
 fi
 
+if ! test x$enable_vxlan = "xyes" ; then
+  if test x$warn_vxlan = "xyes" ; then
+    AC_MSG_WARN([VDE VXLAN support has been disabled.])
+    AS_ECHO
+  fi
+fi
+
 if ! test x$enable_python = "xyes" ; then
     AC_MSG_WARN([Python libraries support has been disabled because python is
 not installed on your system, or because it could not be found. Please install

Modified: trunk/vde-2/man/Makefile.am
===================================================================
--- trunk/vde-2/man/Makefile.am 2014-01-15 11:18:47 UTC (rev 568)
+++ trunk/vde-2/man/Makefile.am 2014-01-30 10:32:16 UTC (rev 569)
@@ -1,4 +1,4 @@
-static_mans = dpipe.1 slirpvde.1 unixterm.1 vde_plug.1 vdeq.1 vde_switch.1 
wirefilter.1 vde_cryptcab.1 vde_plug2tap.1 vde_over_ns.1 vde_l3.1 vde_tunctl.8 
vde_autolink.1 unixcmd.1 vdeterm.1 vde_router.1
+static_mans = dpipe.1 slirpvde.1 unixterm.1 vde_plug.1 vdeq.1 vde_switch.1 
wirefilter.1 vde_cryptcab.1 vde_plug2tap.1 vde_over_ns.1 vde_l3.1 vde_tunctl.8 
vde_autolink.1 unixcmd.1 vdeterm.1 vde_router.1 vde_vxlan.1
 if ENABLE_PCAP
   static_mans += vde_pcapplug.1
 endif

Added: trunk/vde-2/man/vde_vxlan.1
===================================================================
--- trunk/vde-2/man/vde_vxlan.1                         (rev 0)
+++ trunk/vde-2/man/vde_vxlan.1 2014-01-30 10:32:16 UTC (rev 569)
@@ -0,0 +1,78 @@
+.TH VDE_VXLAN 1 "October 26, 2013" "Virtual Distributed Ethernet"
+.SH NAME
+vde_vxlan \- VXLAN tunnel endpoint for VDE
+.SH SYNOPSIS
+.B vde_vxlan
+.BI --vxlan-id
+.I vxlan_id
+.BI --vxlan-addr
+.I multicast_address
+[
+.BI --vxlan-port
+.I udp_port
+]
+[
+.BI --vxlan-mttl
+.I multicast_ttl
+]
+[
+.BI --sock
+.I vde_socket_dir
+]
+[
+.BI --port
+.I vde_port
+]
+[
+.BI --daemon
+]
+[
+.BI --verbose
+]
+.br
+.SH DESCRIPTION
+A
+\fBvde_vxlan\fP 
+is a Virtual eXtensible LAN (VXLAN) tunnel endpoint for the vde architecture,
+that can connect a \fBvde_switch (1)\fP to a VXLAN segment.
+
+.SH OPTIONS
+
+.TP
+.B --vxlan-id
+ID of the VXLAN (VNI)
+.TP
+.B --vxlan-addr
+Multicast address of the VXLAN
+.TP
+.B --vxlan-port
+Port of the VXLAN (default 4879)
+.TP
+.B --vxlan-mttl
+Multicast TTL (default 1)
+.TP
+.B --sock
+Socket directory of the VDE switch
+.TP
+.B --port
+Port of the VDE switch
+.TP
+.B --daemon
+Run in background
+.TP
+.B --verbose
+Show debug output
+
+.SH NOTICE
+Virtual Distributed Ethernet is not related in any way with
+www.vde.com ("Verband der Elektrotechnik, Elektronik und Informationstechnik"
+i.e. the German "Association for Electrical, Electronic & Information
+Technologies").
+
+.SH SEE ALSO
+\fBvde_switch\fP(1),
+.br
+.SH AUTHORS
+vde_vxlan is a tool by Alessandro Ghedini <alessan...@ghedini.me>
+
+VDE is a project by Renzo Davoli <re...@cs.unibo.it>

Modified: trunk/vde-2/src/Makefile.am
===================================================================
--- trunk/vde-2/src/Makefile.am 2014-01-15 11:18:47 UTC (rev 568)
+++ trunk/vde-2/src/Makefile.am 2014-01-30 10:32:16 UTC (rev 569)
@@ -38,6 +38,10 @@
   SUBDIRS += vde_router
 endif
 
+if ENABLE_VXLAN
+  SUBDIRS += vde_vxlan
+endif
+
 if ENABLE_KERNEL_SWITCH
   SUBDIRS += kvde_switch
 endif

Added: trunk/vde-2/src/vde_vxlan/Makefile.am
===================================================================
--- trunk/vde-2/src/vde_vxlan/Makefile.am                               (rev 0)
+++ trunk/vde-2/src/vde_vxlan/Makefile.am       2014-01-30 10:32:16 UTC (rev 
569)
@@ -0,0 +1,14 @@
+moddir = $(pkglibdir)/vde_vxlan
+
+AM_LDFLAGS =
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src/vde_switch -I.
+
+if ENABLE_PROFILE
+  AM_CFLAGS = -pg --coverage
+  AM_LDFLAGS += -pg --coverage
+endif
+
+bin_PROGRAMS = vde_vxlan
+vde_vxlan_SOURCES = vde_vxlan.c vxlan_hash.c log.c plug.c vxlan.c
+vde_vxlan_LDADD = $(top_builddir)/src/common/libvdecommon.la \
+                 $(top_builddir)/src/lib/libvdeplug.la

Added: trunk/vde-2/src/vde_vxlan/log.c
===================================================================
--- trunk/vde-2/src/vde_vxlan/log.c                             (rev 0)
+++ trunk/vde-2/src/vde_vxlan/log.c     2014-01-30 10:32:16 UTC (rev 569)
@@ -0,0 +1,56 @@
+/*
+ * VDE - vde_vxlan Network emulator for vde
+ * Copyright (C) 2014 Renzo Davoli, Alessandro Ghedini VirtualSquare
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <stdarg.h>
+
+#include "log.h"
+
+static const char *prog = "vde_vxlan";
+
+int logok = 0;
+int debug = 0;
+
+void printlog(int priority, const char *format, ...) {
+       va_list arg;
+
+       if (!debug && priority == LOG_DEBUG)
+               return;
+
+       va_start(arg, format);
+       if (logok)
+               vsyslog(priority, format, arg);
+       else {
+               fprintf(stderr, "%s: ", prog);
+               vfprintf(stderr, format, arg);
+               fprintf(stderr, "\n");
+       }
+       va_end(arg);
+}
+
+void printoutc(FILE *f, const char *format, ...) {
+       va_list arg;
+
+       va_start (arg, format);
+       if (f) {
+               vfprintf(f,format,arg);
+               fprintf(f,"\n");
+       } else
+               printlog(LOG_INFO,format,arg);
+       va_end(arg);
+}

Added: trunk/vde-2/src/vde_vxlan/log.h
===================================================================
--- trunk/vde-2/src/vde_vxlan/log.h                             (rev 0)
+++ trunk/vde-2/src/vde_vxlan/log.h     2014-01-30 10:32:16 UTC (rev 569)
@@ -0,0 +1,29 @@
+/*
+ * VDE - vde_vxlan Network emulator for vde
+ * Copyright (C) 2014 Renzo Davoli, Alessandro Ghedini VirtualSquare
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <syslog.h>
+
+extern int logok;
+extern int debug;
+
+void printlog(int priority, const char *format, ...);
+void printoutc(FILE *f, const char *format, ...);

Added: trunk/vde-2/src/vde_vxlan/plug.c
===================================================================
--- trunk/vde-2/src/vde_vxlan/plug.c                            (rev 0)
+++ trunk/vde-2/src/vde_vxlan/plug.c    2014-01-30 10:32:16 UTC (rev 569)
@@ -0,0 +1,107 @@
+/*
+ * VDE - vde_vxlan Network emulator for vde
+ * Copyright (C) 2014 Renzo Davoli, Alessandro Ghedini VirtualSquare
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <stdlib.h>
+#include <poll.h>
+
+#include <libvdeplug.h>
+
+#include "vxlan_hash.h"
+#include "log.h"
+#include "vxlan.h"
+#include "plug.h"
+
+static VDECONN *conn;
+
+void plug_open(char *path, int port, struct pollfd *pfd) {
+       struct vde_open_args open_args = {
+               .port  = port,
+               .group = NULL,
+               .mode  = 0700
+       };
+
+       conn = vde_open(path, "vde_vxlan:", &open_args);
+
+       if (conn == NULL) {
+               printlog(LOG_ERR,"vde_open(\"%s\"): %s", path ? path
+                               : "DEF_SWITCH", strerror(errno));
+               exit(1);
+       }
+
+       pfd[0].fd = vde_ctlfd(conn);
+       pfd[0].events = POLLIN | POLLHUP;
+
+       pfd[1].fd = vde_datafd(conn);
+       pfd[1].events = POLLIN | POLLHUP;
+}
+
+void plug_process() {
+       struct vxlan_pkt pkt;
+
+       in_addr_t dest_addr;
+
+       int nx = vde_recv(conn, (void *) &pkt.pkt, sizeof(pkt), 0);
+
+       if (nx < 0)
+               printlog(LOG_ERR, "vde_recv(): %s",
+                               strerror(errno));
+
+       printlog(LOG_DEBUG, "VDE packet");
+
+       find_in_hash_update(pkt.pkt.header.src, vxlan_id, 1, NULL);
+
+       if ((pkt.pkt.header.dest[0] == 0xff) &&
+           (pkt.pkt.header.dest[1] == 0xff) &&
+           (pkt.pkt.header.dest[2] == 0xff) &&
+           (pkt.pkt.header.dest[3] == 0xff) &&
+           (pkt.pkt.header.dest[4] == 0xff) &&
+           (pkt.pkt.header.dest[5] == 0xff)) {
+               printlog(LOG_DEBUG, "Broadcast send");
+
+               vxlan_send(0, &pkt, nx);
+               return;
+       }
+
+       find_in_hash(pkt.pkt.header.dest, vxlan_id, &dest_addr);
+
+       if (dest_addr == 0) {
+               printlog(LOG_DEBUG, "Multicast send");
+               vxlan_send(0, &pkt, nx);
+               return;
+       }
+
+       if (dest_addr > 1) {
+               struct in_addr a;
+               a.s_addr = dest_addr;
+               printlog(LOG_DEBUG, "Send to %s", inet_ntoa(a));
+
+               vxlan_send(dest_addr, &pkt, nx);
+       }
+}
+
+void plug_send(struct eth_pkt *pkt, size_t len) {
+       int nx = vde_send(conn, pkt, len, 0);
+
+       if (nx < 0)
+               printlog(LOG_ERR, "vde_send(): %s", strerror(errno));
+}
+
+void plug_close() {
+       vde_close(conn);
+}

Added: trunk/vde-2/src/vde_vxlan/plug.h
===================================================================
--- trunk/vde-2/src/vde_vxlan/plug.h                            (rev 0)
+++ trunk/vde-2/src/vde_vxlan/plug.h    2014-01-30 10:32:16 UTC (rev 569)
@@ -0,0 +1,24 @@
+/*
+ * VDE - vde_vxlan Network emulator for vde
+ * Copyright (C) 2014 Renzo Davoli, Alessandro Ghedini VirtualSquare
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+void plug_open(char *path, int port, struct pollfd *pfd);
+void plug_close();
+
+void plug_process();
+void plug_send(struct eth_pkt *p, size_t len);

Added: trunk/vde-2/src/vde_vxlan/vde_vxlan.c
===================================================================
--- trunk/vde-2/src/vde_vxlan/vde_vxlan.c                               (rev 0)
+++ trunk/vde-2/src/vde_vxlan/vde_vxlan.c       2014-01-30 10:32:16 UTC (rev 
569)
@@ -0,0 +1,169 @@
+/*
+ * VDE - vde_vxlan Network emulator for vde
+ * Copyright (C) 2014 Renzo Davoli, Alessandro Ghedini VirtualSquare
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <stdlib.h>
+#include <getopt.h>
+#include <poll.h>
+#include <unistd.h>
+
+#include "vxlan_hash.h"
+#include "log.h"
+#include "vxlan.h"
+#include "plug.h"
+
+/* from vde_switch/switch.h */
+
+#define INIT_HASH_SIZE 128
+
+void cleanup();
+void help();
+
+int main(int argc, char *argv[]) {
+       int opts;
+       struct pollfd pfd[3];
+
+       char *plug_addr  = NULL;
+       int   plug_port  = 0;
+
+       int daemonize = 0;
+
+       const char   *short_opts  = "I:A:P:T:s:p:dvh";
+       struct option long_opts[] = {
+               { "vxlan-id",   required_argument, 0, 'I' },
+               { "vxlan-addr", required_argument, 0, 'A' },
+               { "vxlan-port", required_argument, 0, 'P' },
+               { "vxlan-mttl", required_argument, 0, 'T' },
+
+               { "sock",       required_argument, 0, 's' },
+               { "port",       required_argument, 0, 'p' },
+
+               { "daemon",     no_argument,       0, 'd' },
+               { "verbose",    no_argument,       0, 'v' },
+
+               { "help",       no_argument,       0, 'h' },
+               {0, 0, 0, 0}
+       };
+
+       while ((opts = getopt_long(argc, argv, short_opts, long_opts, 0)) != 
-1) {
+               switch (opts) {
+                       /* VXLAN opts */
+                       case 'I': { vxlan_id   = atoi(optarg);      break; }
+                       /* TODO: IPv6 support */
+                       case 'A': { vxlan_addr = inet_addr(optarg); break; }
+                       case 'P': { vxlan_port = atoi(optarg);      break; }
+                       case 'T': { vxlan_mttl = atoi(optarg);      break; }
+
+                       /* VDE opts */
+                       case 's': { plug_addr = strdup(optarg);     break; }
+                       case 'p': { plug_port = atoi(optarg);       break; }
+
+                       case 'd': { daemonize = 1;                  break; }
+                       case 'v': { debug = 1;                      break; }
+
+                       default :
+                       case 'h': { help(); exit(1);                       }
+               }
+       }
+
+       if (vxlan_id == -1) {
+               printlog(LOG_ERR, "Invalid VXLAN ID");
+               exit(1);
+       }
+
+       if (vxlan_addr == INADDR_NONE) {
+               printlog(LOG_ERR, "Invalid VXLAN multicast address");
+               exit(1);
+       }
+
+       atexit(cleanup);
+
+       plug_open(plug_addr, plug_port, pfd);
+
+       vxlan_open(pfd);
+
+       hash_init(INIT_HASH_SIZE);
+
+       if (daemonize && daemon(0, 0)) {
+               printlog(LOG_ERR, "daemon(): %s", strerror(errno));
+               return 1;
+       } else if (daemonize) {
+               logok = 1;
+               openlog("vde_vxlan", LOG_PID, 0);
+               printlog(LOG_INFO, "VDE_VXLAN started");
+       }
+
+       while (1) {
+               int n = poll(pfd, 3, 1000);
+
+               if ((n < 0) && (errno != EINTR)) {
+                       printlog(LOG_ERR, "poll(): %s", strerror(errno));
+                       return 1;
+               }
+
+               if (pfd[0].revents & POLLHUP) {
+                       printlog(LOG_INFO, "VDE connection closed");
+                       return 0;
+               }
+
+               if (pfd[1].revents & POLLHUP) {
+                       printlog(LOG_ERR, "VDE connection error");
+               }
+
+               if (pfd[1].revents & POLLIN) {
+                       plug_process();
+               }
+
+               if (pfd[2].revents & POLLIN) {
+                       vxlan_process();
+               }
+
+               hash_gc();
+       }
+
+       return 0;
+}
+
+void cleanup() {
+       vxlan_close();
+       plug_close();
+}
+
+void help() {
+       #define CMD_HELP(CMDL, CMDS, MSG) printf("  %s, %s\t%s.\n", CMDS, CMDL, 
MSG);
+
+       puts("Usage: vde_vxlan [OPTIONS]\n");
+       puts(" VXLAN Options:");
+
+       CMD_HELP("--vxlan-id",   "-I", "ID of the VXLAN");
+       CMD_HELP("--vxlan-addr", "-A", "Multicast address of the VXLAN");
+       CMD_HELP("--vxlan-port", "-P", "Port of the VXLAN (default 4879)");
+       CMD_HELP("--vxlan-mttl", "-T", "Multicast TTL (default 1)");
+
+       puts("\n VDE Options:");
+
+       CMD_HELP("--sock", "-s", "Socket directory of the VDE switch");
+       CMD_HELP("--port", "-p", "Port of the VDE switch");
+
+       CMD_HELP("--daemon",  "-d", "Run in background");
+       CMD_HELP("--verbose", "-v", "Show debug output");
+
+       CMD_HELP("--help",    "-h", "Show this help");
+
+       puts("");
+}

Added: trunk/vde-2/src/vde_vxlan/vxlan.c
===================================================================
--- trunk/vde-2/src/vde_vxlan/vxlan.c                           (rev 0)
+++ trunk/vde-2/src/vde_vxlan/vxlan.c   2014-01-30 10:32:16 UTC (rev 569)
@@ -0,0 +1,187 @@
+/*
+ * VDE - vde_vxlan Network emulator for vde
+ * Copyright (C) 2014 Renzo Davoli, Alessandro Ghedini VirtualSquare
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <poll.h>
+
+#include <netinet/in.h>
+#include <sys/un.h>
+
+#include "vxlan_hash.h"
+#include "log.h"
+#include "vxlan.h"
+#include "plug.h"
+
+#define ntoh24(p) (((p)[0] << 16) | ((p)[1] << 8) | ((p)[2]))
+#define hton24(p, v) { \
+       p[0] = (((v) >> 16) & 0xFF); \
+       p[1] = (((v) >> 8) & 0xFF); \
+       p[2] = ((v) & 0xFF); \
+}
+
+int       vxlan_id   = -1;
+in_addr_t vxlan_addr = INADDR_NONE;
+int       vxlan_port = 4879;
+int       vxlan_mttl = 1;
+
+static int    vxlan_fd = -1;
+
+void vxlan_open(struct pollfd *pfd) {
+       int sock;
+       int loop = 0;
+
+       struct ip_mreq mc_req;
+       struct sockaddr_in addr_in;
+
+       if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+               printlog(LOG_ERR, "socket(): %s", strerror(errno));
+               exit(1);
+       }
+
+       if ((setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL,
+                                       &vxlan_mttl, sizeof(vxlan_mttl))) < 0) {
+               printlog(LOG_ERR, "setsockopt(TTL): %s", strerror(errno));
+               exit(1);
+       }
+
+       if ((setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP,
+                                       &loop, sizeof(loop))) < 0) {
+               printlog(LOG_ERR, "setsockopt(LOOP): %s", strerror(errno));
+               exit(1);
+       }
+
+       memset(&addr_in, 0, sizeof(addr_in));
+       addr_in.sin_family      = AF_INET;
+       addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
+       addr_in.sin_port        = htons(vxlan_port);
+
+       if ((bind(sock, (struct sockaddr *) &addr_in, sizeof(addr_in))) < 0) {
+               printlog(LOG_ERR, "bind(): %s", strerror(errno));
+               exit(1);
+       }
+
+       /* send an IGMP join request */
+       mc_req.imr_multiaddr.s_addr = vxlan_addr;
+       mc_req.imr_interface.s_addr = htonl(INADDR_ANY);
+
+       if ((setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+                                       &mc_req, sizeof(mc_req))) < 0) {
+               printlog(LOG_ERR, "setsockopt(ADD): %s", strerror(errno));
+               exit(1);
+       }
+
+       vxlan_fd = sock;
+
+       pfd[2].fd = sock;
+       pfd[2].events = POLLIN | POLLHUP;
+}
+
+void vxlan_process() {
+       struct vxlan_pkt pkt;
+
+       struct sockaddr_in src_addr;
+       socklen_t src_addr_len=sizeof(src_addr);
+
+       in_addr_t dest_addr;
+
+       size_t len = recvfrom(vxlan_fd, &pkt, sizeof(pkt), 0,
+                       (struct sockaddr *) &src_addr, &src_addr_len);
+
+       if (len < 0)
+               printlog(LOG_ERR, "recvfrom(): %s", strerror(errno));
+
+       printlog(LOG_DEBUG, "VXLAN packet from 
%s",inet_ntoa(src_addr.sin_addr));
+
+       if (pkt.flags != (1<<3)) {
+               printlog(LOG_ERR, "Invalid flags");
+               return;
+       }
+
+       if (ntoh24(pkt.id) != vxlan_id) {
+               printlog(LOG_DEBUG, "Invalid VNI");
+               return;
+       }
+
+       find_in_hash_update(pkt.pkt.header.src, vxlan_id,
+                       src_addr.sin_addr.s_addr, NULL);
+
+       if ((pkt.pkt.header.dest[0] == 0xff) &&
+           (pkt.pkt.header.dest[1] == 0xff) &&
+           (pkt.pkt.header.dest[2] == 0xff) &&
+           (pkt.pkt.header.dest[3] == 0xff) &&
+           (pkt.pkt.header.dest[4] == 0xff) &&
+           (pkt.pkt.header.dest[5] == 0xff)) {
+               printlog(LOG_DEBUG, "Broadcast send");
+
+               plug_send(&pkt.pkt, len-offsetof(struct vxlan_pkt,pkt));
+               return;
+       }
+
+       find_in_hash(pkt.pkt.header.dest, vxlan_id, &dest_addr);
+
+       switch (dest_addr) {
+               case 0:
+                       printlog(LOG_DEBUG, "Not found");
+               case 1:
+                       plug_send(&pkt.pkt,len-offsetof(struct vxlan_pkt,pkt));
+                       printlog(LOG_DEBUG, "Send to VDE");
+                       break;
+
+               default:
+                       printlog(LOG_DEBUG, "Drop");
+                       break;
+       }
+}
+
+void vxlan_send(in_addr_t addr_s, struct vxlan_pkt *pkt, size_t len) {
+       struct sockaddr_in addr;
+
+       addr.sin_family      = AF_INET;
+       addr.sin_addr.s_addr = addr_s ? addr_s : vxlan_addr;
+       addr.sin_port        = htons(vxlan_port);
+
+       memset(pkt, 0, offsetof(struct vxlan_pkt,pkt));
+       pkt->flags = (1 << 3);
+
+       hton24(pkt->id, vxlan_id);
+
+       if (sendto(vxlan_fd, pkt, len+offsetof(struct vxlan_pkt,pkt), 0,
+                  (struct sockaddr *) &addr, sizeof(addr)) < 0)
+               printlog(LOG_ERR, "sendto(): %s", strerror(errno));
+}
+
+void vxlan_close() {
+       if (vxlan_fd == -1)
+               return;
+
+       struct ip_mreq mc_req;
+
+       mc_req.imr_multiaddr.s_addr = vxlan_addr;
+       mc_req.imr_interface.s_addr = htonl(INADDR_ANY);
+
+       if ((setsockopt(vxlan_fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+                       (void *) &mc_req, sizeof(mc_req))) < 0) {
+               printlog(LOG_ERR, "setsockopt(DROP): %s", strerror(errno));
+               exit(1);
+       }
+
+       close(vxlan_fd);
+}

Added: trunk/vde-2/src/vde_vxlan/vxlan.h
===================================================================
--- trunk/vde-2/src/vde_vxlan/vxlan.h                           (rev 0)
+++ trunk/vde-2/src/vde_vxlan/vxlan.h   2014-01-30 10:32:16 UTC (rev 569)
@@ -0,0 +1,56 @@
+/*
+ * VDE - vde_vxlan Network emulator for vde
+ * Copyright (C) 2014 Renzo Davoli, Alessandro Ghedini VirtualSquare
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+/* from vde_switch/port.h */
+
+#define ETH_ALEN 6
+#define ETH_HEADER_SIZE 14
+
+struct eth_hdr {
+       unsigned char dest[ETH_ALEN];
+       unsigned char src[ETH_ALEN];
+       unsigned char proto[2];
+};
+
+struct eth_pkt {
+       struct eth_hdr header;
+       unsigned char data[1504]; /*including trailer, IF ANY */
+};
+
+struct vxlan_pkt {
+       unsigned char flags;
+       unsigned char priv1[3];
+       unsigned char id[3];
+       unsigned char priv2[1];
+       struct eth_pkt pkt;
+};
+
+extern int       vxlan_id;
+extern in_addr_t vxlan_addr;
+extern int       vxlan_port;
+extern int       vxlan_mttl;
+
+void vxlan_open(struct pollfd *pfd);
+void vxlan_close();
+
+void vxlan_process();
+void vxlan_send(in_addr_t addr, struct vxlan_pkt *p, size_t len);

Added: trunk/vde-2/src/vde_vxlan/vxlan_hash.c
===================================================================
--- trunk/vde-2/src/vde_vxlan/vxlan_hash.c                              (rev 0)
+++ trunk/vde-2/src/vde_vxlan/vxlan_hash.c      2014-01-30 10:32:16 UTC (rev 
569)
@@ -0,0 +1,244 @@
+/*
+ * VDE - vde_vxlan Network emulator for vde
+ * Copyright (C) 2014 Renzo Davoli, Alessandro Ghedini VirtualSquare
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <syslog.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/signal.h>
+
+#include <config.h>
+#include <vde.h>
+#include <vdecommon.h>
+
+#include "log.h"
+#include "switch.h"
+#include "vxlan_hash.h"
+#include "consmgmt.h"
+#include "bitarray.h"
+
+#define MIN_PERSISTENCE_DFL 3
+static int min_persistence=MIN_PERSISTENCE_DFL;
+#define HASH_INIT_BITS 7
+static int hash_bits;
+static int hash_mask;
+#define HASH_SIZE (1 << hash_bits)
+
+struct hash_entry {
+       struct hash_entry *next;
+       struct hash_entry **prev;
+       time_t last_seen;
+       in_addr_t port;
+       u_int64_t dst;
+};
+
+static struct hash_entry **h;
+
+static int calc_hash(u_int64_t src)
+{
+       src ^= src >> 33;
+       src *= 0xff51afd7ed558ccd;
+       src ^= src >> 33;
+       src *= 0xc4ceb9fe1a85ec53;
+       return src & hash_mask;
+}
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define EMAC2MAC6(X) \
+       (u_int)((X)&0xff), (u_int)(((X)>>8)&0xff), (u_int)(((X)>>16)&0xff), \
+  (u_int)(((X)>>24)&0xff), (u_int)(((X)>>32)&0xff), (u_int)(((X)>>40)&0xff)
+#elif BYTE_ORDER == BIG_ENDIAN
+#define EMAC2MAC6(X) \
+       (u_int)(((X)>>24)&0xff), (u_int)(((X)>>16)&0xff), 
(u_int)(((X)>>8)&0xff), \
+  (u_int)((X)&0xff), (u_int)(((X)>>40)&0xff), (u_int)(((X)>>32)&0xff)
+#else
+#error Unknown Endianess
+#endif
+
+#define EMAC2VLAN(X) ((u_int16_t) ((X)>>48))
+#define EMAC2VLAN2(X) ((u_int) (((X)>>48) &0xff)), ((u_int) (((X)>>56) &0xff))
+
+#define find_entry(MAC) \
+       ({struct hash_entry *e; \
+        int k = calc_hash(MAC);\
+        for(e = h[k]; e && e->dst != (MAC); e = e->next)\
+        ;\
+        e; })
+
+
+#define extmac(MAC,VLAN) \
+           ((*(u_int32_t *) &((MAC)[0])) + ((u_int64_t) ((*(u_int16_t *) 
&((MAC)[4]))+ ((u_int64_t) (VLAN) << 16)) << 32))
+
+/* looks in global hash table 'h' for given address, and return associated
+ * port */
+int find_in_hash(unsigned char *dst, int vlan, in_addr_t *out)
+{
+       struct hash_entry *e = find_entry(extmac(dst,vlan));
+       *out = 0;
+       if(e == NULL) return 0;
+       *out = e->port;
+       return 1;
+}
+
+int find_in_hash_update(unsigned char *src, int vlan, in_addr_t port, 
in_addr_t *out)
+{
+       struct hash_entry *e;
+       u_int64_t esrc=extmac(src,vlan);
+       int k = calc_hash(esrc);
+       in_addr_t oldport;
+       time_t now;
+       for(e = h[k]; e && e->dst != esrc; e = e->next)
+               ;
+       if(e == NULL) {
+               e = (struct hash_entry *) malloc(sizeof(*e));
+               if(e == NULL){
+                       printlog(LOG_WARNING,"Failed to malloc hash entry 
%s",strerror(errno));
+                       return 0;
+               }
+
+               DBGOUT(DBGHASHNEW,"%02x:%02x:%02x:%02x:%02x:%02x VLAN %02x:%02x 
Port %d",
+                               EMAC2MAC6(esrc), EMAC2VLAN2(esrc), port);
+               EVENTOUT(DBGHASHNEW,esrc);
+               e->dst = esrc;
+               if(h[k] != NULL) h[k]->prev = &(e->next);
+               e->next = h[k];
+               e->prev = &(h[k]);
+               e->port = port;
+               h[k] = e;
+       }
+       oldport=e->port;
+       now=time(NULL);
+       if (oldport!=port) {
+               if ((now - e->last_seen) > min_persistence) {
+                       e->port=port;
+                       e->last_seen = now;
+               }
+       } else {
+               e->last_seen = now;
+       }
+       if (out != NULL) *out = oldport;
+       return 1;
+}
+
+#define delete_hash_entry(OLD) \
+       ({ \
+        DBGOUT(DBGHASHDEL,"%02x:%02x:%02x:%02x:%02x:%02x VLAN %02x:%02x Port 
%d", EMAC2MAC6(OLD->dst), EMAC2VLAN2(OLD->dst), OLD->port); \
+        EVENTOUT(DBGHASHDEL,OLD->dst);\
+        *((OLD)->prev)=(OLD)->next; \
+        if((OLD)->next != NULL) (OLD)->next->prev = (OLD)->prev; \
+        free((OLD)); \
+        })
+
+
+/* for each entry of the global hash table 'h', calls function f, passing to it
+ * the hash entry and the additional arg 'arg' */
+static void for_all_hash(void (*f)(struct hash_entry *, void *), void *arg)
+{
+       int i;
+       struct hash_entry *e, *next;
+
+       for(i = 0; i < HASH_SIZE; i++){
+               for(e = h[i]; e; e = next){
+                       next = e->next;
+                       (*f)(e, arg);
+               }
+       }
+}
+
+#define GC_INTERVAL 2
+#define GC_EXPIRE 100
+static int gc_interval;
+static int gc_expire;
+
+/* clean from the hash table entries older than GC_EXPIRE seconds, given that
+ * 'now' points to a time_t structure describing the current time */
+static void gc(struct hash_entry *e, void *now)
+{
+       time_t t = *(time_t *) now;
+       if(e->last_seen + gc_expire < t)
+               delete_hash_entry(e);
+}
+
+/* clean old entries in the hash table 'h', and prepare the timer to be called
+ * again between GC_INTERVAL seconds */
+void hash_gc(void)
+{
+       time_t t = time(NULL);
+       static time_t last_t;
+       if (t - last_t > GC_INTERVAL) {
+               for_all_hash(&gc, &t);
+               last_t=t;
+       }
+}
+
+#define HASH_INIT(BIT) \
+       ({ hash_bits=(BIT);\
+        hash_mask=HASH_SIZE-1;\
+        if ((h=(struct hash_entry **) calloc (HASH_SIZE,sizeof (struct 
hash_entry *))) == NULL) {\
+        printlog(LOG_WARNING,"Failed to malloc hash table 
%s",strerror(errno));\
+        exit(1); \
+        }\
+        })
+
+static inline int po2round(int vx)
+{
+       if (vx == 0)
+               return 0;
+       else {
+               register int i=0;
+               register int x=vx-1;
+               while (x) { x>>=1; i++; }
+               if (vx != 1<<i)
+                       printlog(LOG_WARNING,"Hash size must be a power of 2. 
%d rounded to %d",vx,1<<i);
+               return i;
+       }
+}
+
+int hash_set_gc_interval(int p)
+{
+       gc_interval=p;
+       return 0;
+}
+
+int hash_set_gc_expire(int e)
+{
+       gc_expire=e;
+       return 0;
+}
+
+int hash_set_minper(int e)
+{
+       min_persistence=e;
+       return 0;
+}
+
+/* sets sig_alarm as handler for SIGALRM, and run it a first time */
+void hash_init(int hash_size)
+{
+       HASH_INIT(po2round(hash_size));
+
+       gc_interval=GC_INTERVAL;
+       gc_expire=GC_EXPIRE;
+}

Added: trunk/vde-2/src/vde_vxlan/vxlan_hash.h
===================================================================
--- trunk/vde-2/src/vde_vxlan/vxlan_hash.h                              (rev 0)
+++ trunk/vde-2/src/vde_vxlan/vxlan_hash.h      2014-01-30 10:32:16 UTC (rev 
569)
@@ -0,0 +1,35 @@
+/*
+ * VDE - vde_vxlan Network emulator for vde
+ * Copyright (C) 2014 Renzo Davoli, Alessandro Ghedini VirtualSquare
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <netinet/in.h>
+
+#ifndef __HASH_H__
+#define __HASH_H__
+
+extern int find_in_hash(unsigned char *dst, int vlan, in_addr_t *out);
+extern int find_in_hash_update(unsigned char *dst, int vlan, in_addr_t port, 
in_addr_t *out);
+
+extern in_addr_t find_in_hash_v6(unsigned char *dst, int vlan, unsigned char 
*out);
+extern in_addr_t find_in_hash_update_v6(unsigned char *dst, int vlan, unsigned 
char *port, unsigned char *out);
+
+extern void hash_gc(void);
+
+extern void hash_init(int hash_size);
+
+#endif

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
WatchGuard Dimension instantly turns raw network data into actionable 
security intelligence. It gives you real-time visual feedback on key
security issues and trends.  Skip the complicated setup - simply import
a virtual appliance and go from zero to informed in seconds.
http://pubads.g.doubleclick.net/gampad/clk?id=123612991&iu=/4140/ostg.clktrk
_______________________________________________
vde-users mailing list
vde-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/vde-users

Reply via email to