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 */ 47enum { 48 T_CBR23 = 100, T_nrtVBR2_6_UBR12, T_rtVBR236, T_rtVBR2_6 49}; 50 51static 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; 54static 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 58static const u_int fcbr3 = UNI_TRAFFIC_FPCR0_P | UNI_TRAFFIC_FPCR1_P; 59static const u_int bcbr3 = UNI_TRAFFIC_BPCR0_P | UNI_TRAFFIC_BPCR1_P; 60static const u_int fvbr16 = UNI_TRAFFIC_FPCR1_P | UNI_TRAFFIC_FSCR1_P | 61 UNI_TRAFFIC_FMBS1_P; 62static const u_int bvbr16 = UNI_TRAFFIC_BPCR1_P | UNI_TRAFFIC_BSCR1_P | 63 UNI_TRAFFIC_BMBS1_P; 64static const u_int fvbr23 = UNI_TRAFFIC_FPCR1_P | UNI_TRAFFIC_FSCR0_P | 65 UNI_TRAFFIC_FMBS0_P; 66static const u_int bvbr23 = UNI_TRAFFIC_BPCR1_P | UNI_TRAFFIC_BSCR0_P | 67 UNI_TRAFFIC_BMBS0_P; 68static const u_int fvbr4 = UNI_TRAFFIC_FPCR0_P | UNI_TRAFFIC_FPCR1_P; 69static const u_int bvbr4 = UNI_TRAFFIC_BPCR0_P | UNI_TRAFFIC_BPCR1_P; 70 71int 72uni_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} 407