--- zzzz-none-000/linux-2.4.17/net/bridge/br_ioctl.c 2000-11-09 23:57:53.000000000 +0000 +++ sangam-fb-322/linux-2.4.17/net/bridge/br_ioctl.c 2004-11-24 13:22:09.000000000 +0000 @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek * - * $Id: br_ioctl.c,v 1.4 2000/11/08 05:16:40 davem Exp $ + * $Id: br_ioctl.c,v 1.1.1.1.2.2 2003/07/03 18:15:53 qle Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -19,6 +19,39 @@ #include #include "br_private.h" + + + +#ifdef AVM_DELAYQUEUE +void br_token_tick(unsigned long __data) +{ + struct net_bridge *br = (struct net_bridge *)__data; + + if (br->tokens_per_tick) { + int old; + + read_lock(&br->lock); + + old = atomic_read(&br->tokens); + if (atomic_add_return(br->tokens_per_tick, &br->tokens) > 2*br->tokens_per_tick) { + /* saturation */ + atomic_set(&br->tokens, 2*br->tokens_per_tick); +#ifdef AVM_DELAYQUEUE_STAT + br->delayqueue_stat_tokenmax++; +#endif + } + + read_unlock(&br->lock); + + if (old <= 0) br_delayqueue_handle_frames(br); + + /* tick every 100ms, assume that HZ (number of jiffies per sec) is >= 10 */ + br->token_tick.expires = jiffies + HZ/10; + add_timer(&br->token_tick); + } +} +#endif + static int br_ioctl_device(struct net_bridge *br, unsigned int cmd, unsigned long arg0, @@ -73,6 +106,7 @@ b.tcn_timer_value = br_timer_get_residue(&br->tcn_timer); b.topology_change_timer_value = br_timer_get_residue(&br->topology_change_timer); b.gc_timer_value = br_timer_get_residue(&br->gc_timer); + b.br_filter_active = br->br_filter_active; if (copy_to_user((void *)arg0, &b, sizeof(b))) return -EFAULT; @@ -179,6 +213,70 @@ case BRCTL_GET_FDB_ENTRIES: return br_fdb_get_entries(br, (void *)arg0, arg1, arg2); + + case BRCTL_SET_FILTER_STATE: + br->br_filter_active = arg0?1:0; + return 0; + + case BRCTL_SET_FILTER_ENTRY: + return br_add_filter_entry(br, (void *)arg0); + + case BRCTL_DELETE_FILTER_ENTRY: + return br_del_filter_entry(br, (void *)arg0); + + case BRCTL_FLUSH_FILTER_ENTERIES: + return br_flush_filter(br); + + case BRCTL_SHOW_FILTER_ENTERIES: + return br_show_filter_entries(br, (void *)arg0, arg1); + +#ifdef AVM_DELAYQUEUE + case BRCTL_SET_LIMIT: /* limited bridge mode */ + if (arg0 != br->tokens_per_tick) { + if (0 == arg0) { + /* revert to normal operation */ + br->tokens_per_tick = 0; + br->delayqueue_max = 0; + del_timer(&br->token_tick); + br_delayqueue_handle_frames(br); + } else { + unsigned long old = br->tokens_per_tick; + atomic_set(&br->tokens, arg0/2); + br->tokens_per_tick = arg0; + br->delayqueue_max = br->tokens_per_tick * 10 /* queue packets for no more than 1 second */; + if (!old) { + /* switch to limited mode */ + struct timer_list *timer = &br->token_tick; + init_timer(timer); + timer->data = (unsigned long) br; + timer->function = br_token_tick; + timer->expires = jiffies + 1; /* immediate timeout */ + add_timer(timer); + } + } + } + return 0; + +#ifdef AVM_DELAYQUEUE_STAT + case BRCTL_GET_LIMIT_INFO: /* Query how often the bridge limit was reached */ + { + unsigned long data[8]; + data[0] = atomic_read(&br->tokens); + data[1] = br->tokens_per_tick; + data[2] = br->delayqueue_max; + data[3] = br->delayqueue_stat_suspends; + data[4] = br->delayqueue_stat_tokenmax; + data[5] = br->delayqueue_stat_drops; + data[6] = skb_queue_len(&br->delayqueue); + data[7] = 0; + + if (copy_to_user((void *)arg0, &data[0], sizeof(data))) + return -EFAULT; + } + return 0; +#endif + +#endif /* AVM_DELAYQUEUE */ } return -EOPNOTSUPP; @@ -222,8 +320,9 @@ if (cmd == BRCTL_ADD_BRIDGE) return br_add_bridge(buf); + else + return br_del_bridge(buf); - return br_del_bridge(buf); } }