diff options
author | Sean Hefty <sean.hefty@intel.com> | 2009-11-19 16:26:51 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2009-11-19 16:26:51 -0500 |
commit | 923c100ef019bf15fb89b6fa3d3ad0485d25d59b (patch) | |
tree | d871aa34a6702595bc1afa8b8e655810104c9268 /drivers/infiniband | |
parent | 6f8372b69c3198e06cecb1df2cb9682d0c55e657 (diff) |
IB/addr: Simplify resolving IPv4 addresses
Merge resolve local/remote address resolution into a single
data flow to ensure consistent access and use of the local routing
tables.
Based on work from:
David Wilder <dwilder@us.ibm.com>
Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Sean Hefty <sean.hefty@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-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: |