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