diff options
| -rw-r--r-- | drivers/infiniband/core/addr.c | 81 |
1 files changed, 23 insertions, 58 deletions
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index de5fe161a1b9..38a7184ea745 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c | |||
| @@ -184,17 +184,6 @@ static void addr_send_arp(struct sockaddr *dst_in) | |||
| 184 | memset(&fl, 0, sizeof fl); | 184 | memset(&fl, 0, sizeof fl); |
| 185 | 185 | ||
| 186 | switch (dst_in->sa_family) { | 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) | 187 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
| 199 | case AF_INET6: | 188 | case AF_INET6: |
| 200 | { | 189 | { |
| @@ -215,9 +204,9 @@ static void addr_send_arp(struct sockaddr *dst_in) | |||
| 215 | } | 204 | } |
| 216 | } | 205 | } |
| 217 | 206 | ||
| 218 | static int addr4_resolve_remote(struct sockaddr_in *src_in, | 207 | static int addr4_resolve(struct sockaddr_in *src_in, |
| 219 | struct sockaddr_in *dst_in, | 208 | struct sockaddr_in *dst_in, |
| 220 | struct rdma_dev_addr *addr) | 209 | struct rdma_dev_addr *addr) |
| 221 | { | 210 | { |
| 222 | __be32 src_ip = src_in->sin_addr.s_addr; | 211 | __be32 src_ip = src_in->sin_addr.s_addr; |
| 223 | __be32 dst_ip = dst_in->sin_addr.s_addr; | 212 | __be32 dst_ip = dst_in->sin_addr.s_addr; |
| @@ -235,6 +224,16 @@ static int addr4_resolve_remote(struct sockaddr_in *src_in, | |||
| 235 | if (ret) | 224 | if (ret) |
| 236 | goto out; | 225 | goto out; |
| 237 | 226 | ||
| 227 | src_in->sin_family = AF_INET; | ||
| 228 | src_in->sin_addr.s_addr = rt->rt_src; | ||
| 229 | |||
| 230 | if (rt->idev->dev->flags & IFF_LOOPBACK) { | ||
| 231 | ret = rdma_translate_ip((struct sockaddr *) dst_in, addr); | ||
| 232 | if (!ret) | ||
| 233 | memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN); | ||
| 234 | goto put; | ||
| 235 | } | ||
| 236 | |||
| 238 | /* If the device does ARP internally, return 'done' */ | 237 | /* If the device does ARP internally, return 'done' */ |
| 239 | if (rt->idev->dev->flags & IFF_NOARP) { | 238 | if (rt->idev->dev->flags & IFF_NOARP) { |
| 240 | rdma_copy_addr(addr, rt->idev->dev, NULL); | 239 | rdma_copy_addr(addr, rt->idev->dev, NULL); |
| @@ -242,21 +241,14 @@ static int addr4_resolve_remote(struct sockaddr_in *src_in, | |||
| 242 | } | 241 | } |
| 243 | 242 | ||
| 244 | neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->idev->dev); | 243 | neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->idev->dev); |
| 245 | if (!neigh) { | 244 | if (!neigh || !(neigh->nud_state & NUD_VALID)) { |
| 245 | neigh_event_send(rt->u.dst.neighbour, NULL); | ||
| 246 | ret = -ENODATA; | 246 | ret = -ENODATA; |
| 247 | if (neigh) | ||
| 248 | goto release; | ||
| 247 | goto put; | 249 | goto put; |
| 248 | } | 250 | } |
| 249 | 251 | ||
| 250 | if (!(neigh->nud_state & NUD_VALID)) { | ||
| 251 | ret = -ENODATA; | ||
| 252 | goto release; | ||
| 253 | } | ||
| 254 | |||
| 255 | if (!src_ip) { | ||
| 256 | src_in->sin_family = dst_in->sin_family; | ||
| 257 | src_in->sin_addr.s_addr = rt->rt_src; | ||
| 258 | } | ||
| 259 | |||
| 260 | ret = rdma_copy_addr(addr, neigh->dev, neigh->ha); | 252 | ret = rdma_copy_addr(addr, neigh->dev, neigh->ha); |
| 261 | release: | 253 | release: |
| 262 | neigh_release(neigh); | 254 | neigh_release(neigh); |
| @@ -305,12 +297,12 @@ static int addr6_resolve_remote(struct sockaddr_in6 *src_in, | |||
| 305 | } | 297 | } |
| 306 | #endif | 298 | #endif |
| 307 | 299 | ||
| 308 | static int addr_resolve_remote(struct sockaddr *src_in, | 300 | static int addr_resolve(struct sockaddr *src_in, |
| 309 | struct sockaddr *dst_in, | 301 | struct sockaddr *dst_in, |
| 310 | struct rdma_dev_addr *addr) | 302 | struct rdma_dev_addr *addr) |
| 311 | { | 303 | { |
| 312 | if (src_in->sa_family == AF_INET) { | 304 | if (src_in->sa_family == AF_INET) { |
| 313 | return addr4_resolve_remote((struct sockaddr_in *) src_in, | 305 | return addr4_resolve((struct sockaddr_in *) src_in, |
| 314 | (struct sockaddr_in *) dst_in, addr); | 306 | (struct sockaddr_in *) dst_in, addr); |
| 315 | } else | 307 | } else |
| 316 | return addr6_resolve_remote((struct sockaddr_in6 *) src_in, | 308 | return addr6_resolve_remote((struct sockaddr_in6 *) src_in, |
| @@ -330,8 +322,7 @@ static void process_req(struct work_struct *work) | |||
| 330 | if (req->status == -ENODATA) { | 322 | if (req->status == -ENODATA) { |
| 331 | src_in = (struct sockaddr *) &req->src_addr; | 323 | src_in = (struct sockaddr *) &req->src_addr; |
| 332 | dst_in = (struct sockaddr *) &req->dst_addr; | 324 | dst_in = (struct sockaddr *) &req->dst_addr; |
| 333 | req->status = addr_resolve_remote(src_in, dst_in, | 325 | req->status = addr_resolve(src_in, dst_in, req->addr); |
| 334 | req->addr); | ||
| 335 | if (req->status && time_after_eq(jiffies, req->timeout)) | 326 | if (req->status && time_after_eq(jiffies, req->timeout)) |
| 336 | req->status = -ETIMEDOUT; | 327 | req->status = -ETIMEDOUT; |
| 337 | else if (req->status == -ENODATA) | 328 | else if (req->status == -ENODATA) |
| @@ -363,32 +354,6 @@ static int addr_resolve_local(struct sockaddr *src_in, | |||
| 363 | int ret; | 354 | int ret; |
| 364 | 355 | ||
| 365 | switch (dst_in->sa_family) { | 356 | switch (dst_in->sa_family) { |
| 366 | case AF_INET: | ||
| 367 | { | ||
| 368 | __be32 src_ip = ((struct sockaddr_in *) src_in)->sin_addr.s_addr; | ||
| 369 | __be32 dst_ip = ((struct sockaddr_in *) dst_in)->sin_addr.s_addr; | ||
| 370 | |||
| 371 | dev = ip_dev_find(&init_net, dst_ip); | ||
| 372 | if (!dev) | ||
| 373 | return -EADDRNOTAVAIL; | ||
| 374 | |||
| 375 | if (ipv4_is_zeronet(src_ip)) { | ||
| 376 | src_in->sa_family = dst_in->sa_family; | ||
| 377 | ((struct sockaddr_in *) src_in)->sin_addr.s_addr = dst_ip; | ||
| 378 | ret = rdma_copy_addr(addr, dev, dev->dev_addr); | ||
| 379 | } else if (ipv4_is_loopback(src_ip)) { | ||
| 380 | ret = rdma_translate_ip(dst_in, addr); | ||
| 381 | if (!ret) | ||
| 382 | memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN); | ||
| 383 | } else { | ||
| 384 | ret = rdma_translate_ip(src_in, addr); | ||
| 385 | if (!ret) | ||
| 386 | memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN); | ||
| 387 | } | ||
| 388 | dev_put(dev); | ||
| 389 | break; | ||
| 390 | } | ||
| 391 | |||
| 392 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 357 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
| 393 | case AF_INET6: | 358 | case AF_INET6: |
| 394 | { | 359 | { |
| @@ -473,7 +438,7 @@ int rdma_resolve_ip(struct rdma_addr_client *client, | |||
| 473 | 438 | ||
| 474 | req->status = addr_resolve_local(src_in, dst_in, addr); | 439 | req->status = addr_resolve_local(src_in, dst_in, addr); |
| 475 | if (req->status == -EADDRNOTAVAIL) | 440 | if (req->status == -EADDRNOTAVAIL) |
| 476 | req->status = addr_resolve_remote(src_in, dst_in, addr); | 441 | req->status = addr_resolve(src_in, dst_in, addr); |
| 477 | 442 | ||
| 478 | switch (req->status) { | 443 | switch (req->status) { |
| 479 | case 0: | 444 | case 0: |
