Revision: 576
http://sourceforge.net/p/vde/svn/576
Author: rd235
Date: 2014-02-08 21:35:19 +0000 (Sat, 08 Feb 2014)
Log Message:
-----------
vxvde on IPv6 almost complete: self pkt missing
Modified Paths:
--------------
branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxvde.c
Modified: branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxvde.c
===================================================================
--- branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxvde.c 2014-02-08
16:48:32 UTC (rev 575)
+++ branches/rd235/vde-2/src/lib/libvdeplug/libvdeplug_vxvde.c 2014-02-08
21:35:19 UTC (rev 576)
@@ -25,12 +25,13 @@
#include <errno.h>
#include <limits.h>
#include <stdint.h>
+#include <time.h>
+#include <sys/epoll.h>
+#define __USE_GNU
#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"
@@ -114,6 +115,37 @@
return NULL;
}
+static inline socklen_t fam2socklen(void *sockaddr)
+{
+ struct sockaddr *s=sockaddr;
+ switch (s->sa_family) {
+ case AF_INET: return sizeof(struct sockaddr_in);
+ case AF_INET6: return sizeof(struct sockaddr_in6);
+ default: return 0;
+ }
+}
+
+#if 0
+static inline void printaddr(char *msg, void *sockaddr)
+{
+ struct sockaddr *s=sockaddr;
+ struct sockaddr_in *s4=sockaddr;
+ struct sockaddr_in6 *s6=sockaddr;
+ char saddr[INET6_ADDRSTRLEN];
+ switch (s->sa_family) {
+ case AF_INET:
+ fprintf(stderr,"%s %s\n",msg,inet_ntop(AF_INET,
&s4->sin_addr, saddr, sizeof(*s4)));
+ break;
+ case AF_INET6:
+ fprintf(stderr,"%s %s\n",msg,inet_ntop(AF_INET6,
&s6->sin6_addr, saddr, sizeof(*s6)));
+ break;
+ default:
+ fprintf(stderr,"%s UNKNOWN FAMILY
%d\n",msg,s->sa_family);
+ break;
+ }
+}
+#endif
+
static VDECONN *vde_vxvde_open(char *given_sockname, char *descr,int
interface_version,
struct vde_open_args *open_args)
{
@@ -136,9 +168,9 @@
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_protocol = 0; /* Any protocol */
- sockname=strsep(&given_sockname,":/");
- vnistr=strsep(&given_sockname,":/");
- if ((portstr=strsep(&given_sockname,":/")) == NULL)
+ sockname=strsep(&given_sockname,"/");
+ vnistr=strsep(&given_sockname,"/");
+ if ((portstr=strsep(&given_sockname,"/")) == NULL)
portstr=STDPORTSTR;
s = getaddrinfo(sockname, portstr, &hints, &result);
if (s < 0) {
@@ -150,22 +182,76 @@
/* TODO scan the list of results */
for (rp = result; rp != NULL; rp = rp->ai_next) {
switch (rp->ai_family) {
- case AF_INET6:
+ case AF_INET6: {
// currently unsupported
- continue;
+
struct sockaddr_in6 *addr=(struct sockaddr_in6 *)(rp->ai_addr);
+
struct ipv6_mreq mc_req;
+
struct sockaddr_in6 bindaddr;
+
socklen_t bindaddrlen;
+
int one = 1;
+
multiaddr = (struct sockaddr *) addr;
+
+
if ((multifd=socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+
goto error;
+
if ((unifd=socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+
goto error;
+
if ((setsockopt(unifd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+
&ttl, sizeof(ttl))) < 0)
+
goto error;
+
if ((setsockopt(multifd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
+
&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));
+
bindaddr.sin6_family = AF_INET6;
+
memcpy(&bindaddr.sin6_addr, &in6addr_any, sizeof(in6addr_any));
+
bindaddr.sin6_port = addr->sin6_port;
+
if ((bind(multifd, (struct sockaddr *) &bindaddr,
+
sizeof(bindaddr))) < 0) {
+
+
close(multifd);
+
close(unifd);
+
multifd=unifd=-1;
+
continue;
+
}
+
memcpy(&mc_req.ipv6mr_multiaddr, &addr->sin6_addr,
+
sizeof(addr->sin6_addr));
+
mc_req.ipv6mr_interface = 0;
+
if ((setsockopt(multifd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
+
&mc_req, sizeof(mc_req))) < 0)
+
goto error;
+
bindaddr.sin6_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.sin6_port;
+
break;
+
}
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;
+
multiaddr = (struct sockaddr *) addr;
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,
+
if ((setsockopt(unifd, IPPROTO_IP, IP_MULTICAST_TTL,
&ttl, sizeof(ttl))) < 0)
goto error;
int loop=0;
@@ -181,7 +267,6 @@
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;
@@ -275,11 +360,12 @@
if (nfd > 0) {
if (events[0].data.fd == vde_conn->unifd) {
int retval;
- struct sockaddr_in sender;
+ struct sockaddr_storage 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);
+ //printaddr("recv uni",&sender);
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,
@@ -291,19 +377,11 @@
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];
+ struct sockaddr_storage sender;
+ char cmsg[CMSG_SPACE(sizeof(struct
in6_pktinfo)+sizeof(struct in_pktinfo))];
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_namelen = fam2socklen(&vde_conn->multiaddr.vx);
msg.msg_iov=iov;
msg.msg_iovlen=2;
msg.msg_control=cmsg;
@@ -311,28 +389,47 @@
msg.msg_flags=0;
retval=recvmsg(vde_conn->multifd, &msg,
0)-sizeof(struct vxvde_hdr);
//fprintf(stderr, "<- multicast packet len
%d\n",retval);
+ //printaddr("recv multi",&sender);
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;
- }
+ switch (sender.ss_family) {
+ case AF_INET: {
+
struct sockaddr_in *sender4=(struct sockaddr_in
*)&sender;
+
if (sender4->sin_port == vde_conn->uniport) {
+
struct cmsghdr *cmsgptr=CMSG_FIRSTHDR(&msg);
+
struct in_pktinfo *pki=(struct in_pktinfo
*)(CMSG_DATA(cmsgptr));
+
if (sender4->sin_addr.s_addr ==
pki->ipi_spec_dst.s_addr) {
+
//fprintf(stderr,"self packet, rejected
\n");
+
goto error;
+
}
+
}
+
}
+ case AF_INET6: {
+
struct sockaddr_in6 *sender6=(struct sockaddr_in6
*)&sender;
+#if 0
+
{
+
struct cmsghdr *cmsgptr=CMSG_FIRSTHDR(&msg);
+
struct in6_pktinfo *pki=(struct in6_pktinfo
*)(CMSG_DATA(cmsgptr));
+
char saddr[INET6_ADDRSTRLEN];
+
fprintf(stderr,"CMPCMP %s
%d\n",inet_ntop(AF_INET6, &pki->ipi6_addr, saddr,
sizeof(pki->ipi6_addr)),pki->ipi6_ifindex);
+
}
+#endif
+
/* XXX this fails to recognize self sent packets */
+
if (sender6->sin6_port == vde_conn->uniport) {
+
struct cmsghdr *cmsgptr=CMSG_FIRSTHDR(&msg);
+
struct in6_pktinfo *pki=(struct in6_pktinfo
*)(CMSG_DATA(cmsgptr));
+
if (memcmp(&sender6->sin6_addr,
&pki->ipi6_addr, sizeof(struct in6_addr)) == 0) {
+
//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;
}
}
@@ -361,14 +458,8 @@
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;
- }
+ msg.msg_namelen = fam2socklen(destaddr);
+ //printaddr("send multi",destaddr);
memset(&vhdr, 0, sizeof(vhdr));
vhdr.flags = (1 << 3);
@@ -381,15 +472,8 @@
retval = 0;
return retval;
} else {
- socklen_t destlen;
- switch (destaddr->sa_family) {
- case AF_INET: destlen = sizeof(struct sockaddr_in);
-
break;
- case AF_INET6: destlen = sizeof(struct sockaddr_in6);
-
break;
- default:
-
destlen = 0;
- }
+ socklen_t destlen = fam2socklen(destaddr);
+ //printaddr("send uni",destaddr);
return sendto(vde_conn->unifd, buf, len, 0, destaddr, destlen);
}
}
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
