AD

Linux kernel traffic control (20)

Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, for any commercial purposes is strictly prohibited.
msn: [email protected]**
Source: **yfydz.cublog.cn

7.11 tcindex

tcindex  Is based on the data package skb  tcindex  Parameters on the classification of data types, and  tcindex  The value is set in the upper right, the code  net/sched/cls_tcindex.c  Defined  .

7.11.1   Data structure and operating structure of the filter  
// tcindex  Filter Results  
struct tcindex_filter_result {
//   Extended structure  
 struct tcf_exts  exts;
//   Classification  
 struct tcf_result res;
};

// tcindex  Filter  
struct tcindex_filter {
//   Keyword  
 u16 key;
//   Filter Results  
 struct tcindex_filter_result result;
//   Next list  
 struct tcindex_filter *next;
};

// tcindex  Data structure  
struct tcindex_data {
//   Filter results, the perfect hash  ,   Is the array  
 struct tcindex_filter_result *perfect; /* perfect hash; NULL if none */
//   Not perfect hash, is the list in the form  
 struct tcindex_filter **h; /* imperfect hash; only used if !perfect;
          NULL if unused */
//   Mask keyword  
 u16 mask;  /* AND key with mask */
//   The number of shifts  
 int shift;  /* shift ANDed key to the right */
//   The number of hash table  
 int hash;  /* hash table size; 0 if undefined */
 int alloc_hash;  /* allocated size */
 int fall_through; /* 0: only classify if explicit match */
};
 
static struct tcf_ext_map tcindex_ext_map = {
 .police = TCA_TCINDEX_POLICE,
 .action = TCA_TCINDEX_ACT
};
 
//   Operating Structure  
static struct tcf_proto_ops cls_tcindex_ops = {
 .next  = NULL,
 .kind  = "tcindex",
 .classify = tcindex_classify,
 .init  = tcindex_init,
 .destroy = tcindex_destroy,
 .get  = tcindex_get,
 .put  = tcindex_put,
 .change  = tcindex_change,
 .delete  = tcindex_delete,
 .walk  = tcindex_walk,
 .dump  = tcindex_dump,
 .owner  = THIS_MODULE,
};
 
7.11.2   Initialization  
 
static int tcindex_init(struct tcf_proto *tp)
{
 struct tcindex_data *p;
 DPRINTK("tcindex_init(tp %p)\n",tp);
//   Data structure space allocated tcindex  
 p = kzalloc(sizeof(struct tcindex_data),GFP_KERNEL);
 if (!p)
  return -ENOMEM;
//   Set the basic parameters  
 p->mask = 0xffff;
 p->hash = DEFAULT_HASH_SIZE; // 64
 p->fall_through = 1;
//   As the root of rules TCF_PROTO  
 tp->root = p;
 return 0;
}
 
7.11.3   Categories  

#define PRIV(tp) ((struct tcindex_data *) (tp)->root)

static int tcindex_classify(struct sk_buff *skb, struct tcf_proto *tp,
       struct tcf_result *res)
{
// TCF_PROTO  Filtering rules that structure the root data structure tcindex  
 struct tcindex_data *p = PRIV(tp);
 struct tcindex_filter_result *f;
//   According to the data packet tcindex parameter calculation  key:   First, mask cover, and then right a few  
 int key = (skb->tc_index & p->mask) >> p->shift;
 D2PRINTK("tcindex_classify(skb %p,tp %p,res %p),p %p\n",skb,tp,res,p);
//   Filter results based on key search  
 f = tcindex_lookup(p, key);
 if (!f) {
  if (!p->fall_through)
   return -1;
  res->classid = TC_H_MAKE(TC_H_MAJ(tp->q->handle), key);
  res->class = 0;
  D2PRINTK("alg 0x%x\n",res->classid);
  return 0;
 }
//   Filter results found, assigned to the classification results  
 *res = f->res;
 D2PRINTK("map 0x%x\n",res->classid);
//   Expand the implementation of TCF configuration  
 return tcf_exts_exec(skb, &f->exts, res);
}

//   Filter results based on key search  
static struct tcindex_filter_result *
tcindex_lookup(struct tcindex_data *p, u16 key)
{
 struct tcindex_filter *f;
 if (p->perfect)
//   Find the perfect array s  key  Items 
  return tcindex_filter_is_set(p->perfect + key) ?
   p->perfect + key : NULL;
 else if (p->h) {
//   Find the list of non-perfect  
  for (f = p->h[key % p->hash]; f; f = f->next)
   if (f->key == key)
    return &f->result;
 }
 return NULL;
}
 
7.11.4   Release  
 
static void tcindex_destroy(struct tcf_proto *tp)
{
// TCF_PROTO  Filtering rules that structure the root data structure tcindex  
 struct tcindex_data *p = PRIV(tp);
 struct tcf_walker walker;
 DPRINTK("tcindex_destroy(tp %p),p %p\n",tp,p);
//   Traverse the structure initialization  
 walker.count = 0;
 walker.skip = 0;
//   The release of an element  
 walker.fn = &tcindex_destroy_element;
// tcindex  Remove each element of the traversal  
 tcindex_walk(tp,&walker);
//   The release of an array of perfect  
 kfree(p->perfect);
//   Release of non-perfect node  
 kfree(p->h);
//   The release of the data structure tcindex  
 kfree(p);
 tp->root = NULL;
}

static int tcindex_destroy_element(struct tcf_proto *tp,
    unsigned long arg, struct tcf_walker *walker)
{
//   Filter results released tcindex node  ,   Operation does not lock  
 return __tcindex_delete(tp, arg, 0);
}

static int
__tcindex_delete(struct tcf_proto *tp, unsigned long arg, int lock)
{
// TCF_PROTO  Filtering rules that structure the root data structure tcindex  
 struct tcindex_data *p = PRIV(tp);
//   Filter Results  
 struct tcindex_filter_result *r = (struct tcindex_filter_result *) arg;
 struct tcindex_filter *f = NULL;
 DPRINTK("tcindex_delete(tp %p,arg 0x%lx),p %p,f %p\n",tp,arg,p,f);
 if (p->perfect) {
// perfect  Non-empty array, r is  perfect  Items in the array  
//   If the classification is empty, indicating that the filtering results of illegal entry  
  if (!r->res.class)
   return -ENOENT;
 } else {
// r  List the items in the non-perfect  ,   Look at the list  
  int i;
  struct tcindex_filter **walk = NULL;
//   HASH table traverse the number of  
  for (i = 0; i < p->hash; i++)
//   Traverse the list  
   for (walk = p->h+i; *walk; walk = &(*walk)->next)
//   Search filter results items  
    if (&(*walk)->result == r)
     goto found;
//   Not found, return error  
  return -ENOENT;
found:
//   Filter results to find the node, disconnect from the list  
  f = *walk;
  if (lock)
   tcf_tree_lock(tp);
  *walk = f->next;
  if (lock)
   tcf_tree_unlock(tp);
 }
//   Extract and filter binding  
 tcf_unbind_filter(tp, &r->res);
//   TCF extended release  
 tcf_exts_destroy(tp, &r->exts);
//   Filter results released node, which is the original non-  perfect  Node in the list, if it is  perfect  Array on the meaningless  
 kfree(f);
 return 0;
}

7.11.5   Get  

//   Under the handle to find  tcindex  Filter Results Results  
static unsigned long tcindex_get(struct tcf_proto *tp, u32 handle)
{
// TCF_PROTO  Filtering rules that structure the root data structure tcindex  
 struct tcindex_data *p = PRIV(tp);
 struct tcindex_filter_result *r;
 DPRINTK("tcindex_get(tp %p,handle 0x%08x)\n",tp,handle);
//   If the array is non-empty perfect  ,   But the handle exceeds the size of allocated array  ,   Return null  
 if (p->perfect && handle >= p->alloc_hash)
  return 0;
//   According to filter results to find the structure handle  
 r = tcindex_lookup(p, handle);
 return r && tcindex_filter_is_set(r) ? (unsigned long) r : 0UL;
}

7.11.6   Put down  
//   Space function  
static void tcindex_put(struct tcf_proto *tp, unsigned long f)
{
 DPRINTK("tcindex_put(tp %p,f 0x%lx)\n",tp,f);
}

7.11.7   Modify  

//   Tc filter add and modify the rules call  
static int
tcindex_change(struct tcf_proto *tp, unsigned long base, u32 handle,
        struct rtattr **tca, unsigned long *arg)
{
//   Enter the option parameter  
 struct rtattr *opt = tca[TCA_OPTIONS-1];
 struct rtattr *tb[TCA_TCINDEX_MAX];
// TCF_PROTO  Filtering rules that structure the root data structure tcindex  
 struct tcindex_data *p = PRIV(tp);
//   Filter Results  
 struct tcindex_filter_result *r = (struct tcindex_filter_result *) *arg;
 DPRINTK("tcindex_change(tp %p,handle 0x%08x,tca %p,arg %p),opt %p,"
     "p %p,r %p,*arg 0x%lx\n",
     tp, handle, tca, arg, opt, p, r, arg ? *arg : 0L);
//   No parameters, return  
 if (!opt)
  return 0;
//   Parsing the input parameters  
 if (rtattr_parse_nested(tb, TCA_TCINDEX_MAX, opt) < 0)
  return -EINVAL;
//   Parameters set tcindex  
 return tcindex_set_parms(tp, base, handle, p, r, tb, tca[TCA_RATE-1]);
}
 
static int
tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
    struct tcindex_data *p, struct tcindex_filter_result *r,
    struct rtattr **tb, struct rtattr *est)
{
 int err, balloc = 0;
 struct tcindex_filter_result new_filter_result, *old_r = r;
//   Structure used to update, if an error occurs during the update operation  ,   Can not affect the original parameter  
 struct tcindex_filter_result cr;
 struct tcindex_data cp;
 struct tcindex_filter *f = NULL; /* make gcc behave */
 struct tcf_exts e;
// TCF  The legality of treatment extended parameter  
 err = tcf_exts_validate(tp, tb, est, &e, &tcindex_ext_map);
//   Failure to return  
 if (err < 0)
  return err;
//   Initialization of the structure, reproduction or cleared  
 memcpy(&cp, p, sizeof(cp));
 memset(&new_filter_result, 0, sizeof(new_filter_result));
 if (old_r)
  memcpy(&cr, r, sizeof(cr));
 else
  memset(&cr, 0, sizeof(cr));
 err = -EINVAL;
//   Analysis tcindex of  HASH  Table Number  
 if (tb[TCA_TCINDEX_HASH-1]) {
  if (RTA_PAYLOAD(tb[TCA_TCINDEX_HASH-1]) < sizeof(u32))
   goto errout;
  cp.hash = *(u32 *) RTA_DATA(tb[TCA_TCINDEX_HASH-1]);
 }
//   Analysis tcindex mask  
 if (tb[TCA_TCINDEX_MASK-1]) {
  if (RTA_PAYLOAD(tb[TCA_TCINDEX_MASK-1]) < sizeof(u16))
   goto errout;
  cp.mask = *(u16 *) RTA_DATA(tb[TCA_TCINDEX_MASK-1]);
 }
//   Analysis the number of shifts  
 if (tb[TCA_TCINDEX_SHIFT-1]) {
  if (RTA_PAYLOAD(tb[TCA_TCINDEX_SHIFT-1]) < sizeof(u16))
   goto errout;
  cp.shift = *(u16 *) RTA_DATA(tb[TCA_TCINDEX_SHIFT-1]);
 }
 err = -EBUSY;
 /* Hash already allocated, make sure that we still meet the
  * requirements for the allocated hash.
  */
 if (cp.perfect) {
//   If the array has been allocated perfect  ,   Check the parameters are valid  
  if (!valid_perfect_hash(&cp) ||
      cp.hash > cp.alloc_hash)
   goto errout;
 } else
//   Otherwise, if non-empty list of non-perfect  ,   Check whether the number matches the hash  
        if (cp.h && cp.hash != cp.alloc_hash)
  goto errout;
 err = -EINVAL;
//   Analysis fall_through parameters  
 if (tb[TCA_TCINDEX_FALL_THROUGH-1]) {
  if (RTA_PAYLOAD(tb[TCA_TCINDEX_FALL_THROUGH-1]) < sizeof(u32))
   goto errout;
  cp.fall_through =
   *(u32 *) RTA_DATA(tb[TCA_TCINDEX_FALL_THROUGH-1]);
 }
 if (!cp.hash) {
//   Did not set the hash number calculated  
  /* Hash not specified, use perfect hash if the upper limit
   * of the hashing index is below the threshold.
   */
  if ((cp.mask >> cp.shift) < PERFECT_HASH_THRESHOLD)
   cp.hash = (cp.mask >> cp.shift)+1;
  else
   cp.hash = DEFAULT_HASH_SIZE;
 }
// perfect  Did not list an array of distribution and non-perfect  ,   The first operation, to  alloc_hash  Parameter assignment  
 if (!cp.perfect && !cp.h)
  cp.alloc_hash = cp.hash;
 /* Note: this could be as restrictive as if (handle & ~(mask >> shift))
  * but then, we'd fail handles that may become valid after some future
  * mask change. While this is extremely unlikely to ever matter,
  * the check below is safer (and also more backwards-compatible).
  */
//   Check the handle value is valid  
 if (cp.perfect || valid_perfect_hash(&cp))
  if (handle >= cp.alloc_hash)
   goto errout;

 err = -ENOMEM;
 if (!cp.perfect && !cp.h) {
// perfect  Perfect array or list is empty  
  if (valid_perfect_hash(&cp)) {
//   Distribution of hash structure of a space for the filter results  perfect  Array  
   cp.perfect = kcalloc(cp.hash, sizeof(*r), GFP_KERNEL);
   if (!cp.perfect)
    goto errout;
// perfect  Array has been allocated marks  
   balloc = 1;
  } else {
//   Distribution of non-perfect hash table header array  ,   A total of hash key  
// sizeof(f)  Only the pointer size is 32-bit systems  4
   cp.h = kcalloc(cp.hash, sizeof(f), GFP_KERNEL);
   if (!cp.h)
    goto errout;
//   Head the list of non-perfect array of hash marks have been allocated  
   balloc = 2;
  }
 }
//   Find the handle for positioning the filter results items  
 if (cp.perfect)
  r = cp.perfect + handle;
 else
  r = tcindex_lookup(&cp, handle) ? : &new_filter_result;
 if (r == &new_filter_result) {
//   That r should be non-  perfect  The new distribution list of nodes  
//   Distribution tcindex filter structure  
  f = kzalloc(sizeof(*f), GFP_KERNEL);
  if (!f)
   goto errout_alloc;
  }
//   If you have class ID items  
 if (tb[TCA_TCINDEX_CLASSID-1]) {
//   Complete class results  ID
  cr.res.classid = *(u32 *) RTA_DATA(tb[TCA_TCINDEX_CLASSID-1]);
//   Filter binding  
  tcf_bind_filter(tp, &cr.res, base);
  }
// TCF  Extended the results to modify  
 tcf_exts_change(tp, &cr.exts, &e);
 tcf_tree_lock(tp);
//   Filter results have changed, the old structure is cleared filter results  
 if (old_r && old_r != r)
  memset(old_r, 0, sizeof(*old_r));
//  The results of the new structure and the structure of the filter data structure tcindex back copies  ,   Structured data that is updated  
// p  Perfect in the new address of the array  
 memcpy(p, &cp, sizeof(cp));
 memcpy(r, &cr, sizeof(cr));
 if (r == &new_filter_result) {
//   New non-pefect category node  
  struct tcindex_filter **fp;
//   Fill in the filter structure parameters tcindex  
  f->key = handle;
  f->result = new_filter_result;
  f->next = NULL;
//   The structure into the final list  
  for (fp = p->h+(handle % p->hash); *fp; fp = &(*fp)->next)
   /* nothing */;
  *fp = f;
  }
 tcf_tree_unlock(tp);
 return 0;
//   Failure handling  
errout_alloc:
 if (balloc == 1)
  kfree(cp.perfect);
 else if (balloc == 2)
  kfree(cp.h);
errout:
 tcf_exts_destroy(tp, &e);
 return err;
}
 
7.11.8   Delete  

//   The wrapper functions only __tcindex_delete  ,   See the previous analysis  
static int tcindex_delete(struct tcf_proto *tp, unsigned long arg)
{
//   Locking parameter is 1, when the node is disconnected from the list to be locked  
 return __tcindex_delete(tp, arg, 1);
}

7.11.9   Traversal  

static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker)
{
// TCF_PROTO  Filtering rules that structure the root data structure tcindex  
 struct tcindex_data *p = PRIV(tp);
 struct tcindex_filter *f,*next;
 int i;
 DPRINTK("tcindex_walk(tp %p,walker %p),p %p\n",tp,walker,p);
 if (p->perfect) {
// perfect  Array of non-empty  ,
//   Traverse each  
  for (i = 0; i < p->hash; i++) {
//   If the classification categories of illegal, skip the  
   if (!p->perfect[i].res.class)
    continue;
//   Whether the comparison is to skip the item  
   if (walker->count >= walker->skip) {
//   Function is called single-node operation  
    if (walker->fn(tp,
        (unsigned long) (p->perfect+i), walker)
         < 0) {
//   Operation failed, set the interrupt flag  ,   Back  
     walker->stop = 1;
     return;
    }
   }
   walker->count++;
  }
 }
//   If there is no list of non-perfect  ,   Back  
 if (!p->h)
  return;
//   Traverse the list of all non-perfect  
 for (i = 0; i < p->hash; i++) {
  for (f = p->h[i]; f; f = next) {
   next = f->next;
//   Whether the comparison is to skip the item  
   if (walker->count >= walker->skip) {
//   Function is called single-node operation  
    if (walker->fn(tp,(unsigned long) &f->result,
        walker) < 0) {
//   Operation failed, set the interrupt flag  ,   Back  
     walker->stop = 1;
     return;
    }
   }
   walker->count++;
  }
 }
}
 
7.11.10   Output  

static int tcindex_dump(struct tcf_proto *tp, unsigned long fh,
    struct sk_buff *skb, struct tcmsg *t)
{
// TCF_PROTO  Filtering rules that structure the root data structure tcindex  
 struct tcindex_data *p = PRIV(tp);
//   To filter the results structure pointer output  
 struct tcindex_filter_result *r = (struct tcindex_filter_result *) fh;
//   Packet buffers for data positioning completed  
 unsigned char *b = skb->tail;
 struct rtattr *rta;
 DPRINTK("tcindex_dump(tp %p,fh 0x%lx,skb %p,t %p),p %p,r %p,b %p\n",
     tp,fh,skb,t,p,r,b);
 DPRINTK("p->perfect %p p->h %p\n",p->perfect,p->h);
//   Netlink attribute structure as a pointer  
 rta = (struct rtattr *) b;
 RTA_PUT(skb,TCA_OPTIONS,0,NULL);
 if (!fh) {
//   If the handle is  0
//  Will handle the whole set  1
  t->tcm_handle = ~0; /* whatever ... */
//   Fill tcindex various parameters  
//   The number of hash  
  RTA_PUT(skb,TCA_TCINDEX_HASH,sizeof(p->hash),&p->hash);
//   Mask  
  RTA_PUT(skb,TCA_TCINDEX_MASK,sizeof(p->mask),&p->mask);
//   Offset  
  RTA_PUT(skb,TCA_TCINDEX_SHIFT,sizeof(p->shift),&p->shift);
// fall_through
  RTA_PUT(skb,TCA_TCINDEX_FALL_THROUGH,sizeof(p->fall_through),
      &p->fall_through);
  rta->rta_len = skb->tail-b;
 } else {
  if (p->perfect) {
//   If the array is non-empty perfect  
// handle  Value is the r nodes  perfect  The location of the array  
   t->tcm_handle = r-p->perfect;
  } else {
// perfect  Empty array  
   struct tcindex_filter *f;
   int i;
   t->tcm_handle = 0;
//   Traverse the list of non-perfect  ,   Find the result is  r  Filtering entry, its  key  As  handle
   for (i = 0; !t->tcm_handle && i < p->hash; i++) {
    for (f = p->h[i]; !t->tcm_handle && f;
         f = f->next) {
     if (&f->result == r)
      t->tcm_handle = f->key;
    }
   }
  }
  DPRINTK("handle = %d\n",t->tcm_handle);
//   Fill the category classification  
  if (r->res.class)
   RTA_PUT(skb, TCA_TCINDEX_CLASSID, 4, &r->res.classid);
// TCF  Extended Output  
  if (tcf_exts_dump(skb, &r->exts, &tcindex_ext_map) < 0)
   goto rtattr_failure;
//   Fill in the length of the current data  
  rta->rta_len = skb->tail-b;
// TCF  Extended output statistics  
  if (tcf_exts_dump_stats(skb, &r->exts, &tcindex_ext_map) < 0)
   goto rtattr_failure;
 }
 
 return skb->len;
rtattr_failure:
 skb_trim(skb, b - skb->data);
 return -1;
}
 
......   Continued   ......
标签: map, match, linux, mask, commercial purposes, ops, int hash, completeness, hash table size, proto, tcf, traffic control, no1, kernel traffic, police action
分类: Internet
时间: 2011-01-10

相关文章

  1. Linux kernel traffic control (18)

    Linux kernel traffic control (18) Copyleft this document owned by yfydz all, the use of GPL, free to copy, rep ...
  2. Linux kernel traffic control (1)

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the document ...
  3. Linux kernel traffic control (24)

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the document ...
  4. Linux kernel traffic control (11)

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the document ...
  5. Linux kernel traffic control (3)

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the document ...
  6. Linux kernel traffic control (15)

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the document ...
  7. Linux kernel traffic control (16)

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the document ...
  8. Linux kernel traffic control (17)

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the document ...
  9. Linux kernel traffic control (2)

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the document ...
  10. Linux kernel traffic control (4)

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the document ...
  11. Linux kernel traffic control (6)

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the document ...
  12. Linux kernel traffic control (7)

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the document ...
  13. Linux kernel traffic control (9)

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the document ...
  14. Linux kernel traffic control (12)

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the document ...
  15. Linux kernel traffic control (13)

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the document ...
  16. Linux kernel traffic control (14)

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the document ...
  17. Linux kernel traffic control (19)

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the document ...
  18. Linux kernel traffic control (22)

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the document ...
  19. Linux kernel traffic control (23)

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the document ...