diff options
Diffstat (limited to 'sys/contrib/ngatm/netnatm/msg/traffic.c')
-rw-r--r-- | sys/contrib/ngatm/netnatm/msg/traffic.c | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/sys/contrib/ngatm/netnatm/msg/traffic.c b/sys/contrib/ngatm/netnatm/msg/traffic.c new file mode 100644 index 0000000..acaffdb --- /dev/null +++ b/sys/contrib/ngatm/netnatm/msg/traffic.c @@ -0,0 +1,406 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Hartmut Brandt <harti@freebsd.org> + * + * $Begemot: libunimsg/netnatm/msg/traffic.c,v 1.4 2004/07/08 08:22:05 brandt Exp $ + * + * Traffic classification + */ + +#include <netnatm/unimsg.h> +#include <netnatm/msg/unistruct.h> +#include <netnatm/msg/unimsglib.h> +#ifdef _KERNEL +#include <sys/systm.h> +#else +#include <stdio.h> +#endif + +/* + * Try to set the parameters for the CPCS from the parameters of the + * connection. + */ +enum { + T_CBR23 = 100, T_nrtVBR2_6_UBR12, T_rtVBR236, T_rtVBR2_6 +}; + +static const u_int fmask = UNI_TRAFFIC_FPCR0_P | UNI_TRAFFIC_FPCR1_P | + UNI_TRAFFIC_FSCR0_P | UNI_TRAFFIC_FSCR1_P | UNI_TRAFFIC_FMBS0_P | + UNI_TRAFFIC_FMBS1_P | UNI_TRAFFIC_FABR1_P; +static const u_int bmask = UNI_TRAFFIC_BPCR0_P | UNI_TRAFFIC_BPCR1_P | + UNI_TRAFFIC_BSCR0_P | UNI_TRAFFIC_BSCR1_P | UNI_TRAFFIC_BMBS0_P | + UNI_TRAFFIC_BMBS1_P | UNI_TRAFFIC_BABR1_P; + +static const u_int fcbr3 = UNI_TRAFFIC_FPCR0_P | UNI_TRAFFIC_FPCR1_P; +static const u_int bcbr3 = UNI_TRAFFIC_BPCR0_P | UNI_TRAFFIC_BPCR1_P; +static const u_int fvbr16 = UNI_TRAFFIC_FPCR1_P | UNI_TRAFFIC_FSCR1_P | + UNI_TRAFFIC_FMBS1_P; +static const u_int bvbr16 = UNI_TRAFFIC_BPCR1_P | UNI_TRAFFIC_BSCR1_P | + UNI_TRAFFIC_BMBS1_P; +static const u_int fvbr23 = UNI_TRAFFIC_FPCR1_P | UNI_TRAFFIC_FSCR0_P | + UNI_TRAFFIC_FMBS0_P; +static const u_int bvbr23 = UNI_TRAFFIC_BPCR1_P | UNI_TRAFFIC_BSCR0_P | + UNI_TRAFFIC_BMBS0_P; +static const u_int fvbr4 = UNI_TRAFFIC_FPCR0_P | UNI_TRAFFIC_FPCR1_P; +static const u_int bvbr4 = UNI_TRAFFIC_BPCR0_P | UNI_TRAFFIC_BPCR1_P; + +int +uni_classify_traffic(const struct uni_ie_bearer *bearer, + const struct uni_ie_traffic *traffic, + enum uni_traffic_class *fclass, enum uni_traffic_class *bclass, + char *ebuf, size_t ebufsiz) +{ + u_int tclass; + u_int ft, bt, be, ftag, btag; + + /* classify */ + switch (bearer->bclass) { + + case UNI_BEARER_A: + if (!(bearer->h.present & UNI_BEARER_ATC_P)) { + tclass = T_CBR23; + break; + } + switch (bearer->atc) { + + case UNI_BEARER_ATC_CBR1: + tclass = UNI_TRAFFIC_CBR1; + break; + + default: + snprintf(ebuf, ebufsiz, "bad ATC=%#02x for BCOB-A", + bearer->atc); + return (-1); + } + break; + + case UNI_BEARER_C: + if (!(bearer->h.present & UNI_BEARER_ATC_P)) { + tclass = T_nrtVBR2_6_UBR12; + break; + } + switch (bearer->atc) { + + case UNI_BEARER_ATC_VBR1: + tclass = UNI_TRAFFIC_rtVBR1; + break; + + case UNI_BEARER_ATC_VBR: + tclass = T_rtVBR236; + break; + + case UNI_BEARER_ATC_NVBR1: + tclass = UNI_TRAFFIC_nrtVBR1; + break; + + case UNI_BEARER_ATC_ABR: + tclass = UNI_TRAFFIC_ABR; + break; + + default: + snprintf(ebuf, ebufsiz, "bad ATC=%#02x for BCOB-C", + bearer->atc); + return (-1); + } + break; + + case UNI_BEARER_X: + if (!(bearer->h.present & UNI_BEARER_ATC_P)) { + tclass = T_nrtVBR2_6_UBR12; + break; + } + switch (bearer->atc) { + + case UNI_BEARER_ATC_CBR1: + tclass = UNI_TRAFFIC_CBR1; + break; + + case UNI_BEARER_ATC_CBR: + case UNI_BEARER_ATCX_4: + case UNI_BEARER_ATCX_6: + tclass = T_CBR23; + break; + + case UNI_BEARER_ATC_VBR1: + tclass = UNI_TRAFFIC_rtVBR1; + break; + + case UNI_BEARER_ATCX_1: + case UNI_BEARER_ATC_VBR: + tclass = T_rtVBR2_6; + break; + + case UNI_BEARER_ATC_NVBR1: + tclass = UNI_TRAFFIC_nrtVBR1; + break; + + case UNI_BEARER_ATCX_0: + case UNI_BEARER_ATCX_2: + case UNI_BEARER_ATCX_8: + case UNI_BEARER_ATC_NVBR: + tclass = T_nrtVBR2_6_UBR12; + break; + + case UNI_BEARER_ATC_ABR: + tclass = UNI_TRAFFIC_ABR; + break; + + default: + snprintf(ebuf, ebufsiz, "bad ATC=%#02x for BCOB-X", + bearer->atc); + return (-1); + } + break; + + case UNI_BEARER_TVP: + snprintf(ebuf, ebufsiz, "unsupported bearer class tVP"); + return (-1); + + default: + snprintf(ebuf, ebufsiz, "bad bearer class %#02x", + bearer->bclass); + return (-1); + } + + /* + * Now traffic IE + */ + ft = traffic->h.present & fmask; + bt = traffic->h.present & bmask; + be = traffic->h.present & UNI_TRAFFIC_BEST_P; + ftag = (traffic->h.present & UNI_TRAFFIC_MOPT_P) && traffic->t.ftag; + btag = (traffic->h.present & UNI_TRAFFIC_MOPT_P) && traffic->t.btag; + +#define NOBE(C) \ + if (be) { \ + snprintf(ebuf, ebufsiz, "illegal BE for " C); \ + return (-1); \ + } + +#define NOFT(C) \ + if (ftag) { \ + snprintf(ebuf, ebufsiz, "illegal forward tag in " C); \ + return (-1); \ + } + +#define NOBT(C) \ + if (btag) { \ + snprintf(ebuf, ebufsiz, "illegal backward tag in " C); \ + return (-1); \ + } + +#define FBAD(C) do { \ + snprintf(ebuf, ebufsiz, "bad forward CRs for " C); \ + return (-1); \ + } while (0) + +#define BBAD(C) do { \ + snprintf(ebuf, ebufsiz, "bad backward CRs for " C); \ + return (-1); \ + } while (0) + + switch (tclass) { + + case UNI_TRAFFIC_CBR1: + NOBE("CBR.1"); + if (ft != UNI_TRAFFIC_FPCR1_P) + FBAD("CBR.1"); + NOFT("CBR.1"); + if (bt != UNI_TRAFFIC_BPCR1_P) + BBAD("CBR.1"); + NOBT("CBR.1"); + *fclass = *bclass = UNI_TRAFFIC_CBR1; + break; + + case T_CBR23: + NOBE("CBR.2/3"); + if (ft == UNI_TRAFFIC_FPCR0_P) { + *fclass = UNI_TRAFFIC_CBR2; + NOFT("CBR.2"); + } else if (ft == fcbr3) { + *fclass = UNI_TRAFFIC_CBR3; + if (!ftag) { + snprintf(ebuf, ebufsiz, "need forward tagging for CBR.3"); + return (-1); + } + } else + FBAD("CBR.2/3"); + if (bt == UNI_TRAFFIC_BPCR0_P) { + *bclass = UNI_TRAFFIC_CBR2; + NOBT("CBR.2"); + } else if (bt == bcbr3) { + *bclass = UNI_TRAFFIC_CBR3; + if (!btag) { + snprintf(ebuf, ebufsiz, "need backward tagging for CBR.3"); + return (-1); + } + } else + BBAD("CBR.2/3"); + break; + + case UNI_TRAFFIC_rtVBR1: + NOBE("rtVBR.1"); + if (ft != fvbr16) + FBAD("rtVBR.1"); + NOFT("rtVBR.1"); + if (bt != bvbr16) + BBAD("rtVBR.1"); + NOBT("rtVBR.1"); + *fclass = *bclass = UNI_TRAFFIC_rtVBR1; + break; + + case T_rtVBR236: + NOBE("rtVBR.2/3/6"); + if (ft == fvbr23) { + if (ftag) + *fclass = UNI_TRAFFIC_rtVBR3; + else + *fclass = UNI_TRAFFIC_rtVBR2; + } else if (ft == fvbr16) { + *fclass = UNI_TRAFFIC_rtVBR6; + NOFT("rtVBR.6"); + } else + FBAD("rtVBR.2/3/6"); + if (bt == bvbr23) { + if (btag) + *bclass = UNI_TRAFFIC_rtVBR3; + else + *bclass = UNI_TRAFFIC_rtVBR2; + } else if (bt == bvbr16) { + *bclass = UNI_TRAFFIC_rtVBR6; + NOBT("rtVBR.6"); + } else + BBAD("rtVBR.2/3/6"); + break; + + case T_rtVBR2_6: + NOBE("rtVBR.2-6"); + if (ft == fvbr23) { + if (ftag) + *fclass = UNI_TRAFFIC_rtVBR3; + else + *fclass = UNI_TRAFFIC_rtVBR2; + } else if (ft == fvbr4) { + *fclass = UNI_TRAFFIC_rtVBR4; + } else if (ft == UNI_TRAFFIC_FPCR1_P) { + *fclass = UNI_TRAFFIC_rtVBR5; + NOFT("rtVBR.5"); + } else if (ft == fvbr16) { + *fclass = UNI_TRAFFIC_rtVBR6; + NOFT("rtVBR.6"); + } else + FBAD("rtVBR.2-6"); + if (bt == bvbr23) { + if (btag) + *bclass = UNI_TRAFFIC_rtVBR3; + else + *bclass = UNI_TRAFFIC_rtVBR2; + } else if (bt == bvbr4) { + *bclass = UNI_TRAFFIC_rtVBR4; + } else if (bt == UNI_TRAFFIC_BPCR1_P) { + *bclass = UNI_TRAFFIC_rtVBR5; + NOBT("rtVBR.5"); + } else if (bt == bvbr16) { + *bclass = UNI_TRAFFIC_rtVBR6; + NOBT("rtVBR.6"); + } else + BBAD("rtVBR.2-6"); + break; + + case UNI_TRAFFIC_nrtVBR1: + NOBE("nrtVBR.1"); + if (ft != fvbr16) + FBAD("nrtVBR.1"); + NOFT("nrtVBR.1"); + if (bt != bvbr16) + BBAD("nrtVBR.1"); + NOBT("nrtVBR.1"); + *fclass = *bclass = UNI_TRAFFIC_nrtVBR1; + break; + + case T_nrtVBR2_6_UBR12: + if (be) { + if (ft != UNI_TRAFFIC_FPCR1_P) + FBAD("UBR.1/2"); + if (bt != UNI_TRAFFIC_BPCR1_P) + BBAD("UBR.1/2"); + if (ftag) + *fclass = UNI_TRAFFIC_UBR2; + else + *fclass = UNI_TRAFFIC_UBR1; + if (btag) + *bclass = UNI_TRAFFIC_UBR2; + else + *bclass = UNI_TRAFFIC_UBR1; + break; + } + if (ft == fvbr23) { + if (ftag) + *fclass = UNI_TRAFFIC_nrtVBR3; + else + *fclass = UNI_TRAFFIC_nrtVBR2; + } else if (ft == fvbr4) { + *fclass = UNI_TRAFFIC_nrtVBR4; + } else if (ft == UNI_TRAFFIC_FPCR1_P) { + *fclass = UNI_TRAFFIC_nrtVBR5; + NOFT("nrtVBR.5"); + } else if (ft == fvbr16) { + *fclass = UNI_TRAFFIC_nrtVBR6; + NOFT("nrtVBR.6"); + } else + FBAD("nrtVBR.2-6"); + if (bt == bvbr23) { + if (btag) + *bclass = UNI_TRAFFIC_nrtVBR3; + else + *bclass = UNI_TRAFFIC_nrtVBR2; + } else if (bt == bvbr4) { + *bclass = UNI_TRAFFIC_nrtVBR4; + } else if (bt == UNI_TRAFFIC_BPCR1_P) { + *bclass = UNI_TRAFFIC_nrtVBR5; + NOBT("nrtVBR.5"); + } else if (bt == bvbr16) { + *bclass = UNI_TRAFFIC_nrtVBR6; + NOBT("nrtVBR.6"); + } else + BBAD("nrtVBR.2-6"); + break; + + case UNI_TRAFFIC_ABR: + NOBE("ABR"); + if (ft != UNI_TRAFFIC_FPCR1_P) + FBAD("ABR"); + if (bt != UNI_TRAFFIC_BPCR1_P) + BBAD("ABR"); + NOFT("ABR"); + NOBT("ABR"); + *fclass = *bclass = UNI_TRAFFIC_ABR; + break; + } + + return (0); +} |