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