Do you think /sys/netproto needs to use __P() prototypes?
[dragonfly.git] / sys / netproto / atm / uni / sscop.c
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/uni/sscop.c,v 1.6.2.1 2001/09/30 22:54:35 kris Exp $
27  *      @(#) $DragonFly: src/sys/netproto/atm/uni/sscop.c,v 1.5 2003/08/23 10:06:22 rob Exp $
28  */
29
30 /*
31  * ATM Forum UNI Support
32  * ---------------------
33  *
34  * Service Specific Connection Oriented Protocol (SSCOP)
35  *
36  */
37
38 #include <netproto/atm/kern_include.h>
39
40 #include "sscop.h"
41 #include "sscop_misc.h"
42 #include "sscop_pdu.h"
43 #include "sscop_var.h"
44
45 /*
46  * Global variables
47  */
48 int     sscop_vccnt = 0;
49
50 struct sscop            *sscop_head = NULL;
51
52 struct sscop_stat       sscop_stat = {0};
53
54 struct atm_time         sscop_timer = {0, 0};
55
56 struct sp_info  sscop_pool = {
57         "sscop pool",                   /* si_name */
58         sizeof(struct sscop),           /* si_blksiz */
59         5,                              /* si_blkcnt */
60         100                             /* si_maxallow */
61 };
62
63
64 /*
65  * Local functions
66  */
67 static int      sscop_inst (struct stack_defn **, Atm_connvc *);
68
69
70 /*
71  * Local variables
72  */
73 static struct stack_defn        sscop_service = {
74         NULL,
75         SAP_SSCOP,
76         0,
77         sscop_inst,
78         sscop_lower,
79         sscop_upper,
80         0
81 };
82
83 static struct t_atm_cause       sscop_cause = {
84         T_ATM_ITU_CODING,
85         T_ATM_LOC_USER,
86         T_ATM_CAUSE_TEMPORARY_FAILURE,
87         {0, 0, 0, 0}
88 };
89
90 static u_char   sscop_maa_log[MAA_ERROR_COUNT] = {
91         1,      /* A */
92         1,      /* B */
93         1,      /* C */
94         1,      /* D */
95         1,      /* E */
96         1,      /* F */
97         1,      /* G */
98         1,      /* H */
99         1,      /* I */
100         1,      /* J */
101         1,      /* K */
102         1,      /* L */
103         1,      /* M */
104         0,      /* N */
105         0,      /* O */
106         0,      /* P */
107         1,      /* Q */
108         1,      /* R */
109         1,      /* S */
110         1,      /* T */
111         1,      /* U */
112         0,      /* V */
113         0,      /* W */
114         0,      /* X */
115         1       /* INVAL */
116 };
117
118
119 /*
120  * Initialize SSCOP processing
121  * 
122  * This will be called during module loading.  We will register our stack
123  * service and wait for someone to talk to us.
124  *
125  * Arguments:
126  *      none
127  *
128  * Returns:
129  *      0       initialization was successful 
130  *      errno   initialization failed - reason indicated
131  *
132  */
133 int
134 sscop_start()
135 {
136         int     err = 0;
137
138         /*
139          * Register stack service
140          */
141         if ((err = atm_stack_register(&sscop_service)) != 0)
142                 goto done;
143
144         /*
145          * Start up timer
146          */
147         atm_timeout(&sscop_timer, ATM_HZ/SSCOP_HZ, sscop_timeout);
148
149 done:
150         return (err);
151 }
152
153
154 /*
155  * Terminate SSCOP processing 
156  * 
157  * This will be called just prior to unloading the module from memory.  All 
158  * signalling instances should have been terminated by now, so we just free
159  * up all of our resources.
160  *
161  * Called at splnet.
162  *
163  * Arguments:
164  *      none
165  *
166  * Returns:
167  *      0       termination was successful 
168  *      errno   termination failed - reason indicated
169  *
170  */
171 int
172 sscop_stop()
173 {
174         int     err = 0;
175
176         /*
177          * Any connections still exist??
178          */
179         if (sscop_vccnt) {
180
181                 /*
182                  * Yes, can't stop yet
183                  */
184                 return (EBUSY);
185         }
186
187         /*
188          * Stop our timer
189          */
190         (void) atm_untimeout(&sscop_timer);
191
192         /*
193          * Deregister the stack service
194          */
195         (void) atm_stack_deregister(&sscop_service);
196
197         /*
198          * Free our storage pools
199          */
200         atm_release_pool(&sscop_pool);
201
202         return (err);
203 }
204
205
206 /*
207  * SSCOP Stack Instantiation 
208  * 
209  * Called at splnet.
210  *
211  * Arguments:
212  *      ssp     pointer to array of stack definition pointers for connection
213  *              ssp[0] points to upper layer's stack service definition
214  *              ssp[1] points to this layer's stack service definition
215  *              ssp[2] points to lower layer's stack service definition
216  *      cvp     pointer to connection vcc for this stack
217  *
218  * Returns:
219  *      0       instantiation successful
220  *      errno   instantiation failed - reason indicated
221  *
222  */
223 static int
224 sscop_inst(ssp, cvp)
225         struct stack_defn       **ssp;
226         Atm_connvc              *cvp;
227 {
228         struct stack_defn       *sdp_up = ssp[0],
229                                 *sdp_me = ssp[1],
230                                 *sdp_low = ssp[2];
231         struct sscop    *sop;
232         int             err;
233
234         ATM_DEBUG2("sscop_inst: ssp=%p, cvp=%p\n", ssp, cvp);
235
236         /*
237          * Validate lower SAP
238          */
239         if ((sdp_low->sd_sap & SAP_CLASS_MASK) != SAP_CPCS)
240                 return (EINVAL);
241
242         /*
243          * Allocate our control block
244          */
245         sop = (struct sscop *)atm_allocate(&sscop_pool);
246         if (sop == NULL)
247                 return (ENOMEM);
248
249         sop->so_state = SOS_INST;
250         sop->so_connvc = cvp;
251         sop->so_toku = sdp_up->sd_toku;
252         sop->so_upper = sdp_up->sd_upper;
253
254         /*
255          * Store my token into service definition
256          */
257         sdp_me->sd_toku = sop;
258
259         /*
260          * Update and save input buffer headroom
261          */
262         HEADIN(cvp, sizeof(struct pdu_hdr), 0);
263         /* sop->so_headin = cvp->cvc_attr.headin; */
264
265         /*
266          * Pass instantiation down the stack
267          */
268         err = sdp_low->sd_inst(ssp + 1, cvp);
269         if (err) {
270                 /*
271                  * Lower layer instantiation failed, free our resources
272                  */
273                 atm_free((caddr_t)sop);
274                 return (err);
275         }
276
277         /*
278          * Link in connection block
279          */
280         LINK2TAIL(sop, struct sscop, sscop_head, so_next);
281         sscop_vccnt++;
282         sscop_stat.sos_connects++;
283
284         /*
285          * Save and update output buffer headroom
286          */
287         sop->so_headout = cvp->cvc_attr.headout;
288         HEADOUT(cvp, sizeof(struct pdu_hdr), 0);
289
290         /*
291          * Save lower layer's interface info
292          */
293         sop->so_lower = sdp_low->sd_lower;
294         sop->so_tokl = sdp_low->sd_toku;
295
296         /*
297          * Initialize version (until INIT received)
298          */
299         sop->so_vers = SSCOP_VERS_Q2110;
300
301         return (0);
302 }
303
304
305 /*
306  * Report Management Error
307  * 
308  * Called to report an error to the layer management entity.
309  *
310  * Arguments:
311  *      sop     pointer to sscop control block
312  *      code    error code
313  *
314  * Returns:
315  *      none
316  *
317  */
318 void
319 sscop_maa_error(sop, code)
320         struct sscop    *sop;
321         int             code;
322 {
323         int             i;
324
325         /*
326          * Validate error code
327          */
328         if ((code < MAA_ERROR_MIN) ||
329             (code > MAA_ERROR_MAX))
330                 code = MAA_ERROR_INVAL;
331         i = code - MAA_ERROR_MIN;
332
333         /*
334          * Bump statistics counters
335          */
336         sscop_stat.sos_maa_error[i]++;
337
338         /*
339          * Log error message
340          */
341         if (sscop_maa_log[i] != 0) {
342                 struct vccb     *vcp = sop->so_connvc->cvc_vcc;
343                 struct atm_pif  *pip = vcp->vc_pif;
344
345                 log(LOG_ERR,
346                         "sscop_maa_error: intf=%s%d vpi=%d vci=%d code=%c state=%d\n",
347                         pip->pif_name, pip->pif_unit,
348                         vcp->vc_vpi, vcp->vc_vci, code, sop->so_state);
349         }
350 }
351
352
353 /*
354  * Abort an SSCOP connection
355  * 
356  * Called when an unrecoverable or "should never happen" error occurs.
357  * We log a message, send an END PDU to our peer and request the signalling
358  * manager to abort the connection.
359  *
360  * Arguments:
361  *      sop     pointer to sscop control block
362  *      msg     pointer to error message
363  *
364  * Returns:
365  *      none
366  *
367  */
368 void
369 sscop_abort(sop, msg)
370         struct sscop    *sop;
371         char            *msg;
372 {
373         Atm_connvc      *cvp = sop->so_connvc;
374
375         /*
376          * Log and count error
377          */
378         log(LOG_ERR, "%s", msg);
379         sscop_stat.sos_aborts++;
380
381         /*
382          * Send an END PDU as a courtesy to peer
383          */
384         (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
385
386         /*
387          * Set termination state
388          */
389         sop->so_state = SOS_TERM;
390
391         /*
392          * Flush all of our queues
393          */
394         sscop_xmit_drain(sop);
395         sscop_rcvr_drain(sop);
396
397         /*
398          * Tell Connection Manager to abort this connection
399          */
400         (void) atm_cm_abort(cvp, &sscop_cause);
401 }
402