aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorSean Hefty <sean.hefty@intel.com>2009-11-19 16:26:51 -0500
committerRoland Dreier <rolandd@cisco.com>2009-11-19 16:26:51 -0500
commit923c100ef019bf15fb89b6fa3d3ad0485d25d59b (patch)
treed871aa34a6702595bc1afa8b8e655810104c9268 /drivers/infiniband
parent6f8372b69c3198e06cecb1df2cb9682d0c55e657 (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.c81
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
218static int addr4_resolve_remote(struct sockaddr_in *src_in, 207static 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);
261release: 253release:
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
308static int addr_resolve_remote(struct sockaddr *src_in, 300static 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: