Print this page
Overlay fabric router
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/overlay/overlay_target.c
+++ new/usr/src/uts/common/io/overlay/overlay_target.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 13 * Copyright 2018 Joyent, Inc.
14 14 */
15 15
16 16 /*
17 17 * Overlay device target cache management
18 18 *
19 19 * For more information, see the big theory statement in
20 20 * uts/common/io/overlay/overlay.c
21 21 */
22 22
23 23 #include <sys/types.h>
24 24 #include <sys/ethernet.h>
25 25 #include <sys/kmem.h>
26 26 #include <sys/policy.h>
27 27 #include <sys/sysmacros.h>
28 28 #include <sys/stream.h>
29 29 #include <sys/strsun.h>
30 30 #include <sys/strsubr.h>
31 31 #include <sys/mac_provider.h>
32 32 #include <sys/mac_client.h>
33 33 #include <sys/mac_client_priv.h>
34 34 #include <sys/vlan.h>
35 35 #include <sys/crc32.h>
36 36 #include <sys/cred.h>
37 37 #include <sys/file.h>
38 38 #include <sys/errno.h>
39 39 #include <sys/ddi.h>
40 40 #include <sys/sunddi.h>
41 41
42 42 #include <sys/overlay_impl.h>
43 43 #include <sys/sdt.h>
44 44
45 45 /*
46 46 * This is total straw man, but at least it's a prime number. Here we're
47 47 * going to have to go through and do a lot of evaluation and understanding as
48 48 * to how these target caches should grow and shrink, as well as, memory
49 49 * pressure and evictions. This just gives us a starting point that'll be 'good
50 50 * enough', until it's not.
51 51 */
52 52 #define OVERLAY_HSIZE 823
53 53
54 54 /*
55 55 * We use this data structure to keep track of what requests have been actively
56 56 * allocated to a given instance so we know what to put back on the pending
57 57 * list.
58 58 */
59 59 typedef struct overlay_target_hdl {
60 60 minor_t oth_minor; /* RO */
61 61 zoneid_t oth_zoneid; /* RO */
62 62 int oth_oflags; /* RO */
63 63 list_node_t oth_link; /* overlay_target_lock */
64 64 kmutex_t oth_lock;
65 65 list_t oth_outstanding; /* oth_lock */
66 66 } overlay_target_hdl_t;
67 67
68 68 typedef int (*overlay_target_copyin_f)(const void *, void **, size_t *, int);
69 69 typedef int (*overlay_target_ioctl_f)(overlay_target_hdl_t *, void *);
70 70 typedef int (*overlay_target_copyout_f)(void *, void *, size_t, int);
71 71
72 72 typedef struct overaly_target_ioctl {
|
↓ open down ↓ |
72 lines elided |
↑ open up ↑ |
73 73 int oti_cmd; /* ioctl id */
74 74 boolean_t oti_write; /* ioctl requires FWRITE */
75 75 boolean_t oti_ncopyout; /* copyout data? */
76 76 overlay_target_copyin_f oti_copyin; /* copyin func */
77 77 overlay_target_ioctl_f oti_func; /* function to call */
78 78 overlay_target_copyout_f oti_copyout; /* copyin func */
79 79 size_t oti_size; /* size of user level structure */
80 80 } overlay_target_ioctl_t;
81 81
82 82 static kmem_cache_t *overlay_target_cache;
83 -static kmem_cache_t *overlay_entry_cache;
83 +kmem_cache_t *overlay_entry_cache;
84 84 static id_space_t *overlay_thdl_idspace;
85 85 static void *overlay_thdl_state;
86 86
87 87 /*
88 88 * When we support overlay devices in the NGZ, then all of these need to become
89 89 * zone aware, by plugging into the netstack engine and becoming per-netstack
90 90 * data.
91 91 */
92 92 static list_t overlay_thdl_list;
93 93 static kmutex_t overlay_target_lock;
94 94 static kcondvar_t overlay_target_condvar;
95 95 static list_t overlay_target_list;
96 96 static boolean_t overlay_target_excl;
97 97
98 98 /*
99 99 * Outstanding data per hash table entry.
100 100 */
101 -static int overlay_ent_size = 128 * 1024;
101 +int overlay_ent_size = 128 * 1024;
102 102
103 103 /* ARGSUSED */
104 104 static int
105 105 overlay_target_cache_constructor(void *buf, void *arg, int kmflgs)
106 106 {
107 107 overlay_target_t *ott = buf;
108 108
109 109 mutex_init(&ott->ott_lock, NULL, MUTEX_DRIVER, NULL);
110 110 cv_init(&ott->ott_cond, NULL, CV_DRIVER, NULL);
111 111 return (0);
112 112 }
113 113
114 114 /* ARGSUSED */
115 115 static void
116 116 overlay_target_cache_destructor(void *buf, void *arg)
117 117 {
118 118 overlay_target_t *ott = buf;
119 119
120 120 cv_destroy(&ott->ott_cond);
121 121 mutex_destroy(&ott->ott_lock);
122 122 }
123 123
124 124 /* ARGSUSED */
125 125 static int
126 126 overlay_entry_cache_constructor(void *buf, void *arg, int kmflgs)
127 127 {
128 128 overlay_target_entry_t *ote = buf;
129 129
130 130 bzero(ote, sizeof (overlay_target_entry_t));
131 131 mutex_init(&ote->ote_lock, NULL, MUTEX_DRIVER, NULL);
132 132 return (0);
133 133 }
|
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
134 134
135 135 /* ARGSUSED */
136 136 static void
137 137 overlay_entry_cache_destructor(void *buf, void *arg)
138 138 {
139 139 overlay_target_entry_t *ote = buf;
140 140
141 141 mutex_destroy(&ote->ote_lock);
142 142 }
143 143
144 -/* TODO: we will need to modify these to hash/cmp DCID + MAC */
145 -
146 144 static uint64_t
147 145 overlay_mac_hash(const void *v)
148 146 {
149 147 uint32_t crc;
150 148 CRC32(crc, v, ETHERADDRL, -1U, crc32_table);
151 149 return (crc);
152 150 }
153 151
154 152 static int
155 153 overlay_mac_cmp(const void *a, const void *b)
156 154 {
157 155 return (bcmp(a, b, ETHERADDRL));
158 156 }
159 157
158 +static uint64_t
159 +overlay_vl3_hash(const void *v)
160 +{
161 + const overlay_target_entry_t *ote = v;
162 + uint32_t crc;
163 +
164 + CRC32(crc, &ote->ote_ip, sizeof (ote->ote_ip), -1U, crc32_table);
165 + CRC32(crc, &ote->ote_fab, sizeof (ote->ote_fab), crc, crc32_table);
166 + return (crc);
167 +}
168 +
169 +static int
170 +overlay_vl3_cmp(const void *a, const void *b)
171 +{
172 + const overlay_target_entry_t *l = a;
173 + const overlay_target_entry_t *r = b;
174 +
175 + if (l->ote_fab != r->ote_fab ||
176 + bcmp(&l->ote_ip, &r->ote_ip, sizeof (struct in6_addr)) != 0)
177 + return (1);
178 + return (0);
179 +}
180 +
181 +static int
182 +overlay_vl3_avl(const void *a, const void *b)
183 +{
184 + const overlay_target_entry_t *l = a;
185 + const overlay_target_entry_t *r = b;
186 +
187 + if (l->ote_fab < r->ote_fab)
188 + return (-1);
189 + if (l->ote_fab > r->ote_fab)
190 + return (1);
191 + return (memcmp(&l->ote_ip, &r->ote_ip, sizeof (struct in6_addr)));
192 +}
193 +
160 194 /* ARGSUSED */
161 -static void
195 +void
196 +overlay_target_entry_null_dtor(void *arg)
197 +{
198 +}
199 +
200 +/* ARGSUSED */
201 +void
162 202 overlay_target_entry_dtor(void *arg)
163 203 {
164 204 overlay_target_entry_t *ote = arg;
165 205
206 + ASSERT3U(ote->ote_refcnt, ==, 0);
207 +
166 208 ote->ote_flags = 0;
167 209 bzero(ote->ote_addr, ETHERADDRL);
210 + bzero(&ote->ote_ip, sizeof (ote->ote_ip));
168 211 ote->ote_ott = NULL;
169 212 ote->ote_odd = NULL;
213 + ote->ote_fab = NULL;
170 214 freemsgchain(ote->ote_chead);
171 215 ote->ote_chead = ote->ote_ctail = NULL;
172 216 ote->ote_mbsize = 0;
173 217 ote->ote_vtime = 0;
174 218 kmem_cache_free(overlay_entry_cache, ote);
175 219 }
176 220
177 221 static int
178 222 overlay_mac_avl(const void *a, const void *b)
179 223 {
180 224 int i;
181 225 const overlay_target_entry_t *l, *r;
182 226 l = a;
183 227 r = b;
184 228
185 229 for (i = 0; i < ETHERADDRL; i++) {
186 230 if (l->ote_addr[i] > r->ote_addr[i])
187 231 return (1);
188 232 else if (l->ote_addr[i] < r->ote_addr[i])
189 233 return (-1);
190 234 }
191 235
192 236 return (0);
193 237 }
194 238
195 239 void
196 240 overlay_target_init(void)
197 241 {
198 242 int ret;
199 243 ret = ddi_soft_state_init(&overlay_thdl_state,
200 244 sizeof (overlay_target_hdl_t), 1);
201 245 VERIFY(ret == 0);
202 246 overlay_target_cache = kmem_cache_create("overlay_target",
203 247 sizeof (overlay_target_t), 0, overlay_target_cache_constructor,
204 248 overlay_target_cache_destructor, NULL, NULL, NULL, 0);
205 249 overlay_entry_cache = kmem_cache_create("overlay_entry",
206 250 sizeof (overlay_target_entry_t), 0, overlay_entry_cache_constructor,
207 251 overlay_entry_cache_destructor, NULL, NULL, NULL, 0);
208 252 mutex_init(&overlay_target_lock, NULL, MUTEX_DRIVER, NULL);
209 253 cv_init(&overlay_target_condvar, NULL, CV_DRIVER, NULL);
210 254 list_create(&overlay_target_list, sizeof (overlay_target_entry_t),
211 255 offsetof(overlay_target_entry_t, ote_qlink));
212 256 list_create(&overlay_thdl_list, sizeof (overlay_target_hdl_t),
213 257 offsetof(overlay_target_hdl_t, oth_link));
214 258 overlay_thdl_idspace = id_space_create("overlay_target_minors",
215 259 1, INT32_MAX);
216 260 }
217 261
218 262 void
219 263 overlay_target_fini(void)
220 264 {
221 265 id_space_destroy(overlay_thdl_idspace);
222 266 list_destroy(&overlay_thdl_list);
223 267 list_destroy(&overlay_target_list);
224 268 cv_destroy(&overlay_target_condvar);
225 269 mutex_destroy(&overlay_target_lock);
226 270 kmem_cache_destroy(overlay_entry_cache);
227 271 kmem_cache_destroy(overlay_target_cache);
228 272 ddi_soft_state_fini(&overlay_thdl_state);
|
↓ open down ↓ |
49 lines elided |
↑ open up ↑ |
229 273 }
230 274
231 275 void
232 276 overlay_target_free(overlay_dev_t *odd)
233 277 {
234 278 if (odd->odd_target == NULL)
235 279 return;
236 280
237 281 if (odd->odd_target->ott_mode == OVERLAY_TARGET_DYNAMIC) {
238 282 refhash_t *rp = odd->odd_target->ott_u.ott_dyn.ott_dhash;
283 + refhash_t *r3p = odd->odd_target->ott_u.ott_dyn.ott_l3dhash;
239 284 avl_tree_t *ap = &odd->odd_target->ott_u.ott_dyn.ott_tree;
285 + avl_tree_t *a3p = &odd->odd_target->ott_u.ott_dyn.ott_l3tree;
240 286 overlay_target_entry_t *ote;
241 287
242 - /* TODO: remove from L3 trees */
243 -
244 288 /*
245 289 * Our AVL tree and hashtable contain the same elements,
246 290 * therefore we should just remove it from the tree, but then
247 291 * delete the entries when we remove them from the hash table
248 292 * (which happens through the refhash dtor).
249 293 */
250 - while ((ote = avl_first(ap)) != NULL)
294 + while ((ote = avl_first(ap)) != NULL) {
251 295 avl_remove(ap, ote);
252 -
296 + OVERLAY_TARG_ENTRY_REFRELE(ote);
297 + }
253 298 avl_destroy(ap);
299 +
300 + while ((ote = avl_first(a3p)) != NULL) {
301 + avl_remove(a3p, ote);
302 + OVERLAY_TARG_ENTRY_REFRELE(ote);
303 + }
304 + avl_destroy(a3p);
305 +
254 306 for (ote = refhash_first(rp); ote != NULL;
255 307 ote = refhash_next(rp, ote)) {
256 308 refhash_remove(rp, ote);
309 + OVERLAY_TARG_ENTRY_REFRELE(ote);
257 310 }
258 311 refhash_destroy(rp);
312 +
313 + for (ote = refhash_first(r3p); ote != NULL;
314 + ote = refhash_next(r3p, ote)) {
315 + refhash_remove(r3p, ote);
316 + OVERLAY_TARG_ENTRY_REFRELE(ote);
317 + }
318 + refhash_destroy(r3p);
259 319 }
260 320
261 321 ASSERT(odd->odd_target->ott_ocount == 0);
322 + bzero(&odd->odd_target->ott_u, sizeof (odd->odd_target->ott_u));
262 323 kmem_cache_free(overlay_target_cache, odd->odd_target);
324 + odd->odd_target = NULL;
263 325 }
264 326
265 327 int
266 328 overlay_target_busy()
267 329 {
268 330 int ret;
269 331
270 332 mutex_enter(&overlay_target_lock);
271 333 ret = !list_is_empty(&overlay_thdl_list);
272 334 mutex_exit(&overlay_target_lock);
273 335
274 336 return (ret);
275 337 }
276 338
277 -static void
339 +void
278 340 overlay_target_queue(overlay_target_entry_t *entry)
279 341 {
280 342 mutex_enter(&overlay_target_lock);
281 343 mutex_enter(&entry->ote_ott->ott_lock);
282 344 if (entry->ote_ott->ott_flags & OVERLAY_T_TEARDOWN) {
283 345 mutex_exit(&entry->ote_ott->ott_lock);
284 346 mutex_exit(&overlay_target_lock);
285 347 return;
286 348 }
287 349 entry->ote_ott->ott_ocount++;
288 350 mutex_exit(&entry->ote_ott->ott_lock);
289 351 list_insert_tail(&overlay_target_list, entry);
290 352 cv_signal(&overlay_target_condvar);
291 353 mutex_exit(&overlay_target_lock);
292 354 }
293 355
294 356 void
295 357 overlay_target_quiesce(overlay_target_t *ott)
296 358 {
297 359 if (ott == NULL)
298 360 return;
|
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
299 361 mutex_enter(&ott->ott_lock);
300 362 ott->ott_flags |= OVERLAY_T_TEARDOWN;
301 363 while (ott->ott_ocount != 0)
302 364 cv_wait(&ott->ott_cond, &ott->ott_lock);
303 365 mutex_exit(&ott->ott_lock);
304 366 }
305 367
306 368 /*
307 369 * This functions assumes that the destination mode is OVERLAY_PLUGIN_D_IP |
308 370 * OVERLAY_PLUGIN_D_PORT. As we don't have an implementation of anything else at
309 - * this time, say for NVGRE, we drop all packets that mcuh this.
310 - *
311 - * XXX: It might be better to replace the 'sock' argument with
312 - * overlay_target_entry_t** and set it with the found entry in the case
313 - * of OVERLAY_TARGET_OK.
371 + * this time, say for NVGRE, we drop all packets that match this.
314 372 */
315 373 int
316 374 overlay_target_lookup(overlay_dev_t *odd, mblk_t *mp, struct sockaddr *sock,
317 - socklen_t *slenp)
375 + socklen_t *slenp, uint64_t *vidp)
318 376 {
319 377 int ret;
320 378 struct sockaddr_in6 *v6;
321 379 overlay_target_t *ott;
322 380 mac_header_info_t mhi;
323 381 overlay_target_entry_t *entry;
324 382
325 383 ASSERT(odd->odd_target != NULL);
326 384
385 + *vidp = odd->odd_vid;
386 +
327 387 /*
328 388 * At this point, the overlay device is in a mux which means that it's
329 389 * been activated. At this point, parts of the target, such as the mode
330 390 * and the destination are now read-only and we don't have to worry
331 391 * about synchronization for them.
332 392 */
333 393 ott = odd->odd_target;
334 394 if (ott->ott_dest != (OVERLAY_PLUGIN_D_IP | OVERLAY_PLUGIN_D_PORT))
335 395 return (OVERLAY_TARGET_DROP);
336 396
337 397 v6 = (struct sockaddr_in6 *)sock;
338 398 bzero(v6, sizeof (struct sockaddr_in6));
339 399 v6->sin6_family = AF_INET6;
340 400
341 401 if (ott->ott_mode == OVERLAY_TARGET_POINT) {
342 402 mutex_enter(&ott->ott_lock);
343 403 bcopy(&ott->ott_u.ott_point.otp_ip, &v6->sin6_addr,
344 404 sizeof (struct in6_addr));
|
↓ open down ↓ |
8 lines elided |
↑ open up ↑ |
345 405 v6->sin6_port = htons(ott->ott_u.ott_point.otp_port);
346 406 mutex_exit(&ott->ott_lock);
347 407 *slenp = sizeof (struct sockaddr_in6);
348 408
349 409 return (OVERLAY_TARGET_OK);
350 410 }
351 411
352 412 ASSERT(ott->ott_mode == OVERLAY_TARGET_DYNAMIC);
353 413
354 414 /*
355 - * Note we only want the MAC address here, therefore we won't bother
356 - * using mac_vlan_header_info(). If any caller needs the vlan info at
357 - * this point, this should change to a call to mac_vlan_header_info().
415 + * VL2 -> UL3 lookups only need the destination VL2 mac address,
416 + * however, if we end up having to route the packet, we will need
417 + * the source vlan as part of the destination selection.
358 418 */
359 - if (mac_header_info(odd->odd_mh, mp, &mhi) != 0)
419 + if (mac_vlan_header_info(odd->odd_mh, mp, &mhi) != 0)
360 420 return (OVERLAY_TARGET_DROP);
361 421
362 - /*
363 - * TODO: compare mhi.mhi_daddr with odd->macaddr.
364 - * If match,
365 - * get VL3 dest from mp
366 - * lookup target using VL3 dest
367 - * otherwise,
368 - * lookup target using VL2 dest (existing refhash_lookup() call
369 - * below)
370 - */
371 422 mutex_enter(&ott->ott_lock);
372 423 entry = refhash_lookup(ott->ott_u.ott_dyn.ott_dhash,
373 424 mhi.mhi_daddr);
374 425 if (entry == NULL) {
375 426 entry = kmem_cache_alloc(overlay_entry_cache,
376 427 KM_NOSLEEP | KM_NORMALPRI);
377 428 if (entry == NULL) {
378 429 mutex_exit(&ott->ott_lock);
379 430 return (OVERLAY_TARGET_DROP);
380 431 }
381 - /*
382 - * TODO: set entry->ote_dcid, if VL3 lookup, copy dst addr
383 - * into entry->ote_ip. Probably zero out the address we're
384 - * not lookup up (VL2 or VL3) as well.
385 - */
386 432 bcopy(mhi.mhi_daddr, entry->ote_addr, ETHERADDRL);
387 433 entry->ote_chead = entry->ote_ctail = mp;
388 434 entry->ote_mbsize = msgsize(mp);
389 435 entry->ote_flags |= OVERLAY_ENTRY_F_PENDING;
390 436 entry->ote_ott = ott;
391 437 entry->ote_odd = odd;
438 +
439 + OVERLAY_TARG_ENTRY_REFHOLD(entry);
392 440 refhash_insert(ott->ott_u.ott_dyn.ott_dhash, entry);
441 +
442 + OVERLAY_TARG_ENTRY_REFHOLD(entry);
393 443 avl_add(&ott->ott_u.ott_dyn.ott_tree, entry);
444 +
394 445 mutex_exit(&ott->ott_lock);
395 446 overlay_target_queue(entry);
396 447 return (OVERLAY_TARGET_ASYNC);
397 448 }
398 - refhash_hold(ott->ott_u.ott_dyn.ott_dhash, entry);
449 + OVERLAY_TARG_ENTRY_REFHOLD(entry);
399 450 mutex_exit(&ott->ott_lock);
400 451
401 452 mutex_enter(&entry->ote_lock);
402 453 if (entry->ote_flags & OVERLAY_ENTRY_F_DROP) {
403 454 ret = OVERLAY_TARGET_DROP;
455 + } else if (entry->ote_flags & OVERLAY_ENTRY_F_ROUTER) {
456 + ret = overlay_route_lookup(odd, mp, &mhi, sock, slenp, vidp);
404 457 } else if (entry->ote_flags & OVERLAY_ENTRY_F_VALID) {
405 458 bcopy(&entry->ote_dest.otp_ip, &v6->sin6_addr,
406 459 sizeof (struct in6_addr));
407 460 v6->sin6_port = htons(entry->ote_dest.otp_port);
408 461 *slenp = sizeof (struct sockaddr_in6);
409 462 ret = OVERLAY_TARGET_OK;
410 463 } else {
411 464 size_t mlen = msgsize(mp);
412 465
413 466 if (mlen + entry->ote_mbsize > overlay_ent_size) {
414 467 ret = OVERLAY_TARGET_DROP;
415 468 } else {
416 469 if (entry->ote_ctail != NULL) {
417 470 ASSERT(entry->ote_ctail->b_next ==
418 471 NULL);
419 472 entry->ote_ctail->b_next = mp;
420 473 entry->ote_ctail = mp;
421 474 } else {
422 475 entry->ote_chead = mp;
423 476 entry->ote_ctail = mp;
424 477 }
425 478 entry->ote_mbsize += mlen;
426 479 if ((entry->ote_flags &
427 480 OVERLAY_ENTRY_F_PENDING) == 0) {
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
428 481 entry->ote_flags |=
429 482 OVERLAY_ENTRY_F_PENDING;
430 483 overlay_target_queue(entry);
431 484 }
432 485 ret = OVERLAY_TARGET_ASYNC;
433 486 }
434 487 }
435 488 mutex_exit(&entry->ote_lock);
436 489
437 490 mutex_enter(&ott->ott_lock);
438 - refhash_rele(ott->ott_u.ott_dyn.ott_dhash, entry);
491 + OVERLAY_TARG_ENTRY_REFRELE(entry);
439 492 mutex_exit(&ott->ott_lock);
440 493
441 494 return (ret);
442 495 }
443 496
444 497 /* ARGSUSED */
445 498 static int
446 499 overlay_target_info(overlay_target_hdl_t *thdl, void *arg)
447 500 {
448 501 overlay_dev_t *odd;
449 502 overlay_targ_info_t *oti = arg;
450 503
451 504 odd = overlay_hold_by_dlid(oti->oti_linkid);
452 505 if (odd == NULL)
453 506 return (ENOENT);
454 507
455 508 mutex_enter(&odd->odd_lock);
456 509 oti->oti_flags = 0;
457 510 oti->oti_needs = odd->odd_plugin->ovp_dest;
458 511 if (odd->odd_flags & OVERLAY_F_DEGRADED)
459 512 oti->oti_flags |= OVERLAY_TARG_INFO_F_DEGRADED;
460 513 if (odd->odd_flags & OVERLAY_F_ACTIVATED)
461 514 oti->oti_flags |= OVERLAY_TARG_INFO_F_ACTIVE;
462 515 oti->oti_vnetid = odd->odd_vid;
463 516 oti->oti_dcid = odd->odd_dcid;
464 517 mutex_exit(&odd->odd_lock);
465 518 overlay_hold_rele(odd);
|
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
466 519 return (0);
467 520 }
468 521
469 522 /* ARGSUSED */
470 523 static int
471 524 overlay_target_associate(overlay_target_hdl_t *thdl, void *arg)
472 525 {
473 526 overlay_dev_t *odd;
474 527 overlay_target_t *ott;
475 528 overlay_targ_associate_t *ota = arg;
529 + overlay_router_t *ort;
476 530
477 531 odd = overlay_hold_by_dlid(ota->ota_linkid);
478 532 if (odd == NULL)
479 533 return (ENOENT);
480 534
481 535 if (ota->ota_id == 0) {
482 536 overlay_hold_rele(odd);
483 537 return (EINVAL);
484 538 }
485 539
486 540 if (ota->ota_mode != OVERLAY_TARGET_POINT &&
487 541 ota->ota_mode != OVERLAY_TARGET_DYNAMIC) {
488 542 overlay_hold_rele(odd);
489 543 return (EINVAL);
490 544 }
491 545
492 546 if (ota->ota_provides != odd->odd_plugin->ovp_dest) {
493 547 overlay_hold_rele(odd);
494 548 return (EINVAL);
495 549 }
496 550
497 551 if (ota->ota_mode == OVERLAY_TARGET_POINT) {
498 552 if (ota->ota_provides & OVERLAY_PLUGIN_D_IP) {
499 553 if (IN6_IS_ADDR_UNSPECIFIED(&ota->ota_point.otp_ip) ||
500 554 IN6_IS_ADDR_V4COMPAT(&ota->ota_point.otp_ip) ||
501 555 IN6_IS_ADDR_V4MAPPED_ANY(&ota->ota_point.otp_ip)) {
502 556 overlay_hold_rele(odd);
503 557 return (EINVAL);
504 558 }
505 559 }
506 560
507 561 if (ota->ota_provides & OVERLAY_PLUGIN_D_PORT) {
508 562 if (ota->ota_point.otp_port == 0) {
509 563 overlay_hold_rele(odd);
510 564 return (EINVAL);
511 565 }
512 566 }
513 567 }
514 568
515 569 ott = kmem_cache_alloc(overlay_target_cache, KM_SLEEP);
516 570 ott->ott_flags = 0;
517 571 ott->ott_ocount = 0;
|
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
518 572 ott->ott_mode = ota->ota_mode;
519 573 ott->ott_dest = ota->ota_provides;
520 574 ott->ott_id = ota->ota_id;
521 575
522 576 if (ott->ott_mode == OVERLAY_TARGET_POINT) {
523 577 bcopy(&ota->ota_point, &ott->ott_u.ott_point,
524 578 sizeof (overlay_target_point_t));
525 579 } else {
526 580 ott->ott_u.ott_dyn.ott_dhash = refhash_create(OVERLAY_HSIZE,
527 581 overlay_mac_hash, overlay_mac_cmp,
528 - overlay_target_entry_dtor, sizeof (overlay_target_entry_t),
582 + overlay_target_entry_null_dtor,
583 + sizeof (overlay_target_entry_t),
529 584 offsetof(overlay_target_entry_t, ote_reflink),
530 585 offsetof(overlay_target_entry_t, ote_addr), KM_SLEEP);
586 + ott->ott_u.ott_dyn.ott_l3dhash = refhash_create(OVERLAY_HSIZE,
587 + overlay_vl3_hash, overlay_vl3_cmp,
588 + overlay_target_entry_null_dtor,
589 + sizeof (overlay_target_entry_t),
590 + offsetof(overlay_target_entry_t, ote_l3_reflink), 0,
591 + KM_SLEEP);
531 592 avl_create(&ott->ott_u.ott_dyn.ott_tree, overlay_mac_avl,
532 593 sizeof (overlay_target_entry_t),
533 594 offsetof(overlay_target_entry_t, ote_avllink));
595 + avl_create(&ott->ott_u.ott_dyn.ott_l3tree, overlay_vl3_avl,
596 + sizeof (overlay_target_entry_t),
597 + offsetof(overlay_target_entry_t, ote_l3_avllink));
598 +
599 + ort = kmem_zalloc(sizeof (*ort), KM_SLEEP);
600 + mutex_init(&ort->otr_lock, NULL, MUTEX_DRIVER, NULL);
601 + list_create(&ort->otr_tables, sizeof (overlay_route_table_t),
602 + offsetof(overlay_route_table_t, ort_link));
603 + avl_create(&ort->otr_tree, overlay_fabric_avl,
604 + sizeof (overlay_fabric_entry_t),
605 + offsetof(overlay_fabric_entry_t, ofe_avllink));
534 606 }
535 607 mutex_enter(&odd->odd_lock);
536 608 if (odd->odd_flags & OVERLAY_F_VARPD) {
537 609 mutex_exit(&odd->odd_lock);
538 610 kmem_cache_free(overlay_target_cache, ott);
539 611 overlay_hold_rele(odd);
540 612 return (EEXIST);
541 613 }
542 614
543 615 odd->odd_flags |= OVERLAY_F_VARPD;
544 616 odd->odd_target = ott;
545 617 mutex_exit(&odd->odd_lock);
546 618
547 619 overlay_hold_rele(odd);
548 620
549 -
550 621 return (0);
551 622 }
552 623
553 624
554 625 /* ARGSUSED */
555 626 static int
556 627 overlay_target_degrade(overlay_target_hdl_t *thdl, void *arg)
557 628 {
558 629 overlay_dev_t *odd;
559 630 overlay_targ_degrade_t *otd = arg;
560 631
561 632 odd = overlay_hold_by_dlid(otd->otd_linkid);
562 633 if (odd == NULL)
563 634 return (ENOENT);
564 635
565 636 overlay_fm_degrade(odd, otd->otd_buf);
566 637 overlay_hold_rele(odd);
567 638 return (0);
568 639 }
569 640
570 641 /* ARGSUSED */
571 642 static int
572 643 overlay_target_restore(overlay_target_hdl_t *thdl, void *arg)
573 644 {
574 645 overlay_dev_t *odd;
575 646 overlay_targ_id_t *otid = arg;
576 647
577 648 odd = overlay_hold_by_dlid(otid->otid_linkid);
578 649 if (odd == NULL)
579 650 return (ENOENT);
580 651
581 652 overlay_fm_restore(odd);
582 653 overlay_hold_rele(odd);
583 654 return (0);
584 655 }
585 656
586 657 /* ARGSUSED */
587 658 static int
588 659 overlay_target_disassociate(overlay_target_hdl_t *thdl, void *arg)
589 660 {
590 661 overlay_dev_t *odd;
591 662 overlay_targ_id_t *otid = arg;
592 663
593 664 odd = overlay_hold_by_dlid(otid->otid_linkid);
594 665 if (odd == NULL)
595 666 return (ENOENT);
596 667
597 668 mutex_enter(&odd->odd_lock);
598 669 odd->odd_flags &= ~OVERLAY_F_VARPD;
599 670 mutex_exit(&odd->odd_lock);
600 671
|
↓ open down ↓ |
41 lines elided |
↑ open up ↑ |
601 672 overlay_hold_rele(odd);
602 673 return (0);
603 674
604 675 }
605 676
606 677 static int
607 678 overlay_target_lookup_request(overlay_target_hdl_t *thdl, void *arg)
608 679 {
609 680 overlay_targ_lookup_t *otl = arg;
610 681 overlay_target_entry_t *entry;
682 + void *src, *dst;
611 683 clock_t ret, timeout;
612 684 mac_header_info_t mhi;
613 -
614 685 timeout = ddi_get_lbolt() + drv_usectohz(MICROSEC);
615 686 again:
616 687 mutex_enter(&overlay_target_lock);
617 688 while (list_is_empty(&overlay_target_list)) {
618 689 ret = cv_timedwait(&overlay_target_condvar,
619 690 &overlay_target_lock, timeout);
620 691 if (ret == -1) {
621 692 mutex_exit(&overlay_target_lock);
622 693 return (ETIME);
623 694 }
624 695 }
625 696 entry = list_remove_head(&overlay_target_list);
626 697 mutex_exit(&overlay_target_lock);
627 698 mutex_enter(&entry->ote_lock);
628 - if (entry->ote_flags & OVERLAY_ENTRY_F_VALID) {
699 + if (entry->ote_flags &
700 + (OVERLAY_ENTRY_F_PENDING | OVERLAY_ENTRY_F_VL3_PENDING)) {
629 701 ASSERT(entry->ote_chead == NULL);
630 702 mutex_exit(&entry->ote_lock);
631 703 goto again;
632 704 }
633 705 ASSERT(entry->ote_chead != NULL);
634 706
707 +
708 + otl->otl_l3req = (entry->ote_flags & OVERLAY_ENTRY_F_VL3_PENDING) ?
709 + B_TRUE : B_FALSE;
710 +
711 + if (otl->otl_l3req) {
712 + src = &otl->otl_addru.otlu_l3.otl3_srcip;
713 + dst = &otl->otl_addru.otlu_l3.otl3_dstip;
714 + } else {
715 + src = &otl->otl_addru.otlu_l2.otl2_srcaddr;
716 + dst = &otl->otl_addru.otlu_l2.otl2_dstaddr;
717 + }
718 +
635 719 /*
636 - * If we have a bogon that doesn't have a valid mac header, drop it and
637 - * try again.
720 + * If we have a bogon that doesn't have a valid mac header, or an
721 + * invalid IP header for IP requests, drop it and try again.
638 722 */
639 - if (mac_vlan_header_info(entry->ote_odd->odd_mh, entry->ote_chead,
640 - &mhi) != 0) {
723 + if ((mac_vlan_header_info(entry->ote_odd->odd_mh, entry->ote_chead,
724 + &mhi) != 0) ||
725 + (otl->otl_l3req && overlay_mblk_vl3ip(entry->ote_chead, src,
726 + dst) != 0)) {
641 727 boolean_t queue = B_FALSE;
642 728 mblk_t *mp = entry->ote_chead;
643 729 entry->ote_chead = mp->b_next;
644 730 mp->b_next = NULL;
645 731 if (entry->ote_ctail == mp)
646 732 entry->ote_ctail = entry->ote_chead;
647 733 entry->ote_mbsize -= msgsize(mp);
648 734 if (entry->ote_chead != NULL)
649 735 queue = B_TRUE;
650 736 mutex_exit(&entry->ote_lock);
651 737 if (queue == B_TRUE)
652 738 overlay_target_queue(entry);
653 739 freemsg(mp);
654 740 goto again;
655 741 }
656 742
657 - /*
658 - * TODO: If VL3 request,
659 - * set otl->otl_l3req
660 - * Fill in otl_{src,dst}ip
661 - * Else
662 - * clear otl->otl_l3req
663 - */
664 743 otl->otl_dlid = entry->ote_odd->odd_linkid;
665 744 otl->otl_reqid = (uintptr_t)entry;
666 745 otl->otl_varpdid = entry->ote_ott->ott_id;
667 746 otl->otl_vnetid = entry->ote_odd->odd_vid;
668 747
669 748 otl->otl_hdrsize = mhi.mhi_hdrsize;
670 749 otl->otl_pktsize = msgsize(entry->ote_chead) - otl->otl_hdrsize;
671 - bcopy(mhi.mhi_daddr, otl->otl_addru.otlu_l2.otl2_dstaddr, ETHERADDRL);
672 - bcopy(mhi.mhi_saddr, otl->otl_addru.otlu_l2.otl2_srcaddr, ETHERADDRL);
673 750 otl->otl_addru.otlu_l2.otl2_dsttype = mhi.mhi_dsttype;
674 751 otl->otl_addru.otlu_l2.otl2_sap = mhi.mhi_bindsap;
675 752 otl->otl_vlan = VLAN_ID(mhi.mhi_tci);
753 +
754 + /*
755 + * The overlay_mblk_vl3ip() call above fills in dst & src for
756 + * VL3->UL3 requests, so only need to care about VL2->UL3 here.
757 + */
758 + if (!otl->otl_l3req) {
759 + bcopy(mhi.mhi_daddr, dst, ETHERADDRL);
760 + bcopy(mhi.mhi_saddr, src, ETHERADDRL);
761 + }
676 762 mutex_exit(&entry->ote_lock);
677 763
678 764 mutex_enter(&thdl->oth_lock);
679 765 list_insert_tail(&thdl->oth_outstanding, entry);
680 766 mutex_exit(&thdl->oth_lock);
681 767
682 768 return (0);
683 769 }
684 770
685 771 static int
686 772 overlay_target_lookup_respond(overlay_target_hdl_t *thdl, void *arg)
687 773 {
688 774 const overlay_targ_resp_t *otr = arg;
689 775 overlay_target_entry_t *entry;
690 776 mblk_t *mp;
777 + boolean_t is_router = B_FALSE;
691 778
779 + /*
780 + * If we ever support a protocol that uses MAC addresses for the UL
781 + * destination addr, we probably should expand this to check that
782 + * all of otr is zero.
783 + */
784 + if (IN6_IS_ADDR_UNSPECIFIED(&otr->otr_answer.otp_ip) &&
785 + otr->otr_answer.otp_port == 0)
786 + is_router = B_TRUE;
787 +
692 788 mutex_enter(&thdl->oth_lock);
693 789 for (entry = list_head(&thdl->oth_outstanding); entry != NULL;
694 790 entry = list_next(&thdl->oth_outstanding, entry)) {
695 791 if ((uintptr_t)entry == otr->otr_reqid)
696 792 break;
697 793 }
698 794
699 795 if (entry == NULL) {
700 796 mutex_exit(&thdl->oth_lock);
701 797 return (EINVAL);
702 798 }
703 799 list_remove(&thdl->oth_outstanding, entry);
704 800 mutex_exit(&thdl->oth_lock);
705 801
706 802 mutex_enter(&entry->ote_lock);
707 803 bcopy(&otr->otr_answer, &entry->ote_dest,
708 804 sizeof (overlay_target_point_t));
709 805 entry->ote_flags &= ~OVERLAY_ENTRY_F_PENDING;
710 806 entry->ote_flags |= OVERLAY_ENTRY_F_VALID;
807 + if (is_router)
808 + entry->ote_flags |= OVERLAY_ENTRY_F_ROUTER;
711 809 mp = entry->ote_chead;
712 810 entry->ote_chead = NULL;
713 811 entry->ote_ctail = NULL;
714 812 entry->ote_mbsize = 0;
715 813 entry->ote_vtime = gethrtime();
716 814 mutex_exit(&entry->ote_lock);
717 815
718 816 /*
719 817 * For now do an in-situ drain.
720 818 *
721 819 * TODO: overlay_m_tx() will need to perform remote fabric attachment
722 820 * checks, which may leave mblk_t's left in the msg chain for
723 821 * mblk_t's whose connectivity with the target entry are unknown.
724 822 * This will then need to deal with the leftovers.
725 823 */
726 824 mp = overlay_m_tx(entry->ote_odd, mp);
727 825 freemsgchain(mp);
728 826
729 827 mutex_enter(&entry->ote_ott->ott_lock);
730 828 entry->ote_ott->ott_ocount--;
731 829 cv_signal(&entry->ote_ott->ott_cond);
732 830 mutex_exit(&entry->ote_ott->ott_lock);
733 831
734 832 return (0);
735 833 }
736 834
737 835 static int
738 836 overlay_target_lookup_drop(overlay_target_hdl_t *thdl, void *arg)
739 837 {
740 838 const overlay_targ_resp_t *otr = arg;
741 839 overlay_target_entry_t *entry;
742 840 mblk_t *mp;
743 841 boolean_t queue = B_FALSE;
744 842
745 843 mutex_enter(&thdl->oth_lock);
746 844 for (entry = list_head(&thdl->oth_outstanding); entry != NULL;
747 845 entry = list_next(&thdl->oth_outstanding, entry)) {
748 846 if ((uintptr_t)entry == otr->otr_reqid)
749 847 break;
750 848 }
751 849
752 850 if (entry == NULL) {
753 851 mutex_exit(&thdl->oth_lock);
754 852 return (EINVAL);
755 853 }
756 854 list_remove(&thdl->oth_outstanding, entry);
757 855 mutex_exit(&thdl->oth_lock);
758 856
759 857 mutex_enter(&entry->ote_lock);
760 858
761 859 /* Safeguard against a confused varpd */
762 860 if (entry->ote_flags & OVERLAY_ENTRY_F_VALID) {
763 861 entry->ote_flags &= ~OVERLAY_ENTRY_F_PENDING;
764 862 DTRACE_PROBE1(overlay__target__valid__drop,
765 863 overlay_target_entry_t *, entry);
766 864 mutex_exit(&entry->ote_lock);
767 865 goto done;
768 866 }
769 867
770 868 /*
771 869 * TODO: This will need to be smarter. This drop can only apply to
772 870 * packets from the same source fabric as the first mblk_t in the
773 871 * chain. If the target exists, packets from other fabrics which
774 872 * are chained to this target entry may be able to be sent (if we
775 873 * already know they are attached), or we might need to query from
776 874 * those other source fabrics if we don't know if the two are
777 875 * attached.
778 876 */
779 877 mp = entry->ote_chead;
780 878 if (mp != NULL) {
781 879 entry->ote_chead = mp->b_next;
782 880 mp->b_next = NULL;
783 881 if (entry->ote_ctail == mp)
784 882 entry->ote_ctail = entry->ote_chead;
785 883 entry->ote_mbsize -= msgsize(mp);
786 884 }
787 885 if (entry->ote_chead != NULL) {
788 886 queue = B_TRUE;
789 887 entry->ote_flags |= OVERLAY_ENTRY_F_PENDING;
790 888 } else {
791 889 entry->ote_flags &= ~OVERLAY_ENTRY_F_PENDING;
792 890 }
793 891 mutex_exit(&entry->ote_lock);
794 892
795 893 if (queue == B_TRUE)
796 894 overlay_target_queue(entry);
797 895 freemsg(mp);
798 896
799 897 done:
800 898 mutex_enter(&entry->ote_ott->ott_lock);
801 899 entry->ote_ott->ott_ocount--;
802 900 cv_signal(&entry->ote_ott->ott_cond);
803 901 mutex_exit(&entry->ote_ott->ott_lock);
804 902
805 903 return (0);
806 904 }
807 905
808 906 /* ARGSUSED */
809 907 static int
810 908 overlay_target_pkt_copyin(const void *ubuf, void **outp, size_t *bsize,
811 909 int flags)
812 910 {
813 911 overlay_targ_pkt_t *pkt;
814 912 overlay_targ_pkt32_t *pkt32;
815 913
816 914 pkt = kmem_alloc(sizeof (overlay_targ_pkt_t), KM_SLEEP);
817 915 *outp = pkt;
818 916 *bsize = sizeof (overlay_targ_pkt_t);
819 917 if (ddi_model_convert_from(flags & FMODELS) == DDI_MODEL_ILP32) {
820 918 uintptr_t addr;
821 919
822 920 if (ddi_copyin(ubuf, pkt, sizeof (overlay_targ_pkt32_t),
823 921 flags & FKIOCTL) != 0) {
824 922 kmem_free(pkt, *bsize);
825 923 return (EFAULT);
826 924 }
827 925 pkt32 = (overlay_targ_pkt32_t *)pkt;
828 926 addr = pkt32->otp_buf;
829 927 pkt->otp_buf = (void *)addr;
830 928 } else {
831 929 if (ddi_copyin(ubuf, pkt, *bsize, flags & FKIOCTL) != 0) {
832 930 kmem_free(pkt, *bsize);
833 931 return (EFAULT);
834 932 }
835 933 }
836 934 return (0);
837 935 }
838 936
839 937 static int
840 938 overlay_target_pkt_copyout(void *ubuf, void *buf, size_t bufsize,
841 939 int flags)
842 940 {
843 941 if (ddi_model_convert_from(flags & FMODELS) == DDI_MODEL_ILP32) {
844 942 overlay_targ_pkt_t *pkt = buf;
845 943 overlay_targ_pkt32_t *pkt32 = buf;
846 944 uintptr_t addr = (uintptr_t)pkt->otp_buf;
847 945 pkt32->otp_buf = (caddr32_t)addr;
848 946 if (ddi_copyout(buf, ubuf, sizeof (overlay_targ_pkt32_t),
849 947 flags & FKIOCTL) != 0)
850 948 return (EFAULT);
851 949 } else {
852 950 if (ddi_copyout(buf, ubuf, bufsize, flags & FKIOCTL) != 0)
853 951 return (EFAULT);
854 952 }
855 953 return (0);
856 954 }
857 955
858 956 static int
859 957 overlay_target_packet(overlay_target_hdl_t *thdl, void *arg)
860 958 {
861 959 overlay_targ_pkt_t *pkt = arg;
862 960 overlay_target_entry_t *entry;
863 961 mblk_t *mp;
864 962 size_t mlen;
865 963 size_t boff;
866 964
867 965 mutex_enter(&thdl->oth_lock);
868 966 for (entry = list_head(&thdl->oth_outstanding); entry != NULL;
869 967 entry = list_next(&thdl->oth_outstanding, entry)) {
870 968 if ((uintptr_t)entry == pkt->otp_reqid)
871 969 break;
872 970 }
873 971
874 972 if (entry == NULL) {
875 973 mutex_exit(&thdl->oth_lock);
876 974 return (EINVAL);
877 975 }
878 976 mutex_enter(&entry->ote_lock);
879 977 mutex_exit(&thdl->oth_lock);
880 978 mp = entry->ote_chead;
881 979 /* Protect against a rogue varpd */
882 980 if (mp == NULL) {
883 981 mutex_exit(&entry->ote_lock);
884 982 return (EINVAL);
885 983 }
886 984 mlen = MIN(msgsize(mp), pkt->otp_size);
887 985 pkt->otp_size = mlen;
888 986 boff = 0;
889 987 while (mlen > 0) {
890 988 size_t wlen = MIN(MBLKL(mp), mlen);
891 989 if (ddi_copyout(mp->b_rptr,
892 990 (void *)((uintptr_t)pkt->otp_buf + boff),
893 991 wlen, 0) != 0) {
894 992 mutex_exit(&entry->ote_lock);
895 993 return (EFAULT);
896 994 }
897 995 mlen -= wlen;
898 996 boff += wlen;
899 997 mp = mp->b_cont;
900 998 }
901 999 mutex_exit(&entry->ote_lock);
902 1000 return (0);
903 1001 }
904 1002
905 1003 static int
906 1004 overlay_target_inject(overlay_target_hdl_t *thdl, void *arg)
907 1005 {
908 1006 overlay_targ_pkt_t *pkt = arg;
909 1007 overlay_target_entry_t *entry;
910 1008 overlay_dev_t *odd;
911 1009 mblk_t *mp;
912 1010
913 1011 if (pkt->otp_size > ETHERMAX + VLAN_TAGSZ)
914 1012 return (EINVAL);
915 1013
916 1014 mp = allocb(pkt->otp_size, 0);
917 1015 if (mp == NULL)
918 1016 return (ENOMEM);
919 1017
920 1018 if (ddi_copyin(pkt->otp_buf, mp->b_rptr, pkt->otp_size, 0) != 0) {
921 1019 freeb(mp);
922 1020 return (EFAULT);
923 1021 }
924 1022 mp->b_wptr += pkt->otp_size;
925 1023
926 1024 if (pkt->otp_linkid != UINT64_MAX) {
927 1025 odd = overlay_hold_by_dlid(pkt->otp_linkid);
928 1026 if (odd == NULL) {
929 1027 freeb(mp);
930 1028 return (ENOENT);
931 1029 }
932 1030 } else {
933 1031 mutex_enter(&thdl->oth_lock);
934 1032 for (entry = list_head(&thdl->oth_outstanding); entry != NULL;
935 1033 entry = list_next(&thdl->oth_outstanding, entry)) {
936 1034 if ((uintptr_t)entry == pkt->otp_reqid)
937 1035 break;
938 1036 }
939 1037
940 1038 if (entry == NULL) {
941 1039 mutex_exit(&thdl->oth_lock);
942 1040 freeb(mp);
943 1041 return (ENOENT);
944 1042 }
945 1043 odd = entry->ote_odd;
946 1044 mutex_exit(&thdl->oth_lock);
947 1045 }
948 1046
949 1047 mutex_enter(&odd->odd_lock);
950 1048 overlay_io_start(odd, OVERLAY_F_IN_RX);
951 1049 mutex_exit(&odd->odd_lock);
952 1050
953 1051 mac_rx(odd->odd_mh, NULL, mp);
954 1052
955 1053 mutex_enter(&odd->odd_lock);
956 1054 overlay_io_done(odd, OVERLAY_F_IN_RX);
957 1055 mutex_exit(&odd->odd_lock);
958 1056
959 1057 return (0);
960 1058 }
961 1059
962 1060 static int
963 1061 overlay_target_resend(overlay_target_hdl_t *thdl, void *arg)
964 1062 {
965 1063 overlay_targ_pkt_t *pkt = arg;
966 1064 overlay_target_entry_t *entry;
967 1065 overlay_dev_t *odd;
968 1066 mblk_t *mp;
969 1067
970 1068 if (pkt->otp_size > ETHERMAX + VLAN_TAGSZ)
971 1069 return (EINVAL);
972 1070
973 1071 mp = allocb(pkt->otp_size, 0);
974 1072 if (mp == NULL)
975 1073 return (ENOMEM);
976 1074
977 1075 if (ddi_copyin(pkt->otp_buf, mp->b_rptr, pkt->otp_size, 0) != 0) {
978 1076 freeb(mp);
979 1077 return (EFAULT);
980 1078 }
981 1079 mp->b_wptr += pkt->otp_size;
982 1080
983 1081 if (pkt->otp_linkid != UINT64_MAX) {
984 1082 odd = overlay_hold_by_dlid(pkt->otp_linkid);
985 1083 if (odd == NULL) {
986 1084 freeb(mp);
987 1085 return (ENOENT);
988 1086 }
989 1087 } else {
990 1088 mutex_enter(&thdl->oth_lock);
991 1089 for (entry = list_head(&thdl->oth_outstanding); entry != NULL;
992 1090 entry = list_next(&thdl->oth_outstanding, entry)) {
993 1091 if ((uintptr_t)entry == pkt->otp_reqid)
994 1092 break;
995 1093 }
996 1094
997 1095 if (entry == NULL) {
998 1096 mutex_exit(&thdl->oth_lock);
999 1097 freeb(mp);
1000 1098 return (ENOENT);
1001 1099 }
1002 1100 odd = entry->ote_odd;
1003 1101 mutex_exit(&thdl->oth_lock);
1004 1102 }
1005 1103
1006 1104 mp = overlay_m_tx(odd, mp);
1007 1105 freemsgchain(mp);
1008 1106
1009 1107 return (0);
1010 1108 }
1011 1109
1012 1110 typedef struct overlay_targ_list_int {
1013 1111 boolean_t otli_count;
1014 1112 uint32_t otli_cur;
1015 1113 uint32_t otli_nents;
1016 1114 uint32_t otli_ents[];
1017 1115 } overlay_targ_list_int_t;
1018 1116
1019 1117 static int
1020 1118 overlay_target_list_copyin(const void *ubuf, void **outp, size_t *bsize,
1021 1119 int flags)
1022 1120 {
1023 1121 overlay_targ_list_t n;
1024 1122 overlay_targ_list_int_t *otl;
1025 1123
1026 1124 if (ddi_copyin(ubuf, &n, sizeof (overlay_targ_list_t),
1027 1125 flags & FKIOCTL) != 0)
1028 1126 return (EFAULT);
1029 1127
1030 1128 /*
1031 1129 */
1032 1130 if (n.otl_nents >= INT32_MAX / sizeof (uint32_t))
1033 1131 return (EINVAL);
1034 1132 *bsize = sizeof (overlay_targ_list_int_t) +
1035 1133 sizeof (uint32_t) * n.otl_nents;
1036 1134 otl = kmem_zalloc(*bsize, KM_SLEEP);
1037 1135 otl->otli_cur = 0;
1038 1136 otl->otli_nents = n.otl_nents;
1039 1137 if (otl->otli_nents != 0) {
1040 1138 otl->otli_count = B_FALSE;
1041 1139 if (ddi_copyin((void *)((uintptr_t)ubuf +
1042 1140 offsetof(overlay_targ_list_t, otl_ents)),
1043 1141 otl->otli_ents, n.otl_nents * sizeof (uint32_t),
1044 1142 flags & FKIOCTL) != 0) {
1045 1143 kmem_free(otl, *bsize);
1046 1144 return (EFAULT);
1047 1145 }
1048 1146 } else {
1049 1147 otl->otli_count = B_TRUE;
1050 1148 }
1051 1149
1052 1150 *outp = otl;
1053 1151 return (0);
1054 1152 }
1055 1153
1056 1154 static int
1057 1155 overlay_target_ioctl_list_cb(overlay_dev_t *odd, void *arg)
1058 1156 {
1059 1157 overlay_targ_list_int_t *otl = arg;
1060 1158
1061 1159 if (otl->otli_cur < otl->otli_nents)
1062 1160 otl->otli_ents[otl->otli_cur] = odd->odd_linkid;
1063 1161 otl->otli_cur++;
1064 1162 return (0);
1065 1163 }
1066 1164
1067 1165 /* ARGSUSED */
1068 1166 static int
1069 1167 overlay_target_ioctl_list(overlay_target_hdl_t *thdl, void *arg)
1070 1168 {
1071 1169 overlay_dev_iter(overlay_target_ioctl_list_cb, arg);
1072 1170 return (0);
1073 1171 }
1074 1172
1075 1173 /* ARGSUSED */
1076 1174 static int
1077 1175 overlay_target_list_copyout(void *ubuf, void *buf, size_t bufsize, int flags)
1078 1176 {
1079 1177 overlay_targ_list_int_t *otl = buf;
1080 1178
1081 1179 if (ddi_copyout(&otl->otli_cur, ubuf, sizeof (uint32_t),
1082 1180 flags & FKIOCTL) != 0)
1083 1181 return (EFAULT);
1084 1182
1085 1183 if (otl->otli_count == B_FALSE) {
1086 1184 if (ddi_copyout(otl->otli_ents,
1087 1185 (void *)((uintptr_t)ubuf +
1088 1186 offsetof(overlay_targ_list_t, otl_ents)),
1089 1187 sizeof (uint32_t) * otl->otli_nents,
1090 1188 flags & FKIOCTL) != 0)
1091 1189 return (EFAULT);
1092 1190 }
1093 1191 return (0);
1094 1192 }
1095 1193
1096 1194 /* ARGSUSED */
1097 1195 static int
1098 1196 overlay_target_cache_get(overlay_target_hdl_t *thdl, void *arg)
1099 1197 {
1100 1198 int ret = 0;
1101 1199 overlay_dev_t *odd;
1102 1200 overlay_target_t *ott;
1103 1201 overlay_targ_cache_t *otc = arg;
1104 1202
1105 1203 odd = overlay_hold_by_dlid(otc->otc_linkid);
1106 1204 if (odd == NULL)
1107 1205 return (ENOENT);
1108 1206
1109 1207 mutex_enter(&odd->odd_lock);
1110 1208 if (!(odd->odd_flags & OVERLAY_F_VARPD)) {
1111 1209 mutex_exit(&odd->odd_lock);
1112 1210 overlay_hold_rele(odd);
1113 1211 return (ENXIO);
1114 1212 }
1115 1213 ott = odd->odd_target;
1116 1214 if (ott->ott_mode != OVERLAY_TARGET_POINT &&
1117 1215 ott->ott_mode != OVERLAY_TARGET_DYNAMIC) {
1118 1216 mutex_exit(&odd->odd_lock);
1119 1217 overlay_hold_rele(odd);
1120 1218 return (ENOTSUP);
1121 1219 }
1122 1220 mutex_enter(&ott->ott_lock);
|
↓ open down ↓ |
402 lines elided |
↑ open up ↑ |
1123 1221 mutex_exit(&odd->odd_lock);
1124 1222
1125 1223 if (ott->ott_mode == OVERLAY_TARGET_POINT) {
1126 1224 otc->otc_entry.otce_flags = 0;
1127 1225 bcopy(&ott->ott_u.ott_point, &otc->otc_entry.otce_dest,
1128 1226 sizeof (overlay_target_point_t));
1129 1227 } else {
1130 1228 overlay_target_entry_t *ote;
1131 1229 ote = refhash_lookup(ott->ott_u.ott_dyn.ott_dhash,
1132 1230 otc->otc_entry.otce_mac);
1133 - if (ote != NULL) {
1134 - mutex_enter(&ote->ote_lock);
1135 - if ((ote->ote_flags &
1136 - OVERLAY_ENTRY_F_VALID_MASK) != 0) {
1137 - if (ote->ote_flags & OVERLAY_ENTRY_F_DROP) {
1138 - otc->otc_entry.otce_flags =
1139 - OVERLAY_TARGET_CACHE_DROP;
1140 - } else {
1141 - otc->otc_entry.otce_flags = 0;
1142 - bcopy(&ote->ote_dest,
1143 - &otc->otc_entry.otce_dest,
1144 - sizeof (overlay_target_point_t));
1145 - }
1146 - ret = 0;
1231 + if (ote == NULL) {
1232 + ret = ENOENT;
1233 + goto done;
1234 + }
1235 +
1236 + mutex_enter(&ote->ote_lock);
1237 + if ((ote->ote_flags & OVERLAY_ENTRY_F_VALID_MASK) != 0) {
1238 + if (ote->ote_flags & OVERLAY_ENTRY_F_DROP) {
1239 + otc->otc_entry.otce_flags =
1240 + OVERLAY_TARGET_CACHE_DROP;
1241 + } else if (ote->ote_flags & OVERLAY_ENTRY_F_ROUTER) {
1242 + otc->otc_entry.otce_flags =
1243 + OVERLAY_TARGET_CACHE_ROUTER;
1147 1244 } else {
1148 - ret = ENOENT;
1245 + otc->otc_entry.otce_flags = 0;
1246 + bcopy(&ote->ote_dest, &otc->otc_entry.otce_dest,
1247 + sizeof (overlay_target_point_t));
1149 1248 }
1150 - mutex_exit(&ote->ote_lock);
1249 + ret = 0;
1151 1250 } else {
1152 1251 ret = ENOENT;
1153 1252 }
1253 + mutex_exit(&ote->ote_lock);
1154 1254 }
1155 1255
1256 +done:
1156 1257 mutex_exit(&ott->ott_lock);
1157 1258 overlay_hold_rele(odd);
1158 1259
1159 1260 return (ret);
1160 1261 }
1161 1262
1162 1263 /* ARGSUSED */
1163 1264 static int
1164 1265 overlay_target_cache_set(overlay_target_hdl_t *thdl, void *arg)
1165 1266 {
1166 1267 overlay_dev_t *odd;
1167 1268 overlay_target_t *ott;
1168 1269 overlay_target_entry_t *ote;
1169 1270 overlay_targ_cache_t *otc = arg;
1170 1271 mblk_t *mp = NULL;
1171 1272
1172 - if (otc->otc_entry.otce_flags & ~OVERLAY_TARGET_CACHE_DROP)
1273 + if (otc->otc_entry.otce_flags &
1274 + ~(OVERLAY_TARGET_CACHE_DROP | OVERLAY_TARGET_CACHE_ROUTER))
1173 1275 return (EINVAL);
1174 1276
1277 + if (otc->otc_entry.otce_flags ==
1278 + (OVERLAY_TARGET_CACHE_DROP | OVERLAY_TARGET_CACHE_ROUTER))
1279 + return (EINVAL);
1280 +
1175 1281 odd = overlay_hold_by_dlid(otc->otc_linkid);
1176 1282 if (odd == NULL)
1177 1283 return (ENOENT);
1178 1284
1179 1285 mutex_enter(&odd->odd_lock);
1180 1286 if (!(odd->odd_flags & OVERLAY_F_VARPD)) {
1181 1287 mutex_exit(&odd->odd_lock);
1182 1288 overlay_hold_rele(odd);
1183 1289 return (ENXIO);
1184 1290 }
1185 1291 ott = odd->odd_target;
1186 1292 if (ott->ott_mode != OVERLAY_TARGET_DYNAMIC) {
1187 1293 mutex_exit(&odd->odd_lock);
1188 1294 overlay_hold_rele(odd);
1189 1295 return (ENOTSUP);
1190 1296 }
1191 1297 mutex_enter(&ott->ott_lock);
1192 1298 mutex_exit(&odd->odd_lock);
1193 1299
1194 1300 ote = refhash_lookup(ott->ott_u.ott_dyn.ott_dhash,
1195 1301 otc->otc_entry.otce_mac);
1196 1302 if (ote == NULL) {
1197 1303 ote = kmem_cache_alloc(overlay_entry_cache, KM_SLEEP);
1198 1304 bcopy(otc->otc_entry.otce_mac, ote->ote_addr, ETHERADDRL);
1199 1305 ote->ote_chead = ote->ote_ctail = NULL;
1200 1306 ote->ote_mbsize = 0;
1201 1307 ote->ote_ott = ott;
1202 1308 ote->ote_odd = odd;
1203 1309 mutex_enter(&ote->ote_lock);
|
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
1204 1310 refhash_insert(ott->ott_u.ott_dyn.ott_dhash, ote);
1205 1311 avl_add(&ott->ott_u.ott_dyn.ott_tree, ote);
1206 1312 } else {
1207 1313 mutex_enter(&ote->ote_lock);
1208 1314 }
1209 1315
1210 1316 if (otc->otc_entry.otce_flags & OVERLAY_TARGET_CACHE_DROP) {
1211 1317 ote->ote_flags |= OVERLAY_ENTRY_F_DROP;
1212 1318 } else {
1213 1319 ote->ote_flags |= OVERLAY_ENTRY_F_VALID;
1320 + if (otc->otc_entry.otce_flags & OVERLAY_TARGET_CACHE_ROUTER)
1321 + ote->ote_flags |= OVERLAY_ENTRY_F_ROUTER;
1214 1322 bcopy(&otc->otc_entry.otce_dest, &ote->ote_dest,
1215 1323 sizeof (overlay_target_point_t));
1216 1324 mp = ote->ote_chead;
1217 1325 ote->ote_chead = NULL;
1218 1326 ote->ote_ctail = NULL;
1219 1327 ote->ote_mbsize = 0;
1220 1328 ote->ote_vtime = gethrtime();
1221 1329 }
1222 1330
1223 1331 mutex_exit(&ote->ote_lock);
1224 1332 mutex_exit(&ott->ott_lock);
1225 1333
1226 1334 if (mp != NULL) {
1227 1335 mp = overlay_m_tx(ote->ote_odd, mp);
1228 1336 freemsgchain(mp);
1229 1337 }
1230 1338
1231 1339 overlay_hold_rele(odd);
1232 1340
1233 1341 return (0);
1234 1342 }
1235 1343
1236 1344 /* ARGSUSED */
1237 1345 static int
1238 1346 overlay_target_cache_remove(overlay_target_hdl_t *thdl, void *arg)
1239 1347 {
1240 1348 int ret = 0;
1241 1349 overlay_dev_t *odd;
1242 1350 overlay_target_t *ott;
1243 1351 overlay_target_entry_t *ote;
1244 1352 overlay_targ_cache_t *otc = arg;
1245 1353
1246 1354 odd = overlay_hold_by_dlid(otc->otc_linkid);
1247 1355 if (odd == NULL)
1248 1356 return (ENOENT);
1249 1357
1250 1358 mutex_enter(&odd->odd_lock);
1251 1359 if (!(odd->odd_flags & OVERLAY_F_VARPD)) {
1252 1360 mutex_exit(&odd->odd_lock);
1253 1361 overlay_hold_rele(odd);
1254 1362 return (ENXIO);
1255 1363 }
1256 1364 ott = odd->odd_target;
1257 1365 if (ott->ott_mode != OVERLAY_TARGET_DYNAMIC) {
1258 1366 mutex_exit(&odd->odd_lock);
1259 1367 overlay_hold_rele(odd);
1260 1368 return (ENOTSUP);
1261 1369 }
1262 1370 mutex_enter(&ott->ott_lock);
1263 1371 mutex_exit(&odd->odd_lock);
1264 1372
1265 1373 ote = refhash_lookup(ott->ott_u.ott_dyn.ott_dhash,
1266 1374 otc->otc_entry.otce_mac);
1267 1375 if (ote != NULL) {
1268 1376 mutex_enter(&ote->ote_lock);
1269 1377 ote->ote_flags &= ~OVERLAY_ENTRY_F_VALID_MASK;
1270 1378 mutex_exit(&ote->ote_lock);
1271 1379 ret = 0;
1272 1380 } else {
1273 1381 ret = ENOENT;
1274 1382 }
1275 1383
1276 1384 mutex_exit(&ott->ott_lock);
1277 1385 overlay_hold_rele(odd);
1278 1386
1279 1387 return (ret);
1280 1388 }
1281 1389
1282 1390 /* ARGSUSED */
1283 1391 static int
1284 1392 overlay_target_cache_flush(overlay_target_hdl_t *thdl, void *arg)
1285 1393 {
1286 1394 avl_tree_t *avl;
1287 1395 overlay_dev_t *odd;
1288 1396 overlay_target_t *ott;
1289 1397 overlay_target_entry_t *ote;
1290 1398 overlay_targ_cache_t *otc = arg;
1291 1399
1292 1400 odd = overlay_hold_by_dlid(otc->otc_linkid);
1293 1401 if (odd == NULL)
1294 1402 return (ENOENT);
1295 1403
1296 1404 mutex_enter(&odd->odd_lock);
1297 1405 if (!(odd->odd_flags & OVERLAY_F_VARPD)) {
1298 1406 mutex_exit(&odd->odd_lock);
1299 1407 overlay_hold_rele(odd);
1300 1408 return (ENXIO);
1301 1409 }
1302 1410 ott = odd->odd_target;
1303 1411 if (ott->ott_mode != OVERLAY_TARGET_DYNAMIC) {
1304 1412 mutex_exit(&odd->odd_lock);
1305 1413 overlay_hold_rele(odd);
1306 1414 return (ENOTSUP);
1307 1415 }
1308 1416 mutex_enter(&ott->ott_lock);
1309 1417 mutex_exit(&odd->odd_lock);
1310 1418 avl = &ott->ott_u.ott_dyn.ott_tree;
1311 1419
1312 1420 for (ote = avl_first(avl); ote != NULL; ote = AVL_NEXT(avl, ote)) {
1313 1421 mutex_enter(&ote->ote_lock);
1314 1422 ote->ote_flags &= ~OVERLAY_ENTRY_F_VALID_MASK;
1315 1423 mutex_exit(&ote->ote_lock);
1316 1424 }
1317 1425 ote = refhash_lookup(ott->ott_u.ott_dyn.ott_dhash,
1318 1426 otc->otc_entry.otce_mac);
1319 1427
1320 1428 mutex_exit(&ott->ott_lock);
1321 1429 overlay_hold_rele(odd);
1322 1430
1323 1431 return (0);
1324 1432 }
1325 1433
1326 1434 static int
1327 1435 overlay_target_cache_iter_copyin(const void *ubuf, void **outp, size_t *bsize,
1328 1436 int flags)
1329 1437 {
1330 1438 overlay_targ_cache_iter_t base, *iter;
1331 1439
1332 1440 if (ddi_copyin(ubuf, &base, sizeof (overlay_targ_cache_iter_t),
1333 1441 flags & FKIOCTL) != 0)
1334 1442 return (EFAULT);
1335 1443
1336 1444 if (base.otci_count > OVERLAY_TARGET_ITER_MAX)
1337 1445 return (E2BIG);
1338 1446
1339 1447 if (base.otci_count == 0)
1340 1448 return (EINVAL);
1341 1449
1342 1450 *bsize = sizeof (overlay_targ_cache_iter_t) +
1343 1451 base.otci_count * sizeof (overlay_targ_cache_entry_t);
1344 1452 iter = kmem_alloc(*bsize, KM_SLEEP);
1345 1453 bcopy(&base, iter, sizeof (overlay_targ_cache_iter_t));
1346 1454 *outp = iter;
1347 1455
1348 1456 return (0);
1349 1457 }
1350 1458
1351 1459 typedef struct overlay_targ_cache_marker {
1352 1460 uint8_t otcm_mac[ETHERADDRL];
1353 1461 uint16_t otcm_done;
1354 1462 } overlay_targ_cache_marker_t;
1355 1463
1356 1464 /* ARGSUSED */
1357 1465 static int
1358 1466 overlay_target_cache_iter(overlay_target_hdl_t *thdl, void *arg)
1359 1467 {
1360 1468 overlay_dev_t *odd;
1361 1469 overlay_target_t *ott;
1362 1470 overlay_target_entry_t lookup, *ent;
1363 1471 overlay_targ_cache_marker_t *mark;
1364 1472 avl_index_t where;
1365 1473 avl_tree_t *avl;
1366 1474 uint16_t written = 0;
1367 1475
1368 1476 overlay_targ_cache_iter_t *iter = arg;
1369 1477 mark = (void *)&iter->otci_marker;
1370 1478
1371 1479 if (mark->otcm_done != 0) {
1372 1480 iter->otci_count = 0;
1373 1481 return (0);
1374 1482 }
1375 1483
1376 1484 odd = overlay_hold_by_dlid(iter->otci_linkid);
1377 1485 if (odd == NULL)
1378 1486 return (ENOENT);
1379 1487
1380 1488 mutex_enter(&odd->odd_lock);
1381 1489 if (!(odd->odd_flags & OVERLAY_F_VARPD)) {
1382 1490 mutex_exit(&odd->odd_lock);
1383 1491 overlay_hold_rele(odd);
1384 1492 return (ENXIO);
1385 1493 }
1386 1494 ott = odd->odd_target;
1387 1495 if (ott->ott_mode != OVERLAY_TARGET_DYNAMIC &&
1388 1496 ott->ott_mode != OVERLAY_TARGET_POINT) {
1389 1497 mutex_exit(&odd->odd_lock);
1390 1498 overlay_hold_rele(odd);
1391 1499 return (ENOTSUP);
1392 1500 }
1393 1501
1394 1502 /*
1395 1503 * Holding this lock across the entire iteration probably isn't very
1396 1504 * good. We should perhaps add an r/w lock for the avl tree. But we'll
1397 1505 * wait until we now it's necessary before we do more.
1398 1506 */
1399 1507 mutex_enter(&ott->ott_lock);
1400 1508 mutex_exit(&odd->odd_lock);
1401 1509
1402 1510 if (ott->ott_mode == OVERLAY_TARGET_POINT) {
1403 1511 overlay_targ_cache_entry_t *out = &iter->otci_ents[0];
1404 1512 bzero(out->otce_mac, ETHERADDRL);
1405 1513 out->otce_flags = 0;
1406 1514 bcopy(&ott->ott_u.ott_point, &out->otce_dest,
1407 1515 sizeof (overlay_target_point_t));
1408 1516 written++;
1409 1517 mark->otcm_done = 1;
1410 1518 }
1411 1519
1412 1520 avl = &ott->ott_u.ott_dyn.ott_tree;
1413 1521 bcopy(mark->otcm_mac, lookup.ote_addr, ETHERADDRL);
1414 1522 ent = avl_find(avl, &lookup, &where);
1415 1523
1416 1524 /*
1417 1525 * NULL ent means that the entry does not exist, so we want to start
1418 1526 * with the closest node in the tree. This means that we implicitly rely
1419 1527 * on the tree's order and the first node will be the mac 00:00:00:00:00
1420 1528 * and the last will be ff:ff:ff:ff:ff:ff.
1421 1529 */
1422 1530 if (ent == NULL) {
1423 1531 ent = avl_nearest(avl, where, AVL_AFTER);
1424 1532 if (ent == NULL) {
1425 1533 mark->otcm_done = 1;
1426 1534 goto done;
1427 1535 }
1428 1536 }
1429 1537
1430 1538 for (; ent != NULL && written < iter->otci_count;
1431 1539 ent = AVL_NEXT(avl, ent)) {
1432 1540 overlay_targ_cache_entry_t *out = &iter->otci_ents[written];
1433 1541 mutex_enter(&ent->ote_lock);
1434 1542 if ((ent->ote_flags & OVERLAY_ENTRY_F_VALID_MASK) == 0) {
1435 1543 mutex_exit(&ent->ote_lock);
1436 1544 continue;
1437 1545 }
1438 1546 bcopy(ent->ote_addr, out->otce_mac, ETHERADDRL);
1439 1547 out->otce_flags = 0;
1440 1548 if (ent->ote_flags & OVERLAY_ENTRY_F_DROP)
1441 1549 out->otce_flags |= OVERLAY_TARGET_CACHE_DROP;
1442 1550 if (ent->ote_flags & OVERLAY_ENTRY_F_VALID)
1443 1551 bcopy(&ent->ote_dest, &out->otce_dest,
1444 1552 sizeof (overlay_target_point_t));
1445 1553 written++;
1446 1554 mutex_exit(&ent->ote_lock);
1447 1555 }
1448 1556
1449 1557 if (ent != NULL) {
1450 1558 bcopy(ent->ote_addr, mark->otcm_mac, ETHERADDRL);
1451 1559 } else {
1452 1560 mark->otcm_done = 1;
1453 1561 }
1454 1562
1455 1563 done:
1456 1564 iter->otci_count = written;
1457 1565 mutex_exit(&ott->ott_lock);
1458 1566 overlay_hold_rele(odd);
1459 1567
1460 1568 return (0);
1461 1569 }
1462 1570
1463 1571 /* ARGSUSED */
1464 1572 static int
1465 1573 overlay_target_cache_iter_copyout(void *ubuf, void *buf, size_t bufsize,
1466 1574 int flags)
1467 1575 {
1468 1576 size_t outsize;
1469 1577 const overlay_targ_cache_iter_t *iter = buf;
1470 1578
1471 1579 outsize = sizeof (overlay_targ_cache_iter_t) +
1472 1580 iter->otci_count * sizeof (overlay_targ_cache_entry_t);
1473 1581
1474 1582 if (ddi_copyout(buf, ubuf, outsize, flags & FKIOCTL) != 0)
1475 1583 return (EFAULT);
1476 1584
1477 1585 return (0);
1478 1586 }
1479 1587
1480 1588 static overlay_target_ioctl_t overlay_target_ioctab[] = {
1481 1589 { OVERLAY_TARG_INFO, B_TRUE, B_TRUE,
1482 1590 NULL, overlay_target_info,
1483 1591 NULL, sizeof (overlay_targ_info_t) },
1484 1592 { OVERLAY_TARG_ASSOCIATE, B_TRUE, B_FALSE,
1485 1593 NULL, overlay_target_associate,
1486 1594 NULL, sizeof (overlay_targ_associate_t) },
1487 1595 { OVERLAY_TARG_DISASSOCIATE, B_TRUE, B_FALSE,
1488 1596 NULL, overlay_target_disassociate,
1489 1597 NULL, sizeof (overlay_targ_id_t) },
1490 1598 { OVERLAY_TARG_DEGRADE, B_TRUE, B_FALSE,
1491 1599 NULL, overlay_target_degrade,
1492 1600 NULL, sizeof (overlay_targ_degrade_t) },
1493 1601 { OVERLAY_TARG_RESTORE, B_TRUE, B_FALSE,
1494 1602 NULL, overlay_target_restore,
1495 1603 NULL, sizeof (overlay_targ_id_t) },
1496 1604 { OVERLAY_TARG_LOOKUP, B_FALSE, B_TRUE,
1497 1605 NULL, overlay_target_lookup_request,
1498 1606 NULL, sizeof (overlay_targ_lookup_t) },
1499 1607 { OVERLAY_TARG_RESPOND, B_TRUE, B_FALSE,
1500 1608 NULL, overlay_target_lookup_respond,
1501 1609 NULL, sizeof (overlay_targ_resp_t) },
1502 1610 { OVERLAY_TARG_DROP, B_TRUE, B_FALSE,
1503 1611 NULL, overlay_target_lookup_drop,
1504 1612 NULL, sizeof (overlay_targ_resp_t) },
1505 1613 { OVERLAY_TARG_PKT, B_TRUE, B_TRUE,
1506 1614 overlay_target_pkt_copyin,
1507 1615 overlay_target_packet,
1508 1616 overlay_target_pkt_copyout,
1509 1617 sizeof (overlay_targ_pkt_t) },
1510 1618 { OVERLAY_TARG_INJECT, B_TRUE, B_FALSE,
1511 1619 overlay_target_pkt_copyin,
1512 1620 overlay_target_inject,
1513 1621 NULL, sizeof (overlay_targ_pkt_t) },
1514 1622 { OVERLAY_TARG_RESEND, B_TRUE, B_FALSE,
1515 1623 overlay_target_pkt_copyin,
1516 1624 overlay_target_resend,
1517 1625 NULL, sizeof (overlay_targ_pkt_t) },
1518 1626 { OVERLAY_TARG_LIST, B_FALSE, B_TRUE,
1519 1627 overlay_target_list_copyin,
1520 1628 overlay_target_ioctl_list,
1521 1629 overlay_target_list_copyout,
1522 1630 sizeof (overlay_targ_list_t) },
1523 1631 { OVERLAY_TARG_CACHE_GET, B_FALSE, B_TRUE,
1524 1632 NULL, overlay_target_cache_get,
1525 1633 NULL, sizeof (overlay_targ_cache_t) },
1526 1634 { OVERLAY_TARG_CACHE_SET, B_TRUE, B_TRUE,
1527 1635 NULL, overlay_target_cache_set,
1528 1636 NULL, sizeof (overlay_targ_cache_t) },
1529 1637 { OVERLAY_TARG_CACHE_REMOVE, B_TRUE, B_TRUE,
1530 1638 NULL, overlay_target_cache_remove,
1531 1639 NULL, sizeof (overlay_targ_cache_t) },
1532 1640 { OVERLAY_TARG_CACHE_FLUSH, B_TRUE, B_TRUE,
1533 1641 NULL, overlay_target_cache_flush,
1534 1642 NULL, sizeof (overlay_targ_cache_t) },
1535 1643 { OVERLAY_TARG_CACHE_ITER, B_FALSE, B_TRUE,
1536 1644 overlay_target_cache_iter_copyin,
1537 1645 overlay_target_cache_iter,
1538 1646 overlay_target_cache_iter_copyout,
1539 1647 sizeof (overlay_targ_cache_iter_t) },
1540 1648 { 0 }
1541 1649 };
1542 1650
1543 1651 int
1544 1652 overlay_target_open(dev_t *devp, int flags, int otype, cred_t *credp)
1545 1653 {
1546 1654 minor_t mid;
1547 1655 overlay_target_hdl_t *thdl;
1548 1656
1549 1657 if (secpolicy_dl_config(credp) != 0)
1550 1658 return (EPERM);
1551 1659
1552 1660 if (getminor(*devp) != 0)
1553 1661 return (ENXIO);
1554 1662
1555 1663 if (otype & OTYP_BLK)
1556 1664 return (EINVAL);
1557 1665
1558 1666 if (flags & ~(FREAD | FWRITE | FEXCL))
1559 1667 return (EINVAL);
1560 1668
1561 1669 if ((flags & FWRITE) &&
1562 1670 !(flags & FEXCL))
1563 1671 return (EINVAL);
1564 1672
1565 1673 if (!(flags & FREAD) && !(flags & FWRITE))
1566 1674 return (EINVAL);
1567 1675
1568 1676 if (crgetzoneid(credp) != GLOBAL_ZONEID)
1569 1677 return (EPERM);
1570 1678
1571 1679 mid = id_alloc(overlay_thdl_idspace);
1572 1680 if (ddi_soft_state_zalloc(overlay_thdl_state, mid) != 0) {
1573 1681 id_free(overlay_thdl_idspace, mid);
1574 1682 return (ENXIO);
1575 1683 }
1576 1684
1577 1685 thdl = ddi_get_soft_state(overlay_thdl_state, mid);
1578 1686 VERIFY(thdl != NULL);
1579 1687 thdl->oth_minor = mid;
1580 1688 thdl->oth_zoneid = crgetzoneid(credp);
1581 1689 thdl->oth_oflags = flags;
1582 1690 mutex_init(&thdl->oth_lock, NULL, MUTEX_DRIVER, NULL);
1583 1691 list_create(&thdl->oth_outstanding, sizeof (overlay_target_entry_t),
1584 1692 offsetof(overlay_target_entry_t, ote_qlink));
1585 1693 *devp = makedevice(getmajor(*devp), mid);
1586 1694
1587 1695 mutex_enter(&overlay_target_lock);
1588 1696 if ((flags & FEXCL) && overlay_target_excl == B_TRUE) {
1589 1697 mutex_exit(&overlay_target_lock);
1590 1698 list_destroy(&thdl->oth_outstanding);
1591 1699 mutex_destroy(&thdl->oth_lock);
1592 1700 ddi_soft_state_free(overlay_thdl_state, mid);
1593 1701 id_free(overlay_thdl_idspace, mid);
1594 1702 return (EEXIST);
1595 1703 } else if ((flags & FEXCL) != 0) {
1596 1704 VERIFY(overlay_target_excl == B_FALSE);
1597 1705 overlay_target_excl = B_TRUE;
1598 1706 }
1599 1707 list_insert_tail(&overlay_thdl_list, thdl);
1600 1708 mutex_exit(&overlay_target_lock);
1601 1709
1602 1710 return (0);
1603 1711 }
1604 1712
1605 1713 /* ARGSUSED */
1606 1714 int
1607 1715 overlay_target_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
1608 1716 int *rvalp)
1609 1717 {
1610 1718 overlay_target_ioctl_t *ioc;
1611 1719 overlay_target_hdl_t *thdl;
1612 1720
1613 1721 if (secpolicy_dl_config(credp) != 0)
1614 1722 return (EPERM);
1615 1723
1616 1724 if ((thdl = ddi_get_soft_state(overlay_thdl_state,
1617 1725 getminor(dev))) == NULL)
1618 1726 return (ENXIO);
1619 1727
1620 1728 for (ioc = &overlay_target_ioctab[0]; ioc->oti_cmd != 0; ioc++) {
1621 1729 int ret;
1622 1730 caddr_t buf;
1623 1731 size_t bufsize;
1624 1732
1625 1733 if (ioc->oti_cmd != cmd)
1626 1734 continue;
1627 1735
1628 1736 if (ioc->oti_write == B_TRUE && !(mode & FWRITE))
1629 1737 return (EBADF);
1630 1738
1631 1739 if (ioc->oti_copyin == NULL) {
1632 1740 bufsize = ioc->oti_size;
1633 1741 buf = kmem_alloc(bufsize, KM_SLEEP);
1634 1742 if (ddi_copyin((void *)(uintptr_t)arg, buf, bufsize,
1635 1743 mode & FKIOCTL) != 0) {
1636 1744 kmem_free(buf, bufsize);
1637 1745 return (EFAULT);
1638 1746 }
1639 1747 } else {
1640 1748 if ((ret = ioc->oti_copyin((void *)(uintptr_t)arg,
1641 1749 (void **)&buf, &bufsize, mode)) != 0)
1642 1750 return (ret);
1643 1751 }
1644 1752
1645 1753 ret = ioc->oti_func(thdl, buf);
1646 1754 if (ret == 0 && ioc->oti_size != 0 &&
1647 1755 ioc->oti_ncopyout == B_TRUE) {
1648 1756 if (ioc->oti_copyout == NULL) {
1649 1757 if (ddi_copyout(buf, (void *)(uintptr_t)arg,
1650 1758 bufsize, mode & FKIOCTL) != 0)
1651 1759 ret = EFAULT;
1652 1760 } else {
1653 1761 ret = ioc->oti_copyout((void *)(uintptr_t)arg,
1654 1762 buf, bufsize, mode);
1655 1763 }
1656 1764 }
1657 1765
1658 1766 kmem_free(buf, bufsize);
1659 1767 return (ret);
1660 1768 }
1661 1769
1662 1770 return (ENOTTY);
1663 1771 }
1664 1772
1665 1773 /* ARGSUSED */
1666 1774 int
1667 1775 overlay_target_close(dev_t dev, int flags, int otype, cred_t *credp)
1668 1776 {
1669 1777 overlay_target_hdl_t *thdl;
1670 1778 overlay_target_entry_t *entry;
1671 1779 minor_t mid = getminor(dev);
1672 1780
1673 1781 if ((thdl = ddi_get_soft_state(overlay_thdl_state, mid)) == NULL)
1674 1782 return (ENXIO);
1675 1783
1676 1784 mutex_enter(&overlay_target_lock);
1677 1785 list_remove(&overlay_thdl_list, thdl);
1678 1786 mutex_enter(&thdl->oth_lock);
1679 1787 while ((entry = list_remove_head(&thdl->oth_outstanding)) != NULL)
1680 1788 list_insert_tail(&overlay_target_list, entry);
1681 1789 cv_signal(&overlay_target_condvar);
1682 1790 mutex_exit(&thdl->oth_lock);
1683 1791 if ((thdl->oth_oflags & FEXCL) != 0) {
1684 1792 VERIFY(overlay_target_excl == B_TRUE);
1685 1793 overlay_target_excl = B_FALSE;
1686 1794 }
1687 1795 mutex_exit(&overlay_target_lock);
1688 1796
1689 1797 list_destroy(&thdl->oth_outstanding);
1690 1798 mutex_destroy(&thdl->oth_lock);
1691 1799 mid = thdl->oth_minor;
1692 1800 ddi_soft_state_free(overlay_thdl_state, mid);
1693 1801 id_free(overlay_thdl_idspace, mid);
1694 1802
1695 1803 return (0);
1696 1804 }
|
↓ open down ↓ |
473 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX