diff options
38 files changed, 1074 insertions, 903 deletions
diff --git a/Documentation/infiniband/ipoib.txt b/Documentation/infiniband/ipoib.txt index 6d40f00b358c..64eeb55d0c09 100644 --- a/Documentation/infiniband/ipoib.txt +++ b/Documentation/infiniband/ipoib.txt | |||
| @@ -36,11 +36,11 @@ Datagram vs Connected modes | |||
| 36 | fabric with a 2K MTU, the IPoIB MTU will be 2048 - 4 = 2044 bytes. | 36 | fabric with a 2K MTU, the IPoIB MTU will be 2048 - 4 = 2044 bytes. |
| 37 | 37 | ||
| 38 | In connected mode, the IB RC (Reliable Connected) transport is used. | 38 | In connected mode, the IB RC (Reliable Connected) transport is used. |
| 39 | Connected mode is to takes advantage of the connected nature of the | 39 | Connected mode takes advantage of the connected nature of the IB |
| 40 | IB transport and allows an MTU up to the maximal IP packet size of | 40 | transport and allows an MTU up to the maximal IP packet size of 64K, |
| 41 | 64K, which reduces the number of IP packets needed for handling | 41 | which reduces the number of IP packets needed for handling large UDP |
| 42 | large UDP datagrams, TCP segments, etc and increases the performance | 42 | datagrams, TCP segments, etc and increases the performance for large |
| 43 | for large messages. | 43 | messages. |
| 44 | 44 | ||
| 45 | In connected mode, the interface's UD QP is still used for multicast | 45 | In connected mode, the interface's UD QP is still used for multicast |
| 46 | and communication with peers that don't support connected mode. In | 46 | and communication with peers that don't support connected mode. In |
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index bd07803e9183..abbb06996f9e 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c | |||
| @@ -36,7 +36,6 @@ | |||
| 36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
| 37 | #include <linux/inetdevice.h> | 37 | #include <linux/inetdevice.h> |
| 38 | #include <linux/workqueue.h> | 38 | #include <linux/workqueue.h> |
| 39 | #include <linux/if_arp.h> | ||
| 40 | #include <net/arp.h> | 39 | #include <net/arp.h> |
| 41 | #include <net/neighbour.h> | 40 | #include <net/neighbour.h> |
| 42 | #include <net/route.h> | 41 | #include <net/route.h> |
| @@ -92,22 +91,12 @@ EXPORT_SYMBOL(rdma_addr_unregister_client); | |||
| 92 | int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, | 91 | int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, |
| 93 | const unsigned char *dst_dev_addr) | 92 | const unsigned char *dst_dev_addr) |
| 94 | { | 93 | { |
| 95 | switch (dev->type) { | 94 | dev_addr->dev_type = dev->type; |
| 96 | case ARPHRD_INFINIBAND: | ||
| 97 | dev_addr->dev_type = RDMA_NODE_IB_CA; | ||
| 98 | break; | ||
| 99 | case ARPHRD_ETHER: | ||
| 100 | dev_addr->dev_type = RDMA_NODE_RNIC; | ||
| 101 | break; | ||
| 102 | default: | ||
| 103 | return -EADDRNOTAVAIL; | ||
| 104 | } | ||
| 105 | |||
| 106 | memcpy(dev_addr->src_dev_addr, dev->dev_addr, MAX_ADDR_LEN); | 95 | memcpy(dev_addr->src_dev_addr, dev->dev_addr, MAX_ADDR_LEN); |
| 107 | memcpy(dev_addr->broadcast, dev->broadcast, MAX_ADDR_LEN); | 96 | memcpy(dev_addr->broadcast, dev->broadcast, MAX_ADDR_LEN); |
| 108 | if (dst_dev_addr) | 97 | if (dst_dev_addr) |
| 109 | memcpy(dev_addr->dst_dev_addr, dst_dev_addr, MAX_ADDR_LEN); | 98 | memcpy(dev_addr->dst_dev_addr, dst_dev_addr, MAX_ADDR_LEN); |
| 110 | dev_addr->src_dev = dev; | 99 | dev_addr->bound_dev_if = dev->ifindex; |
| 111 | return 0; | 100 | return 0; |
| 112 | } | 101 | } |
| 113 | EXPORT_SYMBOL(rdma_copy_addr); | 102 | EXPORT_SYMBOL(rdma_copy_addr); |
| @@ -117,6 +106,15 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr) | |||
| 117 | struct net_device *dev; | 106 | struct net_device *dev; |
| 118 | int ret = -EADDRNOTAVAIL; | 107 | int ret = -EADDRNOTAVAIL; |
| 119 | 108 | ||
| 109 | if (dev_addr->bound_dev_if) { | ||
| 110 | dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if); | ||
| 111 | if (!dev) | ||
| 112 | return -ENODEV; | ||
| 113 | ret = rdma_copy_addr(dev_addr, dev, NULL); | ||
| 114 | dev_put(dev); | ||
| 115 | return ret; | ||
| 116 | } | ||
| 117 | |||
| 120 | switch (addr->sa_family) { | 118 | switch (addr->sa_family) { |
| 121 | case AF_INET: | 119 | case AF_INET: |
| 122 | dev = ip_dev_find(&init_net, | 120 | dev = ip_dev_find(&init_net, |
| @@ -131,6 +129,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr) | |||
| 131 | 129 | ||
| 132 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 130 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
| 133 | case AF_INET6: | 131 | case AF_INET6: |
| 132 | read_lock(&dev_base_lock); | ||
| 134 | for_each_netdev(&init_net, dev) { | 133 | for_each_netdev(&init_net, dev) { |
| 135 | if (ipv6_chk_addr(&init_net, | 134 | if (ipv6_chk_addr(&init_net, |
| 136 | &((struct sockaddr_in6 *) addr)->sin6_addr, | 135 | &((struct sockaddr_in6 *) addr)->sin6_addr, |
| @@ -139,6 +138,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr) | |||
| 139 | break; | 138 | break; |
| 140 | } | 139 | } |
| 141 | } | 140 | } |
| 141 | read_unlock(&dev_base_lock); | ||
| 142 | break; | 142 | break; |
| 143 | #endif | 143 | #endif |
| 144 | } | 144 | } |
| @@ -176,48 +176,9 @@ static void queue_req(struct addr_req *req) | |||
| 176 | mutex_unlock(&lock); | 176 | mutex_unlock(&lock); |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | static void addr_send_arp(struct sockaddr *dst_in) | 179 | static int addr4_resolve(struct sockaddr_in *src_in, |
| 180 | { | 180 | struct sockaddr_in *dst_in, |
| 181 | struct rtable *rt; | 181 | struct rdma_dev_addr *addr) |
| 182 | struct flowi fl; | ||
| 183 | |||
| 184 | memset(&fl, 0, sizeof fl); | ||
| 185 | |||
| 186 | switch (dst_in->sa_family) { | ||
| 187 | case AF_INET: | ||
| 188 | fl.nl_u.ip4_u.daddr = | ||
| 189 | ((struct sockaddr_in *) dst_in)->sin_addr.s_addr; | ||
| 190 | |||
| 191 | if (ip_route_output_key(&init_net, &rt, &fl)) | ||
| 192 | return; | ||
| 193 | |||
| 194 | neigh_event_send(rt->u.dst.neighbour, NULL); | ||
| 195 | ip_rt_put(rt); | ||
| 196 | break; | ||
| 197 | |||
| 198 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 199 | case AF_INET6: | ||
| 200 | { | ||
| 201 | struct dst_entry *dst; | ||
| 202 | |||
| 203 | fl.nl_u.ip6_u.daddr = | ||
| 204 | ((struct sockaddr_in6 *) dst_in)->sin6_addr; | ||
| 205 | |||
