Parallelize in_ifaddrhead operation
[dragonfly.git] / sys / netproto / atm / ipatm / ipatm_load.c
CommitLineData
984263bc
MD
1/*
2 *
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
6 *
7 *
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
12 *
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
20 *
21 * Copyright 1994-1998 Network Computing Services, Inc.
22 *
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
25 *
26 * @(#) $FreeBSD: src/sys/netatm/ipatm/ipatm_load.c,v 1.6 2000/01/17 20:49:43 mks Exp $
1b562c24 27 * @(#) $DragonFly: src/sys/netproto/atm/ipatm/ipatm_load.c,v 1.10 2008/06/08 08:38:05 sephe Exp $
984263bc
MD
28 */
29
30/*
31 * IP Over ATM Support
32 * -------------------
33 *
34 * Support for running as a loadable kernel module
35 *
36 */
37
38#ifndef ATM_IP_MODULE
39#include "opt_atm.h"
40#endif
41
d2438d69 42#include <netproto/atm/kern_include.h>
984263bc 43
1f2de5d4
MD
44#include "ipatm.h"
45#include "ipatm_var.h"
984263bc 46
984263bc
MD
47/*
48 * Global variables
49 */
50int ipatm_vccnt = 0;
51int ipatm_vcidle = IPATM_VCIDLE;
52int ipatm_print = 0;
53u_long last_map_ipdst = 0;
54struct ipvcc* last_map_ipvcc = NULL;
55
56struct ip_nif *ipatm_nif_head = NULL;
57
58struct ipatm_stat ipatm_stat = {0};
59
60struct atm_time ipatm_itimer = {0, 0}; /* VCC idle timer */
61
62Atm_endpoint ipatm_endpt = {
63 NULL,
64 ENDPT_IP,
65 ipatm_ioctl,
66 ipatm_getname,
67 ipatm_connected,
68 ipatm_cleared,
69 ipatm_incoming,
70 NULL,
71 NULL,
72 NULL,
73 ipatm_cpcs_data,
74 NULL,
75 NULL,
76 NULL,
77 NULL
78};
79
80struct sp_info ipatm_vcpool = {
81 "ipatm vcc pool", /* si_name */
82 sizeof(struct ipvcc), /* si_blksiz */
83 10, /* si_blkcnt */
84 100 /* si_maxallow */
85};
86
87struct sp_info ipatm_nifpool = {
88 "ipatm nif pool", /* si_name */
89 sizeof(struct ip_nif), /* si_blksiz */
90 5, /* si_blkcnt */
91 52 /* si_maxallow */
92};
93
94
95/*
96 * Local functions
97 */
3e0c9cba
RG
98static int ipatm_start (void);
99static int ipatm_stop (void);
984263bc
MD
100
101
102/*
103 * Local variables
104 */
105static struct atm_ncm ipatm_ncm = {
106 NULL,
107 AF_INET,
108 ipatm_ifoutput,
109 ipatm_nifstat
110};
111
112static struct ipatm_listener {
113 Atm_attributes attr;
114 Atm_connection *conn;
115} ipatm_listeners[] = {
116{
117 { NULL, /* nif */
118 CMAPI_CPCS, /* api */
119 0, /* api_init */
120 0, /* headin */
121 0, /* headout */
122 { /* aal */
123 T_ATM_PRESENT,
124 ATM_AAL5
125 },
126 { /* traffic */
127 T_ATM_PRESENT,
128 {
129 {
130 T_ATM_ABSENT,
131 0,
132 T_ATM_ABSENT,
133 T_ATM_ABSENT,
134 T_ATM_ABSENT,
135 T_ATM_ABSENT,
136 T_NO
137 },
138 {
139 T_ATM_ABSENT,
140 0,
141 T_ATM_ABSENT,
142 T_ATM_ABSENT,
143 T_ATM_ABSENT,
144 T_ATM_ABSENT,
145 T_NO
146 },
147 T_YES
148 },
149 },
150 { /* bearer */
151 T_ATM_ANY
152 },
153 { /* bhli */
154 T_ATM_ABSENT
155 },
156 { /* blli */
157 T_ATM_PRESENT,
158 T_ATM_ABSENT,
159 {
160 {
161 T_ATM_SIMPLE_ID,
162 },
163 {
164 T_ATM_ABSENT
165 }
166 }
167 },
168 { /* llc */
169 T_ATM_PRESENT,
170 {
171 T_ATM_LLC_SHARING,
172 IPATM_LLC_LEN,
173 IPATM_LLC_HDR
174 }
175 },
176 { /* called */
177 T_ATM_ANY
178 },
179 { /* calling */
180 T_ATM_ANY
181 },
182 { /* qos */
183 T_ATM_PRESENT,
184 {
185 T_ATM_NETWORK_CODING,
186 {
187 T_ATM_QOS_CLASS_0,
188 },
189 {
190 T_ATM_QOS_CLASS_0
191 }
192 }
193 },
194 { /* transit */
195 T_ATM_ANY
196 },
197 { /* cause */
198 T_ATM_ABSENT
199 },
200 },
201 NULL
202},
203{
204 { NULL, /* nif */
205 CMAPI_CPCS, /* api */
206 0, /* api_init */
207 0, /* headin */
208 0, /* headout */
209 { /* aal */
210 T_ATM_PRESENT,
211 ATM_AAL5
212 },
213 { /* traffic */
214 T_ATM_PRESENT,
215 {
216 {
217 T_ATM_ABSENT,
218 0,
219 T_ATM_ABSENT,
220 T_ATM_ABSENT,
221 T_ATM_ABSENT,
222 T_ATM_ABSENT,
223 T_NO
224 },
225 {
226 T_ATM_ABSENT,
227 0,
228 T_ATM_ABSENT,
229 T_ATM_ABSENT,
230 T_ATM_ABSENT,
231 T_ATM_ABSENT,
232 T_NO
233 },
234 T_YES
235 },
236 },
237 { /* bearer */
238 T_ATM_ANY
239 },
240 { /* bhli */
241 T_ATM_ABSENT
242 },
243 { /* blli */
244 T_ATM_ABSENT,
245 T_ATM_ABSENT
246 },
247 { /* llc */
248 T_ATM_ABSENT
249 },
250 { /* called */
251 T_ATM_ANY
252 },
253 { /* calling */
254 T_ATM_ANY
255 },
256 { /* qos */
257 T_ATM_PRESENT,
258 {
259 T_ATM_NETWORK_CODING,
260 {
261 T_ATM_QOS_CLASS_0,
262 },
263 {
264 T_ATM_QOS_CLASS_0
265 }
266 }
267 },
268 { /* transit */
269 T_ATM_ANY
270 },
271 { /* cause */
272 T_ATM_ABSENT
273 },
274 },
275 NULL
276},
277{
278 { NULL, /* nif */
279 CMAPI_CPCS, /* api */
280 0, /* api_init */
281 0, /* headin */
282 0, /* headout */
283 { /* aal */
284 T_ATM_PRESENT,
285 ATM_AAL3_4
286 },
287 { /* traffic */
288 T_ATM_PRESENT,
289 {
290 {
291 T_ATM_ABSENT,
292 0,
293 T_ATM_ABSENT,
294 T_ATM_ABSENT,
295 T_ATM_ABSENT,
296 T_ATM_ABSENT,
297 T_NO
298 },
299 {
300 T_ATM_ABSENT,
301 0,
302 T_ATM_ABSENT,
303 T_ATM_ABSENT,
304 T_ATM_ABSENT,
305 T_ATM_ABSENT,
306 T_NO
307 },
308 T_YES
309 },
310 },
311 { /* bearer */
312 T_ATM_ANY
313 },
314 { /* bhli */
315 T_ATM_ABSENT
316 },
317 { /* blli */
318 T_ATM_ABSENT,
319 T_ATM_ABSENT
320 },
321 { /* llc */
322 T_ATM_ABSENT
323 },
324 { /* called */
325 T_ATM_ANY
326 },
327 { /* calling */
328 T_ATM_ANY
329 },
330 { /* qos */
331 T_ATM_PRESENT,
332 {
333 T_ATM_NETWORK_CODING,
334 {
335 T_ATM_QOS_CLASS_0,
336 },
337 {
338 T_ATM_QOS_CLASS_0
339 }
340 }
341 },
342 { /* transit */
343 T_ATM_ANY
344 },
345 { /* cause */
346 T_ATM_ABSENT
347 },
348 },
349 NULL
350},
351};
352
353static struct t_atm_cause ipatm_cause = {
354 T_ATM_ITU_CODING,
355 T_ATM_LOC_USER,
356 T_ATM_CAUSE_UNSPECIFIED_NORMAL,
357 {0, 0, 0, 0}
358};
359
360
361/*
362 * Initialize ipatm processing
363 *
364 * This will be called during module loading. We'll just register
365 * ourselves and wait for the packets to start flying.
366 *
367 * Arguments:
368 * none
369 *
370 * Returns:
371 * 0 startup was successful
372 * errno startup failed - reason indicated
373 *
374 */
375static int
9855a82b 376ipatm_start(void)
984263bc
MD
377{
378 struct atm_pif *pip;
379 struct atm_nif *nip;
0139ebde 380 int err, i;
984263bc
MD
381
382 /*
383 * Verify software version
384 */
385 if (atm_version != ATM_VERSION) {
386 log(LOG_ERR, "version mismatch: ipatm=%d.%d kernel=%d.%d\n",
387 ATM_VERS_MAJ(ATM_VERSION), ATM_VERS_MIN(ATM_VERSION),
388 ATM_VERS_MAJ(atm_version), ATM_VERS_MIN(atm_version));
389 return (EINVAL);
390 }
391
392 /*
393 * Register ourselves as a network convergence module
394 */
395 err = atm_netconv_register(&ipatm_ncm);
396 if (err)
397 goto done;
398
399 /*
400 * Register ourselves as an ATM endpoint
401 */
402 err = atm_endpoint_register(&ipatm_endpt);
403 if (err)
404 goto done;
405
406 /*
407 * Get current system configuration
408 */
0139ebde 409 crit_enter();
984263bc
MD
410 for (pip = atm_interface_head; pip; pip = pip->pif_next) {
411 /*
412 * Process each network interface
413 */
414 for (nip = pip->pif_nif; nip; nip = nip->nif_pnext) {
415 struct ifnet *ifp = (struct ifnet *)nip;
416 struct in_ifaddr *ia;
1b562c24 417 struct in_ifaddr_container *iac;
984263bc
MD
418
419 /*
420 * Attach interface
421 */
422 err = ipatm_nifstat(NCM_ATTACH, nip, 0);
423 if (err) {
0139ebde 424 crit_exit();
984263bc
MD
425 goto done;
426 }
427
428 /*
429 * If IP address has been set, register it
430 */
1b562c24
SZ
431 TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) {
432 if (iac->ia->ia_ifp == ifp)
984263bc
MD
433 break;
434 }
1b562c24
SZ
435 if (iac) {
436 ia = iac->ia;
984263bc
MD
437 err = ipatm_nifstat(NCM_SETADDR, nip, (int)ia);
438 if (err) {
0139ebde 439 crit_exit();
984263bc
MD
440 goto done;
441 }
442 }
443 }
444 }
0139ebde 445 crit_exit();
984263bc
MD
446
447 /*
448 * Fill in union fields
449 */
450 ipatm_aal5llc.aal.v.aal5.forward_max_SDU_size =
451 ATM_NIF_MTU + IPATM_LLC_LEN;
452 ipatm_aal5llc.aal.v.aal5.backward_max_SDU_size =
453 ATM_NIF_MTU + IPATM_LLC_LEN;
454 ipatm_aal5llc.aal.v.aal5.SSCS_type = T_ATM_NULL;
455 ipatm_aal5llc.blli.v.layer_2_protocol.ID.simple_ID = T_ATM_BLLI2_I8802;
456
457 ipatm_aal5null.aal.v.aal5.forward_max_SDU_size = ATM_NIF_MTU;
458 ipatm_aal5null.aal.v.aal5.backward_max_SDU_size = ATM_NIF_MTU;
459 ipatm_aal5null.aal.v.aal5.SSCS_type = T_ATM_NULL;
460
461 ipatm_aal4null.aal.v.aal4.forward_max_SDU_size = ATM_NIF_MTU;
462 ipatm_aal4null.aal.v.aal4.backward_max_SDU_size = ATM_NIF_MTU;
463 ipatm_aal4null.aal.v.aal4.SSCS_type = T_ATM_NULL;
464 ipatm_aal4null.aal.v.aal4.mid_low = 0;
465 ipatm_aal4null.aal.v.aal4.mid_high = 1023;
466
467 /*
468 * Listen for incoming calls
469 */
470 for (i = 0;
471 i < (sizeof(ipatm_listeners) / sizeof(struct ipatm_listener));
472 i++) {
473 struct attr_aal *aalp = &ipatm_listeners[i].attr.aal;
474 int maxsdu = ATM_NIF_MTU;
475
476 /*
477 * Fill in union fields
478 */
479 if (ipatm_listeners[i].attr.blli.tag_l2 == T_ATM_PRESENT) {
480 struct t_atm_blli *bp = &ipatm_listeners[i].attr.blli.v;
481
482 bp->layer_2_protocol.ID.simple_ID = T_ATM_BLLI2_I8802;
483 maxsdu += IPATM_LLC_LEN;
484 }
485 if (aalp->type == ATM_AAL5) {
486 aalp->v.aal5.forward_max_SDU_size = maxsdu;
487 aalp->v.aal5.backward_max_SDU_size = maxsdu;
488 aalp->v.aal5.SSCS_type = T_ATM_NULL;
489 } else {
490 aalp->v.aal4.forward_max_SDU_size = maxsdu;
491 aalp->v.aal4.backward_max_SDU_size = maxsdu;
492 aalp->v.aal4.SSCS_type = T_ATM_NULL;
493 aalp->v.aal4.mid_low = 0;
494 aalp->v.aal4.mid_high = 1023;
495 }
496
497 /*
498 * Now start listening
499 */
500 if ((err = atm_cm_listen(&ipatm_endpt, (void *)i,
501 &ipatm_listeners[i].attr,
502 &ipatm_listeners[i].conn)) != 0)
503 goto done;
504 }
505
506 /*
507 * Start background VCC idle timer
508 */
509 atm_timeout(&ipatm_itimer, IPATM_IDLE_TIME, ipatm_itimeout);
510
511done:
512 return (err);
513}
514
515
516/*
517 * Halt ipatm processing
518 *
519 * This will be called just prior to unloading the module from
520 * memory. All IP VCCs must be terminated before the protocol can
521 * be shutdown.
522 *
523 * Arguments:
524 * none
525 *
526 * Returns:
527 * 0 shutdown was successful
528 * errno shutdown failed - reason indicated
529 *
530 */
531static int
9855a82b 532ipatm_stop(void)
984263bc
MD
533{
534 struct ip_nif *inp;
535 int err = 0, i;
984263bc
MD
536
537 /*
538 * Any VCCs still open??
539 */
0139ebde 540 crit_enter();
984263bc 541 if (ipatm_vccnt) {
984263bc
MD
542 /* Yes, can't stop now */
543 err = EBUSY;
544 goto done;
545 }
546
547 /*
548 * Kill VCC idle timer
549 */
9855a82b 550 atm_untimeout(&ipatm_itimer);
984263bc
MD
551
552 /*
553 * Stop listening for incoming calls
554 */
555 for (i = 0;
556 i < (sizeof(ipatm_listeners) / sizeof(struct ipatm_listener));
557 i++) {
558 if (ipatm_listeners[i].conn != NULL) {
9855a82b 559 atm_cm_release(ipatm_listeners[i].conn, &ipatm_cause);
984263bc
MD
560 }
561 }
562
563 /*
564 * Detach all our interfaces
565 */
566 while ((inp = ipatm_nif_head) != NULL) {
9855a82b 567 ipatm_nifstat(NCM_DETACH, inp->inf_nif, 0);
984263bc
MD
568 }
569
570 /*
571 * De-register from system
572 */
9855a82b
SW
573 atm_netconv_deregister(&ipatm_ncm);
574 atm_endpoint_deregister(&ipatm_endpt);
984263bc
MD
575
576 /*
577 * Free up our storage pools
578 */
579 atm_release_pool(&ipatm_vcpool);
580 atm_release_pool(&ipatm_nifpool);
581
582done:
0139ebde 583 crit_exit();
984263bc
MD
584 return (err);
585}
586
587
588#ifdef ATM_IP_MODULE
589/*
590 *******************************************************************
591 *
592 * Loadable Module Support
593 *
594 *******************************************************************
595 */
3e0c9cba
RG
596static int ipatm_doload (void);
597static int ipatm_dounload (void);
984263bc
MD
598
599/*
600 * Generic module load processing
601 *
602 * This function is called by an OS-specific function when this
603 * module is being loaded.
604 *
605 * Arguments:
606 * none
607 *
608 * Returns:
609 * 0 load was successful
610 * errno load failed - reason indicated
611 *
612 */
613static int
9855a82b 614ipatm_doload(void)
984263bc
MD
615{
616 int err = 0;
617
618 /*
619 * Start us up
620 */
621 err = ipatm_start();
622 if (err)
623 /* Problems, clean up */
9855a82b 624 ipatm_stop();
984263bc
MD
625
626 return (err);
627}
628
629
630/*
631 * Generic module unload processing
632 *
633 * This function is called by an OS-specific function when this
634 * module is being unloaded.
635 *
636 * Arguments:
637 * none
638 *
639 * Returns:
640 * 0 unload was successful
641 * errno unload failed - reason indicated
642 *
643 */
644static int
9855a82b 645ipatm_dounload(void)
984263bc
MD
646{
647 int err = 0;
648
649 /*
650 * OK, try to clean up our mess
651 */
652 err = ipatm_stop();
653
654 return (err);
655}
656
984263bc
MD
657#include <sys/exec.h>
658#include <sys/sysent.h>
659#include <sys/lkm.h>
660
661/*
662 * Loadable miscellaneous module description
663 */
664MOD_MISC(ipatm);
665
666
667/*
668 * Loadable module support "load" entry point
669 *
670 * This is the routine called by the lkm driver whenever the
671 * modload(1) command is issued for this module.
672 *
673 * Arguments:
674 * lkmtp pointer to lkm drivers's structure
675 * cmd lkm command code
676 *
677 * Returns:
678 * 0 command was successful
679 * errno command failed - reason indicated
680 *
681 */
682static int
9855a82b 683ipatm_load(struct lkm_table *lkmtp, int cmd)
984263bc
MD
684{
685 return(ipatm_doload());
686}
687
688
689/*
690 * Loadable module support "unload" entry point
691 *
692 * This is the routine called by the lkm driver whenever the
693 * modunload(1) command is issued for this module.
694 *
695 * Arguments:
696 * lkmtp pointer to lkm drivers's structure
697 * cmd lkm command code
698 *
699 * Returns:
700 * 0 command was successful
701 * errno command failed - reason indicated
702 *
703 */
704static int
9855a82b 705ipatm_unload(struct lkm_table *lkmtp, int cmd)
984263bc
MD
706{
707 return(ipatm_dounload());
708}
709
710
711/*
712 * Loadable module support entry point
713 *
714 * This is the routine called by the lkm driver for all loadable module
715 * functions for this driver. This routine name must be specified
716 * on the modload(1) command. This routine will be called whenever the
717 * modload(1), modunload(1) or modstat(1) commands are issued for this
718 * module.
719 *
720 * Arguments:
721 * lkmtp pointer to lkm drivers's structure
722 * cmd lkm command code
723 * ver lkm version
724 *
725 * Returns:
726 * 0 command was successful
727 * errno command failed - reason indicated
728 *
729 */
730int
9855a82b 731ipatm_mod(struct lkm_table *lkmtp, int cmd, int ver)
984263bc
MD
732{
733 MOD_DISPATCH(ipatm, lkmtp, cmd, ver,
734 ipatm_load, ipatm_unload, lkm_nullcmd);
735}
984263bc
MD
736
737#else /* !ATM_IP_MODULE */
738
739/*
740 *******************************************************************
741 *
742 * Kernel Compiled Module Support
743 *
744 *******************************************************************
745 */
3e0c9cba 746static void ipatm_doload (void *);
984263bc
MD
747
748SYSINIT(atmipatm, SI_SUB_PROTO_END, SI_ORDER_ANY, ipatm_doload, NULL)
749
750/*
751 * Kernel initialization
752 *
753 * Arguments:
754 * arg Not used
755 *
756 * Returns:
757 * none
758 *
759 */
760static void
761ipatm_doload(void *arg)
762{
763 int err = 0;
764
765 /*
766 * Start us up
767 */
768 err = ipatm_start();
769 if (err) {
770 /* Problems, clean up */
9855a82b 771 ipatm_stop();
984263bc
MD
772
773 log(LOG_ERR, "IP over ATM unable to initialize (%d)!!\n", err);
774 }
775 return;
776}
777#endif /* ATM_IP_MODULE */
778