]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/ngatm/netnatm/msg/traffic.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / contrib / ngatm / netnatm / msg / traffic.c
1 /*
2  * Copyright (c) 2001-2003
3  *      Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4  *      All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * Author: Hartmut Brandt <harti@freebsd.org>
28  *
29  * $Begemot: libunimsg/netnatm/msg/traffic.c,v 1.4 2004/07/08 08:22:05 brandt Exp $
30  *
31  * Traffic classification
32  */
33
34 #include <netnatm/unimsg.h>
35 #include <netnatm/msg/unistruct.h>
36 #include <netnatm/msg/unimsglib.h>
37 #ifdef _KERNEL
38 #include <sys/systm.h>
39 #else
40 #include <stdio.h>
41 #endif
42
43 /*
44  * Try to set the parameters for the CPCS from the parameters of the
45  * connection.
46  */
47 enum {
48         T_CBR23 = 100, T_nrtVBR2_6_UBR12, T_rtVBR236, T_rtVBR2_6
49 };
50
51 static const u_int fmask = UNI_TRAFFIC_FPCR0_P | UNI_TRAFFIC_FPCR1_P |
52     UNI_TRAFFIC_FSCR0_P | UNI_TRAFFIC_FSCR1_P | UNI_TRAFFIC_FMBS0_P |
53     UNI_TRAFFIC_FMBS1_P | UNI_TRAFFIC_FABR1_P;
54 static const u_int bmask = UNI_TRAFFIC_BPCR0_P | UNI_TRAFFIC_BPCR1_P |
55     UNI_TRAFFIC_BSCR0_P | UNI_TRAFFIC_BSCR1_P | UNI_TRAFFIC_BMBS0_P |
56     UNI_TRAFFIC_BMBS1_P | UNI_TRAFFIC_BABR1_P;
57
58 static const u_int fcbr3 = UNI_TRAFFIC_FPCR0_P | UNI_TRAFFIC_FPCR1_P;
59 static const u_int bcbr3 = UNI_TRAFFIC_BPCR0_P | UNI_TRAFFIC_BPCR1_P;
60 static const u_int fvbr16 = UNI_TRAFFIC_FPCR1_P | UNI_TRAFFIC_FSCR1_P |
61     UNI_TRAFFIC_FMBS1_P;
62 static const u_int bvbr16 = UNI_TRAFFIC_BPCR1_P | UNI_TRAFFIC_BSCR1_P |
63     UNI_TRAFFIC_BMBS1_P;
64 static const u_int fvbr23 = UNI_TRAFFIC_FPCR1_P | UNI_TRAFFIC_FSCR0_P |
65     UNI_TRAFFIC_FMBS0_P;
66 static const u_int bvbr23 = UNI_TRAFFIC_BPCR1_P | UNI_TRAFFIC_BSCR0_P |
67     UNI_TRAFFIC_BMBS0_P;
68 static const u_int fvbr4 = UNI_TRAFFIC_FPCR0_P | UNI_TRAFFIC_FPCR1_P;
69 static const u_int bvbr4 = UNI_TRAFFIC_BPCR0_P | UNI_TRAFFIC_BPCR1_P;
70
71 int
72 uni_classify_traffic(const struct uni_ie_bearer *bearer,
73     const struct uni_ie_traffic *traffic,
74     enum uni_traffic_class *fclass, enum uni_traffic_class *bclass,
75     char *ebuf, size_t ebufsiz)
76 {
77         u_int tclass;
78         u_int ft, bt, be, ftag, btag;
79
80         /* classify */
81         switch (bearer->bclass) {
82
83           case UNI_BEARER_A:
84                 if (!(bearer->h.present & UNI_BEARER_ATC_P)) {
85                         tclass = T_CBR23;
86                         break;
87                 }
88                 switch (bearer->atc) {
89
90                   case UNI_BEARER_ATC_CBR1:
91                         tclass = UNI_TRAFFIC_CBR1;
92                         break;
93
94                   default:
95                         snprintf(ebuf, ebufsiz, "bad ATC=%#02x for BCOB-A",
96                             bearer->atc);
97                         return (-1);
98                 }
99                 break;
100
101           case UNI_BEARER_C:
102                 if (!(bearer->h.present & UNI_BEARER_ATC_P)) {
103                         tclass = T_nrtVBR2_6_UBR12;
104                         break;
105                 }
106                 switch (bearer->atc) {
107
108                   case UNI_BEARER_ATC_VBR1:
109                         tclass = UNI_TRAFFIC_rtVBR1;
110                         break;
111
112                   case UNI_BEARER_ATC_VBR:
113                         tclass = T_rtVBR236;
114                         break;
115
116                   case UNI_BEARER_ATC_NVBR1:
117                         tclass = UNI_TRAFFIC_nrtVBR1;
118                         break;
119
120                   case UNI_BEARER_ATC_ABR:
121                         tclass = UNI_TRAFFIC_ABR;
122                         break;
123
124                   default:
125                         snprintf(ebuf, ebufsiz, "bad ATC=%#02x for BCOB-C",
126                             bearer->atc);
127                         return (-1);
128                 }
129                 break;
130
131           case UNI_BEARER_X:
132                 if (!(bearer->h.present & UNI_BEARER_ATC_P)) {
133                         tclass = T_nrtVBR2_6_UBR12;
134                         break;
135                 }
136                 switch (bearer->atc) {
137
138                   case UNI_BEARER_ATC_CBR1:
139                         tclass = UNI_TRAFFIC_CBR1;
140                         break;
141
142                   case UNI_BEARER_ATC_CBR:
143                   case UNI_BEARER_ATCX_4:
144                   case UNI_BEARER_ATCX_6:
145                         tclass = T_CBR23;
146                         break;
147
148                   case UNI_BEARER_ATC_VBR1:
149                         tclass = UNI_TRAFFIC_rtVBR1;
150                         break;
151
152                   case UNI_BEARER_ATCX_1:
153                   case UNI_BEARER_ATC_VBR:
154                         tclass = T_rtVBR2_6;
155                         break;
156
157                   case UNI_BEARER_ATC_NVBR1:
158                         tclass = UNI_TRAFFIC_nrtVBR1;
159                         break;
160
161                   case UNI_BEARER_ATCX_0:
162                   case UNI_BEARER_ATCX_2:
163                   case UNI_BEARER_ATCX_8:
164                   case UNI_BEARER_ATC_NVBR:
165                         tclass = T_nrtVBR2_6_UBR12;
166                         break;
167
168                   case UNI_BEARER_ATC_ABR:
169                         tclass = UNI_TRAFFIC_ABR;
170                         break;
171
172                   default:
173                         snprintf(ebuf, ebufsiz, "bad ATC=%#02x for BCOB-X",
174                             bearer->atc);
175                         return (-1);
176                 }
177                 break;
178
179           case UNI_BEARER_TVP:
180                 snprintf(ebuf, ebufsiz, "unsupported bearer class tVP");
181                 return (-1);
182
183           default:
184                 snprintf(ebuf, ebufsiz, "bad bearer class %#02x",
185                     bearer->bclass);
186                 return (-1);
187         }
188
189         /*
190          * Now traffic IE
191          */
192         ft = traffic->h.present & fmask;
193         bt = traffic->h.present & bmask;
194         be = traffic->h.present & UNI_TRAFFIC_BEST_P;
195         ftag = (traffic->h.present & UNI_TRAFFIC_MOPT_P) && traffic->t.ftag;
196         btag = (traffic->h.present & UNI_TRAFFIC_MOPT_P) && traffic->t.btag;
197
198 #define NOBE(C)                                                         \
199         if (be) {                                                       \
200                 snprintf(ebuf, ebufsiz, "illegal BE for " C);           \
201                 return (-1);                                            \
202         }
203
204 #define NOFT(C)                                                         \
205         if (ftag) {                                                     \
206                 snprintf(ebuf, ebufsiz, "illegal forward tag in " C);   \
207                 return (-1);                                            \
208         }
209
210 #define NOBT(C)                                                         \
211         if (btag) {                                                     \
212                 snprintf(ebuf, ebufsiz, "illegal backward tag in " C);  \
213                 return (-1);                                            \
214         }
215
216 #define FBAD(C) do {                                                    \
217         snprintf(ebuf, ebufsiz, "bad forward CRs for " C);              \
218         return (-1);                                                    \
219     } while (0)
220
221 #define BBAD(C) do {                                                    \
222         snprintf(ebuf, ebufsiz, "bad backward CRs for " C);             \
223         return (-1);                                                    \
224     } while (0)
225
226         switch (tclass) {
227
228           case UNI_TRAFFIC_CBR1:
229                 NOBE("CBR.1");
230                 if (ft != UNI_TRAFFIC_FPCR1_P)
231                         FBAD("CBR.1");
232                 NOFT("CBR.1");
233                 if (bt != UNI_TRAFFIC_BPCR1_P)
234                         BBAD("CBR.1");
235                 NOBT("CBR.1");
236                 *fclass = *bclass = UNI_TRAFFIC_CBR1;
237                 break;
238
239           case T_CBR23:
240                 NOBE("CBR.2/3");
241                 if (ft == UNI_TRAFFIC_FPCR0_P) {
242                         *fclass = UNI_TRAFFIC_CBR2;
243                         NOFT("CBR.2");
244                 } else if (ft == fcbr3) {
245                         *fclass = UNI_TRAFFIC_CBR3;
246                         if (!ftag) {
247                                 snprintf(ebuf, ebufsiz, "need forward tagging for CBR.3");
248                                 return (-1);
249                         }
250                 } else
251                         FBAD("CBR.2/3");
252                 if (bt == UNI_TRAFFIC_BPCR0_P) {
253                         *bclass = UNI_TRAFFIC_CBR2;
254                         NOBT("CBR.2");
255                 } else if (bt == bcbr3) {
256                         *bclass = UNI_TRAFFIC_CBR3;
257                         if (!btag) {
258                                 snprintf(ebuf, ebufsiz, "need backward tagging for CBR.3");
259                                 return (-1);
260                         }
261                 } else
262                         BBAD("CBR.2/3");
263                 break;
264
265           case UNI_TRAFFIC_rtVBR1:
266                 NOBE("rtVBR.1");
267                 if (ft != fvbr16)
268                         FBAD("rtVBR.1");
269                 NOFT("rtVBR.1");
270                 if (bt != bvbr16)
271                         BBAD("rtVBR.1");
272                 NOBT("rtVBR.1");
273                 *fclass = *bclass = UNI_TRAFFIC_rtVBR1;
274                 break;
275
276           case T_rtVBR236:
277                 NOBE("rtVBR.2/3/6");
278                 if (ft == fvbr23) {
279                         if (ftag)
280                                 *fclass = UNI_TRAFFIC_rtVBR3;
281                         else
282                                 *fclass = UNI_TRAFFIC_rtVBR2;
283                 } else if (ft == fvbr16) {
284                         *fclass = UNI_TRAFFIC_rtVBR6;
285                         NOFT("rtVBR.6");
286                 } else
287                         FBAD("rtVBR.2/3/6");
288                 if (bt == bvbr23) {
289                         if (btag)
290                                 *bclass = UNI_TRAFFIC_rtVBR3;
291                         else
292                                 *bclass = UNI_TRAFFIC_rtVBR2;
293                 } else if (bt == bvbr16) {
294                         *bclass = UNI_TRAFFIC_rtVBR6;
295                         NOBT("rtVBR.6");
296                 } else
297                         BBAD("rtVBR.2/3/6");
298                 break;
299
300           case T_rtVBR2_6:
301                 NOBE("rtVBR.2-6");
302                 if (ft == fvbr23) {
303                         if (ftag)
304                                 *fclass = UNI_TRAFFIC_rtVBR3;
305                         else
306                                 *fclass = UNI_TRAFFIC_rtVBR2;
307                 } else if (ft == fvbr4) {
308                         *fclass = UNI_TRAFFIC_rtVBR4;
309                 } else if (ft == UNI_TRAFFIC_FPCR1_P) {
310                         *fclass = UNI_TRAFFIC_rtVBR5;
311                         NOFT("rtVBR.5");
312                 } else if (ft == fvbr16) {
313                         *fclass = UNI_TRAFFIC_rtVBR6;
314                         NOFT("rtVBR.6");
315                 } else
316                         FBAD("rtVBR.2-6");
317                 if (bt == bvbr23) {
318                         if (btag)
319                                 *bclass = UNI_TRAFFIC_rtVBR3;
320                         else
321                                 *bclass = UNI_TRAFFIC_rtVBR2;
322                 } else if (bt == bvbr4) {
323                         *bclass = UNI_TRAFFIC_rtVBR4;
324                 } else if (bt == UNI_TRAFFIC_BPCR1_P) {
325                         *bclass = UNI_TRAFFIC_rtVBR5;
326                         NOBT("rtVBR.5");
327                 } else if (bt == bvbr16) {
328                         *bclass = UNI_TRAFFIC_rtVBR6;
329                         NOBT("rtVBR.6");
330                 } else
331                         BBAD("rtVBR.2-6");
332                 break;
333
334           case UNI_TRAFFIC_nrtVBR1:
335                 NOBE("nrtVBR.1");
336                 if (ft != fvbr16)
337                         FBAD("nrtVBR.1");
338                 NOFT("nrtVBR.1");
339                 if (bt != bvbr16)
340                         BBAD("nrtVBR.1");
341                 NOBT("nrtVBR.1");
342                 *fclass = *bclass = UNI_TRAFFIC_nrtVBR1;
343                 break;
344
345           case T_nrtVBR2_6_UBR12:
346                 if (be) {
347                         if (ft != UNI_TRAFFIC_FPCR1_P)
348                                 FBAD("UBR.1/2");
349                         if (bt != UNI_TRAFFIC_BPCR1_P)
350                                 BBAD("UBR.1/2");
351                         if (ftag)
352                                 *fclass = UNI_TRAFFIC_UBR2;
353                         else
354                                 *fclass = UNI_TRAFFIC_UBR1;
355                         if (btag)
356                                 *bclass = UNI_TRAFFIC_UBR2;
357                         else
358                                 *bclass = UNI_TRAFFIC_UBR1;
359                         break;
360                 }
361                 if (ft == fvbr23) {
362                         if (ftag)
363                                 *fclass = UNI_TRAFFIC_nrtVBR3;
364                         else
365                                 *fclass = UNI_TRAFFIC_nrtVBR2;
366                 } else if (ft == fvbr4) {
367                         *fclass = UNI_TRAFFIC_nrtVBR4;
368                 } else if (ft == UNI_TRAFFIC_FPCR1_P) {
369                         *fclass = UNI_TRAFFIC_nrtVBR5;
370                         NOFT("nrtVBR.5");
371                 } else if (ft == fvbr16) {
372                         *fclass = UNI_TRAFFIC_nrtVBR6;
373                         NOFT("nrtVBR.6");
374                 } else
375                         FBAD("nrtVBR.2-6");
376                 if (bt == bvbr23) {
377                         if (btag)
378                                 *bclass = UNI_TRAFFIC_nrtVBR3;
379                         else
380                                 *bclass = UNI_TRAFFIC_nrtVBR2;
381                 } else if (bt == bvbr4) {
382                         *bclass = UNI_TRAFFIC_nrtVBR4;
383                 } else if (bt == UNI_TRAFFIC_BPCR1_P) {
384                         *bclass = UNI_TRAFFIC_nrtVBR5;
385                         NOBT("nrtVBR.5");
386                 } else if (bt == bvbr16) {
387                         *bclass = UNI_TRAFFIC_nrtVBR6;
388                         NOBT("nrtVBR.6");
389                 } else
390                         BBAD("nrtVBR.2-6");
391                 break;
392
393           case UNI_TRAFFIC_ABR:
394                 NOBE("ABR");
395                 if (ft != UNI_TRAFFIC_FPCR1_P)
396                         FBAD("ABR");
397                 if (bt != UNI_TRAFFIC_BPCR1_P)
398                         BBAD("ABR");
399                 NOFT("ABR");
400                 NOBT("ABR");
401                 *fclass = *bclass = UNI_TRAFFIC_ABR;
402                 break;
403         }
404
405         return (0);
406 }