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