Do you think /sys/netproto needs to use __P() prototypes?
[dragonfly.git] / sys / netproto / atm / spans / spans_proto.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/spans/spans_proto.c,v 1.4 1999/08/28 00:48:51 peter Exp $
27  *      @(#) $DragonFly: src/sys/netproto/atm/spans/spans_proto.c,v 1.5 2003/08/23 10:06:22 rob Exp $
28  */
29
30 /*
31  * SPANS Signalling Manager
32  * ---------------------------
33  *
34  * SPANS protocol processing module.
35  *
36  */
37
38 #include <netproto/atm/kern_include.h>
39
40 #include "spans_xdr.h"
41 #include "spans_var.h"
42
43 /*
44  * Internal functions
45  */
46 caddr_t spans_getname (void *);
47 void    spans_connected (void *);
48 void    spans_cleared (void *, struct t_atm_cause *);
49 void    spans_cpcs_data (void *, KBuffer *);
50
51
52 /*
53  * ATM endpoint for SPANS signalling channel
54  */
55 static Atm_endpoint     spans_endpt = {
56         NULL,                   /* ep_next */
57         ENDPT_SPANS_SIG,        /* ep_id */
58         NULL,                   /* ep_ioctl */
59         spans_getname,          /* ep_getname */
60         spans_connected,        /* ep_connected */
61         spans_cleared,          /* ep_cleared */
62         NULL,                   /* ep_incoming */
63         NULL,                   /* ep_addparty */
64         NULL,                   /* ep_dropparty */
65         NULL,                   /* ep_cpcs_ctl */
66         spans_cpcs_data,        /* ep_cpcs_data */
67         NULL,                   /* ep_saal_ctl */
68         NULL,                   /* ep_saal_data */
69         NULL,                   /* ep_sscop_ctl */
70         NULL                    /* ep_sscop_data */
71 };
72
73
74 /*
75  * ATM connection attributes for UNI signalling channel
76  */
77 static Atm_attributes   spans_attr = {
78         NULL,                           /* nif */
79         CMAPI_CPCS,                     /* api */
80         0,                              /* api_init */
81         0,                              /* headin */
82         0,                              /* headout */
83         {                               /* aal */
84                 T_ATM_PRESENT,          /* aal.tag */
85                 ATM_AAL3_4              /* aal.aal_type */
86         },
87         {                               /* traffic */
88                 T_ATM_PRESENT,          /* traffic.tag */
89                 {                       /* traffic.v */
90                         {               /* traffic.v.forward */
91                                 T_ATM_ABSENT,   /* PCR_high */
92                                 0,              /* PCR_all */
93                                 T_ATM_ABSENT,   /* SCR_high */
94                                 T_ATM_ABSENT,   /* SCR_all */
95                                 T_ATM_ABSENT,   /* MBS_high */
96                                 T_ATM_ABSENT,   /* MBS_all */
97                                 T_NO,           /* tagging */
98                         },
99                         {               /* traffic.v.backward */
100                                 T_ATM_ABSENT,   /* PCR_high */
101                                 0,              /* PCR_all */
102                                 T_ATM_ABSENT,   /* SCR_high */
103                                 T_ATM_ABSENT,   /* SCR_all */
104                                 T_ATM_ABSENT,   /* MBS_high */
105                                 T_ATM_ABSENT,   /* MBS_all */
106                                 T_NO,           /* tagging */
107                         },
108                         T_YES,          /* best_effort */
109                 }
110         },
111         {                               /* bearer */
112                 T_ATM_PRESENT,          /* bearer.tag */
113                 {                       /* bearer.v */
114                         T_ATM_CLASS_X,          /* class */
115                         T_ATM_NULL,             /* traffic_type */
116                         T_ATM_NO_END_TO_END,    /* timing_req */
117                         T_NO,                   /* clipping */
118                         T_ATM_1_TO_1,           /* conn_conf */
119                 }
120         },
121         {                               /* bhli */
122                 T_ATM_ABSENT,           /* bhli.tag */
123         },
124         {                               /* blli */
125                 T_ATM_ABSENT,           /* blli.tag_l2 */
126                 T_ATM_ABSENT,           /* blli.tag_l3 */
127         },
128         {                               /* llc */
129                 T_ATM_ABSENT,           /* llc.tag */
130         },
131         {                               /* called */
132                 T_ATM_PRESENT,          /* called.tag */
133         },
134         {                               /* calling */
135                 T_ATM_ABSENT,           /* calling.tag */
136         },
137         {                               /* qos */
138                 T_ATM_PRESENT,          /* qos.tag */
139                 {                       /* qos.v */
140                         T_ATM_NETWORK_CODING,   /* coding_standard */
141                         {                       /* qos.v.forward */
142                                 T_ATM_QOS_CLASS_0,      /* class */
143                         },
144                         {                       /* qos.v.backward */
145                                 T_ATM_QOS_CLASS_0,      /* class */
146                         }
147                 }
148         },
149         {                               /* transit */
150                 T_ATM_ABSENT,           /* transit.tag */
151         },
152         {                               /* cause */
153                 T_ATM_ABSENT,           /* cause.tag */
154         }
155 };
156
157
158 /*
159  * SPANS cause structre
160  */
161 struct t_atm_cause spans_cause = {
162         T_ATM_ITU_CODING,               /* coding_standard */
163         T_ATM_LOC_USER,                 /* location */
164         T_ATM_CAUSE_UNSPECIFIED_NORMAL, /* cause_value */
165         { 0, 0, 0, 0 }                  /* diagnostics */
166 };
167
168
169 /*
170  * Process a SPANS timeout
171  *
172  * Called when a previously scheduled spans control block timer expires.
173  * Processing will based on the current SPANS state.
174  *
175  * Called at splnet.
176  *
177  * Arguments:
178  *      tip     pointer to spans timer control block
179  *
180  * Returns:
181  *      none
182  *
183  */
184 void
185 spans_timer(tip)
186         struct atm_time *tip;
187 {
188         struct spans    *spp;
189         spans_msg       *msg;
190         Atm_addr_pvc    *pvcp;
191         int             err;
192
193         /*
194          * Back-off to SPANS control block
195          */
196         spp = (struct spans *)
197                 ((caddr_t)tip - (int)(&((struct spans *)0)->sp_time));
198
199         ATM_DEBUG2("spans_timer: spp=%p,state=%d\n",
200                         spp, spp->sp_state);
201
202         /*
203          * Process timeout based on protocol state
204          */
205         switch (spp->sp_state) {
206
207         case SPANS_INIT:
208
209                 /*
210                  * Open signalling channel
211                  */
212                 spans_attr.nif = spp->sp_pif->pif_nif;
213
214                 spans_attr.aal.v.aal4.forward_max_SDU_size =
215                                 ATM_NIF_MTU;
216                 spans_attr.aal.v.aal4.backward_max_SDU_size =
217                                 ATM_NIF_MTU;
218                 spans_attr.aal.v.aal4.SSCS_type =
219                                 T_ATM_SSCS_SSCOP_UNREL;
220                 spans_attr.aal.v.aal4.mid_low = 0;
221                 spans_attr.aal.v.aal4.mid_high = 0;
222
223                 spans_attr.called.tag = T_ATM_PRESENT;
224                 spans_attr.called.addr.address_format = T_ATM_PVC_ADDR;
225                 spans_attr.called.addr.address_length =
226                         sizeof(Atm_addr_pvc);
227                 pvcp = (Atm_addr_pvc *)spans_attr.called.addr.address;
228                 ATM_PVC_SET_VPI(pvcp, SPANS_SIG_VPI);
229                 ATM_PVC_SET_VCI(pvcp, SPANS_SIG_VCI);
230                 spans_attr.called.subaddr.address_format = T_ATM_ABSENT;
231                 spans_attr.called.subaddr.address_length = 0;
232
233                 spans_attr.traffic.v.forward.PCR_all_traffic =
234                                 spp->sp_pif->pif_pcr;
235                 spans_attr.traffic.v.backward.PCR_all_traffic =
236                                 spp->sp_pif->pif_pcr;
237
238                 err = atm_cm_connect(&spans_endpt, spp, &spans_attr,
239                                 &spp->sp_conn);
240                 if (err) {
241                         log(LOG_CRIT, "spans: signalling channel setup failed\n");
242                         return;
243                 }
244
245                 /*
246                  * Signalling channel open, start probing
247                  */
248                 spp->sp_state = SPANS_PROBE;
249
250                 /* FALLTHRU */
251
252         case SPANS_PROBE:
253         case SPANS_ACTIVE:
254
255                 /*
256                  * Send out SPANS_STAT_REQ message
257                  */
258                 msg = (spans_msg *)atm_allocate(&spans_msgpool);
259                 if (msg == NULL) {
260                         /* Retry later if no memory */
261                         SPANS_TIMER(spp, SPANS_PROBE_ERR_WAIT);
262                         break;
263                 }
264                 msg->sm_vers = SPANS_VERS_1_0;
265                 msg->sm_type = SPANS_STAT_REQ;
266                 msg->sm_stat_req.streq_es_epoch = spp->sp_h_epoch;
267                 if (spans_send_msg(spp, msg)) {
268                         /* Retry later if send fails */
269                         SPANS_TIMER(spp, SPANS_PROBE_ERR_WAIT);
270                         atm_free(msg);
271                         break;
272                 }
273                 atm_free(msg);
274                 spp->sp_probe_ct++;
275
276                 /*
277                  * Check whether we're getting an answer to our probes
278                  */
279                 if (spp->sp_state == SPANS_ACTIVE &&
280                                 spp->sp_probe_ct > SPANS_PROBE_THRESH) {
281                         /*
282                          * Interface is down, notify VCC owners
283                          */
284                         spans_switch_reset(spp, SPANS_UNI_DOWN);
285
286                         /*
287                          * Set new state and increment host epoch so
288                          * switch knows we reset everyting.
289                          */
290                         spp->sp_state = SPANS_PROBE;
291                         spp->sp_h_epoch++;
292                         spp->sp_s_epoch = 0;
293                 }
294
295                 /*
296                  * Keep sending status requests
297                  */
298                 SPANS_TIMER(spp, SPANS_PROBE_INTERVAL);
299
300                 break;
301
302         case SPANS_DETACH:
303                 /*
304                  * Try to terminate the SPANS signalling PVC
305                  */
306                 err = atm_cm_release(spp->sp_conn, &spans_cause);
307                 if (err) {
308                         log(LOG_ERR, "spans: can't close signalling channel\n");
309                 }
310                 break;
311
312         default:
313                 log(LOG_ERR, "spans: timer state: spp=%p, state=%d\n",
314                         spp, spp->sp_state);
315         }
316 }
317
318
319 /*
320  * Process a SPANS VCC timeout
321  *
322  * Called when a previously scheduled SPANS VCCB timer expires.
323  * Processing will based on the current VCC state.
324  *
325  * Called at splnet.
326  *
327  * Arguments:
328  *      tip     pointer to vccb timer control block
329  *
330  * Returns:
331  *      none
332  *
333  */
334 void
335 spans_vctimer(tip)
336         struct atm_time *tip;
337 {
338         int                     err;
339         struct spans            *spp;
340         struct spans_vccb       *svp;
341
342         /*
343          * Get VCCB and SPANS control block addresses
344          */
345         svp = (struct spans_vccb *) ((caddr_t)tip -
346                         (int)(&((struct vccb *)0)->vc_time));
347         spp = (struct spans *)svp->sv_pif->pif_siginst;
348
349         ATM_DEBUG3("spans_vctimer: svp=%p, sstate=%d, ustate=%d\n",
350                         svp, svp->sv_sstate, svp->sv_ustate);
351
352         /*
353          * Process timeout based on protocol state
354          */
355         switch (svp->sv_sstate) {
356
357         case SPANS_VC_ABORT:
358                 /*
359                  * Kill the VCCB and notify the owner
360                  */
361                 err = spans_clear_vcc(spp, svp);
362                 break;
363
364         case SPANS_VC_FREE:
365                 /*
366                  * Free VCCB storage
367                  */
368                 svp->sv_ustate = VCCU_CLOSED;
369                 svp->sv_sstate = SPANS_VC_FREE;
370                 spans_free((struct vccb *)svp);
371                 break;
372
373         case SPANS_VC_POPEN:
374                 /*
375                  * Issued open request, but didn't get response.
376                  */
377                 if (svp->sv_retry < SV_MAX_RETRY) {
378                         /*
379                          * Retransmit the open request
380                          */
381                         err = spans_send_open_req(spp, svp);
382                         svp->sv_retry++;
383                         SPANS_VC_TIMER((struct vccb *) svp, SV_TIMEOUT);
384                 } else {
385                         /*
386                          * Retry limit exceeded--report the open failed
387                          */
388                         svp->sv_ustate = VCCU_CLOSED;
389                         svp->sv_sstate = SPANS_VC_FREE;
390                         svp->sv_connvc->cvc_attr.cause.tag =
391                                         T_ATM_PRESENT;
392                         svp->sv_connvc->cvc_attr.cause.v.coding_standard =
393                                         T_ATM_ITU_CODING;
394                         svp->sv_connvc->cvc_attr.cause.v.location =
395                                         T_ATM_LOC_USER;
396                         svp->sv_connvc->cvc_attr.cause.v.cause_value =
397                                         T_ATM_CAUSE_NO_USER_RESPONDING;
398                         KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
399                                         sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
400                         atm_cm_cleared(svp->sv_connvc);
401                 }
402                 break;
403
404         case SPANS_VC_CLOSE:
405                 /*
406                  * Issued close request, but didn't get response.
407                  */
408                 if (svp->sv_retry < SV_MAX_RETRY) {
409                         /*
410                          * Retransmit the close request
411                          */
412                         err = spans_send_close_req(spp, svp);
413                         svp->sv_retry++;
414                         SPANS_VC_TIMER((struct vccb *) svp, SV_TIMEOUT);
415                 } else {
416                         /*
417                          * Retry limit exceeded--just finish the close
418                          */
419                         svp->sv_sstate = SPANS_VC_FREE;
420                         svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
421                         svp->sv_connvc->cvc_attr.cause.v.coding_standard =
422                                         T_ATM_ITU_CODING;
423                         svp->sv_connvc->cvc_attr.cause.v.location =
424                                         T_ATM_LOC_USER;
425                         svp->sv_connvc->cvc_attr.cause.v.cause_value =
426                                         T_ATM_CAUSE_NO_USER_RESPONDING;
427                         KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
428                                         sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
429                         atm_cm_cleared(svp->sv_connvc);
430                 }
431                 break;
432
433         case SPANS_VC_ACTIVE:
434         case SPANS_VC_ACT_DOWN:
435                 /*
436                  * Shouldn't happen
437                  */
438                 log(LOG_ERR, "spans_vctimer: unexpected state %d\n",
439                                 svp->sv_sstate);
440                 break;
441
442         default:
443                 log(LOG_ERR, "spans: vctimer state: svp=%p, sstate=%d\n",
444                                 svp, svp->sv_sstate);
445         }
446 }
447
448
449 /*
450  * SPANS name routine
451  *
452  * Arguments:
453  *      tok     SPANS signalling channel token (ignored)
454  *
455  * Returns:
456  *      pointer to a string identifying the SPANS signalling manager
457  *
458  */
459 caddr_t
460 spans_getname(tok)
461         void            *tok;
462 {
463         return("SPANS");
464 }
465
466
467 /*
468  * Process a VCC connection notification
469  *
470  * Should never be called
471  *
472  * Arguments:
473  *      tok     user's connection token (SPANS protocol block)
474  *
475  * Returns:
476  *      none
477  *
478  */
479 void
480 spans_connected(tok)
481         void            *tok;
482 {
483         struct spans            *spp = (struct spans *)tok;
484
485         ATM_DEBUG2("spans_connected: spp=%p,state=%d\n",
486                         spp, spp->sp_state);
487
488         /*
489          * Connected routine shouldn't ever get called for a PVC
490          */
491         log(LOG_ERR, "spans: connected function called, tok=%p\n", spp);
492 }
493
494
495 /*
496  * Process a VCC close notification
497  *
498  * Called when the SPANS signalling channel is closed
499  *
500  * Arguments:
501  *      tok     user's connection token (spans protocol block)
502  *      cp      pointer to cause structure
503  *
504  * Returns:
505  *      none
506  *
507  */
508 void
509 spans_cleared(tok, cp)
510         void                    *tok;
511         struct t_atm_cause      *cp;
512 {
513         struct spans    *spp = (struct spans *)tok;
514
515         /*
516          * VCC has been closed.
517          */
518         log(LOG_ERR, "spans: signalling channel closed\n");
519         SPANS_CANCEL(spp);
520         spp->sp_conn = 0;
521 }
522
523
524 /*
525  * SPANS CPCS data handler
526  *
527  * This is the module which receives data on the SPANS signalling
528  * channel.  Processing is based on the indication received from the
529  * AAL and the protocol state.
530  *
531  * Arguments:
532  *      tok     session token (pointer to spans protocol control block)
533  *      m       pointer to buffer with data
534  *
535  * Returns:
536  *      none
537  *
538  */
539 void
540 spans_cpcs_data(tok, m)
541         void    *tok;
542         KBuffer *m;
543 {
544         struct spans    *spp = tok;
545
546         ATM_DEBUG3("spans_cpcs_data: spp=%p,state=%d,m=%p,\n",
547                         spp, spp->sp_state, m);
548
549         /*
550          * Process data
551          */
552         spans_rcv_msg(spp, m);
553 }