1121934Sharti/*
2121934Sharti * Copyright (c) 2001-2003
3121934Sharti *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4121934Sharti * 	All rights reserved.
5121934Sharti *
6121934Sharti * Redistribution and use in source and binary forms, with or without
7121934Sharti * modification, are permitted provided that the following conditions
8121934Sharti * are met:
9121934Sharti * 1. Redistributions of source code must retain the above copyright
10121934Sharti *    notice, this list of conditions and the following disclaimer.
11121934Sharti * 2. Redistributions in binary form must reproduce the above copyright
12121934Sharti *    notice, this list of conditions and the following disclaimer in the
13121934Sharti *    documentation and/or other materials provided with the distribution.
14121934Sharti *
15121934Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16121934Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17121934Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18121934Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19121934Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20121934Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21121934Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22121934Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23121934Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24121934Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25121934Sharti * SUCH DAMAGE.
26121934Sharti *
27121934Sharti * Author: Hartmut Brandt <harti@freebsd.org>
28121934Sharti *
29131826Sharti * $Begemot: libunimsg/netnatm/msg/traffic.c,v 1.4 2004/07/08 08:22:05 brandt Exp $
30121934Sharti *
31121934Sharti * Traffic classification
32121934Sharti */
33121934Sharti
34121934Sharti#include <netnatm/unimsg.h>
35121934Sharti#include <netnatm/msg/unistruct.h>
36121934Sharti#include <netnatm/msg/unimsglib.h>
37121934Sharti#ifdef _KERNEL
38121934Sharti#include <sys/systm.h>
39121934Sharti#else
40121934Sharti#include <stdio.h>
41121934Sharti#endif
42121934Sharti
43121934Sharti/*
44121934Sharti * Try to set the parameters for the CPCS from the parameters of the
45121934Sharti * connection.
46121934Sharti */
47121934Shartienum {
48121934Sharti	T_CBR23 = 100, T_nrtVBR2_6_UBR12, T_rtVBR236, T_rtVBR2_6
49121934Sharti};
50121934Sharti
51121934Shartistatic const u_int fmask = UNI_TRAFFIC_FPCR0_P | UNI_TRAFFIC_FPCR1_P |
52121934Sharti    UNI_TRAFFIC_FSCR0_P | UNI_TRAFFIC_FSCR1_P | UNI_TRAFFIC_FMBS0_P |
53121934Sharti    UNI_TRAFFIC_FMBS1_P | UNI_TRAFFIC_FABR1_P;
54121934Shartistatic const u_int bmask = UNI_TRAFFIC_BPCR0_P | UNI_TRAFFIC_BPCR1_P |
55121934Sharti    UNI_TRAFFIC_BSCR0_P | UNI_TRAFFIC_BSCR1_P | UNI_TRAFFIC_BMBS0_P |
56121934Sharti    UNI_TRAFFIC_BMBS1_P | UNI_TRAFFIC_BABR1_P;
57121934Sharti
58121934Shartistatic const u_int fcbr3 = UNI_TRAFFIC_FPCR0_P | UNI_TRAFFIC_FPCR1_P;
59121934Shartistatic const u_int bcbr3 = UNI_TRAFFIC_BPCR0_P | UNI_TRAFFIC_BPCR1_P;
60121934Shartistatic const u_int fvbr16 = UNI_TRAFFIC_FPCR1_P | UNI_TRAFFIC_FSCR1_P |
61121934Sharti    UNI_TRAFFIC_FMBS1_P;
62121934Shartistatic const u_int bvbr16 = UNI_TRAFFIC_BPCR1_P | UNI_TRAFFIC_BSCR1_P |
63121934Sharti    UNI_TRAFFIC_BMBS1_P;
64121934Shartistatic const u_int fvbr23 = UNI_TRAFFIC_FPCR1_P | UNI_TRAFFIC_FSCR0_P |
65121934Sharti    UNI_TRAFFIC_FMBS0_P;
66121934Shartistatic const u_int bvbr23 = UNI_TRAFFIC_BPCR1_P | UNI_TRAFFIC_BSCR0_P |
67121934Sharti    UNI_TRAFFIC_BMBS0_P;
68121934Shartistatic const u_int fvbr4 = UNI_TRAFFIC_FPCR0_P | UNI_TRAFFIC_FPCR1_P;
69121934Shartistatic const u_int bvbr4 = UNI_TRAFFIC_BPCR0_P | UNI_TRAFFIC_BPCR1_P;
70121934Sharti
71121934Shartiint
72121934Shartiuni_classify_traffic(const struct uni_ie_bearer *bearer,
73121934Sharti    const struct uni_ie_traffic *traffic,
74121934Sharti    enum uni_traffic_class *fclass, enum uni_traffic_class *bclass,
75121934Sharti    char *ebuf, size_t ebufsiz)
76121934Sharti{
77121934Sharti	u_int tclass;
78121934Sharti	u_int ft, bt, be, ftag, btag;
79121934Sharti
80121934Sharti	/* classify */
81121934Sharti	switch (bearer->bclass) {
82121934Sharti
83121934Sharti	  case UNI_BEARER_A:
84121934Sharti		if (!(bearer->h.present & UNI_BEARER_ATC_P)) {
85121934Sharti			tclass = T_CBR23;
86121934Sharti			break;
87121934Sharti		}
88121934Sharti		switch (bearer->atc) {
89121934Sharti
90121934Sharti		  case UNI_BEARER_ATC_CBR1:
91121934Sharti			tclass = UNI_TRAFFIC_CBR1;
92121934Sharti			break;
93121934Sharti
94121934Sharti		  default:
95121934Sharti			snprintf(ebuf, ebufsiz, "bad ATC=%#02x for BCOB-A",
96121934Sharti			    bearer->atc);
97121934Sharti			return (-1);
98121934Sharti		}
99121934Sharti		break;
100121934Sharti
101121934Sharti	  case UNI_BEARER_C:
102121934Sharti		if (!(bearer->h.present & UNI_BEARER_ATC_P)) {
103121934Sharti			tclass = T_nrtVBR2_6_UBR12;
104121934Sharti			break;
105121934Sharti		}
106121934Sharti		switch (bearer->atc) {
107121934Sharti
108121934Sharti		  case UNI_BEARER_ATC_VBR1:
109121934Sharti			tclass = UNI_TRAFFIC_rtVBR1;
110121934Sharti			break;
111121934Sharti
112121934Sharti		  case UNI_BEARER_ATC_VBR:
113121934Sharti			tclass = T_rtVBR236;
114121934Sharti			break;
115121934Sharti
116121934Sharti		  case UNI_BEARER_ATC_NVBR1:
117121934Sharti			tclass = UNI_TRAFFIC_nrtVBR1;
118121934Sharti			break;
119121934Sharti
120121934Sharti		  case UNI_BEARER_ATC_ABR:
121121934Sharti			tclass = UNI_TRAFFIC_ABR;
122121934Sharti			break;
123121934Sharti
124121934Sharti		  default:
125121934Sharti			snprintf(ebuf, ebufsiz, "bad ATC=%#02x for BCOB-C",
126121934Sharti			    bearer->atc);
127121934Sharti			return (-1);
128121934Sharti		}
129121934Sharti		break;
130121934Sharti
131121934Sharti	  case UNI_BEARER_X:
132121934Sharti		if (!(bearer->h.present & UNI_BEARER_ATC_P)) {
133121934Sharti			tclass = T_nrtVBR2_6_UBR12;
134121934Sharti			break;
135121934Sharti		}
136121934Sharti		switch (bearer->atc) {
137121934Sharti
138121934Sharti		  case UNI_BEARER_ATC_CBR1:
139121934Sharti			tclass = UNI_TRAFFIC_CBR1;
140121934Sharti			break;
141121934Sharti
142121934Sharti		  case UNI_BEARER_ATC_CBR:
143121934Sharti		  case UNI_BEARER_ATCX_4:
144121934Sharti		  case UNI_BEARER_ATCX_6:
145121934Sharti			tclass = T_CBR23;
146121934Sharti			break;
147121934Sharti
148121934Sharti		  case UNI_BEARER_ATC_VBR1:
149121934Sharti			tclass = UNI_TRAFFIC_rtVBR1;
150121934Sharti			break;
151121934Sharti
152121934Sharti		  case UNI_BEARER_ATCX_1:
153121934Sharti		  case UNI_BEARER_ATC_VBR:
154121934Sharti			tclass = T_rtVBR2_6;
155121934Sharti			break;
156121934Sharti
157121934Sharti		  case UNI_BEARER_ATC_NVBR1:
158121934Sharti			tclass = UNI_TRAFFIC_nrtVBR1;
159121934Sharti			break;
160121934Sharti
161121934Sharti		  case UNI_BEARER_ATCX_0:
162121934Sharti		  case UNI_BEARER_ATCX_2:
163121934Sharti		  case UNI_BEARER_ATCX_8:
164121934Sharti		  case UNI_BEARER_ATC_NVBR:
165121934Sharti			tclass = T_nrtVBR2_6_UBR12;
166121934Sharti			break;
167121934Sharti
168121934Sharti		  case UNI_BEARER_ATC_ABR:
169121934Sharti			tclass = UNI_TRAFFIC_ABR;
170121934Sharti			break;
171121934Sharti
172121934Sharti		  default:
173121934Sharti			snprintf(ebuf, ebufsiz, "bad ATC=%#02x for BCOB-X",
174121934Sharti			    bearer->atc);
175121934Sharti			return (-1);
176121934Sharti		}
177121934Sharti		break;
178121934Sharti
179121934Sharti	  case UNI_BEARER_TVP:
180121934Sharti		snprintf(ebuf, ebufsiz, "unsupported bearer class tVP");
181121934Sharti		return (-1);
182121934Sharti
183121934Sharti	  default:
184121934Sharti		snprintf(ebuf, ebufsiz, "bad bearer class %#02x",
185121934Sharti		    bearer->bclass);
186121934Sharti		return (-1);
187121934Sharti	}
188121934Sharti
189121934Sharti	/*
190121934Sharti	 * Now traffic IE
191121934Sharti	 */
192121934Sharti	ft = traffic->h.present & fmask;
193121934Sharti	bt = traffic->h.present & bmask;
194121934Sharti	be = traffic->h.present & UNI_TRAFFIC_BEST_P;
195121934Sharti	ftag = (traffic->h.present & UNI_TRAFFIC_MOPT_P) && traffic->t.ftag;
196121934Sharti	btag = (traffic->h.present & UNI_TRAFFIC_MOPT_P) && traffic->t.btag;
197121934Sharti
198121934Sharti#define NOBE(C)								\
199121934Sharti	if (be) {							\
200121934Sharti		snprintf(ebuf, ebufsiz, "illegal BE for " C);		\
201121934Sharti		return (-1);						\
202121934Sharti	}
203121934Sharti
204121934Sharti#define NOFT(C)								\
205121934Sharti	if (ftag) {							\
206121934Sharti		snprintf(ebuf, ebufsiz, "illegal forward tag in " C);	\
207121934Sharti		return (-1);						\
208121934Sharti	}
209121934Sharti
210121934Sharti#define NOBT(C)								\
211121934Sharti	if (btag) {							\
212121934Sharti		snprintf(ebuf, ebufsiz, "illegal backward tag in " C);	\
213121934Sharti		return (-1);						\
214121934Sharti	}
215121934Sharti
216121934Sharti#define FBAD(C) do {							\
217121934Sharti	snprintf(ebuf, ebufsiz, "bad forward CRs for " C);		\
218121934Sharti	return (-1);							\
219121934Sharti    } while (0)
220121934Sharti
221121934Sharti#define BBAD(C) do {							\
222121934Sharti	snprintf(ebuf, ebufsiz, "bad backward CRs for " C);		\
223121934Sharti	return (-1);							\
224121934Sharti    } while (0)
225121934Sharti
226121934Sharti	switch (tclass) {
227121934Sharti
228121934Sharti	  case UNI_TRAFFIC_CBR1:
229121934Sharti		NOBE("CBR.1");
230121934Sharti		if (ft != UNI_TRAFFIC_FPCR1_P)
231121934Sharti			FBAD("CBR.1");
232121934Sharti		NOFT("CBR.1");
233121934Sharti		if (bt != UNI_TRAFFIC_BPCR1_P)
234121934Sharti			BBAD("CBR.1");
235121934Sharti		NOBT("CBR.1");
236121934Sharti		*fclass = *bclass = UNI_TRAFFIC_CBR1;
237121934Sharti		break;
238121934Sharti
239121934Sharti	  case T_CBR23:
240121934Sharti		NOBE("CBR.2/3");
241121934Sharti		if (ft == UNI_TRAFFIC_FPCR0_P) {
242121934Sharti			*fclass = UNI_TRAFFIC_CBR2;
243121934Sharti			NOFT("CBR.2");
244121934Sharti		} else if (ft == fcbr3) {
245121934Sharti			*fclass = UNI_TRAFFIC_CBR3;
246121934Sharti			if (!ftag) {
247121934Sharti				snprintf(ebuf, ebufsiz, "need forward tagging for CBR.3");
248121934Sharti				return (-1);
249121934Sharti			}
250121934Sharti		} else
251121934Sharti			FBAD("CBR.2/3");
252121934Sharti		if (bt == UNI_TRAFFIC_BPCR0_P) {
253121934Sharti			*bclass = UNI_TRAFFIC_CBR2;
254121934Sharti			NOBT("CBR.2");
255121934Sharti		} else if (bt == bcbr3) {
256121934Sharti			*bclass = UNI_TRAFFIC_CBR3;
257121934Sharti			if (!btag) {
258121934Sharti				snprintf(ebuf, ebufsiz, "need backward tagging for CBR.3");
259121934Sharti				return (-1);
260121934Sharti			}
261121934Sharti		} else
262121934Sharti			BBAD("CBR.2/3");
263121934Sharti		break;
264121934Sharti
265121934Sharti	  case UNI_TRAFFIC_rtVBR1:
266121934Sharti		NOBE("rtVBR.1");
267121934Sharti		if (ft != fvbr16)
268121934Sharti			FBAD("rtVBR.1");
269121934Sharti		NOFT("rtVBR.1");
270121934Sharti		if (bt != bvbr16)
271121934Sharti			BBAD("rtVBR.1");
272121934Sharti		NOBT("rtVBR.1");
273121934Sharti		*fclass = *bclass = UNI_TRAFFIC_rtVBR1;
274121934Sharti		break;
275121934Sharti
276121934Sharti	  case T_rtVBR236:
277121934Sharti		NOBE("rtVBR.2/3/6");
278121934Sharti		if (ft == fvbr23) {
279121934Sharti			if (ftag)
280121934Sharti				*fclass = UNI_TRAFFIC_rtVBR3;
281121934Sharti			else
282121934Sharti				*fclass = UNI_TRAFFIC_rtVBR2;
283121934Sharti		} else if (ft == fvbr16) {
284121934Sharti			*fclass = UNI_TRAFFIC_rtVBR6;
285121934Sharti			NOFT("rtVBR.6");
286121934Sharti		} else
287121934Sharti			FBAD("rtVBR.2/3/6");
288121934Sharti		if (bt == bvbr23) {
289121934Sharti			if (btag)
290121934Sharti				*bclass = UNI_TRAFFIC_rtVBR3;
291121934Sharti			else
292121934Sharti				*bclass = UNI_TRAFFIC_rtVBR2;
293121934Sharti		} else if (bt == bvbr16) {
294121934Sharti			*bclass = UNI_TRAFFIC_rtVBR6;
295121934Sharti			NOBT("rtVBR.6");
296121934Sharti		} else
297121934Sharti			BBAD("rtVBR.2/3/6");
298121934Sharti		break;
299121934Sharti
300121934Sharti	  case T_rtVBR2_6:
301121934Sharti		NOBE("rtVBR.2-6");
302121934Sharti		if (ft == fvbr23) {
303121934Sharti			if (ftag)
304121934Sharti				*fclass = UNI_TRAFFIC_rtVBR3;
305121934Sharti			else
306121934Sharti				*fclass = UNI_TRAFFIC_rtVBR2;
307121934Sharti		} else if (ft == fvbr4) {
308121934Sharti			*fclass = UNI_TRAFFIC_rtVBR4;
309121934Sharti		} else if (ft == UNI_TRAFFIC_FPCR1_P) {
310121934Sharti			*fclass = UNI_TRAFFIC_rtVBR5;
311121934Sharti			NOFT("rtVBR.5");
312121934Sharti		} else if (ft == fvbr16) {
313121934Sharti			*fclass = UNI_TRAFFIC_rtVBR6;
314121934Sharti			NOFT("rtVBR.6");
315121934Sharti		} else
316121934Sharti			FBAD("rtVBR.2-6");
317121934Sharti		if (bt == bvbr23) {
318121934Sharti			if (btag)
319121934Sharti				*bclass = UNI_TRAFFIC_rtVBR3;
320121934Sharti			else
321121934Sharti				*bclass = UNI_TRAFFIC_rtVBR2;
322121934Sharti		} else if (bt == bvbr4) {
323121934Sharti			*bclass = UNI_TRAFFIC_rtVBR4;
324121934Sharti		} else if (bt == UNI_TRAFFIC_BPCR1_P) {
325121934Sharti			*bclass = UNI_TRAFFIC_rtVBR5;
326121934Sharti			NOBT("rtVBR.5");
327121934Sharti		} else if (bt == bvbr16) {
328121934Sharti			*bclass = UNI_TRAFFIC_rtVBR6;
329121934Sharti			NOBT("rtVBR.6");
330121934Sharti		} else
331121934Sharti			BBAD("rtVBR.2-6");
332121934Sharti		break;
333121934Sharti
334121934Sharti	  case UNI_TRAFFIC_nrtVBR1:
335121934Sharti		NOBE("nrtVBR.1");
336121934Sharti		if (ft != fvbr16)
337121934Sharti			FBAD("nrtVBR.1");
338121934Sharti		NOFT("nrtVBR.1");
339121934Sharti		if (bt != bvbr16)
340121934Sharti			BBAD("nrtVBR.1");
341121934Sharti		NOBT("nrtVBR.1");
342121934Sharti		*fclass = *bclass = UNI_TRAFFIC_nrtVBR1;
343121934Sharti		break;
344121934Sharti
345121934Sharti	  case T_nrtVBR2_6_UBR12:
346121934Sharti		if (be) {
347121934Sharti			if (ft != UNI_TRAFFIC_FPCR1_P)
348121934Sharti				FBAD("UBR.1/2");
349121934Sharti			if (bt != UNI_TRAFFIC_BPCR1_P)
350121934Sharti				BBAD("UBR.1/2");
351121934Sharti			if (ftag)
352121934Sharti				*fclass = UNI_TRAFFIC_UBR2;
353121934Sharti			else
354121934Sharti				*fclass = UNI_TRAFFIC_UBR1;
355121934Sharti			if (btag)
356121934Sharti				*bclass = UNI_TRAFFIC_UBR2;
357121934Sharti			else
358121934Sharti				*bclass = UNI_TRAFFIC_UBR1;
359121934Sharti			break;
360121934Sharti		}
361121934Sharti		if (ft == fvbr23) {
362121934Sharti			if (ftag)
363121934Sharti				*fclass = UNI_TRAFFIC_nrtVBR3;
364121934Sharti			else
365121934Sharti				*fclass = UNI_TRAFFIC_nrtVBR2;
366121934Sharti		} else if (ft == fvbr4) {
367121934Sharti			*fclass = UNI_TRAFFIC_nrtVBR4;
368121934Sharti		} else if (ft == UNI_TRAFFIC_FPCR1_P) {
369121934Sharti			*fclass = UNI_TRAFFIC_nrtVBR5;
370121934Sharti			NOFT("nrtVBR.5");
371121934Sharti		} else if (ft == fvbr16) {
372121934Sharti			*fclass = UNI_TRAFFIC_nrtVBR6;
373121934Sharti			NOFT("nrtVBR.6");
374121934Sharti		} else
375121934Sharti			FBAD("nrtVBR.2-6");
376121934Sharti		if (bt == bvbr23) {
377121934Sharti			if (btag)
378121934Sharti				*bclass = UNI_TRAFFIC_nrtVBR3;
379121934Sharti			else
380121934Sharti				*bclass = UNI_TRAFFIC_nrtVBR2;
381121934Sharti		} else if (bt == bvbr4) {
382121934Sharti			*bclass = UNI_TRAFFIC_nrtVBR4;
383121934Sharti		} else if (bt == UNI_TRAFFIC_BPCR1_P) {
384121934Sharti			*bclass = UNI_TRAFFIC_nrtVBR5;
385121934Sharti			NOBT("nrtVBR.5");
386121934Sharti		} else if (bt == bvbr16) {
387121934Sharti			*bclass = UNI_TRAFFIC_nrtVBR6;
388121934Sharti			NOBT("nrtVBR.6");
389121934Sharti		} else
390121934Sharti			BBAD("nrtVBR.2-6");
391121934Sharti		break;
392121934Sharti
393121934Sharti	  case UNI_TRAFFIC_ABR:
394121934Sharti		NOBE("ABR");
395121934Sharti		if (ft != UNI_TRAFFIC_FPCR1_P)
396121934Sharti			FBAD("ABR");
397121934Sharti		if (bt != UNI_TRAFFIC_BPCR1_P)
398121934Sharti			BBAD("ABR");
399121934Sharti		NOFT("ABR");
400121934Sharti		NOBT("ABR");
401121934Sharti		*fclass = *bclass = UNI_TRAFFIC_ABR;
402121934Sharti		break;
403121934Sharti	}
404121934Sharti
405121934Sharti	return (0);
406121934Sharti}
407