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$");
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(struct sigmgr *smp)
78 {
79 struct sigmgr *smp2;
80 int s = splnet();
81
82 /*
83 * See if we need to be initialized
84 */
85 if (!atm_init)
86 atm_initialize();
87
88 /*
89 * Make sure there's only one instance of each protocol
90 */
91 for (smp2 = atm_sigmgr_head; smp2 != NULL; smp2 = smp2->sm_next) {
92 if (smp->sm_proto == smp2->sm_proto) {
93 (void) splx(s);
94 return (EEXIST);
95 }
96 }
97
98 /*
99 * Looks okay, link it in
100 */
101 LINK2TAIL(smp, struct sigmgr, atm_sigmgr_head, sm_next);
102
103 (void) splx(s);
104 return (0);
105 }
106
107
108 /*
109 * De-register a Signalling Manager
110 *
111 * Each Signalling Manager must de-register (is this really a word?)
112 * itself before removing itself from the system. This really only
113 * applies to managers about to be modunload'ed. It is the signal
114 * manager's responsibility to ensure that all its protocol instances
115 * have been successfully terminated before de-registering itself.
116 *
117 * Arguments:
118 * smp pointer to Signalling Manager description
119 *
120 * Returns:
121 * 0 deregistration was successful
122 * errno deregistration failed - reason indicated
123 *
124 */
125 int
126 atm_sigmgr_deregister(struct sigmgr *smp)
127 {
128 int found, s = splnet();
129
130 /*
131 * Unlink descriptor
132 */
133 UNLINKF(smp, struct sigmgr, atm_sigmgr_head, sm_next, found);
134
135 (void) splx(s);
136
137 if (!found)
138 return (ENOENT);
139
140 return (0);
141 }
142
143
144 /*
145 * Attach a Signalling Manager to an ATM physical interface
146 *
147 * Each ATM physical interface must have a signalling manager attached to
148 * itself for the signalling protocol to be run across this interface. The
149 * interface must be registered and completely initialized before the attach,
150 * since the signalling manager may initiate virtual circuit activity as part
151 * its response to this call.
152 *
153 * Called at splnet.
154 *
155 * Arguments:
156 * pip pointer to atm physical interface control block
157 * proto requested signalling protocol
158 *
159 * Returns:
160 * 0 attach successful
161 * errno attach failed - reason indicated
162 *
163 */
164 int
165 atm_sigmgr_attach(struct atm_pif *pip, u_char proto)
166 {
167 struct atm_pif *tp;
168 struct sigmgr *smp;
169 int err;
170
171 /*
172 * Make sure interface is registered
173 */
174 for (tp = atm_interface_head; tp != NULL; tp = tp->pif_next) {
175 if (tp == pip)
176 break;
177 }
178 if (tp == NULL) {
179 return (ENOENT);
180 }
181
182 /*
183 * Make sure no signalling manager is already attached
184 */
185 if (pip->pif_sigmgr != NULL) {
186 return (EEXIST);
187 }
188
189 /*
190 * Must have at least one network interface defined
191 */
192 if (pip->pif_nif == NULL)
193 return (ETOOMANYREFS);
194
195 /*
196 * Find requested protocol
197 */
198 for (smp = atm_sigmgr_head; smp != NULL; smp = smp->sm_next) {
199 if (smp->sm_proto == proto)
200 break;
201 }
202 if (smp == NULL) {
203 return (EPROTONOSUPPORT);
204 }
205
206 /*
207 * Tell the signal manager about it
208 */
209 err = (*smp->sm_attach)(smp, pip);
210
211 /*
212 * Tell all registered convergence modules about this
213 */
214 if (!err) {
215 struct atm_nif *nip;
216 struct atm_ncm *ncp;
217
218 for (nip = pip->pif_nif; nip; nip = nip->nif_pnext) {
219 for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
220 if ((err = (*ncp->ncm_stat)
221 (NCM_SIGATTACH, nip, 0)) != 0)
222 break;
223 }
224 if (err)
225 break;
226 }
227
228 if (err) {
229 /*
230 * Someone's unhappy, so back all this out
231 */
232 (void) atm_sigmgr_detach(pip);
233 }
234 }
235
236 return (err);
237 }
238
239
240 /*
241 * Detach an ATM physical interface from a Signalling Manager
242 *
243 * The ATM interface must be detached from the signalling manager
244 * before the interface can be de-registered.
245 *
246 * Called at splnet.
247 *
248 * Arguments:
249 * pip pointer to atm physical interface control block
250 *
251 * Returns:
252 * 0 detach successful
253 * errno detach failed - reason indicated
254 *
255 */
256 int
257 atm_sigmgr_detach(struct atm_pif *pip)
258 {
259 struct atm_pif *tp;
260 struct atm_nif *nip;
261 struct atm_ncm *ncp;
262 int err;
263
264
265 /*
266 * Make sure interface is registered
267 */
268 for (tp = atm_interface_head; tp != NULL; tp = tp->pif_next) {
269 if (tp == pip)
270 break;
271 }
272 if (tp == NULL) {
273 return (ENOENT);
274 }
275
276 /*
277 * Make sure a signalling manager is attached
278 */
279 if (pip->pif_sigmgr == NULL) {
280 return (ENOENT);
281 }
282
283 /*
284 * Tell all registered convergence modules about this
285 */
286 for (nip = pip->pif_nif; nip; nip = nip->nif_pnext) {
287 for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
288 (void) (*ncp->ncm_stat)(NCM_SIGDETACH, nip, 0);
289 }
290 }
291
292 /*
293 * Tell the signal manager about it
294 *
295 * NOTE:
296 * The only reason this should ever fail is if things are really
297 * hosed up somewhere, in which case doing a bunch of NCM_SIGATTACH's
298 * here just doesn't seem to help much.
299 */
300 err = (*pip->pif_sigmgr->sm_detach)(pip);
301
302 return (err);
303 }
304
305
306 /*
307 * Register an ATM Stack Service
308 *
309 * Each ATM stack service provider must register its provided service(s) here.
310 * Each service must be registered separately. Service providers include
311 * both loaded and linked kernel modules. Device driver services are NOT
312 * registered here - their service registry is performed implicitly through
313 * the device interface structure stack services list (pif_services).
314 *
315 * Arguments:
316 * sdp pointer to stack service definition block
317 *
318 * Returns:
319 * 0 registration successful
320 * errno registration failed - reason indicated
321 *
322 */
323 int
324 atm_stack_register(struct stack_defn *sdp)
325 {
326 struct stack_defn *tdp;
327 int s = splnet();
328
329 /*
330 * See if we need to be initialized
331 */
332 if (!atm_init)
333 atm_initialize();
334
335 /*
336 * Ensure no duplicates
337 */
338 for (tdp = atm_stack_head; tdp != NULL; tdp = tdp->sd_next) {
339 if (tdp->sd_sap == sdp->sd_sap)
340 break;
341 }
342 if (tdp != NULL) {
343 (void) splx(s);
344 return (EEXIST);
345 }
346
347 /*
348 * Add stack to list
349 */
350 LINK2TAIL(sdp, struct stack_defn, atm_stack_head, sd_next);
351
352 (void) splx(s);
353 return (0);
354 }
355
356
357 /*
358 * De-register an ATM Stack Service
359 *
360 * Each ATM stack service provider must de-register its registered service(s)
361 * before terminating the service. Specifically, loaded kernel modules
362 * must de-register their services before unloading themselves.
363 *
364 * Arguments:
365 * sdp pointer to stack service definition block
366 *
367 * Returns:
368 * 0 de-registration successful
369 * errno de-registration failed - reason indicated
370 *
371 */
372 int
373 atm_stack_deregister(struct stack_defn *sdp)
374 {
375 int found, s = splnet();
376
377 /*
378 * Remove service from list
379 */
380 UNLINKF(sdp, struct stack_defn, atm_stack_head, sd_next, found);
381 (void) splx(s);
382
383 if (!found)
384 return (ENOENT);
385
386 return (0);
387 }
388
389
390 /*
391 * Create and Instantiate a Stack
392 *
393 * For the requested stack list, locate the stack service definitions
394 * necessary to build the stack to implement the listed services.
395 * The stack service definitions provided by the interface device-driver
396 * are always preferred, since they are (hopefully) done with
397 * hardware assistance from the interface card.
398 *
399 * After the stack has been built, the selected services are called to
400 * notify them of the new stack instantiation. Each service should then
401 * allocate all the resources it requires for this new stack instance.
402 * The service should then wait for subsequent protocol notification
403 * via its stack command handlers.
404 *
405 * Must be called at splnet.
406 *
407 * Arguments:
408 * cvp pointer to connection vcc block for the created stack
409 * tlp pointer to stack list
410 * upf top-of-stack CM upper command handler
411 *
412 * Returns:
413 * 0 stack successfully created
414 * errno failed - reason indicated
415 *
416 */
417 int
418 atm_create_stack(Atm_connvc *cvp, struct stack_list *tlp,
419 void (*upf)(int, void *, intptr_t, intptr_t))
420 {
421 struct stack_defn *sdp, usd;
422 struct stack_inst svs;
423 struct atm_pif *pip = cvp->cvc_attr.nif->nif_pif;
424 int i, err;
425
426
427 /*
428 * Initialize stack (element 0 is for owner's services)
429 */
430 svs.si_srvc[1] = sdp = NULL;
431
432 /*
433 * Locate service provider for each service in the
434 * stack list. We prefer interface driver providers
435 * over kernel module providers.
436 */
437 for (i = 0; i < STACK_CNT; i++) {
438 Sap_t sap;
439
440 /* Stack list is 0-terminated */
441 if ((sap = tlp->sl_sap[i]) == 0)
442 break;
443
444 /*
445 * Search interface's services
446 */
447 for (sdp = pip->pif_services; sdp; sdp = sdp->sd_next)
448 if (sdp->sd_sap == sap)
449 break;
450 if (sdp == NULL) {
451
452 /*
453 * Search kernel services
454 */
455 for (sdp = atm_stack_head; sdp;
456 sdp = sdp->sd_next)
457 if (sdp->sd_sap == sap)
458 break;
459 }
460 if (sdp == NULL) {
461
462 /*
463 * Requested service id not found
464 */
465 return (ENOENT);
466 }
467
468 /*
469 * Save stack definition for this service
470 */
471 svs.si_srvc[i+1] = sdp;
472
473 /*
474 * Quit loop if this service is terminal, ie. if
475 * it takes care of the rest of the stack.
476 */
477 if (sdp->sd_flag & SDF_TERM)
478 break;
479 }
480
481 /*
482 * Ensure stack instance array is located and terminated
483 */
484 if ((svs.si_srvc[1] == NULL) || !(sdp->sd_flag & SDF_TERM)) {
485 return (ENOENT);
486 }
487
488 /*
489 * Setup owner service definition
490 */
491 bzero((caddr_t)&usd, sizeof(struct stack_defn));
492 usd.sd_upper = upf;
493 usd.sd_toku = cvp;
494 svs.si_srvc[0] = &usd;
495
496 /*
497 * Instantiate the stack
498 */
499 err = (*svs.si_srvc[1]->sd_inst)(&svs.si_srvc[0], cvp);
500 if (err) {
501 return (err);
502 }
503
504 /*
505 * Save top 'o stack info
506 */
507 cvp->cvc_lower = svs.si_srvc[1]->sd_lower;
508 cvp->cvc_tokl = svs.si_srvc[1]->sd_toku;
509
510 return (0);
511 }
Cache object: 827bebce89befba0c2971aea256235ba
|