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