Merge tag 'pm+acpi-3.14-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafae...
[cascardo/linux.git] / include / rdma / ib_addr.h
index f3ac0f2..ce55906 100644 (file)
 #include <linux/in6.h>
 #include <linux/if_arp.h>
 #include <linux/netdevice.h>
+#include <linux/inetdevice.h>
 #include <linux/socket.h>
 #include <linux/if_vlan.h>
+#include <net/ipv6.h>
+#include <net/if_inet6.h>
+#include <net/ip.h>
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_pack.h>
+#include <net/ipv6.h>
 
 struct rdma_addr_client {
        atomic_t refcount;
@@ -72,7 +77,8 @@ struct rdma_dev_addr {
  * rdma_translate_ip - Translate a local IP address to an RDMA hardware
  *   address.
  */
-int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr);
+int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr,
+                     u16 *vlan_id);
 
 /**
  * rdma_resolve_ip - Resolve source and destination IP addresses to
@@ -104,6 +110,10 @@ int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev,
 
 int rdma_addr_size(struct sockaddr *addr);
 
+int rdma_addr_find_smac_by_sgid(union ib_gid *sgid, u8 *smac, u16 *vlan_id);
+int rdma_addr_find_dmac_by_grh(union ib_gid *sgid, union ib_gid *dgid, u8 *smac,
+                              u16 *vlan_id);
+
 static inline u16 ib_addr_get_pkey(struct rdma_dev_addr *dev_addr)
 {
        return ((u16)dev_addr->broadcast[8] << 8) | (u16)dev_addr->broadcast[9];
@@ -126,41 +136,60 @@ static inline int rdma_addr_gid_offset(struct rdma_dev_addr *dev_addr)
        return dev_addr->dev_type == ARPHRD_INFINIBAND ? 4 : 0;
 }
 
-static inline void iboe_mac_vlan_to_ll(union ib_gid *gid, u8 *mac, u16 vid)
+static inline u16 rdma_vlan_dev_vlan_id(const struct net_device *dev)
 {
-       memset(gid->raw, 0, 16);
-       *((__be32 *) gid->raw) = cpu_to_be32(0xfe800000);
-       if (vid < 0x1000) {
-               gid->raw[12] = vid & 0xff;
-               gid->raw[11] = vid >> 8;
-       } else {
-               gid->raw[12] = 0xfe;
-               gid->raw[11] = 0xff;
+       return dev->priv_flags & IFF_802_1Q_VLAN ?
+               vlan_dev_vlan_id(dev) : 0xffff;
+}
+
+static inline int rdma_ip2gid(struct sockaddr *addr, union ib_gid *gid)
+{
+       switch (addr->sa_family) {
+       case AF_INET:
+               ipv6_addr_set_v4mapped(((struct sockaddr_in *)
+                                       addr)->sin_addr.s_addr,
+                                      (struct in6_addr *)gid);
+               break;
+       case AF_INET6:
+               memcpy(gid->raw, &((struct sockaddr_in6 *)addr)->sin6_addr, 16);
+               break;
+       default:
+               return -EINVAL;
        }
-       memcpy(gid->raw + 13, mac + 3, 3);
-       memcpy(gid->raw + 8, mac, 3);
-       gid->raw[8] ^= 2;
+       return 0;
 }
 
-static inline u16 rdma_vlan_dev_vlan_id(const struct net_device *dev)
+/* Important - sockaddr should be a union of sockaddr_in and sockaddr_in6 */
+static inline int rdma_gid2ip(struct sockaddr *out, union ib_gid *gid)
 {
-       return dev->priv_flags & IFF_802_1Q_VLAN ?
-               vlan_dev_vlan_id(dev) : 0xffff;
+       if (ipv6_addr_v4mapped((struct in6_addr *)gid)) {
+               struct sockaddr_in *out_in = (struct sockaddr_in *)out;
+               memset(out_in, 0, sizeof(*out_in));
+               out_in->sin_family = AF_INET;
+               memcpy(&out_in->sin_addr.s_addr, gid->raw + 12, 4);
+       } else {
+               struct sockaddr_in6 *out_in = (struct sockaddr_in6 *)out;
+               memset(out_in, 0, sizeof(*out_in));
+               out_in->sin6_family = AF_INET6;
+               memcpy(&out_in->sin6_addr.s6_addr, gid->raw, 16);
+       }
+       return 0;
 }
 
 static inline void iboe_addr_get_sgid(struct rdma_dev_addr *dev_addr,
                                      union ib_gid *gid)
 {
        struct net_device *dev;
-       u16 vid = 0xffff;
+       struct in_device *ip4;
 
        dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if);
        if (dev) {
-               vid = rdma_vlan_dev_vlan_id(dev);
+               ip4 = (struct in_device *)dev->ip_ptr;
+               if (ip4 && ip4->ifa_list && ip4->ifa_list->ifa_address)
+                       ipv6_addr_set_v4mapped(ip4->ifa_list->ifa_address,
+                                              (struct in6_addr *)gid);
                dev_put(dev);
        }
-
-       iboe_mac_vlan_to_ll(gid, dev_addr->src_dev_addr, vid);
 }
 
 static inline void rdma_addr_get_sgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid)