Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  *  ebt_limit
  3  *
  4  *      Authors:
  5  *      Tom Marshall <tommy@home.tig-grr.com>
  6  *
  7  *      Mostly copied from netfilter's ipt_limit.c, see that file for
  8  *      more explanation
  9  *
 10  *  September, 2003
 11  *
 12  */
 13 
 14 #include <linux/netfilter_bridge/ebtables.h>
 15 #include <linux/netfilter_bridge/ebt_limit.h>
 16 #include <linux/module.h>
 17 
 18 #include <linux/netdevice.h>
 19 #include <linux/spinlock.h>
 20 
 21 static DEFINE_SPINLOCK(limit_lock);
 22 
 23 #define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
 24 
 25 #define _POW2_BELOW2(x) ((x)|((x)>>1))
 26 #define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
 27 #define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
 28 #define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
 29 #define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
 30 #define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
 31 
 32 #define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
 33 
 34 static int ebt_limit_match(const struct sk_buff *skb,
 35    const struct net_device *in, const struct net_device *out,
 36    const void *data, unsigned int datalen)
 37 {
 38         struct ebt_limit_info *info = (struct ebt_limit_info *)data;
 39         unsigned long now = jiffies;
 40 
 41         spin_lock_bh(&limit_lock);
 42         info->credit += (now - xchg(&info->prev, now)) * CREDITS_PER_JIFFY;
 43         if (info->credit > info->credit_cap)
 44                 info->credit = info->credit_cap;
 45 
 46         if (info->credit >= info->cost) {
 47                 /* We're not limited. */
 48                 info->credit -= info->cost;
 49                 spin_unlock_bh(&limit_lock);
 50                 return EBT_MATCH;
 51         }
 52 
 53         spin_unlock_bh(&limit_lock);
 54         return EBT_NOMATCH;
 55 }
 56 
 57 /* Precision saver. */
 58 static u_int32_t
 59 user2credits(u_int32_t user)
 60 {
 61         /* If multiplying would overflow... */
 62         if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
 63                 /* Divide first. */
 64                 return (user / EBT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
 65 
 66         return (user * HZ * CREDITS_PER_JIFFY) / EBT_LIMIT_SCALE;
 67 }
 68 
 69 static int ebt_limit_check(const char *tablename, unsigned int hookmask,
 70    const struct ebt_entry *e, void *data, unsigned int datalen)
 71 {
 72         struct ebt_limit_info *info = data;
 73 
 74         if (datalen != EBT_ALIGN(sizeof(struct ebt_limit_info)))
 75                 return -EINVAL;
 76 
 77         /* Check for overflow. */
 78         if (info->burst == 0 ||
 79             user2credits(info->avg * info->burst) < user2credits(info->avg)) {
 80                 printk("Overflow in ebt_limit, try lower: %u/%u\n",
 81                         info->avg, info->burst);
 82                 return -EINVAL;
 83         }
 84 
 85         /* User avg in seconds * EBT_LIMIT_SCALE: convert to jiffies * 128. */
 86         info->prev = jiffies;
 87         info->credit = user2credits(info->avg * info->burst);
 88         info->credit_cap = user2credits(info->avg * info->burst);
 89         info->cost = user2credits(info->avg);
 90         return 0;
 91 }
 92 
 93 static struct ebt_match ebt_limit_reg __read_mostly = {
 94         .name           = EBT_LIMIT_MATCH,
 95         .match          = ebt_limit_match,
 96         .check          = ebt_limit_check,
 97         .me             = THIS_MODULE,
 98 };
 99 
100 static int __init ebt_limit_init(void)
101 {
102         return ebt_register_match(&ebt_limit_reg);
103 }
104 
105 static void __exit ebt_limit_fini(void)
106 {
107         ebt_unregister_match(&ebt_limit_reg);
108 }
109 
110 module_init(ebt_limit_init);
111 module_exit(ebt_limit_fini);
112 MODULE_DESCRIPTION("Ebtables: Rate-limit match");
113 MODULE_LICENSE("GPL");
114 
  This page was automatically generated by the LXR engine.