* Remove (void) casts for discarded return values.
[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.6 2006/01/14 13:36:39 swildner 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(struct atm_time *tip)
186 {
187         struct spans    *spp;
188         spans_msg       *msg;
189         Atm_addr_pvc    *pvcp;
190         int             err;
191
192         /*
193          * Back-off to SPANS control block
194          */
195         spp = (struct spans *)
196                 ((caddr_t)tip - (int)(&((struct spans *)0)->sp_time));
197
198         ATM_DEBUG2("spans_timer: spp=%p,state=%d\n",
199                         spp, spp->sp_state);
200
201         /*
202          * Process timeout based on protocol state
203          */
204         switch (spp->sp_state) {
205
206         case SPANS_INIT:
207
208                 /*
209                  * Open signalling channel
210                  */
211                 spans_attr.nif = spp->sp_pif->pif_nif;
212
213                 spans_attr.aal.v.aal4.forward_max_SDU_size =
214                                 ATM_NIF_MTU;
215                 spans_attr.aal.v.aal4.backward_max_SDU_size =
216                                 ATM_NIF_MTU;
217                 spans_attr.aal.v.aal4.SSCS_type =
218                                 T_ATM_SSCS_SSCOP_UNREL;
219                 spans_attr.aal.v.aal4.mid_low = 0;
220                 spans_attr.aal.v.aal4.mid_high = 0;
221
222                 spans_attr.called.tag = T_ATM_PRESENT;
223                 spans_attr.called.addr.address_format = T_ATM_PVC_ADDR;
224                 spans_attr.called.addr.address_length =
225                         sizeof(Atm_addr_pvc);
226                 pvcp = (Atm_addr_pvc *)spans_attr.called.addr.address;
227                 ATM_PVC_SET_VPI(pvcp, SPANS_SIG_VPI);
228                 ATM_PVC_SET_VCI(pvcp, SPANS_SIG_VCI);
229                 spans_attr.called.subaddr.address_format = T_ATM_ABSENT;
230                 spans_attr.called.subaddr.address_length = 0;
231
232                 spans_attr.traffic.v.forward.PCR_all_traffic =
233                                 spp->sp_pif->pif_pcr;
234                 spans_attr.traffic.v.backward.PCR_all_traffic =
235                                 spp->sp_pif->pif_pcr;
236
237                 err = atm_cm_connect(&spans_endpt, spp, &spans_attr,
238                                 &spp->sp_conn);
239                 if (err) {
240                         log(LOG_CRIT, "spans: signalling channel setup failed\n");
241                         return;
242                 }
243
244                 /*
245                  * Signalling channel open, start probing
246                  */
247                 spp->sp_state = SPANS_PROBE;
248
249                 /* FALLTHRU */
250
251         case SPANS_PROBE:
252         case SPANS_ACTIVE:
253
254                 /*
255                  * Send out SPANS_STAT_REQ message
256                  */
257                 msg = (spans_msg *)atm_allocate(&spans_msgpool);
258                 if (msg == NULL) {
259                         /* Retry later if no memory */
260                         SPANS_TIMER(spp, SPANS_PROBE_ERR_WAIT);
261                         break;
262                 }
263                 msg->sm_vers = SPANS_VERS_1_0;
264                 msg->sm_type = SPANS_STAT_REQ;
265                 msg->sm_stat_req.streq_es_epoch = spp->sp_h_epoch;
266                 if (spans_send_msg(spp, msg)) {
267                         /* Retry later if send fails */
268                         SPANS_TIMER(spp, SPANS_PROBE_ERR_WAIT);
269                         atm_free(msg);
270                         break;
271                 }
272                 atm_free(msg);
273                 spp->sp_probe_ct++;
274
275                 /*
276                  * Check whether we're getting an answer to our probes
277                  */
278                 if (spp->sp_state == SPANS_ACTIVE &&
279                                 spp->sp_probe_ct > SPANS_PROBE_THRESH) {
280                         /*
281                          * Interface is down, notify VCC owners
282                          */
283                         spans_switch_reset(spp, SPANS_UNI_DOWN);
284
285                         /*
286                          * Set new state and increment host epoch so
287                          * switch knows we reset everyting.
288                          */
289                         spp->sp_state = SPANS_PROBE;
290                         spp->sp_h_epoch++;
291                         spp->sp_s_epoch = 0;
292                 }
293
294                 /*
295                  * Keep sending status requests
296                  */
297                 SPANS_TIMER(spp, SPANS_PROBE_INTERVAL);
298
299                 break;
300
301         case SPANS_DETACH:
302                 /*
303                  * Try to terminate the SPANS signalling PVC
304                  */
305                 err = atm_cm_release(spp->sp_conn, &spans_cause);
306                 if (err) {
307                         log(LOG_ERR, "spans: can't close signalling channel\n");
308                 }
309                 break;
310
311         default:
312                 log(LOG_ERR, "spans: timer state: spp=%p, state=%d\n",
313                         spp, spp->sp_state);
314         }
315 }
316
317
318 /*
319  * Process a SPANS VCC timeout
320  *
321  * Called when a previously scheduled SPANS VCCB timer expires.
322  * Processing will based on the current VCC state.
323  *
324  * Called at splnet.
325  *
326  * Arguments:
327  *      tip     pointer to vccb timer control block
328  *
329  * Returns:
330  *      none
331  *
332  */
333 void
334 spans_vctimer(struct atm_time *tip)
335 {
336         int                     err;
337         struct spans            *spp;
338         struct spans_vccb       *svp;
339
340         /*
341          * Get VCCB and SPANS control block addresses
342          */
343         svp = (struct spans_vccb *) ((caddr_t)tip -
344                         (int)(&((struct vccb *)0)->vc_time));
345         spp = (struct spans *)svp->sv_pif->pif_siginst;
346
347         ATM_DEBUG3("spans_vctimer: svp=%p, sstate=%d, ustate=%d\n",
348                         svp, svp->sv_sstate, svp->sv_ustate);
349
350         /*
351          * Process timeout based on protocol state
352          */
353         switch (svp->sv_sstate) {
354
355         case SPANS_VC_ABORT:
356                 /*
357                  * Kill the VCCB and notify the owner
358                  */
359                 err = spans_clear_vcc(spp, svp);
360                 break;
361
362         case SPANS_VC_FREE:
363                 /*
364                  * Free VCCB storage
365                  */
366                 svp->sv_ustate = VCCU_CLOSED;
367                 svp->sv_sstate = SPANS_VC_FREE;
368                 spans_free((struct vccb *)svp);
369                 break;
370
371         case SPANS_VC_POPEN:
372                 /*
373                  * Issued open request, but didn't get response.
374                  */
375                 if (svp->sv_retry < SV_MAX_RETRY) {
376                         /*
377                          * Retransmit the open request
378                          */
379                         err = spans_send_open_req(spp, svp);
380                         svp->sv_retry++;
381                         SPANS_VC_TIMER((struct vccb *) svp, SV_TIMEOUT);
382                 } else {
383                         /*
384                          * Retry limit exceeded--report the open failed
385                          */
386                         svp->sv_ustate = VCCU_CLOSED;
387                         svp->sv_sstate = SPANS_VC_FREE;
388                         svp->sv_connvc->cvc_attr.cause.tag =
389                                         T_ATM_PRESENT;
390                         svp->sv_connvc->cvc_attr.cause.v.coding_standard =
391                                         T_ATM_ITU_CODING;
392                         svp->sv_connvc->cvc_attr.cause.v.location =
393                                         T_ATM_LOC_USER;
394                         svp->sv_connvc->cvc_attr.cause.v.cause_value =
395                                         T_ATM_CAUSE_NO_USER_RESPONDING;
396                         KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
397                                         sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
398                         atm_cm_cleared(svp->sv_connvc);
399                 }
400                 break;
401
402         case SPANS_VC_CLOSE:
403                 /*
404                  * Issued close request, but didn't get response.
405                  */
406                 if (svp->sv_retry < SV_MAX_RETRY) {
407                         /*
408                          * Retransmit the close request
409                          */
410                         err = spans_send_close_req(spp, svp);
411                         svp->sv_retry++;
412                         SPANS_VC_TIMER((struct vccb *) svp, SV_TIMEOUT);
413                 } else {
414                         /*
415                          * Retry limit exceeded--just finish the close
416                          */
417                         svp->sv_sstate = SPANS_VC_FREE;
418                         svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
419                         svp->sv_connvc->cvc_attr.cause.v.coding_standard =
420                                         T_ATM_ITU_CODING;
421                         svp->sv_connvc->cvc_attr.cause.v.location =
422                                         T_ATM_LOC_USER;
423                         svp->sv_connvc->cvc_attr.cause.v.cause_value =
424                                         T_ATM_CAUSE_NO_USER_RESPONDING;
425                         KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
426                                         sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
427                         atm_cm_cleared(svp->sv_connvc);
428                 }
429                 break;
430
431         case SPANS_VC_ACTIVE:
432         case SPANS_VC_ACT_DOWN:
433                 /*
434                  * Shouldn't happen
435                  */
436                 log(LOG_ERR, "spans_vctimer: unexpected state %d\n",
437                                 svp->sv_sstate);
438                 break;
439
440         default:
441                 log(LOG_ERR, "spans: vctimer state: svp=%p, sstate=%d\n",
442                                 svp, svp->sv_sstate);
443         }
444 }
445
446
447 /*
448  * SPANS name routine
449  *
450  * Arguments:
451  *      tok     SPANS signalling channel token (ignored)
452  *
453  * Returns:
454  *      pointer to a string identifying the SPANS signalling manager
455  *
456  */
457 caddr_t
458 spans_getname(void *tok)
459 {
460         return("SPANS");
461 }
462
463
464 /*
465  * Process a VCC connection notification
466  *
467  * Should never be called
468  *
469  * Arguments:
470  *      tok     user's connection token (SPANS protocol block)
471  *
472  * Returns:
473  *      none
474  *
475  */
476 void
477 spans_connected(void *tok)
478 {
479         struct spans            *spp = (struct spans *)tok;
480
481         ATM_DEBUG2("spans_connected: spp=%p,state=%d\n",
482                         spp, spp->sp_state);
483
484         /*
485          * Connected routine shouldn't ever get called for a PVC
486          */
487         log(LOG_ERR, "spans: connected function called, tok=%p\n", spp);
488 }
489
490
491 /*
492  * Process a VCC close notification
493  *
494  * Called when the SPANS signalling channel is closed
495  *
496  * Arguments:
497  *      tok     user's connection token (spans protocol block)
498  *      cp      pointer to cause structure
499  *
500  * Returns:
501  *      none
502  *
503  */
504 void
505 spans_cleared(void *tok, struct t_atm_cause *cp)
506 {
507         struct spans    *spp = (struct spans *)tok;
508
509         /*
510          * VCC has been closed.
511          */
512         log(LOG_ERR, "spans: signalling channel closed\n");
513         SPANS_CANCEL(spp);
514         spp->sp_conn = 0;
515 }
516
517
518 /*
519  * SPANS CPCS data handler
520  *
521  * This is the module which receives data on the SPANS signalling
522  * channel.  Processing is based on the indication received from the
523  * AAL and the protocol state.
524  *
525  * Arguments:
526  *      tok     session token (pointer to spans protocol control block)
527  *      m       pointer to buffer with data
528  *
529  * Returns:
530  *      none
531  *
532  */
533 void
534 spans_cpcs_data(void *tok, KBuffer *m)
535 {
536         struct spans    *spp = tok;
537
538         ATM_DEBUG3("spans_cpcs_data: spp=%p,state=%d,m=%p,\n",
539                         spp, spp->sp_state, m);
540
541         /*
542          * Process data
543          */
544         spans_rcv_msg(spp, m);
545 }