1 /*-
2 * ===================================
3 * HARP | Host ATM Research Platform
4 * ===================================
5 *
6 *
7 * This Host ATM Research Platform ("HARP") file (the "Software") is
8 * made available by Network Computing Services, Inc. ("NetworkCS")
9 * "AS IS". NetworkCS does not provide maintenance, improvements or
10 * support of any kind.
11 *
12 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
13 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
14 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
15 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
16 * In no event shall NetworkCS be responsible for any damages, including
17 * but not limited to consequential damages, arising from or relating to
18 * any use of the Software or related support.
19 *
20 * Copyright 1994-1998 Network Computing Services, Inc.
21 *
22 * Copies of this Software may be made, however, the above copyright
23 * notice must be reproduced on all copies.
24 */
25
26 /*
27 * Core ATM Services
28 * -----------------
29 *
30 * General ATM signalling management
31 */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD: src/sys/netatm/atm_signal.c,v 1.12.4.1 2005/01/31 23:26:25 imp Exp $");
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/socket.h>
39 #include <sys/socketvar.h>
40 #include <net/if.h>
41 #include <netatm/port.h>
42 #include <netatm/queue.h>
43 #include <netatm/atm.h>
44 #include <netatm/atm_sys.h>
45 #include <netatm/atm_sap.h>
46 #include <netatm/atm_cm.h>
47 #include <netatm/atm_if.h>
48 #include <netatm/atm_sigmgr.h>
49 #include <netatm/atm_stack.h>
50 #include <netatm/atm_pcb.h>
51 #include <netatm/atm_var.h>
52
53
54 /*
55 * Local variables
56 */
57 static struct sigmgr *atm_sigmgr_head = NULL;
58 static struct stack_defn *atm_stack_head = NULL;
59
60
61 /*
62 * Register a new Signalling Manager
63 *
64 * Each Signalling Manager must register itself here upon completing
65 * its internal initialization. This applies to both linked and loaded
66 * managers.
67 *
68 * Arguments:
69 * smp pointer to Signalling Manager description
70 *
71 * Returns:
72 * 0 registration was successful
73 * errno registration failed - reason indicated
74 *
75 */
76 int
77 atm_sigmgr_register(smp)
78 struct sigmgr *smp;
79 {
80 struct sigmgr *smp2;
81 int s = splnet();
82
83 /*
84 * See if we need to be initialized
85 */
86 if (!atm_init)
87 atm_initialize();
88
89 /*
90 * Make sure there's only one instance of each protocol
91 */
92 for (smp2 = atm_sigmgr_head; smp2 != NULL; smp2 = smp2->sm_next) {
93 if (smp->sm_proto == smp2->sm_proto) {
94 (void) splx(s);
95 return (EEXIST);
96 }
97 }
98
99 /*
100 * Looks okay, link it in
101 */
102 LINK2TAIL(smp, struct sigmgr, atm_sigmgr_head, sm_next);
103
104 (void) splx(s);
105 return (0);
106 }
107
108
109 /*
110 * De-register a Signalling Manager
111 *
112 * Each Signalling Manager must de-register (is this really a word?)
113 * itself before removing itself from the system. This really only
114 * applies to managers about to be modunload'ed. It is the signal
115 * manager's responsibility to ensure that all its protocol instances
116 * have been successfully terminated before de-registering itself.
117 *
118 * Arguments:
119 * smp pointer to Signalling Manager description
120 *
121 * Returns:
122 * 0 deregistration was successful
123 * errno deregistration failed - reason indicated
124 *
125 */
126 int
127 atm_sigmgr_deregister(smp)
128 struct sigmgr *smp;
129 {
130 int found, s = splnet();
131
132 /*
133 * Unlink descriptor
134 */
135 UNLINKF(smp, struct sigmgr, atm_sigmgr_head, sm_next, found);
136
137 (void) splx(s);
138
139 if (!found)
140 return (ENOENT);
141
142 return (0);
143 }
144
145
146 /*
147 * Attach a Signalling Manager to an ATM physical interface
148 *
149 * Each ATM physical interface must have a signalling manager attached to
150 * itself for the signalling protocol to be run across this interface. The
151 * interface must be registered and completely initialized before the attach,
152 * since the signalling manager may initiate virtual circuit activity as part
153 * its response to this call.
154 *
155 * Called at splnet.
156 *
157 * Arguments:
158 * pip pointer to atm physical interface control block
159 * proto requested signalling protocol
160 *
161 * Returns:
162 * 0 attach successful
163 * errno attach failed - reason indicated
164 *
165 */
166 int
167 atm_sigmgr_attach(pip, proto)
168 struct atm_pif *pip;
169 u_char proto;
170 {
171 struct atm_pif *tp;
172 struct sigmgr *smp;
173 int err;
174
175 /*
176 * Make sure interface is registered
177 */
178 for (tp = atm_interface_head; tp != NULL; tp = tp->pif_next) {
179 if (tp == pip)
180 break;
181 }
182 if (tp == NULL) {
183 return (ENOENT);
184 }
185
186 /*
187 * Make sure no signalling manager is already attached
188 */
189 if (pip->pif_sigmgr != NULL) {
190 return (EEXIST);
191 }
192
193 /*
194 * Must have at least one network interface defined
195 */
196 if (pip->pif_nif == NULL)
197 return (ETOOMANYREFS);
198
199 /*
200 * Find requested protocol
201 */
202 for (smp = atm_sigmgr_head; smp != NULL; smp = smp->sm_next) {
203 if (smp->sm_proto == proto)
204 break;
205 }
206 if (smp == NULL) {
207 return (EPROTONOSUPPORT);
208 }
209
210 /*
211 * Tell the signal manager about it
212 */
213 err = (*smp->sm_attach)(smp, pip);
214
215 /*
216 * Tell all registered convergence modules about this
217 */
218 if (!err) {
219 struct atm_nif *nip;
220 struct atm_ncm *ncp;
221
222 for (nip = pip->pif_nif; nip; nip = nip->nif_pnext) {
223 for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
224 if ((err = (*ncp->ncm_stat)
225 (NCM_SIGATTACH, nip, 0)) != 0)
226 break;
227 }
228 if (err)
229 break;
230 }
231
232 if (err) {
233 /*
234 * Someone's unhappy, so back all this out
235 */
236 (void) atm_sigmgr_detach(pip);
237 }
238 }
239
240 return (err);
241 }
242
243
244 /*
245 * Detach an ATM physical interface from a Signalling Manager
246 *
247 * The ATM interface must be detached from the signalling manager
248 * before the interface can be de-registered.
249 *
250 * Called at splnet.
251 *
252 * Arguments:
253 * pip pointer to atm physical interface control block
254 *
255 * Returns:
256 * 0 detach successful
257 * errno detach failed - reason indicated
258 *
259 */
260 int
261 atm_sigmgr_detach(pip)
262 struct atm_pif *pip;
263 {
264 struct atm_pif *tp;
265 struct atm_nif *nip;
266 struct atm_ncm *ncp;
267 int err;
268
269
270 /*
271 * Make sure interface is registered
272 */
273 for (tp = atm_interface_head; tp != NULL; tp = tp->pif_next) {
274 if (tp == pip)
275 break;
276 }
277 if (tp == NULL) {
278 return (ENOENT);
279 }
280
281 /*
282 * Make sure a signalling manager is attached
283 */
284 if (pip->pif_sigmgr == NULL) {
285 return (ENOENT);
286 }
287
288 /*
289 * Tell all registered convergence modules about this
290 */
291 for (nip = pip->pif_nif; nip; nip = nip->nif_pnext) {
292 for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
293 (void) (*ncp->ncm_stat)(NCM_SIGDETACH, nip, 0);
294 }
295 }
296
297 /*
298 * Tell the signal manager about it
299 *
300 * NOTE:
301 * The only reason this should ever fail is if things are really
302 * hosed up somewhere, in which case doing a bunch of NCM_SIGATTACH's
303 * here just doesn't seem to help much.
304 */
305 err = (*pip->pif_sigmgr->sm_detach)(pip);
306
307 return (err);
308 }
309
310
311 /*
312 * Register an ATM Stack Service
313 *
314 * Each ATM stack service provider must register its provided service(s) here.
315 * Each service must be registered separately. Service providers include
316 * both loaded and linked kernel modules. Device driver services are NOT
317 * registered here - their service registry is performed implicitly through
318 * the device interface structure stack services list (pif_services).
319 *
320 * Arguments:
321 * sdp pointer to stack service definition block
322 *
323 * Returns:
324 * 0 registration successful
325 * errno registration failed - reason indicated
326 *
327 */
328 int
329 atm_stack_register(sdp)
330 struct stack_defn *sdp;
331 {
332 struct stack_defn *tdp;
333 int s = splnet();
334
335 /*
336 * See if we need to be initialized
337 */
338 if (!atm_init)
339 atm_initialize();
340
341 /*
342 * Ensure no duplicates
343 */
344 for (tdp = atm_stack_head; tdp != NULL; tdp = tdp->sd_next) {
345 if (tdp->sd_sap == sdp->sd_sap)
346 break;
347 }
348 if (tdp != NULL) {
349 (void) splx(s);
350 return (EEXIST);
351 }
352
353 /*
354 * Add stack to list
355 */
356 LINK2TAIL(sdp, struct stack_defn, atm_stack_head, sd_next);
357
358 (void) splx(s);
359 return (0);
360 }
361
362
363 /*
364 * De-register an ATM Stack Service
365 *
366 * Each ATM stack service provider must de-register its registered service(s)
367 * before terminating the service. Specifically, loaded kernel modules
368 * must de-register their services before unloading themselves.
369 *
370 * Arguments:
371 * sdp pointer to stack service definition block
372 *
373 * Returns:
374 * 0 de-registration successful
375 * errno de-registration failed - reason indicated
376 *
377 */
378 int
379 atm_stack_deregister(sdp)
380 struct stack_defn *sdp;
381 {
382 int found, s = splnet();
383
384 /*
385 * Remove service from list
386 */
387 UNLINKF(sdp, struct stack_defn, atm_stack_head, sd_next, found);
388 (void) splx(s);
389
390 if (!found)
391 return (ENOENT);
392
393 return (0);
394 }
395
396
397 /*
398 * Create and Instantiate a Stack
399 *
400 * For the requested stack list, locate the stack service definitions
401 * necessary to build the stack to implement the listed services.
402 * The stack service definitions provided by the interface device-driver
403 * are always preferred, since they are (hopefully) done with
404 * hardware assistance from the interface card.
405 *
406 * After the stack has been built, the selected services are called to
407 * notify them of the new stack instantiation. Each service should then
408 * allocate all the resources it requires for this new stack instance.
409 * The service should then wait for subsequent protocol notification
410 * via its stack command handlers.
411 *
412 * Must be called at splnet.
413 *
414 * Arguments:
415 * cvp pointer to connection vcc block for the created stack
416 * tlp pointer to stack list
417 * upf top-of-stack CM upper command handler
418 *
419 * Returns:
420 * 0 stack successfully created
421 * errno failed - reason indicated
422 *
423 */
424 int
425 atm_create_stack(cvp, tlp, upf)
426 Atm_connvc *cvp;
427 struct stack_list *tlp;
428 void (*upf)(int, void *, intptr_t, intptr_t);
429 {
430 struct stack_defn *sdp, usd;
431 struct stack_inst svs;
432 struct atm_pif *pip = cvp->cvc_attr.nif->nif_pif;
433 int i, err;
434
435
436 /*
437 * Initialize stack (element 0 is for owner's services)
438 */
439 svs.si_srvc[1] = sdp = NULL;
440
441 /*
442 * Locate service provider for each service in the
443 * stack list. We prefer interface driver providers
444 * over kernel module providers.
445 */
446 for (i = 0; i < STACK_CNT; i++) {
447 Sap_t sap;
448
449 /* Stack list is 0-terminated */
450 if ((sap = tlp->sl_sap[i]) == 0)
451 break;
452
453 /*
454 * Search interface's services
455 */
456 for (sdp = pip->pif_services; sdp; sdp = sdp->sd_next)
457 if (sdp->sd_sap == sap)
458 break;
459 if (sdp == NULL) {
460
461 /*
462 * Search kernel services
463 */
464 for (sdp = atm_stack_head; sdp;
465 sdp = sdp->sd_next)
466 if (sdp->sd_sap == sap)
467 break;
468 }
469 if (sdp == NULL) {
470
471 /*
472 * Requested service id not found
473 */
474 return (ENOENT);
475 }
476
477 /*
478 * Save stack definition for this service
479 */
480 svs.si_srvc[i+1] = sdp;
481
482 /*
483 * Quit loop if this service is terminal, ie. if
484 * it takes care of the rest of the stack.
485 */
486 if (sdp->sd_flag & SDF_TERM)
487 break;
488 }
489
490 /*
491 * Ensure stack instance array is located and terminated
492 */
493 if ((svs.si_srvc[1] == NULL) || !(sdp->sd_flag & SDF_TERM)) {
494 return (ENOENT);
495 }
496
497 /*
498 * Setup owner service definition
499 */
500 bzero((caddr_t)&usd, sizeof(struct stack_defn));
501 usd.sd_upper = upf;
502 usd.sd_toku = cvp;
503 svs.si_srvc[0] = &usd;
504
505 /*
506 * Instantiate the stack
507 */
508 err = (*svs.si_srvc[1]->sd_inst)(&svs.si_srvc[0], cvp);
509 if (err) {
510 return (err);
511 }
512
513 /*
514 * Save top 'o stack info
515 */
516 cvp->cvc_lower = svs.si_srvc[1]->sd_lower;
517 cvp->cvc_tokl = svs.si_srvc[1]->sd_toku;
518
519 return (0);
520 }
521
Cache object: d5f81820661078abdb760f0030be697b
|