hammer(8): adjust markup & improve wording
[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.6 2006/01/14 13:36:39 swildner 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(void)
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(void)
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         atm_untimeout(&sscop_timer);
191
192         /*
193          * Deregister the stack service
194          */
195         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(struct stack_defn **ssp, Atm_connvc *cvp)
225 {
226         struct stack_defn       *sdp_up = ssp[0],
227                                 *sdp_me = ssp[1],
228                                 *sdp_low = ssp[2];
229         struct sscop    *sop;
230         int             err;
231
232         ATM_DEBUG2("sscop_inst: ssp=%p, cvp=%p\n", ssp, cvp);
233
234         /*
235          * Validate lower SAP
236          */
237         if ((sdp_low->sd_sap & SAP_CLASS_MASK) != SAP_CPCS)
238                 return (EINVAL);
239
240         /*
241          * Allocate our control block
242          */
243         sop = (struct sscop *)atm_allocate(&sscop_pool);
244         if (sop == NULL)
245                 return (ENOMEM);
246
247         sop->so_state = SOS_INST;
248         sop->so_connvc = cvp;
249         sop->so_toku = sdp_up->sd_toku;
250         sop->so_upper = sdp_up->sd_upper;
251
252         /*
253          * Store my token into service definition
254          */
255         sdp_me->sd_toku = sop;
256
257         /*
258          * Update and save input buffer headroom
259          */
260         HEADIN(cvp, sizeof(struct pdu_hdr), 0);
261         /* sop->so_headin = cvp->cvc_attr.headin; */
262
263         /*
264          * Pass instantiation down the stack
265          */
266         err = sdp_low->sd_inst(ssp + 1, cvp);
267         if (err) {
268                 /*
269                  * Lower layer instantiation failed, free our resources
270                  */
271                 atm_free((caddr_t)sop);
272                 return (err);
273         }
274
275         /*
276          * Link in connection block
277          */
278         LINK2TAIL(sop, struct sscop, sscop_head, so_next);
279         sscop_vccnt++;
280         sscop_stat.sos_connects++;
281
282         /*
283          * Save and update output buffer headroom
284          */
285         sop->so_headout = cvp->cvc_attr.headout;
286         HEADOUT(cvp, sizeof(struct pdu_hdr), 0);
287
288         /*
289          * Save lower layer's interface info
290          */
291         sop->so_lower = sdp_low->sd_lower;
292         sop->so_tokl = sdp_low->sd_toku;
293
294         /*
295          * Initialize version (until INIT received)
296          */
297         sop->so_vers = SSCOP_VERS_Q2110;
298
299         return (0);
300 }
301
302
303 /*
304  * Report Management Error
305  * 
306  * Called to report an error to the layer management entity.
307  *
308  * Arguments:
309  *      sop     pointer to sscop control block
310  *      code    error code
311  *
312  * Returns:
313  *      none
314  *
315  */
316 void
317 sscop_maa_error(struct sscop *sop, int code)
318 {
319         int             i;
320
321         /*
322          * Validate error code
323          */
324         if ((code < MAA_ERROR_MIN) ||
325             (code > MAA_ERROR_MAX))
326                 code = MAA_ERROR_INVAL;
327         i = code - MAA_ERROR_MIN;
328
329         /*
330          * Bump statistics counters
331          */
332         sscop_stat.sos_maa_error[i]++;
333
334         /*
335          * Log error message
336          */
337         if (sscop_maa_log[i] != 0) {
338                 struct vccb     *vcp = sop->so_connvc->cvc_vcc;
339                 struct atm_pif  *pip = vcp->vc_pif;
340
341                 log(LOG_ERR,
342                         "sscop_maa_error: intf=%s%d vpi=%d vci=%d code=%c state=%d\n",
343                         pip->pif_name, pip->pif_unit,
344                         vcp->vc_vpi, vcp->vc_vci, code, sop->so_state);
345         }
346 }
347
348
349 /*
350  * Abort an SSCOP connection
351  * 
352  * Called when an unrecoverable or "should never happen" error occurs.
353  * We log a message, send an END PDU to our peer and request the signalling
354  * manager to abort the connection.
355  *
356  * Arguments:
357  *      sop     pointer to sscop control block
358  *      msg     pointer to error message
359  *
360  * Returns:
361  *      none
362  *
363  */
364 void
365 sscop_abort(struct sscop *sop, char *msg)
366 {
367         Atm_connvc      *cvp = sop->so_connvc;
368
369         /*
370          * Log and count error
371          */
372         log(LOG_ERR, "%s", msg);
373         sscop_stat.sos_aborts++;
374
375         /*
376          * Send an END PDU as a courtesy to peer
377          */
378         sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
379
380         /*
381          * Set termination state
382          */
383         sop->so_state = SOS_TERM;
384
385         /*
386          * Flush all of our queues
387          */
388         sscop_xmit_drain(sop);
389         sscop_rcvr_drain(sop);
390
391         /*
392          * Tell Connection Manager to abort this connection
393          */
394         atm_cm_abort(cvp, &sscop_cause);
395 }
396