Revision: 571
http://sourceforge.net/p/vde/svn/571
Author: rd235
Date: 2014-02-07 11:48:49 +0000 (Fri, 07 Feb 2014)
Log Message:
-----------
new feature: vxlan and lxvde modules for libvdeplug
Modified Paths:
--------------
branches/rd235/vde-2/src/lib/libvdeplug/Makefile.am
branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug.c
branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_kvde.c
branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_ptp.c
branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_udp.c
branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vde.c
Added Paths:
-----------
branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxhash.c
branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxhash.h
branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxlan.c
branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxvde.c
Modified: branches/rd235/vde-2/src/lib/libvdeplug/Makefile.am
===================================================================
--- branches/rd235/vde-2/src/lib/libvdeplug/Makefile.am 2014-01-30 10:52:17 UTC
(rev 570)
+++ branches/rd235/vde-2/src/lib/libvdeplug/Makefile.am 2014-02-07 11:48:49 UTC
(rev 571)
@@ -18,6 +18,9 @@
libvdeplug_vde.c \
libvdeplug_kvde.c \
libvdeplug_udp.c \
+ libvdeplug_vxhash.c \
+ libvdeplug_vxlan.c \
+ libvdeplug_vxvde.c \
libvdestream.c
libvdeplug_la_LIBADD = $(LIBADD)
Modified: branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug.c
===================================================================
--- branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug.c 2014-01-30
10:52:17 UTC (rev 570)
+++ branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug.c 2014-02-07
11:48:49 UTC (rev 571)
@@ -40,6 +40,8 @@
extern struct vdeplug_module vdeplug_udp;
extern struct vdeplug_module vdeplug_ptpf;
extern struct vdeplug_module vdeplug_ptpm;
+extern struct vdeplug_module vdeplug_vxlan;
+extern struct vdeplug_module vdeplug_vxvde;
//extern struct vdeplug_module vdeplug_gvde;
static struct vdeplug_module *modules[]={
@@ -48,6 +50,8 @@
&vdeplug_udp,
&vdeplug_ptpf,
&vdeplug_ptpm,
+ &vdeplug_vxlan,
+ &vdeplug_vxvde,
//&vdeplug_gvde,
};
@@ -67,6 +71,7 @@
int pid = getpid();
callerpwd=getpwuid(getuid());
+ //fprintf(stderr, "LIBVDEPLUG OPEN! %s\n",given_sockname);
descrlen=snprintf(newdescr,MAXDESCR,"%s user=%s PID=%d",
descr,(callerpwd != NULL)?callerpwd->pw_name:"??",
Modified: branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_kvde.c
===================================================================
--- branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_kvde.c 2014-01-30
10:52:17 UTC (rev 570)
+++ branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_kvde.c 2014-02-07
11:48:49 UTC (rev 571)
@@ -64,15 +64,11 @@
static char *vde_kvde_check(char *given_sockname)
{
static char tag[]="KVDE:";
- static char atag[]="KVDE{";
- int len;
+ static char atag[]="KVDE/";
if (strncmp(given_sockname,tag,strlen(tag)) == 0)
return given_sockname+strlen(tag);
- len=strlen(given_sockname);
- if (strncmp(given_sockname,atag,strlen(atag)) == 0 &&
- given_sockname[len-1] == '}') {
+ if (strncmp(given_sockname,atag,strlen(atag)) == 0) {
given_sockname[strlen(atag)-1]=':';
- given_sockname[len-1] = 0;
return given_sockname+strlen(atag);
}
return NULL;
Modified: branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_ptp.c
===================================================================
--- branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_ptp.c 2014-01-30
10:52:17 UTC (rev 570)
+++ branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_ptp.c 2014-02-07
11:48:49 UTC (rev 571)
@@ -33,8 +33,6 @@
#include "libvdeplug_mod.h"
#include "canonicalize.h"
-#define USE_IPN
-
static char *vde_ptpf_check(char *given_sockname);
static VDECONN *vde_ptpf_open(char *given_sockname, char *descr,int
interface_version,
struct vde_open_args *open_args);
@@ -77,25 +75,20 @@
static char *vde_ptpf_check(char *given_sockname)
{
static char tag[]="PTPF:";
- static char atag[]="PTPF{";
+ static char atag[]="PTPF/";
static char tag2[]="PTP:";
- static char atag2[]="PTP{";
- int len;
- len=strlen(given_sockname);
+ static char atag2[]="PTP/";
+ int len=strlen(given_sockname);
if (strncmp(given_sockname,tag,strlen(tag)) == 0)
return given_sockname+strlen(tag);
- if (strncmp(given_sockname,atag,strlen(atag)) == 0 &&
- given_sockname[len-1] == '}') {
+ if (strncmp(given_sockname,atag,strlen(atag)) == 0) {
given_sockname[strlen(atag)-1]=':';
- given_sockname[len-1] = 0;
return given_sockname+strlen(atag);
}
if (strncmp(given_sockname,tag2,strlen(tag2)) == 0)
return given_sockname+strlen(tag2);
- if (strncmp(given_sockname,atag2,strlen(atag2)) == 0 &&
- given_sockname[len-1] == '}') {
+ if (strncmp(given_sockname,atag2,strlen(atag2)) == 0) {
given_sockname[strlen(atag2)-1]=':';
- given_sockname[len-1] = 0;
return given_sockname+strlen(atag2);
}
if (len > 2 && given_sockname[len-1] == ']' &&
@@ -109,15 +102,11 @@
static char *vde_ptpm_check(char *given_sockname)
{
static char tag[]="PTPM:";
- static char atag[]="PTPM{";
- int len;
+ static char atag[]="PTPM";
if (strncmp(given_sockname,tag,strlen(tag)) == 0)
return given_sockname+strlen(tag);
- len=strlen(given_sockname);
- if (strncmp(given_sockname,atag,strlen(atag)) == 0 &&
- given_sockname[len-1] == '}') {
+ if (strncmp(given_sockname,atag,strlen(atag)) == 0) {
given_sockname[strlen(atag)-1]=':';
- given_sockname[len-1] = 0;
return given_sockname+strlen(atag);
}
return NULL;
Modified: branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_udp.c
===================================================================
--- branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_udp.c 2014-01-30
10:52:17 UTC (rev 570)
+++ branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_udp.c 2014-02-07
11:48:49 UTC (rev 571)
@@ -62,16 +62,12 @@
static char *vde_udp_check(char *given_sockname)
{
static char tag[]="UDP:";
- static char atag[]="UDP{";
- int len;
+ static char atag[]="UDP/";
char *split;
if (strncmp(given_sockname,tag,strlen(tag)) == 0)
return given_sockname+strlen(tag);
- len=strlen(given_sockname);
- if (strncmp(given_sockname,atag,strlen(atag)) == 0 &&
- given_sockname[len-1] == '}') {
+ if (strncmp(given_sockname,atag,strlen(atag)) == 0) {
given_sockname[strlen(atag)-1]=':';
- given_sockname[len-1] = 0;
return given_sockname+strlen(atag);
}
if((split = strstr(given_sockname,"->")) != NULL && rindex(split,':')
!= NULL)
Modified: branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vde.c
===================================================================
--- branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vde.c 2014-01-30
10:52:17 UTC (rev 570)
+++ branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vde.c 2014-02-07
11:48:49 UTC (rev 571)
@@ -63,15 +63,11 @@
static char *vde_vde_check(char *given_sockname)
{
static char tag[]="VDE:";
- static char atag[]="VDE{";
- int len;
+ static char atag[]="VDE/";
if (strncmp(given_sockname,tag,strlen(tag)) == 0)
return given_sockname+strlen(tag);
- len=strlen(given_sockname);
- if (strncmp(given_sockname,atag,strlen(atag)) == 0 &&
- given_sockname[len-1] == '}') {
+ if (strncmp(given_sockname,atag,strlen(atag)) == 0) {
given_sockname[strlen(atag)-1]=':';
- given_sockname[len-1] = 0;
return given_sockname+strlen(atag);
}
return NULL;
Added: branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxhash.c
===================================================================
--- branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxhash.c
(rev 0)
+++ branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxhash.c 2014-02-07
11:48:49 UTC (rev 571)
@@ -0,0 +1,129 @@
+/*
+ * VDE - vde_vxlan Network emulator for vde
+ * Copyright (C) 2014 Renzo Davoli 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 <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+#include "libvdeplug_vxhash.h"
+
+struct hash_entry6 {
+ u_int64_t edst;
+ time_t last_seen;
+ struct sockaddr_in6 addr;
+};
+
+struct hash_entry4 {
+ u_int64_t edst;
+ time_t last_seen;
+ struct sockaddr_in addr;
+};
+
+struct hash_entry {
+ u_int64_t edst;
+ time_t last_seen;
+ struct sockaddr addr;
+};
+
+static int calc_hash(u_int64_t src, int hash_mask)
+{
+ src ^= src >> 33;
+ src *= 0xff51afd7ed558ccd;
+ src ^= src >> 33;
+ src *= 0xc4ceb9fe1a85ec53;
+ return src & hash_mask;
+}
+
+#define extmac(MAC,VLAN) \
+ ((*(u_int32_t *) &((MAC)[0])) + ((u_int64_t) ((*(u_int16_t *)
&((MAC)[4]))+ ((u_int64_t) (VLAN) << 16)) << 32))
+
+/* look in global hash table for given address, and return associated sockaddr
*/
+struct sockaddr *vx_find_in_hash(void *table, int sa_family, int hash_mask,
+ unsigned char *dst, int vlan, time_t too_old)
+{
+ u_int64_t edst;
+ int index;
+ struct hash_entry *entry;
+
+ if (__builtin_expect(table == NULL, 0))
+ return NULL;
+ if ((dst[0] & 1) == 1) /* broadcast */
+ return NULL;
+ edst=extmac(dst,vlan);
+ index=calc_hash(edst, hash_mask);
+ switch (sa_family) {
+ case AF_INET: entry = (struct hash_entry *)((struct hash_entry4
*)table)+index;
+ break;
+ case AF_INET6: entry = (struct hash_entry *)((struct
hash_entry6 *)table)+index;
+ break;
+ default:
+ return NULL;
+ }
+ if (entry->edst == edst && entry->last_seen >= too_old)
+ return &(entry->addr);
+ else
+ return NULL;
+}
+
+void vx_find_in_hash_update(void *table, int hash_mask,
+ unsigned char *src, int vlan, struct sockaddr *addr, time_t now)
+{
+ u_int64_t esrc;
+ int index;
+ size_t addrlen;
+ struct hash_entry *entry;
+ if (__builtin_expect(table == NULL, 0))
+ return;
+ if ((src[0] & 1) == 1) /* broadcast */
+ return;
+ esrc=extmac(src,vlan);
+ index=calc_hash(esrc, hash_mask);
+
+ switch (addr->sa_family) {
+ case AF_INET: entry = (struct hash_entry *)((struct hash_entry4
*)table)+index;
+ addrlen = sizeof(struct
sockaddr_in);
+ break;
+ case AF_INET6: entry = (struct hash_entry *)((struct
hash_entry6 *)table)+index;
+ addrlen = sizeof(struct
sockaddr_in6);
+ break;
+ default:
+ return;
+ }
+ entry->edst=esrc;
+ memcpy(&(entry->addr),addr,addrlen);
+ entry->last_seen=now;
+}
+
+/* hash_mask must be 2^n - 1 */
+void *vx_hash_init(int sa_family, int hash_mask)
+{
+ size_t elsize;
+ switch (sa_family) {
+ case AF_INET: elsize=sizeof(struct hash_entry4); break;
+ case AF_INET6: elsize=sizeof(struct hash_entry6); break;
+ default:
+ return NULL;
+ }
+
+ return calloc(hash_mask+1, elsize);
+}
+
Added: branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxhash.h
===================================================================
--- branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxhash.h
(rev 0)
+++ branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxhash.h 2014-02-07
11:48:49 UTC (rev 571)
@@ -0,0 +1,34 @@
+/*
+ * VDE - vde_vxlan Network emulator for vde
+ * Copyright (C) 2014 Renzo Davoli 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.
+ */
+#ifndef LIBVDEPLUG_VXHASH_H
+#define LIBVDEPLUG_VXHASH_H
+
+/* look in global hash table for given address, and return associated sockaddr
*/
+struct sockaddr *vx_find_in_hash(void *table, int sa_family, int hash_mask,
+ unsigned char *dst, int vlan, time_t too_old);
+
+/* update the address associated to a MAC address*/
+void vx_find_in_hash_update(void *table, int hash_mask,
+ unsigned char *src, int vlan, struct sockaddr *addr, time_t
now);
+
+/* init the hash table */
+/* hash_mask must be 2^n - 1 */
+void *vx_hash_init(int sa_family, int hash_mask);
+#endif
+
Added: branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxlan.c
===================================================================
--- branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxlan.c
(rev 0)
+++ branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxlan.c 2014-02-07
11:48:49 UTC (rev 571)
@@ -0,0 +1,312 @@
+/*
+ * VDE - vde_vxlan Network emulator for vde
+ * Copyright (C) 2014 Renzo Davoli 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 <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <libvdeplug.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <time.h>
+#include "libvdeplug_mod.h"
+#include "libvdeplug_vxhash.h"
+
+#define STDPORTSTR "4879"
+#define STDTTL 1
+#define STDVNI 1
+#define STDHASHSIZE 1023
+#define STDEXPIRETIME 128
+
+#define ETH_ALEN 6
+#define ETH_HEADER_SIZE 14
+#define IS_BROADCAST(addr) ((addr[0] & 1) == 1)
+
+#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); \
+}
+
+struct eth_hdr {
+ unsigned char dest[ETH_ALEN];
+ unsigned char src[ETH_ALEN];
+ unsigned char proto[2];
+};
+
+struct vxlan_hdr {
+ unsigned char flags;
+ unsigned char priv1[3];
+ unsigned char id[3];
+ unsigned char priv2[1];
+};
+
+static char *vde_vxlan_check(char *given_sockname);
+static VDECONN *vde_vxlan_open(char *given_sockname, char *descr,int
interface_version,
+ struct vde_open_args *open_args);
+static ssize_t vde_vxlan_recv(VDECONN *conn,void *buf,size_t len,int flags);
+static ssize_t vde_vxlan_send(VDECONN *conn,const void *buf,size_t len,int
flags);
+static int vde_vxlan_datafd(VDECONN *conn);
+static int vde_vxlan_ctlfd(VDECONN *conn);
+static int vde_vxlan_close(VDECONN *conn);
+
+struct vde_vxlan_conn {
+ struct vdeplug_module *module;
+ void *table;
+ int hash_mask; // hash table size - 1. This must be 2^n-1
+ int vni;
+ union {
+ struct sockaddr vx;
+ struct sockaddr_in v4;
+ struct sockaddr_in6 v6;
+ } multiaddr;
+ int multifd;
+ int expiretime;
+};
+
+struct vdeplug_module vdeplug_vxlan={
+ .flags=ONLY_BY_CHECK,
+ .vde_check=vde_vxlan_check,
+ .vde_open_real=vde_vxlan_open,
+ .vde_recv=vde_vxlan_recv,
+ .vde_send=vde_vxlan_send,
+ .vde_datafd=vde_vxlan_datafd,
+ .vde_ctlfd=vde_vxlan_ctlfd,
+ .vde_close=vde_vxlan_close
+};
+
+static char *vde_vxlan_check(char *given_sockname) {
+ static char tag[]="VXLAN:";
+ static char atag[]="VXLAN/";
+ if (strncmp(given_sockname,tag,strlen(tag)) == 0)
+ return given_sockname+strlen(tag);
+ if (strncmp(given_sockname,atag,strlen(atag)) == 0) {
+ given_sockname[strlen(atag)-1]=':';
+ return given_sockname+strlen(atag);
+ }
+ return NULL;
+}
+
+static VDECONN *vde_vxlan_open(char *given_sockname, char *descr,int
interface_version,
+ struct vde_open_args *open_args)
+{
+ struct vde_vxlan_conn *newconn;
+ struct addrinfo hints;
+ struct addrinfo *result,*rp;
+ int s;
+ char *portstr;
+ char *vnistr;
+ struct sockaddr *multiaddr=NULL;
+ int multifd=-1;
+ int ttl=STDTTL;
+
+ /* TODO a more complete parsing of options: hash table size */
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
+ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
+ hints.ai_protocol = 0; /* Any protocol */
+ vnistr=strchr(given_sockname,'/');
+ if (vnistr) {
+ *vnistr=0;
+ vnistr++;
+ portstr=strchr(vnistr,'/');
+ if (portstr) {
+ *portstr=0;
+ portstr++;
+ } else
+ portstr=STDPORTSTR;
+ } else
+ portstr=STDPORTSTR;
+ s = getaddrinfo(given_sockname, portstr, &hints, &result);
+ if (s < 0) {
+ fprintf(stderr, "vxlan getaddrinfo: %s\n", gai_strerror(s));
+ errno=ENOENT;
+ return NULL;
+ }
+
+ /* TODO scan the list of results */
+ for (rp = result; rp != NULL; rp = rp->ai_next) {
+ switch (rp->ai_family) {
+ case AF_INET6:
+ // currently unsupported
+ continue;
+ case AF_INET: {
+
struct sockaddr_in *addr=(struct sockaddr_in *)(rp->ai_addr);
+
struct ip_mreq mc_req;
+
multiaddr = (struct sockaddr *) addr;
+
struct sockaddr_in bindaddr;
+
int loop = 0;
+
+
multifd=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+
if (multifd < 0)
+
return NULL;
+
if ((setsockopt(multifd, IPPROTO_IP, IP_MULTICAST_TTL,
+
&ttl, sizeof(ttl))) < 0) {
+
close(multifd);
+
multifd=-1;
+
return NULL;
+
}
+
if ((setsockopt(multifd, IPPROTO_IP, IP_MULTICAST_LOOP,
+
&loop, sizeof(loop))) < 0) {
+
close(multifd);
+
multifd=-1;
+
return NULL;
+
}
+
memset(&bindaddr, 0, sizeof(bindaddr));
+
bindaddr.sin_family = AF_INET;
+
bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
+
bindaddr.sin_port = addr->sin_port;
+
if ((bind(multifd, (struct sockaddr *) &bindaddr,
+
sizeof(bindaddr))) < 0) {
+
close(multifd);
+
multifd=-1;
+
continue;
+
}
+
mc_req.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
+
mc_req.imr_interface.s_addr = htonl(INADDR_ANY);
+
if ((setsockopt(multifd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+
&mc_req, sizeof(mc_req))) < 0) {
+
close(multifd);
+
multifd=-1;
+
return NULL;
+
}
+
}
+ }
+ }
+ if (multifd < 0)
+ return NULL;
+
+ if ((newconn=calloc(1,sizeof(struct vde_vxlan_conn)))==NULL)
+ {
+ errno=ENOMEM;
+ close(multifd);
+ return NULL;
+ }
+
+ newconn->module=&vdeplug_vxlan;
+ newconn->hash_mask=STDHASHSIZE;
+ newconn->table=vx_hash_init(AF_INET, newconn->hash_mask);
+ newconn->vni=vnistr?atoi(vnistr):STDVNI;
+ newconn->expiretime=STDEXPIRETIME;
+ switch (multiaddr->sa_family) {
+ case AF_INET:
+ memcpy(&(newconn->multiaddr.v4), multiaddr,
sizeof(struct sockaddr_in));
+ break;
+ case AF_INET6:
+ memcpy(&(newconn->multiaddr.v6), multiaddr,
sizeof(struct sockaddr_in6));
+ break;
+ }
+ newconn->multifd=multifd;
+ return (VDECONN *) newconn;
+}
+
+static ssize_t vde_vxlan_recv(VDECONN *conn,void *buf,size_t len,int flags) {
+ struct vde_vxlan_conn *vde_conn = (struct vde_vxlan_conn *)conn;
+ struct vxlan_hdr vhdr;
+ struct iovec iov[]={{&vhdr, sizeof(vhdr)},{buf, len}};
+ struct msghdr msg;
+ struct sockaddr_in6 sender;
+ int retval;
+ msg.msg_name=&sender;
+ switch (vde_conn->multiaddr.vx.sa_family) {
+ case AF_INET: msg.msg_namelen = sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6: msg.msg_namelen = sizeof(struct sockaddr_in6);
+ break;
+ default:
+
msg.msg_namelen = 0;
+ }
+ msg.msg_iov=iov;
+ msg.msg_iovlen=2;
+ msg.msg_control=NULL;
+ msg.msg_control=0;
+ msg.msg_flags=0;
+ if (__builtin_expect(((retval=recvmsg(vde_conn->multifd, &msg, 0)
+ -sizeof(struct
vxlan_hdr))>ETH_HEADER_SIZE), 1)) {
+ struct eth_hdr *ehdr=(struct eth_hdr *) buf;
+ if (vhdr.flags != (1<<0) || ntoh24(vhdr.id) != vde_conn->vni)
+ vx_find_in_hash_update(vde_conn->table, vde_conn->hash_mask,
+ ehdr->src, 1, msg.msg_name, time(NULL));
+ return retval;
+ }
+ return 0;
+}
+
+static ssize_t vde_vxlan_send(VDECONN *conn,const void *buf, size_t len,int
flags) {
+ struct vde_vxlan_conn *vde_conn = (struct vde_vxlan_conn *)conn;
+ struct vxlan_hdr vhdr;
+ struct iovec iov[]={{&vhdr, sizeof(vhdr)},{(char *)buf, len}};
+ struct sockaddr *destaddr;
+ static struct msghdr msg;
+ int retval;
+ msg.msg_iov=iov;
+ msg.msg_iovlen=2;
+ struct eth_hdr *ehdr=(struct eth_hdr *) buf;
+ if (len < ETH_HEADER_SIZE)
+ return len; // discard packets shorter than an ethernet header
+ if (IS_BROADCAST(ehdr->dest) ||
+ (destaddr=vx_find_in_hash(vde_conn->table,
vde_conn->multiaddr.vx.sa_family,
+ vde_conn->hash_mask, ehdr->dest, 1, time(NULL)-
vde_conn->expiretime)) == NULL)
+ /* MULTICAST */
+ msg.msg_name = &(vde_conn->multiaddr.vx);
+ else
+ /* UNICAST */
+ msg.msg_name = destaddr;
+ switch (vde_conn->multiaddr.vx.sa_family) {
+ case AF_INET: msg.msg_namelen = sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6: msg.msg_namelen = sizeof(struct sockaddr_in6);
+ break;
+ default:
+
msg.msg_namelen = 0;
+ }
+ memset(&vhdr, 0, sizeof(vhdr));
+ vhdr.flags = (1 << 3);
+
+ hton24(vhdr.id, vde_conn->vni);
+
+ if ((retval=sendmsg(vde_conn->multifd, &msg, 0)) < 0)
+ return -1;
+ retval -= sizeof(struct vxlan_hdr);
+ if (retval < 0)
+ retval = 0;
+ return retval;
+}
+
+static int vde_vxlan_datafd(VDECONN *conn) {
+ struct vde_vxlan_conn *vde_conn = (struct vde_vxlan_conn *)conn;
+ return vde_conn->multifd;
+}
+
+static int vde_vxlan_ctlfd(VDECONN *conn) {
+ return -1;
+}
+
+static int vde_vxlan_close(VDECONN *conn) {
+ struct vde_vxlan_conn *vde_conn = (struct vde_vxlan_conn *)conn;
+ close(vde_conn->multifd);
+ free(vde_conn);
+ return 0;
+}
Added: branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxvde.c
===================================================================
--- branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxvde.c
(rev 0)
+++ branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxvde.c 2014-02-07
11:48:49 UTC (rev 571)
@@ -0,0 +1,430 @@
+/*
+ * VDE - vde_vxvde Network emulator for vde
+ * Copyright (C) 2014 Renzo Davoli 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 <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <libvdeplug.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <time.h>
+#include <sys/epoll.h>
+#include "libvdeplug_mod.h"
+#include "libvdeplug_vxhash.h"
+
+#define STDPORTSTR "4879"
+#define STDTTL 1
+#define STDVNI 1
+#define STDHASHSIZE 1023
+#define STDEXPIRETIME 128
+
+#define ETH_ALEN 6
+#define ETH_HEADER_SIZE 14
+#define IS_BROADCAST(addr) ((addr[0] & 1) == 1)
+
+#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); \
+}
+
+struct eth_hdr {
+ unsigned char dest[ETH_ALEN];
+ unsigned char src[ETH_ALEN];
+ unsigned char proto[2];
+};
+
+struct vxvde_hdr {
+ unsigned char flags;
+ unsigned char priv1[3];
+ unsigned char id[3];
+ unsigned char priv2[1];
+};
+
+static char *vde_vxvde_check(char *given_sockname);
+static VDECONN *vde_vxvde_open(char *given_sockname, char *descr,int
interface_version,
+ struct vde_open_args *open_args);
+static ssize_t vde_vxvde_recv(VDECONN *conn,void *buf,size_t len,int flags);
+static ssize_t vde_vxvde_send(VDECONN *conn,const void *buf,size_t len,int
flags);
+static int vde_vxvde_datafd(VDECONN *conn);
+static int vde_vxvde_ctlfd(VDECONN *conn);
+static int vde_vxvde_close(VDECONN *conn);
+
+struct vde_vxvde_conn {
+ struct vdeplug_module *module;
+ void *table;
+ int hash_mask; // hash table size - 1. This must be 2^n-1
+ int vni;
+ union {
+ struct sockaddr vx;
+ struct sockaddr_in v4;
+ struct sockaddr_in6 v6;
+ } multiaddr;
+ int multifd;
+ int unifd;
+ int pollfd;
+ in_port_t multiport;
+ in_port_t uniport;
+ int expiretime;
+};
+
+struct vdeplug_module vdeplug_vxvde={
+ .flags=ONLY_BY_CHECK,
+ .vde_check=vde_vxvde_check,
+ .vde_open_real=vde_vxvde_open,
+ .vde_recv=vde_vxvde_recv,
+ .vde_send=vde_vxvde_send,
+ .vde_datafd=vde_vxvde_datafd,
+ .vde_ctlfd=vde_vxvde_ctlfd,
+ .vde_close=vde_vxvde_close
+};
+
+static char *vde_vxvde_check(char *given_sockname) {
+ static char tag[]="VXVDE:";
+ static char atag[]="VXVDE/";
+ if (strncmp(given_sockname,tag,strlen(tag)) == 0)
+ return given_sockname+strlen(tag);
+ if (strncmp(given_sockname,atag,strlen(atag)) == 0) {
+ given_sockname[strlen(atag)-1]=':';
+ return given_sockname+strlen(atag);
+ }
+ return NULL;
+}
+
+static VDECONN *vde_vxvde_open(char *given_sockname, char *descr,int
interface_version,
+ struct vde_open_args *open_args)
+{
+ struct vde_vxvde_conn *newconn=NULL;
+ struct addrinfo hints;
+ struct addrinfo *result,*rp;
+ int s;
+ char *portstr;
+ char *vnistr;
+ struct sockaddr *multiaddr=NULL;
+ int multifd=-1;
+ int unifd=-1;
+ int pollfd=-1;
+ int ttl=STDTTL;
+ in_port_t uniport;
+
+ /* TODO a more complete parsing of options: hash table size */
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
+ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
+ hints.ai_protocol = 0; /* Any protocol */
+ vnistr=strchr(given_sockname,'/');
+ if (vnistr) {
+ *vnistr=0;
+ vnistr++;
+ portstr=strchr(vnistr,'/');
+ if (portstr) {
+ *portstr=0;
+ portstr++;
+ } else
+ portstr=STDPORTSTR;
+ } else
+ portstr=STDPORTSTR;
+ s = getaddrinfo(given_sockname, portstr, &hints, &result);
+ if (s < 0) {
+ fprintf(stderr, "vxvde getaddrinfo: %s\n", gai_strerror(s));
+ errno=ENOENT;
+ return NULL;
+ }
+
+ /* TODO scan the list of results */
+ for (rp = result; rp != NULL; rp = rp->ai_next) {
+ switch (rp->ai_family) {
+ case AF_INET6:
+ // currently unsupported
+ continue;
+ case AF_INET: {
+
struct sockaddr_in *addr=(struct sockaddr_in *)(rp->ai_addr);
+
struct ip_mreqn mc_req;
+
multiaddr = (struct sockaddr *) addr;
+
struct sockaddr_in bindaddr;
+
socklen_t bindaddrlen;
+
int one = 1;
+
+
if ((multifd=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+
goto error;
+
if ((unifd=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+
goto error;
+
if ((setsockopt(multifd, IPPROTO_IP, IP_MULTICAST_TTL,
+
&ttl, sizeof(ttl))) < 0)
+
goto error;
+
int loop=0;
+
if ((setsockopt(multifd, IPPROTO_IP, IP_MULTICAST_LOOP,
+
&loop, sizeof(loop))) < 0)
+
goto error;
+
if ((setsockopt(multifd, IPPROTO_IP, IP_PKTINFO,
+
&one, sizeof(one))) < 0)
+
goto error;
+#ifdef SO_REUSEPORT
+
if ((setsockopt(multifd, SOL_SOCKET, SO_REUSEPORT,
+
&one, sizeof(one))) < 0)
+
goto error;
+#endif
+
memset(&bindaddr, 0, sizeof(bindaddr));
+
memset(&bindaddr, 0, sizeof(bindaddr));
+
bindaddr.sin_family = AF_INET;
+
bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
+
bindaddr.sin_port = addr->sin_port;
+
if ((bind(multifd, (struct sockaddr *) &bindaddr,
+
sizeof(bindaddr))) < 0) {
+
close(multifd);
+
close(unifd);
+
multifd=unifd=-1;
+
continue;
+
}
+
mc_req.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
+
mc_req.imr_address.s_addr = htonl(INADDR_ANY);
+
mc_req.imr_ifindex = 0;
+
if ((setsockopt(multifd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+
&mc_req, sizeof(mc_req))) < 0)
+
goto error;
+
bindaddr.sin_port = 0;
+
if ((bind(unifd, (struct sockaddr *) &bindaddr,
+
sizeof(bindaddr))) < 0) {
+
close(multifd);
+
close(unifd);
+
multifd=unifd=-1;
+
continue;
+
}
+
bindaddrlen=sizeof(bindaddr);
+
if (getsockname(unifd, (struct sockaddr *) &bindaddr,
+
&bindaddrlen) < 0)
+
goto error;
+
uniport=bindaddr.sin_port;
+
//fprintf(stderr,"local port %d\n",ntohs(bindaddr.sin_port));
+
/*static char buf[]="test";
+
socklen_t addrs=sizeof(struct sockaddr_in);
+
sendto(unifd, buf, strlen(buf)+1, 0, (struct sockaddr *) addr, addrs);*/
+
}
+ }
+ }
+ if (multifd < 0)
+ return NULL;
+
+ if ((pollfd = epoll_create1(0)) < 0)
+ goto error;
+ else {
+ struct epoll_event ev;
+ ev.events = EPOLLIN;
+ ev.data.fd = multifd;
+ if (epoll_ctl(pollfd, EPOLL_CTL_ADD, multifd, &ev) < 0)
+ goto error;
+ ev.data.fd = unifd;
+ if (epoll_ctl(pollfd, EPOLL_CTL_ADD, unifd, &ev) < 0)
+ goto error;
+ }
+
+ if ((newconn=calloc(1,sizeof(struct vde_vxvde_conn)))==NULL) {
+ errno=ENOMEM;
+ goto error;
+ }
+
+ newconn->module=&vdeplug_vxvde;
+ newconn->hash_mask=STDHASHSIZE;
+ newconn->table=vx_hash_init(AF_INET, newconn->hash_mask);
+ newconn->vni=vnistr?atoi(vnistr):STDVNI;
+ newconn->expiretime=STDEXPIRETIME;
+ switch (multiaddr->sa_family) {
+ case AF_INET:
+ memcpy(&(newconn->multiaddr.v4), multiaddr,
sizeof(struct sockaddr_in));
+ newconn->multiport = newconn->multiaddr.v4.sin_port;
+ break;
+ case AF_INET6:
+ memcpy(&(newconn->multiaddr.v6), multiaddr,
sizeof(struct sockaddr_in6));
+ newconn->multiport = newconn->multiaddr.v6.sin6_port;
+ break;
+ }
+ newconn->multifd=multifd;
+ newconn->unifd=unifd;
+ newconn->uniport=uniport;
+ newconn->pollfd=pollfd;
+ return (VDECONN *) newconn;
+
+error:
+ if (multifd >= 0) close(multifd);
+ if (unifd >= 0) close(unifd);
+ if (pollfd >= 0) close(pollfd);
+ if (newconn != NULL) free(newconn);
+ return NULL;
+}
+
+static ssize_t vde_vxvde_recv(VDECONN *conn,void *buf,size_t len,int flags) {
+ struct vde_vxvde_conn *vde_conn = (struct vde_vxvde_conn *)conn;
+ struct epoll_event events[1];
+ int nfd = epoll_wait(vde_conn->pollfd, events, 1, 0);
+ if (nfd > 0) {
+ if (events[0].data.fd == vde_conn->unifd) {
+ int retval;
+ struct sockaddr_in sender;
+ socklen_t senderlen=sizeof(sender);
+ retval = recvfrom(vde_conn->unifd, buf, len, 0,
+ (struct sockaddr *) &sender,
&senderlen);
+ //fprintf(stderr, "<- unicast packet len %d\n",retval);
+ if (__builtin_expect((retval > ETH_HEADER_SIZE), 1)) {
+ struct eth_hdr *ehdr=(struct eth_hdr *) buf;
+ vx_find_in_hash_update(vde_conn->table,
vde_conn->hash_mask,
+ ehdr->src, 1, (struct sockaddr
*) &sender, time(NULL));
+ return retval;
+ } else
+ goto error;
+ } else /*if (events[0].data.fd == vde_conn->multifd)*/ {
+ struct vxvde_hdr vhdr;
+ struct iovec iov[]={{&vhdr, sizeof(vhdr)},{buf, len}};
+ struct msghdr msg;
+ struct sockaddr_in sender;
+
+ char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))+1024];
+ int retval;
+ msg.msg_name=&sender;
+ switch (vde_conn->multiaddr.vx.sa_family) {
+ case AF_INET: msg.msg_namelen = sizeof(struct
sockaddr_in);
+
break;
+ case AF_INET6: msg.msg_namelen = sizeof(struct
sockaddr_in6);
+
break;
+ default:
+
msg.msg_namelen = 0;
+ }
+ msg.msg_iov=iov;
+ msg.msg_iovlen=2;
+ msg.msg_control=cmsg;
+ msg.msg_controllen=sizeof(cmsg);
+ msg.msg_flags=0;
+ retval=recvmsg(vde_conn->multifd, &msg,
0)-sizeof(struct vxvde_hdr);
+ //fprintf(stderr, "<- multicast packet len
%d\n",retval);
+ if (__builtin_expect((retval > ETH_HEADER_SIZE), 1)) {
+ struct eth_hdr *ehdr=(struct eth_hdr *) buf;
+ if (sender.sin_port == vde_conn->uniport) {
+ struct cmsghdr
*cmsgptr=CMSG_FIRSTHDR(&msg);
+ struct in_pktinfo *pki=(struct
in_pktinfo*)(CMSG_DATA(cmsgptr));
+ if (sender.sin_addr.s_addr ==
pki->ipi_spec_dst.s_addr) {
+ //fprintf(stderr,"self packet,
rejected \n");
+ goto error;
+ }
+ }
+ if (vhdr.flags != (1<<0) || ntoh24(vhdr.id) !=
vde_conn->vni)
+ vx_find_in_hash_update(vde_conn->table,
vde_conn->hash_mask,
+ ehdr->src, 1,
msg.msg_name, time(NULL));
+ return retval;
+ }
+ /*
+ struct cmsghdr *cmsgptr=CMSG_FIRSTHDR(&msg);
+ struct in_pktinfo *pki=(struct
in_pktinfo*)(CMSG_DATA(cmsgptr));
+ fprintf(stderr,"%d %s ",msg.msg_controllen,
inet_ntoa(pki->ipi_spec_dst));
+ fprintf(stderr,"%s- ",inet_ntoa(pki->ipi_addr));
+ fprintf(stderr,"%s port
%d\n",inet_ntoa(sender.sin_addr),ntohs(sender.sin_port));
+ */
+ goto error;
+ }
+ }
+error:
+ errno = EAGAIN;
+ *((unsigned char *)buf)=0;
+ return 1;
+}
+
+static ssize_t vde_vxvde_vxsend(struct vde_vxvde_conn *vde_conn,
+ struct sockaddr *destaddr, const void *buf, size_t len,int
flags) {
+ struct vxvde_hdr vhdr;
+ struct iovec iov[]={{&vhdr, sizeof(vhdr)},{(char *)buf, len}};
+ static struct msghdr msg;
+ int retval;
+ msg.msg_iov=iov;
+ msg.msg_iovlen=2;
+ msg.msg_name = destaddr;
+ switch (destaddr->sa_family) {
+ case AF_INET: msg.msg_namelen = sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6: msg.msg_namelen = sizeof(struct sockaddr_in6);
+ break;
+ default:
+
msg.msg_namelen = 0;
+ }
+ memset(&vhdr, 0, sizeof(vhdr));
+ vhdr.flags = (1 << 3);
+
+ hton24(vhdr.id, vde_conn->vni);
+
+ if ((retval=sendmsg(vde_conn->unifd, &msg, 0)) < 0)
+ return -1;
+ retval -= sizeof(struct vxvde_hdr);
+ if (retval < 0)
+ retval = 0;
+ return retval;
+}
+
+static ssize_t vde_vxvde_send(VDECONN *conn,const void *buf, size_t len,int
flags) {
+ struct vde_vxvde_conn *vde_conn = (struct vde_vxvde_conn *)conn;
+ struct eth_hdr *ehdr=(struct eth_hdr *) buf;
+ struct sockaddr *destaddr;
+ if (len < ETH_HEADER_SIZE)
+ return len; // discard packets shorter than an ethernet header
+ if (__builtin_expect(
+ (IS_BROADCAST(ehdr->dest) ||
+ (destaddr=vx_find_in_hash(vde_conn->table,
vde_conn->multiaddr.vx.sa_family,
+ vde_conn->hash_mask, ehdr->dest, 1, time(NULL)-
vde_conn->expiretime)) == NULL),
+ 0)) {
+ return vde_vxvde_vxsend(vde_conn, &(vde_conn->multiaddr.vx),
buf, len, flags);
+ } else {
+ socklen_t destlen;
+ in_port_t destport;
+ switch (destaddr->sa_family) {
+ case AF_INET: destlen = sizeof(struct sockaddr_in);
+
destport = ((struct sockaddr_in *) destaddr)->sin_port;
+
break;
+ case AF_INET6: destlen = sizeof(struct sockaddr_in6);
+
destport = ((struct sockaddr_in6 *) destaddr)->sin6_port;
+
break;
+ default:
+
destlen = 0;
+
destport = 0;
+ }
+ if (__builtin_expect(destport != vde_conn->multiport, 1)) {
+ return sendto(vde_conn->unifd, buf, len, 0, destaddr,
destlen);
+ } else { /* compatibility with vxlan! */
+ return vde_vxvde_vxsend(vde_conn, destaddr, buf, len,
flags);
+ }
+ }
+}
+
+static int vde_vxvde_datafd(VDECONN *conn) {
+ struct vde_vxvde_conn *vde_conn = (struct vde_vxvde_conn *)conn;
+ return vde_conn->pollfd;
+}
+
+static int vde_vxvde_ctlfd(VDECONN *conn) {
+ return -1;
+}
+
+static int vde_vxvde_close(VDECONN *conn) {
+ struct vde_vxvde_conn *vde_conn = (struct vde_vxvde_conn *)conn;
+ close(vde_conn->multifd);
+ free(vde_conn);
+ return 0;
+}
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
Managing the Performance of Cloud-Based Applications
Take advantage of what the Cloud has to offer - Avoid Common Pitfalls.
Read the Whitepaper.
http://pubads.g.doubleclick.net/gampad/clk?id=121051231&iu=/4140/ostg.clktrk
_______________________________________________
vde-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/vde-users