Print this page
5045 use atomic_{inc,dec}_* instead of atomic_add_*
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/neti_impl.c
+++ new/usr/src/uts/common/io/neti_impl.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 2008 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 #include <sys/param.h>
27 27 #include <sys/atomic.h>
28 28 #include <sys/kmem.h>
29 29 #include <sys/rwlock.h>
30 30 #include <sys/errno.h>
31 31 #include <sys/queue.h>
32 32 #include <inet/common.h>
33 33 #include <inet/led.h>
34 34 #include <inet/ip.h>
35 35 #include <sys/neti.h>
36 36 #include <sys/zone.h>
37 37
38 38 static net_handle_t net_find(const char *protocol, neti_stack_t *ns);
39 39
40 40 static net_handle_t
41 41 net_find(const char *protocol, neti_stack_t *nts)
42 42 {
43 43 struct net_data *n;
44 44
45 45 ASSERT(protocol != NULL);
46 46 ASSERT(nts != NULL);
47 47
48 48 LIST_FOREACH(n, &nts->nts_netd_head, netd_list) {
49 49 ASSERT(n->netd_info.netp_name != NULL);
50 50 /*
51 51 * If they're trying to find a protocol that is being
52 52 * shutdown, just ignore it..
53 53 */
54 54 if (n->netd_condemned != 0)
55 55 continue;
56 56 if (strcmp(n->netd_info.netp_name, protocol) == 0) {
57 57 break;
58 58 }
59 59 }
60 60
61 61 return (n);
62 62 }
63 63
64 64 net_handle_t
65 65 net_protocol_register(netid_t id, const net_protocol_t *info)
66 66 {
67 67 struct net_data *n, *new;
68 68 neti_stack_t *nts;
69 69
70 70 ASSERT(info != NULL);
71 71
72 72 nts = net_getnetistackbyid(id);
73 73 if (nts == NULL)
74 74 return (NULL);
75 75
76 76 new = kmem_alloc(sizeof (*new), KM_SLEEP);
77 77 new->netd_refcnt = 1;
78 78 new->netd_hooks = NULL;
79 79 new->netd_info = *info;
80 80 new->netd_stack = nts;
81 81 new->netd_condemned = 0;
82 82
83 83 mutex_enter(&nts->nts_lock);
84 84 n = net_find(info->netp_name, nts);
85 85 if (n != NULL) {
86 86 mutex_exit(&nts->nts_lock);
87 87 kmem_free(new, sizeof (*new));
88 88 return (NULL);
89 89 }
90 90
91 91 if (LIST_EMPTY(&nts->nts_netd_head)) {
92 92 LIST_INSERT_HEAD(&nts->nts_netd_head, new, netd_list);
93 93 } else {
94 94 LIST_INSERT_AFTER(LIST_FIRST(&nts->nts_netd_head),
95 95 new, netd_list);
96 96 }
97 97 mutex_exit(&nts->nts_lock);
98 98
99 99 return (new);
100 100 }
101 101
102 102 int
103 103 net_protocol_unregister(net_handle_t info)
104 104 {
105 105 neti_stack_t *nts;
106 106
107 107 ASSERT(info != NULL);
108 108
109 109 nts = info->netd_stack;
110 110 ASSERT(nts != NULL);
111 111
112 112 mutex_enter(&nts->nts_lock);
113 113 LIST_REMOVE(info, netd_list);
114 114 info->netd_stack = NULL;
115 115 mutex_exit(&nts->nts_lock);
116 116
117 117 (void) net_protocol_release(info);
118 118
119 119 return (0);
120 120 }
121 121
122 122 net_handle_t
123 123 net_protocol_lookup(netid_t netid, const char *protocol)
124 124 {
125 125 neti_stack_t *nts;
126 126 net_handle_t nd;
↓ open down ↓ |
126 lines elided |
↑ open up ↑ |
127 127
128 128 ASSERT(protocol != NULL);
129 129
130 130 nts = net_getnetistackbyid(netid);
131 131 if (nts == NULL)
132 132 return (NULL);
133 133
134 134 mutex_enter(&nts->nts_lock);
135 135 nd = net_find(protocol, nts);
136 136 if (nd != NULL)
137 - atomic_add_32((uint_t *)&nd->netd_refcnt, 1);
137 + atomic_inc_32((uint_t *)&nd->netd_refcnt);
138 138 mutex_exit(&nts->nts_lock);
139 139 return (nd);
140 140 }
141 141
142 142 /*
143 143 * Note: the man page specifies "returns -1 if the value passed in is unknown
144 144 * to this framework". We are not doing a lookup in this function, just a
145 145 * simply add to the netd_refcnt of the net_handle_t passed in, so -1 is never a
146 146 * return value.
147 147 */
148 148 int
149 149 net_protocol_release(net_handle_t info)
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
150 150 {
151 151
152 152 ASSERT(info->netd_refcnt > 0);
153 153 /*
154 154 * Is this safe? No hold on nts_lock? Consider that if the caller
155 155 * of net_protocol_release() is going to free this structure then
156 156 * it is now the only owner (refcnt==1) and it will have been
157 157 * removed from the nts_netd_head list on the neti_stack_t from a
158 158 * call to net_protocol_unregister already, so it is thus an orphan.
159 159 */
160 - if (atomic_add_32_nv((uint_t *)&info->netd_refcnt, -1) == 0) {
160 + if (atomic_dec_32_nv((uint_t *)&info->netd_refcnt) == 0) {
161 161 ASSERT(info->netd_hooks == NULL);
162 162 ASSERT(info->netd_stack == NULL);
163 163 kmem_free(info, sizeof (struct net_data));
164 164 }
165 165
166 166 return (0);
167 167 }
168 168
169 169 net_handle_t
170 170 net_protocol_walk(netid_t netid, net_handle_t info)
171 171 {
172 172 struct net_data *n = NULL;
173 173 boolean_t found = B_FALSE;
174 174 neti_stack_t *nts;
175 175
176 176 nts = net_getnetistackbyid(netid);
177 177 ASSERT(nts != NULL);
178 178
179 179 if (info == NULL)
180 180 found = B_TRUE;
181 181
182 182 mutex_enter(&nts->nts_lock);
183 183 LIST_FOREACH(n, &nts->nts_netd_head, netd_list) {
184 184 if (found) {
185 185 /*
186 186 * We are only interested in finding protocols that
187 187 * are not in some sort of shutdown state. There is
188 188 * no need to check for netd_stack==NULL because
189 189 * that implies it is no longer on this list.
190 190 */
191 191 if (n->netd_condemned == 0)
192 192 continue;
193 193 break;
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
194 194 }
195 195
196 196 if (n == info)
197 197 found = B_TRUE;
198 198 }
199 199
200 200 if (info != NULL)
201 201 (void) net_protocol_release(info);
202 202
203 203 if (n != NULL)
204 - atomic_add_32((uint_t *)&n->netd_refcnt, 1);
204 + atomic_inc_32((uint_t *)&n->netd_refcnt);
205 205
206 206 mutex_exit(&nts->nts_lock);
207 207
208 208 return (n);
209 209 }
210 210
211 211 /*
212 212 * Public accessor functions
213 213 */
214 214 int
215 215 net_getifname(net_handle_t info, phy_if_t nic, char *buffer,
216 216 const size_t buflen)
217 217 {
218 218
219 219 ASSERT(info != NULL);
220 220
221 221 if (info->netd_condemned != 0 || info->netd_stack == NULL)
222 222 return (-1);
223 223
224 224 return (info->netd_info.netp_getifname(info, nic, buffer, buflen));
225 225 }
226 226
227 227 int
228 228 net_getmtu(net_handle_t info, phy_if_t nic, lif_if_t ifdata)
229 229 {
230 230
231 231 ASSERT(info != NULL);
232 232
233 233 if (info->netd_condemned != 0 || info->netd_stack == NULL)
234 234 return (-1);
235 235
236 236 return (info->netd_info.netp_getmtu(info, nic, ifdata));
237 237 }
238 238
239 239 int
240 240 net_getpmtuenabled(net_handle_t info)
241 241 {
242 242
243 243 ASSERT(info != NULL);
244 244
245 245 if (info->netd_condemned != 0 || info->netd_stack == NULL)
246 246 return (-1);
247 247
248 248 return (info->netd_info.netp_getpmtuenabled(info));
249 249 }
250 250
251 251 int
252 252 net_getlifaddr(net_handle_t info, phy_if_t nic, lif_if_t ifdata,
253 253 int nelem, net_ifaddr_t type[], void *storage)
254 254 {
255 255
256 256 ASSERT(info != NULL);
257 257
258 258 if (info->netd_condemned != 0 || info->netd_stack == NULL)
259 259 return (-1);
260 260
261 261 return (info->netd_info.netp_getlifaddr(info, nic, ifdata,
262 262 nelem, type, storage));
263 263 }
264 264
265 265 int
266 266 net_getlifzone(net_handle_t info, phy_if_t phy_ifdata, lif_if_t ifdata,
267 267 zoneid_t *zoneid)
268 268 {
269 269 ASSERT(info != NULL);
270 270
271 271 if (info->netd_condemned != 0 || info->netd_stack == NULL)
272 272 return (-1);
273 273
274 274 return (info->netd_info.neti_getlifzone(info, phy_ifdata, ifdata,
275 275 zoneid));
276 276 }
277 277
278 278 int
279 279 net_getlifflags(net_handle_t info, phy_if_t phy_ifdata, lif_if_t ifdata,
280 280 uint64_t *flags)
281 281 {
282 282 ASSERT(info != NULL);
283 283
284 284 if (info->netd_condemned != 0 || info->netd_stack == NULL)
285 285 return (-1);
286 286
287 287 return (info->netd_info.neti_getlifflags(info, phy_ifdata, ifdata,
288 288 flags));
289 289 }
290 290
291 291 phy_if_t
292 292 net_phygetnext(net_handle_t info, phy_if_t nic)
293 293 {
294 294
295 295 ASSERT(info != NULL);
296 296
297 297 if (info->netd_condemned != 0 || info->netd_stack == NULL)
298 298 return ((phy_if_t)-1);
299 299
300 300 return (info->netd_info.netp_phygetnext(info, nic));
301 301 }
302 302
303 303 phy_if_t
304 304 net_phylookup(net_handle_t info, const char *name)
305 305 {
306 306
307 307 ASSERT(info != NULL);
308 308
309 309 if (info->netd_condemned != 0 || info->netd_stack == NULL)
310 310 return ((phy_if_t)-1);
311 311
312 312 return (info->netd_info.netp_phylookup(info, name));
313 313 }
314 314
315 315 lif_if_t
316 316 net_lifgetnext(net_handle_t info, phy_if_t ifidx, lif_if_t ifdata)
317 317 {
318 318
319 319 ASSERT(info != NULL);
320 320
321 321 if (info->netd_condemned != 0 || info->netd_stack == NULL)
322 322 return ((lif_if_t)-1);
323 323
324 324 return (info->netd_info.netp_lifgetnext(info, ifidx, ifdata));
325 325 }
326 326
327 327 int
328 328 net_inject(net_handle_t info, inject_t style, net_inject_t *packet)
329 329 {
330 330
331 331 ASSERT(info != NULL);
332 332
333 333 if (info->netd_condemned != 0 || info->netd_stack == NULL)
334 334 return (-1);
335 335
336 336 return (info->netd_info.netp_inject(info, style, packet));
337 337 }
338 338
339 339 phy_if_t
340 340 net_routeto(net_handle_t info, struct sockaddr *address, struct sockaddr *next)
341 341 {
342 342
343 343 ASSERT(info != NULL);
344 344
345 345 if (info->netd_condemned != 0 || info->netd_stack == NULL)
346 346 return ((phy_if_t)-1);
347 347
348 348 return (info->netd_info.netp_routeto(info, address, next));
349 349 }
350 350
351 351 int
352 352 net_ispartialchecksum(net_handle_t info, mblk_t *mp)
353 353 {
354 354
355 355 ASSERT(info != NULL);
356 356 ASSERT(mp != NULL);
357 357
358 358 if (info->netd_condemned != 0 || info->netd_stack == NULL)
359 359 return (-1);
360 360
361 361 return (info->netd_info.netp_ispartialchecksum(info, mp));
362 362 }
363 363
364 364 int
365 365 net_isvalidchecksum(net_handle_t info, mblk_t *mp)
366 366 {
367 367
368 368 ASSERT(info != NULL);
369 369 ASSERT(mp != NULL);
370 370
371 371 if (info->netd_condemned != 0 || info->netd_stack == NULL)
372 372 return (-1);
373 373
374 374 return (info->netd_info.netp_isvalidchecksum(info, mp));
375 375 }
376 376
377 377 /*
378 378 * Hooks related functions
379 379 */
380 380
381 381 /*
382 382 * Function: net_family_register
383 383 * Returns: int - 0 = Succ, Else = Fail
384 384 * Parameters: info(I) - protocol
385 385 * hf(I) - family pointer
386 386 *
387 387 * Call hook_family_add to register family
388 388 *
389 389 * There is no need to bump netd_refcnt in the two functions
390 390 * net_family_register and net_family_unregister because the caller of these
391 391 * two functions is assumed to "own" a reference on 'info' via an earlier
392 392 * call to net_protocol_register(). Thus the owner is expected to do a
393 393 * call to net_protocol_unregister() after having done a
394 394 * net_family_unregister() to make sure things are properly cleaned up.
395 395 * Passing a pointer to info->netd_hooks into hook_family_add is required
396 396 * so that this can be set before the notify functions are called. If this
397 397 * does not happen, the notify function may do something that seems fine,
398 398 * like add a notify function to the family but cause a panic because
399 399 * netd_hooks is NULL when we get to hook_family_notify_register.
400 400 */
401 401 int
402 402 net_family_register(net_handle_t info, hook_family_t *hf)
403 403 {
404 404 netstack_t *ns;
405 405
406 406 ASSERT(info != NULL);
407 407 ASSERT(hf != NULL);
408 408
409 409 if (info->netd_condemned != 0 || info->netd_stack == NULL)
410 410 return (ESHUTDOWN);
411 411
412 412 if (info->netd_hooks != NULL)
413 413 return (EEXIST);
414 414
415 415 ns = info->netd_stack->nts_netstack;
416 416 ASSERT(ns != NULL);
417 417 if (hook_family_add(hf, ns->netstack_hook,
418 418 (void **)&info->netd_hooks) == NULL)
419 419 return (EEXIST);
420 420
421 421 return (0);
422 422 }
423 423
424 424 /*
425 425 * Function: net_family_unregister
426 426 * Returns: int - transparent value, explained by caller
427 427 * Parameters: info(I) - protocol
428 428 * hf(I) - family pointer
429 429 *
430 430 * Call hook_family_remove to unregister family
431 431 */
432 432 int
433 433 net_family_unregister(net_handle_t info, hook_family_t *hf)
434 434 {
435 435 int ret;
436 436
437 437 ASSERT(info != NULL);
438 438 ASSERT(hf != NULL);
439 439
440 440 if (info->netd_hooks == NULL)
441 441 return (ENXIO);
442 442
443 443 if (strcmp(info->netd_hooks->hfi_family.hf_name,
444 444 hf->hf_name) != 0)
445 445 return (EINVAL);
446 446
447 447 ret = hook_family_remove(info->netd_hooks);
448 448 if (ret == 0)
449 449 info->netd_hooks = NULL;
450 450
451 451 return (ret);
452 452 }
453 453
454 454 int
455 455 net_family_shutdown(net_handle_t info, hook_family_t *hf)
456 456 {
457 457
458 458 ASSERT(info != NULL);
459 459 ASSERT(hf != NULL);
460 460
461 461 if (info->netd_hooks == NULL)
462 462 return (ENXIO);
463 463
464 464 if (strcmp(info->netd_hooks->hfi_family.hf_name,
465 465 hf->hf_name) != 0)
466 466 return (EINVAL);
467 467
468 468 return (hook_family_shutdown(info->netd_hooks));
469 469 }
470 470
471 471 /*
472 472 * Function: net_event_register
473 473 * Returns: internal event pointer - NULL = Fail
474 474 * Parameters: info(I) - protocol
475 475 * he(I) - event pointer
476 476 *
477 477 * Call hook_event_add to register event on specific family
478 478 * Internal event pointer is returned so caller can get
479 479 * handle to run hooks
480 480 */
481 481 hook_event_token_t
482 482 net_event_register(net_handle_t info, hook_event_t *he)
483 483 {
484 484 hook_event_int_t *hei;
485 485
486 486 ASSERT(info != NULL);
487 487 ASSERT(he != NULL);
488 488
489 489 if (info->netd_hooks == NULL || info->netd_condemned != 0 ||
490 490 info->netd_stack == NULL)
491 491 return (NULL);
492 492
493 493 hei = hook_event_add(info->netd_hooks, he);
494 494 return ((hook_event_token_t)hei);
495 495 }
496 496
497 497 /*
498 498 * Function: net_event_unregister
499 499 * Returns: int - transparent value, explained by caller
500 500 * Parameters: info(I) - protocol
501 501 * he(I) - event pointer
502 502 *
503 503 * Call hook_event_remove to unregister event on specific family
504 504 */
505 505 int
506 506 net_event_unregister(net_handle_t info, hook_event_t *he)
507 507 {
508 508
509 509 ASSERT(info != NULL);
510 510 ASSERT(he != NULL);
511 511
512 512 if (info->netd_hooks == NULL)
513 513 return (ENXIO);
514 514
515 515 return (hook_event_remove(info->netd_hooks, he));
516 516 }
517 517
518 518 int
519 519 net_event_shutdown(net_handle_t info, hook_event_t *he)
520 520 {
521 521
522 522 ASSERT(info != NULL);
523 523 ASSERT(he != NULL);
524 524
525 525 if (info->netd_hooks == NULL)
526 526 return (ENXIO);
527 527
528 528 return (hook_event_shutdown(info->netd_hooks, he));
529 529 }
530 530
531 531 /*
532 532 * Function: net_hook_register
533 533 * Returns: int - transparent value, explained by caller
534 534 * Parameters: info(I) - protocol
535 535 * event(I) - event name
536 536 * h(I) - hook pointer
537 537 *
538 538 * Call hook_register to add hook on specific family/event
539 539 */
540 540 int
541 541 net_hook_register(net_handle_t info, char *event, hook_t *h)
542 542 {
543 543
544 544 ASSERT(info != NULL);
545 545 ASSERT(event != NULL);
546 546 ASSERT(h != NULL);
547 547
548 548 if (info->netd_condemned != 0 || info->netd_stack == NULL)
549 549 return (ESHUTDOWN);
550 550
551 551 if (info->netd_hooks == NULL)
552 552 return (ENXIO);
553 553
554 554 return (hook_register(info->netd_hooks, event, h));
555 555 }
556 556
557 557 /*
558 558 * Function: net_hook_unregister
559 559 * Returns: int - transparent value, explained by caller
560 560 * Parameters: info(I) - protocol
561 561 * event(I) - event name
562 562 * h(I) - hook pointer
563 563 *
564 564 * Call hook_unregister to remove hook on specific family/event
565 565 */
566 566 int
567 567 net_hook_unregister(net_handle_t info, char *event, hook_t *h)
568 568 {
569 569
570 570 ASSERT(info != NULL);
571 571 ASSERT(event != NULL);
572 572 ASSERT(h != NULL);
573 573
574 574 if (info->netd_hooks == NULL)
575 575 return (ENXIO);
576 576
577 577 return (hook_unregister(info->netd_hooks, event, h));
578 578 }
579 579
580 580 netid_t
581 581 net_getnetid(net_handle_t netd)
582 582 {
583 583
584 584 if (netd->netd_stack == NULL)
585 585 return (-1);
586 586 return (netd->netd_stack->nts_id);
587 587 }
588 588
589 589 net_inject_t *
590 590 net_inject_alloc(const int version)
591 591 {
592 592 net_inject_t *ni;
593 593
594 594 ni = kmem_zalloc(sizeof (*ni), KM_NOSLEEP);
595 595 if (ni == NULL)
596 596 return (NULL);
597 597
598 598 ni->ni_version = version;
599 599 return (ni);
600 600 }
601 601
602 602 void
603 603 net_inject_free(net_inject_t *ni)
604 604 {
605 605 kmem_free(ni, sizeof (*ni));
606 606 }
607 607
608 608 kstat_t *
609 609 net_kstat_create(netid_t netid, char *module, int instance, char *name,
610 610 char *class, uchar_t type, ulong_t ndata, uchar_t ks_flag)
611 611 {
612 612 netstackid_t stackid = net_getnetstackidbynetid(netid);
613 613
614 614 if (stackid == -1)
615 615 return (NULL);
616 616
617 617 return (kstat_create_netstack(module, instance, name, class, type,
618 618 ndata, ks_flag, stackid));
619 619 }
620 620
621 621 void
622 622 net_kstat_delete(netid_t netid, kstat_t *ks)
623 623 {
624 624 netstackid_t stackid = net_getnetstackidbynetid(netid);
625 625
626 626 if (stackid != -1)
627 627 kstat_delete_netstack(ks, stackid);
628 628 }
629 629
630 630 int
631 631 net_event_notify_register(net_handle_t family, char *event,
632 632 hook_notify_fn_t callback, void *arg)
633 633 {
634 634 int error;
635 635
636 636 if (family->netd_condemned != 0 || family->netd_stack == NULL)
637 637 return (ESHUTDOWN);
638 638
639 639 error = hook_event_notify_register(family->netd_hooks, event,
640 640 callback, arg);
641 641
642 642 return (error);
643 643 }
644 644
645 645 int
646 646 net_event_notify_unregister(net_handle_t family, char *event,
647 647 hook_notify_fn_t callback)
648 648 {
649 649 int error;
650 650
651 651 error = hook_event_notify_unregister(family->netd_hooks, event,
652 652 callback);
653 653
654 654 return (error);
655 655 }
656 656
657 657 int
658 658 net_protocol_notify_register(net_handle_t family, hook_notify_fn_t callback,
659 659 void *arg)
660 660 {
661 661 int error;
662 662
663 663 if (family->netd_condemned != 0 || family->netd_stack == NULL)
664 664 return (ESHUTDOWN);
665 665
666 666 error = hook_family_notify_register(family->netd_hooks, callback,
667 667 arg);
668 668
669 669 return (error);
670 670 }
671 671
672 672 int
673 673 net_protocol_notify_unregister(net_handle_t family, hook_notify_fn_t callback)
674 674 {
675 675 int error;
676 676
677 677 error = hook_family_notify_unregister(family->netd_hooks, callback);
678 678
679 679 return (error);
680 680 }
↓ open down ↓ |
466 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX