linux/net/sched/cls_rsvp.h
<<
>>
Prefs
   1/*
   2 * net/sched/cls_rsvp.h Template file for RSVPv[46] classifiers.
   3 *
   4 *              This program is free software; you can redistribute it and/or
   5 *              modify it under the terms of the GNU General Public License
   6 *              as published by the Free Software Foundation; either version
   7 *              2 of the License, or (at your option) any later version.
   8 *
   9 * Authors:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  10 */
  11
  12/*
  13   Comparing to general packet classification problem,
  14   RSVP needs only sevaral relatively simple rules:
  15
  16   * (dst, protocol) are always specified,
  17     so that we are able to hash them.
  18   * src may be exact, or may be wildcard, so that
  19     we can keep a hash table plus one wildcard entry.
  20   * source port (or flow label) is important only if src is given.
  21
  22   IMPLEMENTATION.
  23
  24   We use a two level hash table: The top level is keyed by
  25   destination address and protocol ID, every bucket contains a list
  26   of "rsvp sessions", identified by destination address, protocol and
  27   DPI(="Destination Port ID"): triple (key, mask, offset).
  28
  29   Every bucket has a smaller hash table keyed by source address
  30   (cf. RSVP flowspec) and one wildcard entry for wildcard reservations.
  31   Every bucket is again a list of "RSVP flows", selected by
  32   source address and SPI(="Source Port ID" here rather than
  33   "security parameter index"): triple (key, mask, offset).
  34
  35
  36   NOTE 1. All the packets with IPv6 extension headers (but AH and ESP)
  37   and all fragmented packets go to the best-effort traffic class.
  38
  39
  40   NOTE 2. Two "port id"'s seems to be redundant, rfc2207 requires
  41   only one "Generalized Port Identifier". So that for classic
  42   ah, esp (and udp,tcp) both *pi should coincide or one of them
  43   should be wildcard.
  44
  45   At first sight, this redundancy is just a waste of CPU
  46   resources. But DPI and SPI add the possibility to assign different
  47   priorities to GPIs. Look also at note 4 about tunnels below.
  48
  49
  50   NOTE 3. One complication is the case of tunneled packets.
  51   We implement it as following: if the first lookup
  52   matches a special session with "tunnelhdr" value not zero,
  53   flowid doesn't contain the true flow ID, but the tunnel ID (1...255).
  54   In this case, we pull tunnelhdr bytes and restart lookup
  55   with tunnel ID added to the list of keys. Simple and stupid 8)8)
  56   It's enough for PIMREG and IPIP.
  57
  58
  59   NOTE 4. Two GPIs make it possible to parse even GRE packets.
  60   F.e. DPI can select ETH_P_IP (and necessary flags to make
  61   tunnelhdr correct) in GRE protocol field and SPI matches
  62   GRE key. Is it not nice? 8)8)
  63
  64
  65   Well, as result, despite its simplicity, we get a pretty
  66   powerful classification engine.  */
  67
  68
  69struct rsvp_head {
  70        u32                     tmap[256/32];
  71        u32                     hgenerator;
  72        u8                      tgenerator;
  73        struct rsvp_session     *ht[256];
  74};
  75
  76struct rsvp_session {
  77        struct rsvp_session     *next;
  78        __be32                  dst[RSVP_DST_LEN];
  79        struct tc_rsvp_gpi      dpi;
  80        u8                      protocol;
  81        u8                      tunnelid;
  82        /* 16 (src,sport) hash slots, and one wildcard source slot */
  83        struct rsvp_filter      *ht[16 + 1];
  84};
  85
  86
  87struct rsvp_filter {
  88        struct rsvp_filter      *next;
  89        __be32                  src[RSVP_DST_LEN];
  90        struct tc_rsvp_gpi      spi;
  91        u8                      tunnelhdr;
  92
  93        struct tcf_result       res;
  94        struct tcf_exts         exts;
  95
  96        u32                     handle;
  97        struct rsvp_session     *sess;
  98};
  99
 100static inline unsigned int hash_dst(__be32 *dst, u8 protocol, u8 tunnelid)
 101{
 102        unsigned int h = (__force __u32)dst[RSVP_DST_LEN - 1];
 103
 104        h ^= h>>16;
 105        h ^= h>>8;
 106        return (h ^ protocol ^ tunnelid) & 0xFF;
 107}
 108
 109static inline unsigned int hash_src(__be32 *src)
 110{
 111        unsigned int h = (__force __u32)src[RSVP_DST_LEN-1];
 112
 113        h ^= h>>16;
 114        h ^= h>>8;
 115        h ^= h>>4;
 116        return h & 0xF;
 117}
 118
 119static struct tcf_ext_map rsvp_ext_map = {
 120        .police = TCA_RSVP_POLICE,
 121        .action = TCA_RSVP_ACT
 122};
 123
 124#define RSVP_APPLY_RESULT()                             \
 125{                                                       \
 126        int r = tcf_exts_exec(skb, &f->exts, res);      \
 127        if (r < 0)                                      \
 128                continue;                               \
 129        else if (r > 0)                                 \
 130                return r;                               \
 131}
 132
 133static int rsvp_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 134                         struct tcf_result *res)
 135{
 136        struct rsvp_session **sht = ((struct rsvp_head *)tp->root)->ht;
 137        struct rsvp_session *s;
 138        struct rsvp_filter *f;
 139        unsigned int h1, h2;
 140        __be32 *dst, *src;
 141        u8 protocol;
 142        u8 tunnelid = 0;
 143        u8 *xprt;
 144#if RSVP_DST_LEN == 4
 145        struct ipv6hdr *nhptr;
 146
 147        if (!pskb_network_may_pull(skb, sizeof(*nhptr)))
 148                return -1;
 149        nhptr = ipv6_hdr(skb);
 150#else
 151        struct iphdr *nhptr;
 152
 153        if (!pskb_network_may_pull(skb, sizeof(*nhptr)))
 154                return -1;
 155        nhptr = ip_hdr(skb);
 156#endif
 157
 158restart:
 159
 160#if RSVP_DST_LEN == 4
 161        src = &nhptr->saddr.s6_addr32[0];
 162        dst = &nhptr->daddr.s6_addr32[0];
 163        protocol = nhptr->nexthdr;
 164        xprt = ((u8 *)nhptr) + sizeof(struct ipv6hdr);
 165#else
 166        src = &nhptr->saddr;
 167        dst = &nhptr->daddr;
 168        protocol = nhptr->protocol;
 169        xprt = ((u8 *)nhptr) + (nhptr->ihl<<2);
 170        if (ip_is_fragment(nhptr))
 171                return -1;
 172#endif
 173
 174        h1 = hash_dst(dst, protocol, tunnelid);
 175        h2 = hash_src(src);
 176
 177        for (s = sht[h1]; s; s = s->next) {
 178                if (dst[RSVP_DST_LEN-1] == s->dst[RSVP_DST_LEN - 1] &&
 179                    protocol == s->protocol &&
 180                    !(s->dpi.mask &
 181                      (*(u32 *)(xprt + s->dpi.offset) ^ s->dpi.key)) &&
 182#if RSVP_DST_LEN == 4
 183                    dst[0] == s->dst[0] &&
 184                    dst[1] == s->dst[1] &&
 185                    dst[2] == s->dst[2] &&
 186#endif
 187                    tunnelid == s->tunnelid) {
 188
 189                        for (f = s->ht[h2]; f; f = f->next) {
 190                                if (src[RSVP_DST_LEN-1] == f->src[RSVP_DST_LEN - 1] &&
 191                                    !(f->spi.mask & (*(u32 *)(xprt + f->spi.offset) ^ f->spi.key))
 192#if RSVP_DST_LEN == 4
 193                                    &&
 194                                    src[0] == f->src[0] &&
 195                                    src[1] == f->src[1] &&
 196                                    src[2] == f->src[2]
 197#endif
 198                                    ) {
 199                                        *res = f->res;
 200                                        RSVP_APPLY_RESULT();
 201
 202matched:
 203                                        if (f->tunnelhdr == 0)
 204                                                return 0;
 205
 206                                        tunnelid = f->res.classid;
 207                                        nhptr = (void *)(xprt + f->tunnelhdr - sizeof(*nhptr));
 208                                        goto restart;
 209                                }
 210                        }
 211
 212                        /* And wildcard bucket... */
 213                        for (f = s->ht[16]; f; f = f->next) {
 214                                *res = f->res;
 215                                RSVP_APPLY_RESULT();
 216                                goto matched;
 217                        }
 218                        return -1;
 219                }
 220        }
 221        return -1;
 222}
 223
 224static unsigned long rsvp_get(struct tcf_proto *tp, u32 handle)
 225{
 226        struct rsvp_session **sht = ((struct rsvp_head *)tp->root)->ht;
 227        struct rsvp_session *s;
 228        struct rsvp_filter *f;
 229        unsigned int h1 = handle & 0xFF;
 230        unsigned int h2 = (handle >> 8) & 0xFF;
 231
 232        if (h2 > 16)
 233                return 0;
 234
 235        for (s = sht[h1]; s; s = s->next) {
 236                for (f = s->ht[h2]; f; f = f->next) {
 237                        if (f->handle == handle)
 238                                return (unsigned long)f;
 239                }
 240        }
 241        return 0;
 242}
 243
 244static void rsvp_put(struct tcf_proto *tp, unsigned long f)
 245{
 246}
 247
 248static int rsvp_init(struct tcf_proto *tp)
 249{
 250        struct rsvp_head *data;
 251
 252        data = kzalloc(sizeof(struct rsvp_head), GFP_KERNEL);
 253        if (data) {
 254                tp->root = data;
 255                return 0;
 256        }
 257        return -ENOBUFS;
 258}
 259
 260static void
 261rsvp_delete_filter(struct tcf_proto *tp, struct rsvp_filter *f)
 262{
 263        tcf_unbind_filter(tp, &f->res);
 264        tcf_exts_destroy(tp, &f->exts);
 265        kfree(f);
 266}
 267
 268static void rsvp_destroy(struct tcf_proto *tp)
 269{
 270        struct rsvp_head *data = xchg(&tp->root, NULL);
 271        struct rsvp_session **sht;
 272        int h1, h2;
 273
 274        if (data == NULL)
 275                return;
 276
 277        sht = data->ht;
 278
 279        for (h1 = 0; h1 < 256; h1++) {
 280                struct rsvp_session *s;
 281
 282                while ((s = sht[h1]) != NULL) {
 283                        sht[h1] = s->next;
 284
 285                        for (h2 = 0; h2 <= 16; h2++) {
 286                                struct rsvp_filter *f;
 287
 288                                while ((f = s->ht[h2]) != NULL) {
 289                                        s->ht[h2] = f->next;
 290                                        rsvp_delete_filter(tp, f);
 291                                }
 292                        }
 293                        kfree(s);
s294                a>        if ( 195        a>        if ( 196        kfree(dats);
 1      a>        if ( 278
 148static int rsvp_filter(struct tcf_proto *tp, unsigned long NULL)
 2) {
 271        struct rsvp_filterr *tpr *rsvp_filterd long)NUs);
 292        unsigned int f = f->hands);
 203        struct rsvp_session ** 204        struct rsvp_session *f = f-> 195  igned int  276
 177        for (st = &s->h  for (e >> 8) &];pr *>f; st =sizeof(*ot)->next) {
 208              izeof(*/a>[2] == ) {
 209                  truct (ts);
 210                  izeof(*/a/a>] = f->next;
 291                  truct (ts);
 212                        rsvp_delete_filter(tp, f);
 273
 214                        
 205
 216                        for ( 217                                if (s->ht[ 218                                        return 0;
 259
 210                         291                        for (rsvp_head *)tp->root)->ht[e; 8) &];/span>
 212                        **next) {
 203                              izeof(*) {
 204                                  truct (ts);
 195                                   **s->next;
 286                                  truct (ts);
 287
 218                                        kfree(s);
 289                                        return 0;
 290                                a>        if ( 291                        a>        if ( 2     a>        if ( 233                        return 0;
s294                a>        if ( 195        a>        if ( 236        return 0;
 1      a>        if ( 278
 148s      unsigned int tcf_proto *tp, unse(NULL)
 2) {
 271        struct rsvp_head *data = tp->roturn 0;
 272        int  243
s294        w  int  195            int u32  276
 217              ee(dat)-> 21+2 == 0)
 218                  e(dat)-> 212 289          d int f = dat)-> 2|e(NU; 0xFF;
 290                if (rsvp_ger(tp,  == 0)
 291                        r2  252        a>        if ( 253        return 0;
 2      a>        if ( 205
 248static int _bode=exts" class="sref">_bodfilter(struct rsvp_head *da> == 0)
 2) {
 218  tatic int f = dat)-> 21e >5turn 0;
 289    int u32 f<1h2ee(dat)-> 21e; 8) &a1F>s);
 2);
 291        if (dat)->ht[[1]32  == 0)
 212                return 0;
 263        dat)->ht[ =  264        rturn -1;
 2      a>        if ( 276
 268static void _recyce=handle" class="sref">_recyce=filter(struct rsvp_head *da> == 0)
 2) {
 289        struct rsvp_session **sht = dat)->ht;
 270    int u32 h256/32];/span>
 271        int h1, h2;
 2     a>        if ( 263        , 0, - sr(tr));
 284
 235        for (h1 = 0; h1 < 256; h1++) {
 286                struct rsvp_session *s;
 217                for (s = sht[h1]; s; s = s->next) {
 218                        for (h2 = 0; h2 <= 16; h2++) {
 289                                struct rsvp_filter *f;
 2);
 291                                for (f = s->ht[h2]; f; f = s->next) {
 282                                        if (f->tunnelhdr == 0)
 283                                          continue>f;
 204                                  truct dat)-> 21d = f->res.classid;
 285                                  truct _bode=exts" class="sref">_bodfilte *da>id;
 286                                a>        if ( 217                        }
 288                }
 289        }
 2);
 291        dat)->h1, h1/a> - sr(tr));
 242}
 243
 244s  int u32 de=u32" class="gen_sref">filter(struct rsvp_head *da> == 0)
 245{
 196        int  287
 288        for ( 289                for ( 290                      ++truct dat)-> 21d == 0)
 291                          truct dat)-> 21d 282                        if (_bode=exts" class="sref">_bodfilte *da>> == 0)
 283                                r2 dat)-> 2urn -1;
s294                a>        if ( 195            int _recyce=handle" class="sref">_recyce=filte *da>id;
 256        }
 257        return 0;
 258}
 259
 260sconst       struct u32 ht[u3+ 1h2++) {
 291  ht[. 21d =  21},>++) {
 212  ht[. 21d =  283                              es. 21d = u)1},>++) {
 214  ht[. 21d =  285                              es. 21d = u)1},>++) {
 216  ht[. 21d(sizeof(struct u)1},>++) {
 2}turn 0;
 278
 148static int tcf_proto *tp, unsigned long  210                   int u32 handh>++) {
 291                       struct  212                 , unsignedo *NULL)
 2a>++) {
 204        struct rsvp_head *data = tp->roturn 0;
 195        struct rsvp_filter * *turn 0;
 286        struct rsvp_session * * 286        struct uon *uoa>]) != NUs);
 218        struct data = );
 289        struct ht[u3+ 1hs);
 290  r(struct u32  291        unsigned int h1, h2;
 252        h2;
 233  igned int h2;
 284
 195        if (data == NULL)
 286                r2 hand ?return - 287
 252        ta = h1, uh1, dah1, >id;
 195        if (t1a> == 0)
 210                r2 h2;
 281
 252        ta = tcfvalisre=handle" class="sref">tcfvalisre=filte *tp, h1, , &t_macode=tp" class="sref"">t_macef">>id;
 195        if (t1a> == 0)
s294                r2 h2;
 205
 196        rsvp_filterdo *NUh2;
 217        if (++) {
 218                 259
 290                if (f->hand]) != hand<,a>[1]32 hand> == 0)
 291                  gotor2 NUh2;
 212                if (ht[++) {
 283                    if (f->res.classta = ht[;
 214                   a> = tp, &f->rh1,  285          58}
 276
 217          /a> = tcfchang=handle" class="sref">tcfchang=filte *tp, &f->utp, & 218                return 0;
 289        }
 2);
 291         252        ta 195        if (hand> == 0)
 214          gotor2 NUh2;
 195        if (ht[ == NULL)
 286          gotor2 NUh2;
 287
 252        taNUh2;
 289    int f = rsvp_filt)h1,  270        if ( == NULL)
 291          gotor2 NUh2;
 2     a>        if ( 263        h2<16h2;
 195        if (ht[++) {
 195            int f->rh1, ht[ - sr(f->rtr));
 286                h2<  if (f->rr));
 217        }
 218        if (ht[++) {
 289          t[uoa>]) != ht[));
 290           *f->uoa>]) != u>f->u));
 291           *f->tunnelhdr>]) != u>f->tunnelh));
 282        }
 195        if (ht[ 204            if (f->res.classta = ht[;
 205
 196        oa>]) != ht[;
 217    if (h1<  if (h1, uo?>]) != u>f->tcfco>de=u32" class="">tcfco>f">uo: 0,<, uo?>]) != u>f->=classid" class="sref">=cf">uo: 0;
 278
 289    int ta 270         if (f->hand<1<  if (tp  if (h|   for (2 == 0)
 291          gotor2  2     a>        if ( 195        if (f->tunnelh++) {
 204            if (ta 195                if (f->res.classt2255> == 0)
 286                  gotor2  287
 218            int ta 289                if (f->res.classtr,a>[1]/a>));
 290                 if (f->res.classtr32 de=u32" class="gen_sref">filte *da>>dr == 0)
 291                  gotor2  282        }
 243
s294        for (dat)->ht[h1<  for (s *NUs = s->next) {
 195                if (ht[s->ht[ 286              , uo,a>[1]32 u>f->tcfco>de=u32" class="">tcfco>f">uoa == s->tcfco>de=u32" class="">tcfco>f">uo,a>[1]/a>));
 217                int u>f->s->s-> 2#   t[ 289              >->h0 == s->h0,a>[1]/a>));
 290              >->h1 == s->h1,a>[1]/a>));
 291              >->h2 == s->h2,a>[1]/a>));
 2#endif/a>));
 283              ]) != u>f->=classid" class="sref">=cf">uoa == s->=classid" class="sref">=cf">uxt) {
 284
 2>-> 2:84
 286                        tpriate sesvp_sket... */
 287
 218                    if (tr3, &s->ht[h287
 259
 210                   *f->s;
 291                        if (f->tunnelhdr == 0)
 212                           *tp, &f->rh1,  243
 204                   *tcfchang=handle" class="sref">tcfchang=filte *tp, &f->utp, & 205
 286                        for (tr3, &s->ht[h2er *t   if (tr3,(r *)>s->nex05
 217                              ((r *)>s->ues.uo,  *f->ues.u)]) != f->ues.u)05
 218                                  breakh2;
 289                   *s->ne>s *turn 0;
 210                   * 291                  r *1d = ;
 2     a>        if ( 283                  r *NUh2, unsigne)/a> = ;
 204                        return 0;
 285          58}
 286  58}
 287
 252         259
 210  2 NUh2NUh2;
 291        s = rsvp_sessi)h1,  252        if (s == NULL)
 283          gotor2 s294    int s->h1, h1/a> - sr(s->tr));
 205
 196        if (uxt) {
 217          /a> = s->u>f-> 218           a> = s->tcfco>de=u32" class="">tcfco>f">uoa32 u>f->tcfco>de=u32" class="">tcfco>f">u));
 289          t[s->=classid" class="sref">=cf">udr>]) != u>f->=cf">u));
 290  58}
 291        for (dat)->ht[h1 *next) {
 212              ((r *u, &s->u)]) != s->u)/a>) {
 283                  breakh2;
 214  58}
 285  ]) != s->ne>s * 196         217  r *s;
 278
 289  gotor2  2>s;
 2);
 22  252        s;
 12 NU:84
s294    int tcfdestrodestroy" class="sref">tcfdestrodfilte *tp, & 195        r2 h2;
 258}
 287
 248svoidstruct tcf_proto *tpc(struct NULL)
 2) {
 270        struct rsvp_head *tp->roturn 0;
 291        unsigned int h1, turn 0;
 2     a>        if ( 263        if (NU>f->NULL)
 204                turn 0;
 205
 286        for (aa<0]32 a1256]32 ++xt) {
 217                struct rsvp_session * 278
 289                for (s = ht[]s = s = s->next) {
 290          86        for (h1<0]32 h1 ++xt) {
 291          17                struct rsvp_filter * 2     a>        if ( 283                  86        for (f = s->ht[h1< *f = s->next) {
 204                                        if (NU>f->a1  if (NU>f->next) {
 285                                            if (NU>f->++turn 0;
 286                                          continueturn 0;
 217                                  58}
 218                                        if (NU>f->tp/, unsigne)/a> = , NULt1a>t) {
 289                                            if (NU>f->NUh2<1turn 0;
 290          86                                turn 0;
 291                                  58}
 212                                    if (NU>f->++turn 0;
 283                  86  58}
 204          86  58}
 195          58}
 286  58}
 258}
 278
 248signed int (struct tcf_proto *tp, unsigne = h78
 290                     struct tpc(struct NULL)
 2) {
 282        struct rsvp_filter *rsvp_filterd/a> = turn 0;
 282        struct rsvp_session *s294  , unscharon *f = ;
 195        struct  286  c(struct  28truct uturn 0;
 287
 218        if ( == NULL)
 289                r2 >f->uturn 0;
 210  2 s = f-> 2urn 0;
 252        NU>f->s = f->handturn 0;
 243
s294    int ]) != h1, ;
 195        if ( == NULL)
 286          gotor2  287
 218        if (h1,  - sr(s->th1, &s->tr87
 289          gotor2  210  2 ues.s-> 291        ues.uoa>]) != f->uturn 0;
 252        ues.tcfco>de=u32" class="">tcfco>f">uoa32 s->tcfco>de=u32" class="">tcfco>f">uturn 0;
 263        ues.=classid" class="sref">=cf">udr>]) != s->=classid" class="sref">=cf">uturn 0;
s294    int ues.tunnelhdr" class="sref">tunnelhdr>]) != f->tunnelhturn 0;
 285  ]) != ues. 196        if (h1,  - sr(uxh1, &uxr87
 217          gotor2  218        if (f->res.classt2/a>,a>[1]/a>));
 289      2 h1, , f->res.classxr87
 210          gotor2  291      ((/a> = f->handt28)o, 0xFF)16t2/a>,a>[1]/a>));
 212        if (h1,  - sr(f->rth1, f->rtr/a>));
 283          gotor2  284
 195        if (tcfdumcode=tp" class="sref">tcfdumcfilte *h1, &f->utp, &rtt1a>84
 286          gotor2  287
 252   ) != h1, ;
 259
 210        if (tcfdumc_48tcfdumc_48 *h1, &f->utp, &rtt1a>84
 291          gotor2  252        r2 >f->uturn 0;
 243
s22  285  ]) != h1, ;
 196        r-1turn 0;
 258}
 278
 248sc(struct  19truct  19truct  290  es. 291     =5  ]) != h/a>) {
 291  es. 291 =5  ]) != h/a>) {
 212  es. 291     =5  ]) != h/a>) {
 283  es.h/a>) {
 214  es. 291      =5  ]) != h/a>) {
 285  es.h/a>) {
 196  es.h/a>) {
 217  es.h/a>) {
 217  es. 289  es.) {
 290  es. 2}turn 0;
 2     a>        if ( 148signed int r2 84
s2) {
 195        r2  1;
 258}
 287
 248svoidstruct r2 84
 2) {
 210  2  1;
 258}
 2     a>        if ( 12  *84
s22  *84
 2


The original LXR software by the 4 LXR lassunitdef">h this experis="cal vervp_skby 4 lx_@lasux.nof">re
lx_.lasux.no kincly hostedkby 4 Redpill Lase=t ASef">h e=tvider of Lasux consulting and oper