]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
sdp: ipv6 support
authorAmir Vadai <amirv@mellanox.co.il>
Mon, 27 Dec 2010 09:58:26 +0000 (11:58 +0200)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Tue, 6 Oct 2015 12:05:37 +0000 (05:05 -0700)
Signed-off-by: Amir Vadai <amirv@mellanox.co.il>
drivers/infiniband/ulp/sdp/sdp.h
drivers/infiniband/ulp/sdp/sdp_cma.c
drivers/infiniband/ulp/sdp/sdp_main.c
drivers/infiniband/ulp/sdp/sdp_proc.c
include/rdma/sdp_socket.h

index 5bce6caa1c6506d42e808cf09b04c87b8a0d191a..828f3c58021094aef81f08dc9455649574620077 100644 (file)
 #include <rdma/ib_cm.h>
 #include "sdp_dbg.h"
 
+#ifndef NIPQUAD
+#define NIPQUAD(addr) \
+        ((unsigned char *)&addr)[0], \
+        ((unsigned char *)&addr)[1], \
+        ((unsigned char *)&addr)[2], \
+        ((unsigned char *)&addr)[3]
+#endif
+
+#ifndef NIPQUAD_FMT
+#define NIPQUAD_FMT "%u.%u.%u.%u"
+#endif
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#ifndef NIP6
+#define NIP6(addr) \
+        ntohs((addr).s6_addr16[0]), \
+        ntohs((addr).s6_addr16[1]), \
+        ntohs((addr).s6_addr16[2]), \
+        ntohs((addr).s6_addr16[3]), \
+        ntohs((addr).s6_addr16[4]), \
+        ntohs((addr).s6_addr16[5]), \
+        ntohs((addr).s6_addr16[6]), \
+        ntohs((addr).s6_addr16[7])
+#endif
+
+#ifndef NIP6_FMT
+#define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
+#endif
+#endif
+
 #define sk_ssk(ssk) ((struct sock *)ssk)
 
 /* Interval between sucessive polls in the Tx routine when polling is used
@@ -455,6 +485,9 @@ struct sdp_sock {
        int inline_thresh;
 
        int last_bind_err;
+
+       /* ipv6_pinfo has to be the last member of tcp6_sock, see inet6_sk_generic */
+       struct ipv6_pinfo inet6;
 };
 
 static inline void tx_sa_reset(struct tx_srcavail_state *tx_sa)
index bc1bf172e84dc6a059cfe8cdf888318b302b5595..d06c01b6f9676ac52f4066f8ebf27b340491a07f 100644 (file)
@@ -381,7 +381,12 @@ int sdp_cma_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
                hh.bsdh.mid = SDP_MID_HELLO;
                hh.bsdh.len = htonl(sizeof(struct sdp_hh));
                hh.max_adverts = 1;
-               hh.ipv_cap = 0x40;
+       
+               hh.ipv_cap = 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+                       inet6_sk(sk) ? 0x60 : 
+#endif
+                       0x40;
                hh.majv_minv = SDP_MAJV_MINV;
                sdp_init_buffers(sdp_sk(sk), rcvbuf_initial_size);
                hh.bsdh.bufs = htons(rx_ring_posted(sdp_sk(sk)));
@@ -389,8 +394,17 @@ int sdp_cma_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
                                rx_ring_posted(sdp_sk(sk)));
                hh.localrcvsz = hh.desremrcvsz = htonl(sdp_sk(sk)->recv_frags *
                                PAGE_SIZE + sizeof(struct sdp_bsdh));
-               inet_sk(sk)->saddr = inet_sk(sk)->rcv_saddr =
-                       ((struct sockaddr_in *)&id->route.addr.src_addr)->sin_addr.s_addr;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+               if (inet6_sk(sk)) {
+                       inet6_sk(sk)->saddr = inet6_sk(sk)->rcv_saddr =
+                               ((struct sockaddr_in6 *)&id->route.addr.src_addr)->sin6_addr;
+               }
+                       else 
+#endif
+               {
+                       inet_sk(sk)->saddr = inet_sk(sk)->rcv_saddr =
+                               ((struct sockaddr_in *)&id->route.addr.src_addr)->sin_addr.s_addr;
+               }
                memset(&conn_param, 0, sizeof conn_param);
                conn_param.private_data_len = sizeof hh;
                conn_param.private_data = &hh;
index 7824ebd6023e3e8ceff4415419078509cf613c71..f92d645605fb5846f1f35b44f5d5c73959817f6e 100644 (file)
@@ -67,6 +67,7 @@ unsigned int csum_partial_copy_from_user_new (const char *src, char *dst,
 #include <linux/socket.h>
 #include <net/protocol.h>
 #include <net/inet_common.h>
+#include <net/ipv6.h>
 #include <rdma/rdma_cm.h>
 #include <rdma/ib_fmr_pool.h>
 #include <rdma/ib_verbs.h>
@@ -149,17 +150,12 @@ static int sdp_get_port(struct sock *sk, unsigned short snum)
 {
        struct sdp_sock *ssk = sdp_sk(sk);
        struct sockaddr_in *src_addr;
+       int addr_len;
        int rc;
 
-       struct sockaddr_in addr = {
-               .sin_family = AF_INET,
-               .sin_port = htons(snum),
-               .sin_addr.s_addr = inet_sk(sk)->rcv_saddr,
-       };
+       struct sockaddr_storage addr;
 
        sdp_add_to_history(sk, __func__);
-       sdp_dbg(sk, "%s: %u.%u.%u.%u:%hu\n", __func__,
-               NIPQUAD(addr.sin_addr.s_addr), ntohs(addr.sin_port));
 
        if (!ssk->id)
                ssk->id = rdma_create_id(sdp_cma_handler, sk, RDMA_PS_SDP);
@@ -167,9 +163,36 @@ static int sdp_get_port(struct sock *sk, unsigned short snum)
        if (!ssk->id)
               return -ENOMEM;
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       if (inet6_sk(sk)) {
+               struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
+               addr6->sin6_family = AF_INET6,
+               addr6->sin6_port = htons(snum),
+               ipv6_addr_copy(&addr6->sin6_addr, &inet6_sk(sk)->rcv_saddr);
+
+               addr_len = sizeof addr6;
+
+               sdp_dbg(sk, "%s: " NIP6_FMT ":%u\n", __func__,
+                               NIP6(addr6->sin6_addr), ntohs(addr6->sin6_port));
+       }
+               else 
+#endif
+       {
+               struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
+
+               addr4->sin_family = AF_INET,
+               addr4->sin_port = htons(snum),
+               addr4->sin_addr.s_addr = inet_sk(sk)->rcv_saddr;
+
+               addr_len = sizeof addr4;
+
+               sdp_dbg(sk, "%s: " NIPQUAD_FMT ":%u\n", __func__,
+                               NIPQUAD(addr4->sin_addr.s_addr), ntohs(addr4->sin_port));
+       }
+
        /* IP core seems to bind many times to the same address */
        /* TODO: I don't really understand why. Find out. */
-       if (!memcmp(&addr, &ssk->id->route.addr.src_addr, sizeof addr))
+       if (!memcmp(&addr, &ssk->id->route.addr.src_addr, addr_len))
                return 0;
 
        rc = ssk->last_bind_err = rdma_bind_addr(ssk->id, (struct sockaddr *)&addr);
@@ -760,7 +783,49 @@ out:
        sdp_common_release(sk);
 }
 
-static int sdp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static int sdp_ipv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+{
+       struct sdp_sock *ssk = sdp_sk(sk);
+       struct sockaddr_in6 src_addr = {
+               .sin6_family = AF_INET6,
+               .sin6_port = htons(inet_sk(sk)->sport),
+       };
+       int rc;
+
+       if (addr_len < SIN6_LEN_RFC2133) 
+               return -EINVAL;
+
+       if (!inet6_sk(sk))
+               return -EAFNOSUPPORT;
+
+       src_addr.sin6_addr = inet6_sk(sk)->saddr;
+
+       if (!ssk->id) {
+               rc = sdp_get_port(sk, 0);
+               if (rc)
+                       return rc;
+               inet_sk(sk)->sport = htons(inet_sk(sk)->num);
+       }
+
+       rc = rdma_resolve_addr(ssk->id, (struct sockaddr *)&src_addr,
+                              uaddr, SDP_RESOLVE_TIMEOUT);
+       if (rc) {
+               sdp_dbg(sk, "rdma_resolve_addr failed: %d\n", rc);
+               return rc;
+       }
+
+       sdp_dbg(sk, "%s " NIP6_FMT ":%hu -> " NIP6_FMT ":%hu\n", __func__,
+               NIP6(src_addr.sin6_addr),
+               ntohs(src_addr.sin6_port),
+               NIP6(((struct sockaddr_in6 *)uaddr)->sin6_addr),
+               ntohs(((struct sockaddr_in6 *)uaddr)->sin6_port));
+
+       return 0;
+}
+#endif
+
+static int sdp_ipv4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 {
        struct sdp_sock *ssk = sdp_sk(sk);
        struct sockaddr_in src_addr = {
@@ -770,25 +835,11 @@ static int sdp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        };
        int rc;
 
-       sdp_add_to_history(sk, __func__);
-       ssk->cpu = smp_processor_id();
-       release_sock(sk);
-       flush_workqueue(sdp_wq);
-       lock_sock(sk);
-       if (sk->sk_err) {
-               sdp_warn(sk, "Can't connect, socket marked with error: %d\n",
-                               sk->sk_err);
-               return -sk->sk_err;
-       }
+       sdp_warn(sk, "Connecting. addr_len = %d\n", addr_len);
 
         if (addr_len < sizeof(struct sockaddr_in))
                 return -EINVAL;
 
-       if (uaddr->sa_family == AF_INET_SDP)
-               uaddr->sa_family = AF_INET;
-       else if (uaddr->sa_family != AF_INET)
-               return -EAFNOSUPPORT;
-
        if (!ssk->id) {
                rc = sdp_get_port(sk, 0);
                if (rc)
@@ -796,19 +847,58 @@ static int sdp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                inet_sk(sk)->sport = htons(inet_sk(sk)->num);
        }
 
+       rc = rdma_resolve_addr(ssk->id, (struct sockaddr *)&src_addr,
+                              uaddr, SDP_RESOLVE_TIMEOUT);
+       if (rc) {
+               sdp_dbg(sk, "rdma_resolve_addr failed: %d\n", rc);
+               return rc;
+       }
+
        sdp_dbg(sk, "%s %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n", __func__,
                NIPQUAD(src_addr.sin_addr.s_addr),
                ntohs(src_addr.sin_port),
                NIPQUAD(((struct sockaddr_in *)uaddr)->sin_addr.s_addr),
                ntohs(((struct sockaddr_in *)uaddr)->sin_port));
 
-       rc = rdma_resolve_addr(ssk->id, (struct sockaddr *)&src_addr,
-                              uaddr, SDP_RESOLVE_TIMEOUT);
-       if (rc) {
-               sdp_dbg(sk, "rdma_resolve_addr failed: %d\n", rc);
-               return rc;
+       return 0;
+}
+
+static int sdp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+{
+       struct sdp_sock *ssk = sdp_sk(sk);
+       int rc;
+
+       sdp_add_to_history(sk, __func__);
+       ssk->cpu = smp_processor_id();
+       release_sock(sk);
+       flush_workqueue(sdp_wq);
+       lock_sock(sk);
+       if (sk->sk_err) {
+               sdp_warn(sk, "Can't connect, socket marked with error: %d\n",
+                               sk->sk_err);
+               return -sk->sk_err;
        }
 
+       /* Treat AF_INET_SDP as if it is AF_INET */
+       if (uaddr->sa_family == AF_INET_SDP)
+               uaddr->sa_family = AF_INET;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       else if (uaddr->sa_family == AF_INET6_SDP)
+               uaddr->sa_family = AF_INET6;
+#endif
+
+       if (uaddr->sa_family == AF_INET)
+               rc = sdp_ipv4_connect(sk, uaddr, addr_len);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       else if (uaddr->sa_family == AF_INET6)
+               rc = sdp_ipv6_connect(sk, uaddr, addr_len);
+#endif
+       else
+               rc = -EAFNOSUPPORT;
+
+       if (rc)
+               return rc;
+
        sdp_exch_state(sk, TCPF_CLOSE, TCP_SYN_SENT);
        return 0;
 }
@@ -2587,6 +2677,32 @@ recv_urg:
        goto out;
 }
 
+static int sdp_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+{
+       struct sock *sk = sock->sk;
+       int rc = -EAFNOSUPPORT; 
+
+       switch (uaddr->sa_family) {
+               case AF_INET:
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+                       if (inet6_sk(sk))
+                               rc = -EINVAL;
+                       else
+#endif
+                               rc = inet_bind(sock, uaddr, addr_len);
+                       break;
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+               case AF_INET6:
+                       if (inet6_sk(sk))
+                               rc = inet6_bind(sock, uaddr, addr_len);
+                       break;
+#endif
+       }
+
+       return rc;
+}
+
 static int sdp_listen(struct sock *sk, int backlog)
 {
        struct sdp_sock *ssk = sdp_sk(sk);
@@ -2753,7 +2869,7 @@ static struct proto_ops sdp_proto_ops = {
        .family     = PF_INET,
        .owner      = THIS_MODULE,
        .release    = inet_release,
-       .bind       = inet_bind,
+       .bind       = sdp_bind,
        .connect    = inet_stream_connect, /* TODO: inet_datagram connect would
                                              autobind, but need to fix get_port
                                              with port 0 first. */
@@ -2772,7 +2888,7 @@ static struct proto_ops sdp_proto_ops = {
        .sendpage   = sock_no_sendpage,
 };
 
-static int sdp_create_socket(struct net *net, struct socket *sock, int protocol)
+static int sdp_create_ipvx_socket(struct net *net, struct socket *sock, int protocol)
 {
        struct sock *sk;
        int rc;
@@ -2821,6 +2937,31 @@ static int sdp_create_socket(struct net *net, struct socket *sock, int protocol)
        return 0;
 }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static inline struct ipv6_pinfo *inet6_sk_generic(struct sock *sk)
+{
+       const int offset = sk->sk_prot->obj_size - sizeof(struct ipv6_pinfo);
+
+       return (struct ipv6_pinfo *)(((u8 *)sk) + offset);
+}
+
+static int sdp_create_v6_socket(struct net *net, struct socket *sock, int protocol)
+{
+       int rc;
+
+       rc = sdp_create_ipvx_socket(net, sock, protocol);
+       if (!rc)
+               inet_sk(sock->sk)->pinet6 = inet6_sk_generic(sock->sk);
+
+       return rc;
+}
+#endif
+
+static int sdp_create_v4_socket(struct net *net, struct socket *sock, int protocol)
+{
+       return sdp_create_ipvx_socket(net, sock, protocol);
+}
+
 static void sdp_add_device(struct ib_device *device)
 {
        struct sdp_device *sdp_dev;
@@ -2951,9 +3092,17 @@ kill_socks:
 
 static struct net_proto_family sdp_net_proto = {
        .family = AF_INET_SDP,
-       .create = sdp_create_socket,
+       .create = sdp_create_v4_socket,
+       .owner  = THIS_MODULE,
+};
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static struct net_proto_family sdp_net6_proto = {
+       .family = AF_INET6_SDP,
+       .create = sdp_create_v6_socket,
        .owner  = THIS_MODULE,
 };
+#endif
 
 struct ib_client sdp_client = {
        .name   = "sdp",
@@ -2999,10 +3148,18 @@ static int __init sdp_init(void)
 
        rc = sock_register(&sdp_net_proto);
        if (rc) {
-               printk(KERN_WARNING "sock_register failed: %d\n", rc);
+               printk(KERN_WARNING "sock_register sdp IPv4 failed: %d\n", rc);
                goto error_sock_reg;
        }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       rc = sock_register(&sdp_net6_proto);
+       if (rc) {
+               printk(KERN_WARNING "sock_register sdp IPv6 failed: %d\n", rc);
+               goto error_sock_reg6;
+       }
+#endif
+
        sdp_proc_init();
 
        atomic_set(&sdp_current_mem_usage, 0);
@@ -3011,6 +3168,10 @@ static int __init sdp_init(void)
 
        return 0;
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+error_sock_reg6:
+       sock_unregister(PF_INET_SDP);
+#endif
 error_sock_reg:
        proto_unregister(&sdp_proto);
 error_proto_reg:
@@ -3027,6 +3188,7 @@ no_mem_sockets_allocated:
 
 static void __exit sdp_exit(void)
 {
+       sock_unregister(PF_INET6_SDP);
        sock_unregister(PF_INET_SDP);
        proto_unregister(&sdp_proto);
 
index d88d0d0747b21a4d48bb23cfb9c01076cd4677b0..bf41f5e9b7e4017888a3411220ea06cccd95d4ba 100644 (file)
@@ -139,10 +139,8 @@ static void sdp_seq_stop(struct seq_file *seq, void *v)
 
 #define TMPSZ 150
 
-static int sdp_seq_show(struct seq_file *seq, void *v)
+static int sdp_v4_seq_show(struct seq_file *seq, int num, struct sock *sk)
 {
-       struct sdp_iter_state *st;
-       struct sock *sk = v;
        char tmpbuf[TMPSZ + 1];
        unsigned int dest;
        unsigned int src;
@@ -152,15 +150,6 @@ static int sdp_seq_show(struct seq_file *seq, void *v)
        __u16 srcp;
        __u32 rx_queue, tx_queue;
 
-       if (v == SEQ_START_TOKEN) {
-               seq_printf(seq, "%-*s\n", TMPSZ - 1,
-                               "  sl  local_address rem_address        "
-                               "uid inode   rx_queue tx_queue state");
-               goto out;
-       }
-
-       st = seq->private;
-
        dest = inet_sk(sk)->daddr;
        src = inet_sk(sk)->rcv_saddr;
        destp = ntohs(inet_sk(sk)->dport);
@@ -171,11 +160,71 @@ static int sdp_seq_show(struct seq_file *seq, void *v)
        tx_queue = sdp_sk(sk)->write_seq - sdp_sk(sk)->tx_ring.una_seq;
 
        sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X %5d %lu       %08X:%08X %X",
-               st->num, src, srcp, dest, destp, uid, inode,
+               num, src, srcp, dest, destp, uid, inode,
                rx_queue, tx_queue, sk->sk_state);
 
        seq_printf(seq, "%-*s\n", TMPSZ - 1, tmpbuf);
 
+       return 0;
+}
+
+static int sdp_v6_seq_show(struct seq_file *seq, int num, struct sock *sk)
+{
+       char tmpbuf[TMPSZ + 1];
+       struct in6_addr *src;
+       struct in6_addr *dest;
+       int uid;
+       unsigned long inode;
+       __u16 destp;
+       __u16 srcp;
+       __u32 rx_queue, tx_queue;
+
+       dest = &inet6_sk(sk)->daddr;
+       src = &inet6_sk(sk)->rcv_saddr;
+       destp = ntohs(inet_sk(sk)->dport);
+       srcp = ntohs(inet_sk(sk)->sport);
+       uid = sock_i_uid(sk);
+       inode = sock_i_ino(sk);
+       rx_queue = rcv_nxt(sdp_sk(sk)) - sdp_sk(sk)->copied_seq;
+       tx_queue = sdp_sk(sk)->write_seq - sdp_sk(sk)->tx_ring.una_seq;
+
+       sprintf(tmpbuf,
+                  "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
+                  "%5d %lu     %08X:%08X %X",
+                  num,
+                  src->s6_addr32[0], src->s6_addr32[1],
+                  src->s6_addr32[2], src->s6_addr32[3],
+                  srcp,
+                  dest->s6_addr32[0], dest->s6_addr32[1],
+                  dest->s6_addr32[2], dest->s6_addr32[3],
+                  destp,
+                  uid, inode,
+                  rx_queue, tx_queue, sk->sk_state);
+
+       seq_printf(seq, "%-*s\n", TMPSZ - 1, tmpbuf);
+
+       return 0;
+}
+
+static int sdp_seq_show(struct seq_file *seq, void *v)
+{
+       struct sdp_iter_state *st;
+       struct sock *sk = v;
+
+       if (v == SEQ_START_TOKEN) {
+               seq_printf(seq, "%-*s\n", TMPSZ - 1,
+                               "  sl  local_address rem_address        "
+                               "uid inode   rx_queue tx_queue state");
+               goto out;
+       }
+
+       st = seq->private;
+
+       if (inet6_sk(sk))
+               sdp_v6_seq_show(seq, st->num, sk);
+       else
+               sdp_v4_seq_show(seq, st->num, sk);
+
        sock_put(sk, SOCK_REF_SEQ);
 out:
        return 0;
index 902dc97443487f5b40419f7e9ae16cb9dc4f7bfe..c289f99659824fd9892ae1d0ec71faeb9537f8d9 100644 (file)
@@ -8,6 +8,11 @@
 #define PF_INET_SDP AF_INET_SDP
 #endif
 
+#ifndef AF_INET6_SDP
+#define AF_INET6_SDP 28
+#define PF_INET6_SDP AF_INET6_SDP
+#endif
+
 #ifndef SDP_ZCOPY_THRESH
 #define SDP_ZCOPY_THRESH 80
 #endif
@@ -16,6 +21,4 @@
 #define SDP_LAST_BIND_ERR 81
 #endif
 
-/* TODO: AF_INET6_SDP ? */
-
 #endif