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
vde-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/vde-users

Reply via email to