Tom Tucker wrote:
I think I understand where I'm upside down now. In my world, you don't know which interface to send the ARP request on until you've identified the local interface and you can't identify the local interface until you've looked up the route.
Not all interface have a path to all remote peers.

We have the same restriction. I lookup the route based on the destination IP address to get the local interface.

In your world, you can't look up the path record until you've identified the remote GID. What I don't get is, if you have more than one IB interface, which interface do you submit your IPoIB ARP request on? All of them?

It's based on the device returned by the route lookup. I've attached the relevant code portion below. If the code below fails, I generate an ARP, wait for the reply, then re-execute the code.

Not sure what a "normal IP ARP" message is. In my world, ARP and IP are peer protocols. ARP does not sit on top of IP, nor is it a special kind of IP message. Forgive my ignorance, but does IPoIB have ARP built into it?

I was being confusing. The ARP is sent on the IPoIB net_device to map an IP address to the remote hardware address. There's nothing special about the ARP.

- Sean

static int addr_resolve_remote(struct sockaddr_in *src_in,
                               struct sockaddr_in *dst_in,
                               struct ib_addr *addr)
{
        u32 src_ip = src_in->sin_addr.s_addr;
        u32 dst_ip = dst_in->sin_addr.s_addr;
        struct flowi fl;
        struct rtable *rt;
        struct neighbour *neigh;
        int ret;

        memset(&fl, 0, sizeof fl);
        fl.nl_u.ip4_u.daddr = dst_ip;
        fl.nl_u.ip4_u.saddr = src_ip;
        ret = ip_route_output_key(&rt, &fl);
        if (ret)
                goto out;

        neigh = neigh_lookup(&arp_tbl, &dst_ip, rt->idev->dev);
        if (!neigh) {
                ret = -ENODATA;
                goto err1;
        }

        if (!(neigh->nud_state & NUD_VALID)) {
                ret = -ENODATA;
                goto err2;
        }

        if (!src_ip) {
                src_in->sin_family = dst_in->sin_family;
                src_in->sin_addr.s_addr = rt->rt_src;
        }

        addr->sgid = *(union ib_gid *) (neigh->dev->dev_addr + 4);
        addr->dgid = *(union ib_gid *) (neigh->ha + 4);
        addr->pkey = addr_get_pkey(neigh->dev);

err2:
        neigh_release(neigh);
err1:
        ip_rt_put(rt);
out:
        return ret;
}

static void addr_send_arp(struct sockaddr_in *dst_in)
{
        struct rtable *rt;
        struct flowi fl;
        u32 dst_ip = dst_in->sin_addr.s_addr;

        memset(&fl, 0, sizeof fl);
        fl.nl_u.ip4_u.daddr = dst_ip;
        if (ip_route_output_key(&rt, &fl))
                return;

        arp_send(ARPOP_REQUEST, ETH_P_ARP, dst_ip, rt->idev->dev, rt->rt_src,
                 NULL, rt->idev->dev->dev_addr, NULL);
        ip_rt_put(rt);
}
_______________________________________________
openib-general mailing list
[email protected]
http://openib.org/mailman/listinfo/openib-general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to