1b86efd96Sagiri /*
2b86efd96Sagiri  * CDDL HEADER START
3b86efd96Sagiri  *
4b86efd96Sagiri  * The contents of this file are subject to the terms of the
5b86efd96Sagiri  * Common Development and Distribution License (the "License").
6b86efd96Sagiri  * You may not use this file except in compliance with the License.
7b86efd96Sagiri  *
8b86efd96Sagiri  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9b86efd96Sagiri  * or http://www.opensolaris.org/os/licensing.
10b86efd96Sagiri  * See the License for the specific language governing permissions
11b86efd96Sagiri  * and limitations under the License.
12b86efd96Sagiri  *
13b86efd96Sagiri  * When distributing Covered Code, include this CDDL HEADER in each
14b86efd96Sagiri  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15b86efd96Sagiri  * If applicable, add the following below this CDDL HEADER, with the
16b86efd96Sagiri  * fields enclosed by brackets "[]" replaced with your own identifying
17b86efd96Sagiri  * information: Portions Copyright [yyyy] [name of copyright owner]
18b86efd96Sagiri  *
19b86efd96Sagiri  * CDDL HEADER END
20b86efd96Sagiri  */
21b86efd96Sagiri /*
220dc2366fSVenugopal Iyer  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23b86efd96Sagiri  * Use is subject to license terms.
24b86efd96Sagiri  */
25b86efd96Sagiri 
26b86efd96Sagiri #include <sys/types.h>
27b86efd96Sagiri #include <net/if.h>
28b86efd96Sagiri #include <net/if_types.h>
29b86efd96Sagiri #include <inet/ip.h>
30b86efd96Sagiri #include <inet/ip_ire.h>
31b86efd96Sagiri #include <inet/ip_if.h>
320dc2366fSVenugopal Iyer #include <sys/ethernet.h>
33015f8fffShiremath #include <sys/ib/mgt/ibcm/ibcm_arp.h>
34b86efd96Sagiri 
35015f8fffShiremath extern char cmlog[];
36015f8fffShiremath 
37015f8fffShiremath _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibcm_arp_streams_t))
38015f8fffShiremath 
39bd670b35SErik Nordmark static void ibcm_resolver_ack(ip2mac_t *, void *);
40bd670b35SErik Nordmark static int ibcm_nce_lookup(ibcm_arp_prwqn_t *wqnp, ill_t *ill, zoneid_t zid);
41b86efd96Sagiri 
42b86efd96Sagiri /*
43b86efd96Sagiri  * delete a wait queue node from the list.
44b86efd96Sagiri  * assumes mutex is acquired
45b86efd96Sagiri  */
46b86efd96Sagiri void
ibcm_arp_delete_prwqn(ibcm_arp_prwqn_t * wqnp)47bd670b35SErik Nordmark ibcm_arp_delete_prwqn(ibcm_arp_prwqn_t *wqnp)
48b86efd96Sagiri {
49015f8fffShiremath 	ibcm_arp_streams_t *ib_s;
50b86efd96Sagiri 
51bd670b35SErik Nordmark 	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_delete_prwqn(%p)", wqnp);
52b86efd96Sagiri 
53bd670b35SErik Nordmark 	ib_s = wqnp->ib_str;
54015f8fffShiremath 	ib_s->wqnp = NULL;
55015f8fffShiremath 	kmem_free(wqnp, sizeof (ibcm_arp_prwqn_t));
56b86efd96Sagiri }
57b86efd96Sagiri 
58b86efd96Sagiri /*
59b86efd96Sagiri  * allocate a wait queue node, and insert it in the list
60b86efd96Sagiri  */
61d3a82192SShantkumar Hiremath static ibcm_arp_prwqn_t *
ibcm_arp_create_prwqn(ibcm_arp_streams_t * ib_s,ibt_ip_addr_t * dst_addr,ibt_ip_addr_t * src_addr)62015f8fffShiremath ibcm_arp_create_prwqn(ibcm_arp_streams_t *ib_s, ibt_ip_addr_t *dst_addr,
63bd670b35SErik Nordmark     ibt_ip_addr_t *src_addr)
64b86efd96Sagiri {
65015f8fffShiremath 	ibcm_arp_prwqn_t *wqnp;
66b86efd96Sagiri 
67015f8fffShiremath 	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_create_prwqn(ib_s: 0x%p)", ib_s);
68b86efd96Sagiri 
69b86efd96Sagiri 	if (dst_addr == NULL) {
70b86efd96Sagiri 		return (NULL);
71b86efd96Sagiri 	}
72015f8fffShiremath 	if ((wqnp = kmem_zalloc(sizeof (ibcm_arp_prwqn_t), KM_NOSLEEP)) ==
73015f8fffShiremath 	    NULL) {
74b86efd96Sagiri 		return (NULL);
75b86efd96Sagiri 	}
76015f8fffShiremath 	wqnp->dst_addr = *dst_addr;
77b86efd96Sagiri 
78b86efd96Sagiri 	if (src_addr) {
79b86efd96Sagiri 		wqnp->usrc_addr = *src_addr;
80b86efd96Sagiri 	}
81bd670b35SErik Nordmark 	wqnp->ib_str = ib_s;
82d3a82192SShantkumar Hiremath 	wqnp->ifproto = (dst_addr->family == AF_INET) ?
83d3a82192SShantkumar Hiremath 	    ETHERTYPE_IP : ETHERTYPE_IPV6;
84b86efd96Sagiri 
85015f8fffShiremath 	ib_s->wqnp = wqnp;
86b86efd96Sagiri 
87015f8fffShiremath 	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_create_prwqn: Return wqnp: %p", wqnp);
88b86efd96Sagiri 
89b86efd96Sagiri 	return (wqnp);
90b86efd96Sagiri }
91b86efd96Sagiri 
92b86efd96Sagiri 
93e11c3f44Smeem /*
94e11c3f44Smeem  * Check if the interface is loopback or IB.
95e11c3f44Smeem  */
965ce5f367Srshoaib static int
ibcm_arp_check_interface(ill_t * ill)97e11c3f44Smeem ibcm_arp_check_interface(ill_t *ill)
985ce5f367Srshoaib {
99e11c3f44Smeem 	if (IS_LOOPBACK(ill) || ill->ill_type == IFT_IB)
100e11c3f44Smeem 		return (0);
1015ce5f367Srshoaib 
102e11c3f44Smeem 	return (ETIMEDOUT);
1035ce5f367Srshoaib }
1045ce5f367Srshoaib 
105b86efd96Sagiri int
ibcm_resolver_pr_lookup(ibcm_arp_streams_t * ib_s,ibt_ip_addr_t * dst_addr,ibt_ip_addr_t * src_addr,zoneid_t myzoneid)106bd670b35SErik Nordmark ibcm_resolver_pr_lookup(ibcm_arp_streams_t *ib_s, ibt_ip_addr_t *dst_addr,
107*26190627SShantkumar Hiremath     ibt_ip_addr_t *src_addr, zoneid_t myzoneid)
108b86efd96Sagiri {
109015f8fffShiremath 	ibcm_arp_prwqn_t *wqnp;
110e11c3f44Smeem 	ire_t	*ire = NULL;
111bd670b35SErik Nordmark 	ipif_t	*ipif = NULL;
112bd670b35SErik Nordmark 	ill_t	*ill = NULL;
113bd670b35SErik Nordmark 	ill_t	*hwaddr_ill = NULL;
1145ce5f367Srshoaib 	ip_stack_t *ipst;
115bd670b35SErik Nordmark 	ipaddr_t	setsrcv4;
116bd670b35SErik Nordmark 	in6_addr_t	setsrcv6;
1175ce5f367Srshoaib 
118d3a82192SShantkumar Hiremath 	IBCM_PRINT_IP("ibcm_arp_pr_lookup: SRC", src_addr);
119d3a82192SShantkumar Hiremath 	IBCM_PRINT_IP("ibcm_arp_pr_lookup: DST", dst_addr);
120b86efd96Sagiri 
121bd670b35SErik Nordmark 	if ((wqnp = ibcm_arp_create_prwqn(ib_s, dst_addr, src_addr)) == NULL) {
122bd670b35SErik Nordmark 		IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: "
123015f8fffShiremath 		    "ibcm_arp_create_prwqn failed");
124015f8fffShiremath 		ib_s->status = ENOMEM;
1255ce5f367Srshoaib 		return (1);
126b86efd96Sagiri 	}
127b86efd96Sagiri 
128*26190627SShantkumar Hiremath 	ipst = netstack_find_by_zoneid(myzoneid)->netstack_ip;
129d3a82192SShantkumar Hiremath 	if (dst_addr->family == AF_INET) {
130d3a82192SShantkumar Hiremath 		/*
131bd670b35SErik Nordmark 		 * get an ire for the destination adress.
132bd670b35SErik Nordmark 		 * Note that we can't use MATCH_IRE_ILL since that would
133*26190627SShantkumar Hiremath 		 * require that the first ill we find have ire_ill set.
134d3a82192SShantkumar Hiremath 		 */
135bd670b35SErik Nordmark 		setsrcv4 = INADDR_ANY;
136bd670b35SErik Nordmark 		ire = ire_route_recursive_v4(dst_addr->un.ip4addr, 0, NULL,
137*26190627SShantkumar Hiremath 		    myzoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst,
138bd670b35SErik Nordmark 		    &setsrcv4, NULL, NULL);
139bd670b35SErik Nordmark 
140bd670b35SErik Nordmark 		ASSERT(ire != NULL);
141bd670b35SErik Nordmark 		if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
142bd670b35SErik Nordmark 			IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: "
143bd670b35SErik Nordmark 			    "ire_route_recursive_v4 failed");
144bd670b35SErik Nordmark 			ib_s->status = EFAULT;
145bd670b35SErik Nordmark 			goto fail;
146bd670b35SErik Nordmark 		}
147bd670b35SErik Nordmark 		ill = ire_nexthop_ill(ire);
148bd670b35SErik Nordmark 		if (ill == NULL) {
149bd670b35SErik Nordmark 			IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: "
150bd670b35SErik Nordmark 			    "ire_nexthop_ill failed");
151bd670b35SErik Nordmark 			ib_s->status = EFAULT;
152bd670b35SErik Nordmark 			goto fail;
153bd670b35SErik Nordmark 		}
154*26190627SShantkumar Hiremath 
155*26190627SShantkumar Hiremath 		/* Pick a source address */
156*26190627SShantkumar Hiremath 		if (ip_select_source_v4(ill, setsrcv4, dst_addr->un.ip4addr,
157*26190627SShantkumar Hiremath 		    INADDR_ANY, myzoneid, ipst, &wqnp->src_addr.un.ip4addr,
158*26190627SShantkumar Hiremath 		    NULL, NULL) != 0) {
159*26190627SShantkumar Hiremath 			ib_s->status = EADDRNOTAVAIL;
160d3a82192SShantkumar Hiremath 			goto fail;
161d3a82192SShantkumar Hiremath 		}
1625ce5f367Srshoaib 
163bd670b35SErik Nordmark 		wqnp->gateway.un.ip4addr = ire->ire_gateway_addr;
164d3a82192SShantkumar Hiremath 		wqnp->netmask.un.ip4addr = ire->ire_mask;
165d3a82192SShantkumar Hiremath 		wqnp->src_addr.family = wqnp->gateway.family =
166d3a82192SShantkumar Hiremath 		    wqnp->netmask.family = AF_INET;
167d3a82192SShantkumar Hiremath 
168d3a82192SShantkumar Hiremath 	} else if (dst_addr->family == AF_INET6) {
169d3a82192SShantkumar Hiremath 		/*
170bd670b35SErik Nordmark 		 * get an ire for the destination adress.
171bd670b35SErik Nordmark 		 * Note that we can't use MATCH_IRE_ILL since that would
172bd670b35SErik Nordmark 		 * require that the first ill we find have ire_ill set. Thus
173bd670b35SErik Nordmark 		 * we compare ire_ill against ipif_ill after the lookup.
174d3a82192SShantkumar Hiremath 		 */
175bd670b35SErik Nordmark 		setsrcv6 = ipv6_all_zeros;
176bd670b35SErik Nordmark 		ire = ire_route_recursive_v6(&dst_addr->un.ip6addr, 0, NULL,
177*26190627SShantkumar Hiremath 		    myzoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst,
178bd670b35SErik Nordmark 		    &setsrcv6, NULL, NULL);
179bd670b35SErik Nordmark 
180bd670b35SErik Nordmark 		ASSERT(ire != NULL);
181bd670b35SErik Nordmark 		if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
182bd670b35SErik Nordmark 			IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: "
183bd670b35SErik Nordmark 			    "ire_route_recursive_v6 failed");
184bd670b35SErik Nordmark 			ib_s->status = EFAULT;
185bd670b35SErik Nordmark 			goto fail;
186bd670b35SErik Nordmark 		}
187bd670b35SErik Nordmark 		ill = ire_nexthop_ill(ire);
188bd670b35SErik Nordmark 		if (ill == NULL) {
189bd670b35SErik Nordmark 			IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: "
190bd670b35SErik Nordmark 			    "ire_nexthop_ill failed");
191bd670b35SErik Nordmark 			ib_s->status = EFAULT;
192bd670b35SErik Nordmark 			goto fail;
193bd670b35SErik Nordmark 		}
194bd670b35SErik Nordmark 
195*26190627SShantkumar Hiremath 		/* Pick a source address */
196*26190627SShantkumar Hiremath 		if (ip_select_source_v6(ill, &setsrcv6, &dst_addr->un.ip6addr,
197*26190627SShantkumar Hiremath 		    myzoneid, ipst, B_FALSE, IPV6_PREFER_SRC_DEFAULT,
198*26190627SShantkumar Hiremath 		    &wqnp->src_addr.un.ip6addr, NULL, NULL) != 0) {
199*26190627SShantkumar Hiremath 			ib_s->status = EADDRNOTAVAIL;
200d3a82192SShantkumar Hiremath 			goto fail;
201d3a82192SShantkumar Hiremath 		}
202d3a82192SShantkumar Hiremath 
203bd670b35SErik Nordmark 		wqnp->gateway.un.ip6addr = ire->ire_gateway_addr_v6;
204d3a82192SShantkumar Hiremath 		wqnp->netmask.un.ip6addr = ire->ire_mask_v6;
205d3a82192SShantkumar Hiremath 		wqnp->src_addr.family = wqnp->gateway.family =
206d3a82192SShantkumar Hiremath 		    wqnp->netmask.family = AF_INET6;
207d3a82192SShantkumar Hiremath 	}
2085ce5f367Srshoaib 
209e11c3f44Smeem 	(void) strlcpy(wqnp->ifname, ill->ill_name, sizeof (wqnp->ifname));
2105ce5f367Srshoaib 
211e11c3f44Smeem 	/*
212e11c3f44Smeem 	 * For IPMP data addresses, we need to use the hardware address of the
213e11c3f44Smeem 	 * interface bound to the given address.
214e11c3f44Smeem 	 */
215e11c3f44Smeem 	if (IS_IPMP(ill)) {
216*26190627SShantkumar Hiremath 		if (wqnp->src_addr.family == AF_INET) {
217*26190627SShantkumar Hiremath 			ipif = ipif_lookup_addr(wqnp->src_addr.un.ip4addr, ill,
218*26190627SShantkumar Hiremath 			    myzoneid, ipst);
219*26190627SShantkumar Hiremath 		} else {
220*26190627SShantkumar Hiremath 			ipif = ipif_lookup_addr_v6(&wqnp->src_addr.un.ip6addr,
221*26190627SShantkumar Hiremath 			    ill, myzoneid, ipst);
222*26190627SShantkumar Hiremath 		}
223*26190627SShantkumar Hiremath 		if (ipif == NULL) {
224*26190627SShantkumar Hiremath 			ib_s->status = ENETUNREACH;
225*26190627SShantkumar Hiremath 			goto fail;
226*26190627SShantkumar Hiremath 		}
227*26190627SShantkumar Hiremath 
228e11c3f44Smeem 		if ((hwaddr_ill = ipmp_ipif_hold_bound_ill(ipif)) == NULL) {
229bd670b35SErik Nordmark 			IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: "
230bd670b35SErik Nordmark 			    "no bound ill for IPMP interface %s",
231bd670b35SErik Nordmark 			    ill->ill_name);
232e11c3f44Smeem 			ib_s->status = EFAULT;
233e11c3f44Smeem 			goto fail;
234e11c3f44Smeem 		}
235e11c3f44Smeem 	} else {
236e11c3f44Smeem 		hwaddr_ill = ill;
237bd670b35SErik Nordmark 		ill_refhold(hwaddr_ill);	/* for symmetry */
238e11c3f44Smeem 	}
2395ce5f367Srshoaib 
240e11c3f44Smeem 	if ((ib_s->status = ibcm_arp_check_interface(hwaddr_ill)) != 0) {
241bd670b35SErik Nordmark 		IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: "
242015f8fffShiremath 		    "ibcm_arp_check_interface failed");
243e11c3f44Smeem 		goto fail;
2445ce5f367Srshoaib 	}
2455ce5f367Srshoaib 
246d3a82192SShantkumar Hiremath 	bcopy(hwaddr_ill->ill_phys_addr, &wqnp->src_mac,
247d3a82192SShantkumar Hiremath 	    hwaddr_ill->ill_phys_addr_length);
248d3a82192SShantkumar Hiremath 
249bd670b35SErik Nordmark 	IBTF_DPRINTF_L4(cmlog, "ibcm_resolver_pr_lookup: outgoing if:%s",
250d3a82192SShantkumar Hiremath 	    wqnp->ifname);
251d3a82192SShantkumar Hiremath 
252d3a82192SShantkumar Hiremath 	/*
253d3a82192SShantkumar Hiremath 	 * at this stage, we have the source address and the IB
254d3a82192SShantkumar Hiremath 	 * interface, now get the destination mac address from
255d3a82192SShantkumar Hiremath 	 * arp or ipv6 drivers
256d3a82192SShantkumar Hiremath 	 */
257*26190627SShantkumar Hiremath 	ib_s->status = ibcm_nce_lookup(wqnp, ill, myzoneid);
258bd670b35SErik Nordmark 	if (ib_s->status != 0) {
259bd670b35SErik Nordmark 		IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: "
260bd670b35SErik Nordmark 		    "ibcm_nce_lookup failed: %d", ib_s->status);
261bd670b35SErik Nordmark 		goto fail;
262b86efd96Sagiri 	}
263b86efd96Sagiri 
264e11c3f44Smeem 	ill_refrele(hwaddr_ill);
265bd670b35SErik Nordmark 	ill_refrele(ill);
266bd670b35SErik Nordmark 	ire_refrele(ire);
267*26190627SShantkumar Hiremath 	if (ipif != NULL)
268*26190627SShantkumar Hiremath 		ipif_refrele(ipif);
269e11c3f44Smeem 	netstack_rele(ipst->ips_netstack);
270b86efd96Sagiri 
271bd670b35SErik Nordmark 	IBTF_DPRINTF_L4(cmlog, "ibcm_resolver_pr_lookup: Return: 0x%p", wqnp);
272b86efd96Sagiri 	return (0);
273e11c3f44Smeem fail:
274e11c3f44Smeem 	if (hwaddr_ill != NULL)
275e11c3f44Smeem 		ill_refrele(hwaddr_ill);
276bd670b35SErik Nordmark 	if (ill != NULL)
277bd670b35SErik Nordmark 		ill_refrele(ill);
278e11c3f44Smeem 	if (ire != NULL)
279bd670b35SErik Nordmark 		ire_refrele(ire);
280bd670b35SErik Nordmark 	if (ipif != NULL)
281bd670b35SErik Nordmark 		ipif_refrele(ipif);
282bd670b35SErik Nordmark 	ibcm_arp_delete_prwqn(wqnp);
283e11c3f44Smeem 	netstack_rele(ipst->ips_netstack);
284e11c3f44Smeem 	return (1);
285b86efd96Sagiri }
286b86efd96Sagiri 
287b86efd96Sagiri /*
288bd670b35SErik Nordmark  * Query the neighbor cache for IPv4/IPv6 to mac address mapping.
289b86efd96Sagiri  */
290bd670b35SErik Nordmark static int
ibcm_nce_lookup(ibcm_arp_prwqn_t * wqnp,ill_t * ill,zoneid_t zoneid)291bd670b35SErik Nordmark ibcm_nce_lookup(ibcm_arp_prwqn_t *wqnp, ill_t *ill, zoneid_t zoneid)
292b86efd96Sagiri {
293bd670b35SErik Nordmark 	ip2mac_t	ip2m;
294bd670b35SErik Nordmark 	sin_t		*sin;
295bd670b35SErik Nordmark 	sin6_t		*sin6;
296bd670b35SErik Nordmark 	ip2mac_id_t	ip2mid;
297bd670b35SErik Nordmark 	int		err;
298bd670b35SErik Nordmark 
299bd670b35SErik Nordmark 	if (wqnp->src_addr.family != wqnp->dst_addr.family) {
300bd670b35SErik Nordmark 		IBTF_DPRINTF_L2(cmlog, "ibcm_nce_lookup: Mis-match SRC_ADDR "
301bd670b35SErik Nordmark 		    "Family: %d, DST_ADDR Family %d", wqnp->src_addr.family,
302bd670b35SErik Nordmark 		    wqnp->dst_addr.family);
303bd670b35SErik Nordmark 		return (1);
304b86efd96Sagiri 	}
305bd670b35SErik Nordmark 	bzero(&ip2m, sizeof (ip2m));
306b86efd96Sagiri 
307bd670b35SErik Nordmark 	if (wqnp->dst_addr.family == AF_INET) {
308bd670b35SErik Nordmark 		sin = (sin_t *)&ip2m.ip2mac_pa;
309bd670b35SErik Nordmark 		sin->sin_family = AF_INET;
310bd670b35SErik Nordmark 		sin->sin_addr.s_addr = wqnp->dst_addr.un.ip4addr;
311bd670b35SErik Nordmark 	} else if (wqnp->dst_addr.family == AF_INET6) {
312bd670b35SErik Nordmark 		sin6 = (sin6_t *)&ip2m.ip2mac_pa;
313bd670b35SErik Nordmark 		sin6->sin6_family = AF_INET6;
314bd670b35SErik Nordmark 		sin6->sin6_addr = wqnp->dst_addr.un.ip6addr;
315b86efd96Sagiri 	} else {
316bd670b35SErik Nordmark 		IBTF_DPRINTF_L2(cmlog, "ibcm_nce_lookup: Invalid DST_ADDR "
317bd670b35SErik Nordmark 		    "Family: %d", wqnp->dst_addr.family);
318d3a82192SShantkumar Hiremath 		return (1);
319d3a82192SShantkumar Hiremath 	}
320d3a82192SShantkumar Hiremath 
321d3a82192SShantkumar Hiremath 	ip2m.ip2mac_ifindex = ill->ill_phyint->phyint_ifindex;
322d3a82192SShantkumar Hiremath 
323d3a82192SShantkumar Hiremath 	wqnp->flags |= IBCM_ARP_PR_RESOLVE_PENDING;
324bd670b35SErik Nordmark 
325d3a82192SShantkumar Hiremath 	/*
326d3a82192SShantkumar Hiremath 	 * issue the request to IP for Neighbor Discovery
327d3a82192SShantkumar Hiremath 	 */
328bd670b35SErik Nordmark 	ip2mid = ip2mac(IP2MAC_RESOLVE, &ip2m, ibcm_resolver_ack, wqnp,
329d3a82192SShantkumar Hiremath 	    zoneid);
330d3a82192SShantkumar Hiremath 	err = ip2m.ip2mac_err;
331d3a82192SShantkumar Hiremath 	if (err == EINPROGRESS) {
332d3a82192SShantkumar Hiremath 		wqnp->ip2mac_id = ip2mid;
333d3a82192SShantkumar Hiremath 		wqnp->flags |= IBCM_ARP_PR_RESOLVE_PENDING;
334d3a82192SShantkumar Hiremath 		err = 0;
335d3a82192SShantkumar Hiremath 	} else if (err == 0) {
336bd670b35SErik Nordmark 		ibcm_resolver_ack(&ip2m, wqnp);
337d3a82192SShantkumar Hiremath 	}
338d3a82192SShantkumar Hiremath 	return (err);
339d3a82192SShantkumar Hiremath }
340d3a82192SShantkumar Hiremath 
341d3a82192SShantkumar Hiremath /*
342d3a82192SShantkumar Hiremath  * do sanity checks on the link-level sockaddr
343d3a82192SShantkumar Hiremath  */
344d3a82192SShantkumar Hiremath static boolean_t
ibcm_check_sockdl(struct sockaddr_dl * sdl)345d3a82192SShantkumar Hiremath ibcm_check_sockdl(struct sockaddr_dl *sdl)
346d3a82192SShantkumar Hiremath {
347d3a82192SShantkumar Hiremath 
348d3a82192SShantkumar Hiremath 	if (sdl->sdl_type != IFT_IB || sdl->sdl_alen != IPOIB_ADDRL)
349d3a82192SShantkumar Hiremath 		return (B_FALSE);
350d3a82192SShantkumar Hiremath 
351d3a82192SShantkumar Hiremath 	return (B_TRUE);
352d3a82192SShantkumar Hiremath }
353d3a82192SShantkumar Hiremath 
354d3a82192SShantkumar Hiremath /*
355d3a82192SShantkumar Hiremath  * callback for resolver lookups, both for success and failure.
356d3a82192SShantkumar Hiremath  * If Address resolution was succesful: return GID info.
357d3a82192SShantkumar Hiremath  */
358d3a82192SShantkumar Hiremath static void
ibcm_resolver_ack(ip2mac_t * ip2macp,void * arg)359bd670b35SErik Nordmark ibcm_resolver_ack(ip2mac_t *ip2macp, void *arg)
360d3a82192SShantkumar Hiremath {
361d3a82192SShantkumar Hiremath 	ibcm_arp_prwqn_t *wqnp = (ibcm_arp_prwqn_t *)arg;
362d3a82192SShantkumar Hiremath 	ibcm_arp_streams_t *ib_s;
363d3a82192SShantkumar Hiremath 	uchar_t *cp;
364d3a82192SShantkumar Hiremath 	int err = 0;
365d3a82192SShantkumar Hiremath 
366bd670b35SErik Nordmark 	IBTF_DPRINTF_L4(cmlog, "ibcm_resolver_ack(%p, %p)", ip2macp, wqnp);
367d3a82192SShantkumar Hiremath 
368bd670b35SErik Nordmark 	ib_s = wqnp->ib_str;
369d3a82192SShantkumar Hiremath 	mutex_enter(&ib_s->lock);
370d3a82192SShantkumar Hiremath 
371d3a82192SShantkumar Hiremath 	if (ip2macp->ip2mac_err != 0) {
372d3a82192SShantkumar Hiremath 		wqnp->flags &= ~IBCM_ARP_PR_RESOLVE_PENDING;
373d3a82192SShantkumar Hiremath 		cv_broadcast(&ib_s->cv);
374d3a82192SShantkumar Hiremath 		err = EHOSTUNREACH;
375d3a82192SShantkumar Hiremath 		goto user_callback;
376d3a82192SShantkumar Hiremath 	}
377d3a82192SShantkumar Hiremath 
378d3a82192SShantkumar Hiremath 	if (!ibcm_check_sockdl(&ip2macp->ip2mac_ha)) {
379bd670b35SErik Nordmark 		IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_ack: Error: "
380d3a82192SShantkumar Hiremath 		    "interface %s is not IB\n", wqnp->ifname);
381d3a82192SShantkumar Hiremath 		err = EHOSTUNREACH;
382d3a82192SShantkumar Hiremath 		goto user_callback;
383d3a82192SShantkumar Hiremath 	}
384d3a82192SShantkumar Hiremath 
385d3a82192SShantkumar Hiremath 	cp = (uchar_t *)LLADDR(&ip2macp->ip2mac_ha);
386d3a82192SShantkumar Hiremath 	bcopy(cp, &wqnp->dst_mac, IPOIB_ADDRL);
387d3a82192SShantkumar Hiremath 
388d3a82192SShantkumar Hiremath 	/*
389d3a82192SShantkumar Hiremath 	 * at this point we have src/dst gid's derived from the mac addresses
390d3a82192SShantkumar Hiremath 	 * now get the hca, port
391d3a82192SShantkumar Hiremath 	 */
392d3a82192SShantkumar Hiremath 	bcopy(&wqnp->src_mac.ipoib_gidpref, &wqnp->sgid, sizeof (ib_gid_t));
393d3a82192SShantkumar Hiremath 	bcopy(&wqnp->dst_mac.ipoib_gidpref, &wqnp->dgid, sizeof (ib_gid_t));
394d3a82192SShantkumar Hiremath 
395d3a82192SShantkumar Hiremath 	IBCM_H2N_GID(wqnp->sgid);
396d3a82192SShantkumar Hiremath 	IBCM_H2N_GID(wqnp->dgid);
397d3a82192SShantkumar Hiremath 
398d3a82192SShantkumar Hiremath user_callback:
399bd670b35SErik Nordmark 
400bd670b35SErik Nordmark 	ib_s->status = err;
401bd670b35SErik Nordmark 	ib_s->done = B_TRUE;
402bd670b35SErik Nordmark 
403bd670b35SErik Nordmark 	/* lock is held by the caller. */
404bd670b35SErik Nordmark 	cv_signal(&ib_s->cv);
405d3a82192SShantkumar Hiremath 	mutex_exit(&ib_s->lock);
406d3a82192SShantkumar Hiremath }
407