* 2 of the License, or (at your option) any later version.
*
* Derived from the non IP parts of dev.c 1.0.19
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors: Ross Biro
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Mark Evans, <evansmp@uhura.aston.ac.uk>
*
#include <asm/uaccess.h>
#include <asm/system.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/cpu.h>
#include <linux/types.h>
#include <linux/kallsyms.h>
#include <linux/netpoll.h>
#include <linux/rcupdate.h>
-#include <linux/vserver/network.h>
+#include <linux/delay.h>
#ifdef CONFIG_NET_RADIO
#include <linux/wireless.h> /* Note : will define WIRELESS_EXT */
#include <net/iw_handler.h>
#endif /* CONFIG_NET_RADIO */
+#include <linux/vs_network.h>
#include <asm/current.h>
-/* This define, if set, will randomly drop a packet when congestion
- * is more than moderate. It helps fairness in the multi-interface
- * case when one of them is a hog, but it kills performance for the
- * single interface case so it is off now by default.
- */
-#undef RAND_LIE
-
-/* Setting this will sample the queue lengths and thus congestion
- * via a timer instead of as each packet is received.
- */
-#undef OFFLINE_SAMPLE
-
/*
* The list of packet types we will receive (as opposed to discard)
* and the routines to invoke.
* 86DD IPv6
*/
-static spinlock_t ptype_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(ptype_lock);
static struct list_head ptype_base[16]; /* 16 way hashed list */
static struct list_head ptype_all; /* Taps */
-#ifdef OFFLINE_SAMPLE
-static void sample_queue(unsigned long dummy);
-static struct timer_list samp_timer = TIMER_INITIALIZER(sample_queue, 0, 0);
-#endif
-
/*
* The @dev_base list is protected by @dev_base_lock and the rtln
* semaphore.
* semaphore held.
*/
struct net_device *dev_base;
-struct net_device **dev_tail = &dev_base;
-rwlock_t dev_base_lock = RW_LOCK_UNLOCKED;
+static struct net_device **dev_tail = &dev_base;
+DEFINE_RWLOCK(dev_base_lock);
EXPORT_SYMBOL(dev_base);
EXPORT_SYMBOL(dev_base_lock);
* Device drivers call our routines to queue packets here. We empty the
* queue in the local softnet handler.
*/
-DEFINE_PER_CPU(struct softnet_data, softnet_data) = { 0, };
-
-#ifdef CONFIG_NET_FASTROUTE
-int netdev_fastroute;
-int netdev_fastroute_obstacles;
-#endif
+DEFINE_PER_CPU(struct softnet_data, softnet_data) = { NULL };
#ifdef CONFIG_SYSFS
extern int netdev_sysfs_init(void);
#define netdev_unregister_sysfs(dev) do { } while(0)
#endif
-/* netdump function */
-void (*netdump_func) (struct pt_regs *regs) = NULL;
/*******************************************************************************
int hash;
spin_lock_bh(&ptype_lock);
-#ifdef CONFIG_NET_FASTROUTE
- if (pt->af_packet_priv) {
- netdev_fastroute_obstacles++;
- dev_clear_fastroute(pt->dev);
- }
-#endif
if (pt->type == htons(ETH_P_ALL)) {
netdev_nit++;
list_add_rcu(&pt->list, &ptype_all);
spin_unlock_bh(&ptype_lock);
}
-extern void linkwatch_run_queue(void);
-
-
-
/**
* __dev_remove_pack - remove packet handler
* @pt: packet type declaration
list_for_each_entry(pt1, head, list) {
if (pt == pt1) {
-#ifdef CONFIG_NET_FASTROUTE
- if (pt->af_packet_priv)
- netdev_fastroute_obstacles--;
-#endif
list_del_rcu(&pt->list);
goto out;
}
* returns 0 on error and 1 on success. This is a generic routine to
* all netdevices.
*/
-int netdev_boot_setup_add(char *name, struct ifmap *map)
+static int netdev_boot_setup_add(char *name, struct ifmap *map)
{
struct netdev_boot_setup *s;
int i;
return dev;
}
-/*
- Return value is changed to int to prevent illegal usage in future.
- It is still legal to use to check for device existence.
-
- User should understand, that the result returned by this function
- is meaningless, if it was not issued under rtnl semaphore.
- */
-
-/**
- * dev_get - test if a device exists
- * @name: name to test for
- *
- * Test if a name exists. Returns true if the name is found. In order
- * to be sure the name is not allocated or removed during the test the
- * caller must hold the rtnl semaphore.
- *
- * This function exists only for back compatibility with older
- * drivers.
- */
-int __dev_get(const char *name)
-{
- struct net_device *dev;
-
- read_lock(&dev_base_lock);
- dev = __dev_get_by_name(name);
- read_unlock(&dev_base_lock);
- return dev != NULL;
-}
-
/**
* __dev_get_by_index - find a device by its ifindex
* @ifindex: index of device
return dev;
}
-struct net_device *__dev_getfirstbyhwtype(unsigned short type)
-{
- struct net_device *dev;
-
- for (dev = dev_base; dev; dev = dev->next)
- if (dev->type == type)
- break;
- return dev;
-}
-
-EXPORT_SYMBOL(__dev_getfirstbyhwtype);
+EXPORT_SYMBOL(dev_getbyhwaddr);
struct net_device *dev_getfirstbyhwtype(unsigned short type)
{
struct net_device *dev;
rtnl_lock();
- dev = __dev_getfirstbyhwtype(type);
- if (dev)
- dev_hold(dev);
+ for (dev = dev_base; dev; dev = dev->next) {
+ if (dev->type == type) {
+ dev_hold(dev);
+ break;
+ }
+ }
rtnl_unlock();
return dev;
}
struct net_device *dev;
read_lock(&dev_base_lock);
- dev = __dev_get_by_flags(if_flags, mask);
- if (dev)
- dev_hold(dev);
- read_unlock(&dev_base_lock);
- return dev;
-}
-
-/**
- * __dev_get_by_flags - find any device with given flags
- * @if_flags: IFF_* values
- * @mask: bitmask of bits in if_flags to check
- *
- * Search for any interface with the given flags. Returns NULL if a device
- * is not found or a pointer to the device. The caller must hold either
- * the RTNL semaphore or @dev_base_lock.
- */
-
-struct net_device *__dev_get_by_flags(unsigned short if_flags, unsigned short mask)
-{
- struct net_device *dev;
-
for (dev = dev_base; dev != NULL; dev = dev->next) {
- if (((dev->flags ^ if_flags) & mask) == 0)
- return dev;
+ if (((dev->flags ^ if_flags) & mask) == 0) {
+ dev_hold(dev);
+ break;
+ }
}
- return NULL;
+ read_unlock(&dev_base_lock);
+ return dev;
}
/**
return err;
}
+/**
+ * netdev_features_change - device changes fatures
+ * @dev: device to cause notification
+ *
+ * Called to indicate a device has changed features.
+ */
+void netdev_features_change(struct net_device *dev)
+{
+ notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev);
+}
+EXPORT_SYMBOL(netdev_features_change);
+
/**
* netdev_state_change - device changes state
* @dev: device to cause notification
}
-/*
- * Some old buggy device drivers change get_stats after registering
- * the device. Try and trap them here.
- * This can be elimnated when all devices are known fixed.
- */
-static inline int get_stats_changed(struct net_device *dev)
-{
- int changed = dev->last_stats != dev->get_stats;
- dev->last_stats = dev->get_stats;
- return changed;
-}
-
/**
* dev_open - prepare an interface for use.
* @dev: device to open
if (dev->flags & IFF_UP)
return 0;
- /*
- * Check for broken device drivers.
- */
- if (get_stats_changed(dev) && net_ratelimit()) {
- printk(KERN_ERR "%s: driver changed get_stats after register\n",
- dev->name);
- }
-
/*
* Is it even present?
*/
clear_bit(__LINK_STATE_START, &dev->state);
}
- /*
- * Check for more broken device drivers.
- */
- if (get_stats_changed(dev) && net_ratelimit()) {
- printk(KERN_ERR "%s: driver changed get_stats in open\n",
- dev->name);
- }
-
/*
* If it went open OK then:
*/
return ret;
}
-#ifdef CONFIG_NET_FASTROUTE
-
-static void dev_do_clear_fastroute(struct net_device *dev)
-{
- if (dev->accept_fastpath) {
- int i;
-
- for (i = 0; i <= NETDEV_FASTROUTE_HMASK; i++) {
- struct dst_entry *dst;
-
- write_lock_irq(&dev->fastpath_lock);
- dst = dev->fastpath[i];
- dev->fastpath[i] = NULL;
- write_unlock_irq(&dev->fastpath_lock);
-
- dst_release(dst);
- }
- }
-}
-
-void dev_clear_fastroute(struct net_device *dev)
-{
- if (dev) {
- dev_do_clear_fastroute(dev);
- } else {
- read_lock(&dev_base_lock);
- for (dev = dev_base; dev; dev = dev->next)
- dev_do_clear_fastroute(dev);
- read_unlock(&dev_base_lock);
- }
-}
-#endif
-
/**
* dev_close - shutdown an interface.
* @dev: device to shutdown
smp_mb__after_clear_bit(); /* Commit netif_running(). */
while (test_bit(__LINK_STATE_RX_SCHED, &dev->state)) {
/* No hurry. */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
+ msleep(1);
}
/*
*/
dev->flags &= ~IFF_UP;
-#ifdef CONFIG_NET_FASTROUTE
- dev_clear_fastroute(dev);
-#endif
/*
* Tell people we are down
return notifier_call_chain(&netdev_chain, val, v);
}
+/* When > 0 there are consumers of rx skb time stamps */
+static atomic_t netstamp_needed = ATOMIC_INIT(0);
+
+void net_enable_timestamp(void)
+{
+ atomic_inc(&netstamp_needed);
+}
+
+void net_disable_timestamp(void)
+{
+ atomic_dec(&netstamp_needed);
+}
+
+void __net_timestamp(struct sk_buff *skb)
+{
+ struct timeval tv;
+
+ do_gettimeofday(&tv);
+ skb_set_timestamp(skb, &tv);
+}
+EXPORT_SYMBOL(__net_timestamp);
+
+static inline void net_timestamp(struct sk_buff *skb)
+{
+ if (atomic_read(&netstamp_needed))
+ __net_timestamp(skb);
+ else {
+ skb->tstamp.off_sec = 0;
+ skb->tstamp.off_usec = 0;
+ }
+}
+
/*
* Support routine. Sends outgoing frames to any network
* taps currently in use.
*/
+#if !((defined(CONFIG_VNET) || defined(CONFIG_VNET_MODULE)))
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12)
+static
+#endif
+#endif
void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
{
struct packet_type *ptype;
- net_timestamp(&skb->stamp);
+
+ net_timestamp(skb);
rcu_read_lock();
list_for_each_entry_rcu(ptype, &ptype_all, list) {
skb2->h.raw = skb2->nh.raw;
skb2->pkt_type = PACKET_OUTGOING;
- ptype->func(skb2, skb->dev, ptype);
+ ptype->func(skb2, skb->dev, ptype, skb->dev);
}
}
rcu_read_unlock();
* Invalidate hardware checksum when packet is to be mangled, and
* complete checksum manually on outgoing path.
*/
-int skb_checksum_help(struct sk_buff **pskb, int inward)
+int skb_checksum_help(struct sk_buff *skb, int inward)
{
unsigned int csum;
- int ret = 0, offset = (*pskb)->h.raw - (*pskb)->data;
+ int ret = 0, offset = skb->h.raw - skb->data;
if (inward) {
- (*pskb)->ip_summed = CHECKSUM_NONE;
+ skb->ip_summed = CHECKSUM_NONE;
goto out;
}
- if (skb_shared(*pskb) || skb_cloned(*pskb)) {
- struct sk_buff *newskb = skb_copy(*pskb, GFP_ATOMIC);
- if (!newskb) {
- ret = -ENOMEM;
+ if (skb_cloned(skb)) {
+ ret = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+ if (ret)
goto out;
- }
- if ((*pskb)->sk)
- skb_set_owner_w(newskb, (*pskb)->sk);
- kfree_skb(*pskb);
- *pskb = newskb;
}
- if (offset > (int)(*pskb)->len)
- BUG();
- csum = skb_checksum(*pskb, offset, (*pskb)->len-offset, 0);
+ BUG_ON(offset > (int)skb->len);
+ csum = skb_checksum(skb, offset, skb->len-offset, 0);
- offset = (*pskb)->tail - (*pskb)->h.raw;
- if (offset <= 0)
- BUG();
- if ((*pskb)->csum + 2 > offset)
- BUG();
+ offset = skb->tail - skb->h.raw;
+ BUG_ON(offset <= 0);
+ BUG_ON(skb->csum + 2 > offset);
- *(u16*)((*pskb)->h.raw + (*pskb)->csum) = csum_fold(csum);
- (*pskb)->ip_summed = CHECKSUM_NONE;
+ *(u16*)(skb->h.raw + skb->csum) = csum_fold(csum);
+ skb->ip_summed = CHECKSUM_NONE;
out:
return ret;
}
+/* Take action when hardware reception checksum errors are detected. */
+#ifdef CONFIG_BUG
+void netdev_rx_csum_fault(struct net_device *dev)
+{
+ if (net_ratelimit()) {
+ printk(KERN_ERR "%s: hw csum failure.\n",
+ dev ? dev->name : "<unknown>");
+ dump_stack();
+ }
+}
+EXPORT_SYMBOL(netdev_rx_csum_fault);
+#endif
+
#ifdef CONFIG_HIGHMEM
/* Actually, we should eliminate this check as soon as we know, that:
* 1. IOMMU is present and allows to map all the memory.
return 0;
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
- if (skb_shinfo(skb)->frags[i].page >= highmem_start_page)
+ if (PageHighMem(skb_shinfo(skb)->frags[i].page))
return 1;
return 0;
#define illegal_highdma(dev, skb) (0)
#endif
-extern void skb_release_data(struct sk_buff *);
-
/* Keep head the same: replace data */
-int __skb_linearize(struct sk_buff *skb, int gfp_mask)
+int __skb_linearize(struct sk_buff *skb, gfp_t gfp_mask)
{
unsigned int size;
u8 *data;
atomic_set(&ninfo->dataref, 1);
ninfo->tso_size = skb_shinfo(skb)->tso_size;
ninfo->tso_segs = skb_shinfo(skb)->tso_segs;
+ ninfo->ufo_size = skb_shinfo(skb)->ufo_size;
ninfo->nr_frags = 0;
ninfo->frag_list = NULL;
return 0;
}
-#define HARD_TX_LOCK_BH(dev, cpu) { \
+#define HARD_TX_LOCK(dev, cpu) { \
if ((dev->features & NETIF_F_LLTX) == 0) { \
- spin_lock_bh(&dev->xmit_lock); \
+ spin_lock(&dev->xmit_lock); \
dev->xmit_lock_owner = cpu; \
} \
}
-#define HARD_TX_UNLOCK_BH(dev) { \
+#define HARD_TX_UNLOCK(dev) { \
if ((dev->features & NETIF_F_LLTX) == 0) { \
dev->xmit_lock_owner = -1; \
- spin_unlock_bh(&dev->xmit_lock); \
+ spin_unlock(&dev->xmit_lock); \
} \
}
* A negative errno code is returned on a failure. A success does not
* guarantee the frame will be transmitted as it may be dropped due
* to congestion or traffic shaping.
+ *
+ * -----------------------------------------------------------------------------------
+ * I notice this method can also return errors from the queue disciplines,
+ * including NET_XMIT_DROP, which is a positive value. So, errors can also
+ * be positive.
+ *
+ * Regardless of the return value, the skb is consumed, so it is currently
+ * difficult to retry a send to this method. (You can bump the ref count
+ * before sending to hold a reference for retry if you are careful.)
+ *
+ * When calling this method, interrupts MUST be enabled. This is because
+ * the BH enable code must have IRQs enabled so that it will not deadlock.
+ * --BLG
*/
int dev_queue_xmit(struct sk_buff *skb)
(!(dev->features & (NETIF_F_HW_CSUM | NETIF_F_NO_CSUM)) &&
(!(dev->features & NETIF_F_IP_CSUM) ||
skb->protocol != htons(ETH_P_IP))))
- if (skb_checksum_help(&skb, 0))
+ if (skb_checksum_help(skb, 0))
goto out_kfree_skb;
- rcu_read_lock();
+ spin_lock_prefetch(&dev->queue_lock);
+
+ /* Disable soft irqs for various locks below. Also
+ * stops preemption for RCU.
+ */
+ local_bh_disable();
+
/* Updates of qdisc are serialized by queue_lock.
* The struct Qdisc which is pointed to by qdisc is now a
* rcu structure - it may be accessed without acquiring
* also serializes access to the device queue.
*/
- q = dev->qdisc;
- smp_read_barrier_depends();
+ q = rcu_dereference(dev->qdisc);
#ifdef CONFIG_NET_CLS_ACT
skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_EGRESS);
#endif
if (q->enqueue) {
/* Grab device queue */
- spin_lock_bh(&dev->queue_lock);
-
- rc = q->enqueue(skb, q);
-
- qdisc_run(dev);
-
- spin_unlock_bh(&dev->queue_lock);
- rcu_read_unlock();
- rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc;
- goto out;
+ spin_lock(&dev->queue_lock);
+ q = dev->qdisc;
+ if (q->enqueue) {
+ rc = q->enqueue(skb, q);
+ qdisc_run(dev);
+ spin_unlock(&dev->queue_lock);
+
+ rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc;
+ goto out;
+ }
+ spin_unlock(&dev->queue_lock);
}
- rcu_read_unlock();
/* The device has no queue. Common case for software devices:
loopback, all the sorts of tunnels...
Either shot noqueue qdisc, it is even simpler 8)
*/
if (dev->flags & IFF_UP) {
- int cpu = get_cpu();
+ int cpu = smp_processor_id(); /* ok because BHs are off */
if (dev->xmit_lock_owner != cpu) {
- HARD_TX_LOCK_BH(dev, cpu);
- put_cpu();
+ HARD_TX_LOCK(dev, cpu);
if (!netif_queue_stopped(dev)) {
if (netdev_nit)
rc = 0;
if (!dev->hard_start_xmit(skb, dev)) {
- HARD_TX_UNLOCK_BH(dev);
+ HARD_TX_UNLOCK(dev);
goto out;
}
}
- HARD_TX_UNLOCK_BH(dev);
+ HARD_TX_UNLOCK(dev);
if (net_ratelimit())
printk(KERN_CRIT "Virtual device %s asks to "
"queue packet!\n", dev->name);
- goto out_enetdown;
} else {
- put_cpu();
/* Recursion is detected! It is possible,
* unfortunately */
if (net_ratelimit())
"%s, fix it urgently!\n", dev->name);
}
}
-out_enetdown:
+
rc = -ENETDOWN;
+ local_bh_enable();
+
out_kfree_skb:
kfree_skb(skb);
+ return rc;
out:
+ local_bh_enable();
return rc;
}
Receiver routines
=======================================================================*/
-int netdev_max_backlog = 300;
+int netdev_max_backlog = 1000;
+int netdev_budget = 300;
int weight_p = 64; /* old backlog weight */
-/* These numbers are selected based on intuition and some
- * experimentatiom, if you have more scientific way of doing this
- * please go ahead and fix things.
- */
-int no_cong_thresh = 10;
-int no_cong = 20;
-int lo_cong = 100;
-int mod_cong = 290;
DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, };
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-atomic_t netdev_dropping = ATOMIC_INIT(0);
-static unsigned long netdev_fc_mask = 1;
-unsigned long netdev_fc_xoff;
-spinlock_t netdev_fc_lock = SPIN_LOCK_UNLOCKED;
-
-static struct
-{
- void (*stimul)(struct net_device *);
- struct net_device *dev;
-} netdev_fc_slots[BITS_PER_LONG];
-
-int netdev_register_fc(struct net_device *dev,
- void (*stimul)(struct net_device *dev))
-{
- int bit = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&netdev_fc_lock, flags);
- if (netdev_fc_mask != ~0UL) {
- bit = ffz(netdev_fc_mask);
- netdev_fc_slots[bit].stimul = stimul;
- netdev_fc_slots[bit].dev = dev;
- set_bit(bit, &netdev_fc_mask);
- clear_bit(bit, &netdev_fc_xoff);
- }
- spin_unlock_irqrestore(&netdev_fc_lock, flags);
- return bit;
-}
-
-void netdev_unregister_fc(int bit)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&netdev_fc_lock, flags);
- if (bit > 0) {
- netdev_fc_slots[bit].stimul = NULL;
- netdev_fc_slots[bit].dev = NULL;
- clear_bit(bit, &netdev_fc_mask);
- clear_bit(bit, &netdev_fc_xoff);
- }
- spin_unlock_irqrestore(&netdev_fc_lock, flags);
-}
-
-static void netdev_wakeup(void)
-{
- unsigned long xoff;
-
- spin_lock(&netdev_fc_lock);
- xoff = netdev_fc_xoff;
- netdev_fc_xoff = 0;
- while (xoff) {
- int i = ffz(~xoff);
- xoff &= ~(1 << i);
- netdev_fc_slots[i].stimul(netdev_fc_slots[i].dev);
- }
- spin_unlock(&netdev_fc_lock);
-}
-#endif
-
-static void get_sample_stats(int cpu)
-{
-#ifdef RAND_LIE
- unsigned long rd;
- int rq;
-#endif
- struct softnet_data *sd = &per_cpu(softnet_data, cpu);
- int blog = sd->input_pkt_queue.qlen;
- int avg_blog = sd->avg_blog;
-
- avg_blog = (avg_blog >> 1) + (blog >> 1);
-
- if (avg_blog > mod_cong) {
- /* Above moderate congestion levels. */
- sd->cng_level = NET_RX_CN_HIGH;
-#ifdef RAND_LIE
- rd = net_random();
- rq = rd % netdev_max_backlog;
- if (rq < avg_blog) /* unlucky bastard */
- sd->cng_level = NET_RX_DROP;
-#endif
- } else if (avg_blog > lo_cong) {
- sd->cng_level = NET_RX_CN_MOD;
-#ifdef RAND_LIE
- rd = net_random();
- rq = rd % netdev_max_backlog;
- if (rq < avg_blog) /* unlucky bastard */
- sd->cng_level = NET_RX_CN_HIGH;
-#endif
- } else if (avg_blog > no_cong)
- sd->cng_level = NET_RX_CN_LOW;
- else /* no congestion */
- sd->cng_level = NET_RX_SUCCESS;
-
- sd->avg_blog = avg_blog;
-}
-
-#ifdef OFFLINE_SAMPLE
-static void sample_queue(unsigned long dummy)
-{
-/* 10 ms 0r 1ms -- i don't care -- JHS */
- int next_tick = 1;
- int cpu = smp_processor_id();
-
- get_sample_stats(cpu);
- next_tick += jiffies;
- mod_timer(&samp_timer, next_tick);
-}
-#endif
-
-
/**
* netif_rx - post buffer to the network code
* @skb: buffer to post
int netif_rx(struct sk_buff *skb)
{
- int this_cpu;
struct softnet_data *queue;
unsigned long flags;
-#ifdef CONFIG_NETPOLL
- if (skb->dev->netpoll_rx && netpoll_rx(skb)) {
- kfree_skb(skb);
+ /* if netpoll wants it, pretend we never saw it */
+ if (netpoll_rx(skb))
return NET_RX_DROP;
- }
-#endif
-
- if (!skb->stamp.tv_sec)
- net_timestamp(&skb->stamp);
+
+ if (!skb->tstamp.off_sec)
+ net_timestamp(skb);
/*
* The code is rearranged so that the path is the most
* short when CPU is congested, but is still operating.
*/
local_irq_save(flags);
- this_cpu = smp_processor_id();
queue = &__get_cpu_var(softnet_data);
__get_cpu_var(netdev_rx_stat).total++;
if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {
if (queue->input_pkt_queue.qlen) {
- if (queue->throttle)
- goto drop;
-
enqueue:
dev_hold(skb->dev);
__skb_queue_tail(&queue->input_pkt_queue, skb);
-#ifndef OFFLINE_SAMPLE
- get_sample_stats(this_cpu);
-#endif
local_irq_restore(flags);
- return queue->cng_level;
- }
-
- if (queue->throttle) {
- queue->throttle = 0;
-#ifdef CONFIG_NET_HW_FLOWCONTROL
- if (atomic_dec_and_test(&netdev_dropping))
- netdev_wakeup();
-#endif
+ return NET_RX_SUCCESS;
}
netif_rx_schedule(&queue->backlog_dev);
goto enqueue;
}
- if (!queue->throttle) {
- queue->throttle = 1;
- __get_cpu_var(netdev_rx_stat).throttled++;
-#ifdef CONFIG_NET_HW_FLOWCONTROL
- atomic_inc(&netdev_dropping);
-#endif
- }
-
-drop:
__get_cpu_var(netdev_rx_stat).dropped++;
local_irq_restore(flags);
return NET_RX_DROP;
}
-static __inline__ void skb_bond(struct sk_buff *skb)
+int netif_rx_ni(struct sk_buff *skb)
+{
+ int err;
+
+ preempt_disable();
+ err = netif_rx(skb);
+ if (local_softirq_pending())
+ do_softirq();
+ preempt_enable();
+
+ return err;
+}
+
+EXPORT_SYMBOL(netif_rx_ni);
+
+static inline struct net_device *skb_bond(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
- if (dev->master) {
- skb->real_dev = skb->dev;
+ if (dev->master)
skb->dev = dev->master;
- }
+
+ return dev;
}
static void net_tx_action(struct softirq_action *h)
}
static __inline__ int deliver_skb(struct sk_buff *skb,
- struct packet_type *pt_prev, int last)
+ struct packet_type *pt_prev,
+ struct net_device *orig_dev)
{
atomic_inc(&skb->users);
- return pt_prev->func(skb, skb->dev, pt_prev);
+ return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
}
-
#if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE)
-int (*br_handle_frame_hook)(struct sk_buff *skb);
+int (*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff **pskb);
+struct net_bridge;
+struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
+ unsigned char *addr);
+void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
-static __inline__ int handle_bridge(struct sk_buff *skb,
- struct packet_type *pt_prev)
+static __inline__ int handle_bridge(struct sk_buff **pskb,
+ struct packet_type **pt_prev, int *ret,
+ struct net_device *orig_dev)
{
- int ret = NET_RX_DROP;
- if (pt_prev)
- ret = deliver_skb(skb, pt_prev, 0);
+ struct net_bridge_port *port;
- return ret;
-}
-
-#endif
-
-static inline int __handle_bridge(struct sk_buff *skb,
- struct packet_type **pt_prev, int *ret)
-{
-#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
- if (skb->dev->br_port && skb->pkt_type != PACKET_LOOPBACK) {
- *ret = handle_bridge(skb, *pt_prev);
- if (br_handle_frame_hook(skb) == 0)
- return 1;
+ if ((*pskb)->pkt_type == PACKET_LOOPBACK ||
+ (port = rcu_dereference((*pskb)->dev->br_port)) == NULL)
+ return 0;
+ if (*pt_prev) {
+ *ret = deliver_skb(*pskb, *pt_prev, orig_dev);
*pt_prev = NULL;
- }
-#endif
- return 0;
+ }
+
+ return br_handle_frame_hook(port, pskb);
}
-
+#else
+#define handle_bridge(skb, pt_prev, ret, orig_dev) (0)
+#endif
#ifdef CONFIG_NET_CLS_ACT
/* TODO: Maybe we should just force sch_ingress to be compiled in
* the ingress scheduler, you just cant add policies on ingress.
*
*/
-int ing_filter(struct sk_buff *skb)
+static int ing_filter(struct sk_buff *skb)
{
struct Qdisc *q;
struct net_device *dev = skb->dev;
__u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd);
if (MAX_RED_LOOP < ttl++) {
printk("Redir loop detected Dropping packet (%s->%s)\n",
- skb->input_dev?skb->input_dev->name:"??",skb->dev->name);
+ skb->input_dev->name, skb->dev->name);
return TC_ACT_SHOT;
}
skb->tc_verd = SET_TC_RTTL(skb->tc_verd,ttl);
skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS);
- if (NULL == skb->input_dev) {
- skb->input_dev = skb->dev;
- printk("ing_filter: fixed %s out %s\n",skb->input_dev->name,skb->dev->name);
- }
+
spin_lock(&dev->ingress_lock);
if ((q = dev->qdisc_ingress) != NULL)
result = q->enqueue(skb, q);
int netif_receive_skb(struct sk_buff *skb)
{
struct packet_type *ptype, *pt_prev;
+ struct net_device *orig_dev;
int ret = NET_RX_DROP;
unsigned short type;
-#ifdef CONFIG_NETPOLL
- if (skb->dev->netpoll_rx && skb->dev->poll && netpoll_rx(skb)) {
- kfree_skb(skb);
+ /* if we've gotten here through NAPI, check netpoll */
+ if (skb->dev->poll && netpoll_rx(skb))
return NET_RX_DROP;
- }
-#endif
- if (!skb->stamp.tv_sec)
- net_timestamp(&skb->stamp);
+ if (!skb->tstamp.off_sec)
+ net_timestamp(skb);
- skb_bond(skb);
+ if (!skb->input_dev)
+ skb->input_dev = skb->dev;
- __get_cpu_var(netdev_rx_stat).total++;
+ orig_dev = skb_bond(skb);
-#ifdef CONFIG_NET_FASTROUTE
- if (skb->pkt_type == PACKET_FASTROUTE) {
- __get_cpu_var(netdev_rx_stat).fastroute_deferred_out++;
- return dev_queue_xmit(skb);
- }
-#endif
+ __get_cpu_var(netdev_rx_stat).total++;
skb->h.raw = skb->nh.raw = skb->data;
skb->mac_len = skb->nh.raw - skb->mac.raw;
pt_prev = NULL;
+
+ rcu_read_lock();
+
#ifdef CONFIG_NET_CLS_ACT
if (skb->tc_verd & TC_NCLS) {
skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
- rcu_read_lock();
goto ncls;
}
- #endif
+#endif
- rcu_read_lock();
list_for_each_entry_rcu(ptype, &ptype_all, list) {
if (!ptype->dev || ptype->dev == skb->dev) {
if (pt_prev)
- ret = deliver_skb(skb, pt_prev, 0);
+ ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = ptype;
}
}
#ifdef CONFIG_NET_CLS_ACT
if (pt_prev) {
- atomic_inc(&skb->users);
- ret = pt_prev->func(skb, skb->dev, pt_prev);
+ ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = NULL; /* noone else should process this after*/
} else {
skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
handle_diverter(skb);
- if (__handle_bridge(skb, &pt_prev, &ret))
+ if (handle_bridge(&skb, &pt_prev, &ret, orig_dev))
goto out;
type = skb->protocol;
if (ptype->type == type &&
(!ptype->dev || ptype->dev == skb->dev)) {
if (pt_prev)
- ret = deliver_skb(skb, pt_prev, 0);
+ ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = ptype;
}
}
if (pt_prev) {
- ret = pt_prev->func(skb, skb->dev, pt_prev);
+ ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
} else {
kfree_skb(skb);
/* Jamal, now you will not able to escape explaining
struct softnet_data *queue = &__get_cpu_var(softnet_data);
unsigned long start_time = jiffies;
+ backlog_dev->weight = weight_p;
for (;;) {
struct sk_buff *skb;
struct net_device *dev;
if (work >= quota || jiffies - start_time > 1)
break;
-#ifdef CONFIG_NET_HW_FLOWCONTROL
- if (queue->throttle &&
- queue->input_pkt_queue.qlen < no_cong_thresh ) {
- queue->throttle = 0;
- if (atomic_dec_and_test(&netdev_dropping)) {
- netdev_wakeup();
- break;
- }
- }
-#endif
}
backlog_dev->quota -= work;
smp_mb__before_clear_bit();
netif_poll_enable(backlog_dev);
- if (queue->throttle) {
- queue->throttle = 0;
-#ifdef CONFIG_NET_HW_FLOWCONTROL
- if (atomic_dec_and_test(&netdev_dropping))
- netdev_wakeup();
-#endif
- }
local_irq_enable();
return 0;
}
{
struct softnet_data *queue = &__get_cpu_var(softnet_data);
unsigned long start_time = jiffies;
- int budget = netdev_max_backlog;
+ int budget = netdev_budget;
+ void *have;
-
local_irq_disable();
while (!list_empty(&queue->poll_list)) {
dev = list_entry(queue->poll_list.next,
struct net_device, poll_list);
+ have = netpoll_poll_lock(dev);
if (dev->quota <= 0 || dev->poll(dev, &budget)) {
+ netpoll_poll_unlock(have);
local_irq_disable();
list_del(&dev->poll_list);
list_add_tail(&dev->poll_list, &queue->poll_list);
else
dev->quota = dev->weight;
} else {
+ netpoll_poll_unlock(have);
dev_put(dev);
local_irq_disable();
}
total = 0;
for (dev = dev_base; dev; dev = dev->next) {
- if (!dev_in_nx_info(dev, current->nx_info))
+ if (vx_flags(VXF_HIDE_NETIF, 0) &&
+ !dev_in_nx_info(dev, current->nx_info))
continue;
for (i = 0; i < NPROTO; i++) {
if (gifconf_list[i]) {
{
struct nx_info *nxi = current->nx_info;
- if (!dev_in_nx_info(dev, nxi))
+ if (vx_flags(VXF_HIDE_NETIF, 0) && !dev_in_nx_info(dev, nxi))
return;
if (dev->get_stats) {
struct net_device_stats *stats = dev->get_stats(dev);
struct netif_rx_stats *s = v;
seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
- s->total, s->dropped, s->time_squeeze, s->throttled,
- s->fastroute_hit, s->fastroute_success, s->fastroute_defer,
- s->fastroute_deferred_out,
-#if 0
- s->fastroute_latency_reduction
-#else
- s->cpu_collision
-#endif
- );
+ s->total, s->dropped, s->time_squeeze, 0,
+ 0, 0, 0, 0, /* was fastroute */
+ s->cpu_collision );
return 0;
}
{
unsigned short old_flags = dev->flags;
- dev->flags |= IFF_PROMISC;
if ((dev->promiscuity += inc) == 0)
dev->flags &= ~IFF_PROMISC;
- if (dev->flags ^ old_flags) {
-#ifdef CONFIG_NET_FASTROUTE
- if (dev->flags & IFF_PROMISC) {
- netdev_fastroute_obstacles++;
- dev_clear_fastroute(dev);
- } else
- netdev_fastroute_obstacles--;
-#endif
+ else
+ dev->flags |= IFF_PROMISC;
+ if (dev->flags != old_flags) {
dev_mc_upload(dev);
printk(KERN_INFO "device %s %s promiscuous mode\n",
dev->name, (dev->flags & IFF_PROMISC) ? "entered" :
return err;
}
+int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
+{
+ int err;
+
+ if (!dev->set_mac_address)
+ return -EOPNOTSUPP;
+ if (sa->sa_family != dev->type)
+ return -EINVAL;
+ if (!netif_device_present(dev))
+ return -ENODEV;
+ err = dev->set_mac_address(dev, sa);
+ if (!err)
+ notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);
+ return err;
+}
/*
* Perform the SIOCxIFxxx calls.
return dev_set_mtu(dev, ifr->ifr_mtu);
case SIOCGIFHWADDR:
- memcpy(ifr->ifr_hwaddr.sa_data, dev->dev_addr,
- min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len));
+ if (!dev->addr_len)
+ memset(ifr->ifr_hwaddr.sa_data, 0, sizeof ifr->ifr_hwaddr.sa_data);
+ else
+ memcpy(ifr->ifr_hwaddr.sa_data, dev->dev_addr,
+ min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len));
ifr->ifr_hwaddr.sa_family = dev->type;
return 0;
case SIOCSIFHWADDR:
- if (!dev->set_mac_address)
- return -EOPNOTSUPP;
- if (ifr->ifr_hwaddr.sa_family != dev->type)
- return -EINVAL;
- if (!netif_device_present(dev))
- return -ENODEV;
- err = dev->set_mac_address(dev, &ifr->ifr_hwaddr);
- if (!err)
- notifier_call_chain(&netdev_chain,
- NETDEV_CHANGEADDR, dev);
- return err;
+ return dev_set_mac_address(dev, &ifr->ifr_hwaddr);
case SIOCSIFHWBROADCAST:
if (ifr->ifr_hwaddr.sa_family != dev->type)
case SIOCBONDENSLAVE:
case SIOCBONDRELEASE:
case SIOCBONDSETHWADDR:
- case SIOCBONDSLAVEINFOQUERY:
- case SIOCBONDINFOQUERY:
case SIOCBONDCHANGEACTIVE:
case SIOCBRADDIF:
case SIOCBRDELIF:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
+ /* fall through */
+ case SIOCBONDSLAVEINFOQUERY:
+ case SIOCBONDINFOQUERY:
dev_load(ifr.ifr_name);
rtnl_lock();
ret = dev_ifsioc(&ifr, cmd);
/* Follow me in net/core/wireless.c */
ret = wireless_process_ioctl(&ifr, cmd);
rtnl_unlock();
- if (!ret && IW_IS_GET(cmd) &&
+ if (IW_IS_GET(cmd) &&
copy_to_user(arg, &ifr,
sizeof(struct ifreq)))
ret = -EFAULT;
* number. The caller must hold the rtnl semaphore or the
* dev_base_lock to be sure it remains unique.
*/
-int dev_new_index(void)
+static int dev_new_index(void)
{
static int ifindex;
for (;;) {
static int dev_boot_phase = 1;
/* Delayed registration/unregisteration */
-static spinlock_t net_todo_list_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(net_todo_list_lock);
static struct list_head net_todo_list = LIST_HEAD_INIT(net_todo_list);
static inline void net_set_todo(struct net_device *dev)
* chain. 0 is returned on success. A negative errno code is returned
* on a failure to set up the device, or if the name is a duplicate.
*
- * Callers must hold the rtnl semaphore. See the comment at the
- * end of Space.c for details about the locking. You may want
+ * Callers must hold the rtnl semaphore. You may want
* register_netdev() instead of this.
*
* BUGS:
spin_lock_init(&dev->ingress_lock);
#endif
-#ifdef CONFIG_NET_FASTROUTE
- dev->fastpath_lock = RW_LOCK_UNLOCKED;
-#endif
-
ret = alloc_divert_blk(dev);
if (ret)
goto out;
dev->features &= ~NETIF_F_SG;
}
+ /* TSO requires that SG is present as well. */
+ if ((dev->features & NETIF_F_TSO) &&
+ !(dev->features & NETIF_F_SG)) {
+ printk("%s: Dropping NETIF_F_TSO since no SG feature.\n",
+ dev->name);
+ dev->features &= ~NETIF_F_TSO;
+ }
+ if (dev->features & NETIF_F_UFO) {
+ if (!(dev->features & NETIF_F_HW_CSUM)) {
+ printk(KERN_ERR "%s: Dropping NETIF_F_UFO since no "
+ "NETIF_F_HW_CSUM feature.\n",
+ dev->name);
+ dev->features &= ~NETIF_F_UFO;
+ }
+ if (!(dev->features & NETIF_F_SG)) {
+ printk(KERN_ERR "%s: Dropping NETIF_F_UFO since no "
+ "NETIF_F_SG feature.\n",
+ dev->name);
+ dev->features &= ~NETIF_F_UFO;
+ }
+ }
+
/*
* nil rebuild_header routine,
* that should be never called and used as just bug trap.
goto out;
}
+/**
+ * register_netdev - register a network device
+ * @dev: device to register
+ *
+ * Take a completed network device structure and add it to the kernel
+ * interfaces. A %NETDEV_REGISTER message is sent to the netdev notifier
+ * chain. 0 is returned on success. A negative errno code is returned
+ * on a failure to set up the device, or if the name is a duplicate.
+ *
+ * This is a wrapper around register_netdev that takes the rtnl semaphore
+ * and expands the device name if you passed a format string to
+ * alloc_netdev.
+ */
+int register_netdev(struct net_device *dev)
+{
+ int err;
+
+ rtnl_lock();
+
+ /*
+ * If the name is a format string the caller wants us to do a
+ * name allocation.
+ */
+ if (strchr(dev->name, '%')) {
+ err = dev_alloc_name(dev, dev->name);
+ if (err < 0)
+ goto out;
+ }
+
+ /*
+ * Back compatibility hook. Kill this one in 2.5
+ */
+ if (dev->name[0] == 0 || dev->name[0] == ' ') {
+ err = dev_alloc_name(dev, "eth%d");
+ if (err < 0)
+ goto out;
+ }
+
+ err = register_netdevice(dev);
+out:
+ rtnl_unlock();
+ return err;
+}
+EXPORT_SYMBOL(register_netdev);
+
/*
* netdev_wait_allrefs - wait until all references are gone.
*
while (atomic_read(&dev->refcnt) != 0) {
if (time_after(jiffies, rebroadcast_time + 1 * HZ)) {
rtnl_shlock();
- rtnl_exlock();
/* Rebroadcast unregister notification */
notifier_call_chain(&netdev_chain,
linkwatch_run_queue();
}
- rtnl_exunlock();
rtnl_shunlock();
rebroadcast_time = jiffies;
}
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ / 4);
+ msleep(250);
if (time_after(jiffies, warning_time + 10 * HZ)) {
printk(KERN_EMERG "unregister_netdevice: "
switch(dev->reg_state) {
case NETREG_REGISTERING:
+ dev->reg_state = NETREG_REGISTERED;
err = netdev_register_sysfs(dev);
if (err)
printk(KERN_ERR "%s: failed sysfs registration (%d)\n",
dev->name, err);
- dev->reg_state = NETREG_REGISTERED;
break;
case NETREG_UNREGISTERING:
up(&net_todo_run_mutex);
}
+/**
+ * alloc_netdev - allocate network device
+ * @sizeof_priv: size of private data to allocate space for
+ * @name: device name format string
+ * @setup: callback to initialize device
+ *
+ * Allocates a struct net_device with private data area for driver use
+ * and performs basic initialization.
+ */
+struct net_device *alloc_netdev(int sizeof_priv, const char *name,
+ void (*setup)(struct net_device *))
+{
+ void *p;
+ struct net_device *dev;
+ int alloc_size;
+
+ /* ensure 32-byte alignment of both the device and private area */
+ alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST;
+ alloc_size += sizeof_priv + NETDEV_ALIGN_CONST;
+
+ p = kmalloc(alloc_size, GFP_KERNEL);
+ if (!p) {
+ printk(KERN_ERR "alloc_dev: Unable to allocate device.\n");
+ return NULL;
+ }
+ memset(p, 0, alloc_size);
+
+ dev = (struct net_device *)
+ (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
+ dev->padded = (char *)dev - (char *)p;
+
+ if (sizeof_priv)
+ dev->priv = netdev_priv(dev);
+
+ setup(dev);
+ strcpy(dev->name, name);
+ return dev;
+}
+EXPORT_SYMBOL(alloc_netdev);
+
/**
* free_netdev - free network device
* @dev: device
void synchronize_net(void)
{
might_sleep();
- synchronize_kernel();
+ synchronize_rcu();
}
/**
* from the kernel tables. On success 0 is returned, on a failure
* a negative errno code is returned.
*
- * Callers must hold the rtnl semaphore. See the comment at the
- * end of Space.c for details about the locking. You may want
+ * Callers must hold the rtnl semaphore. You may want
* unregister_netdev() instead of this.
*/
synchronize_net();
-#ifdef CONFIG_NET_FASTROUTE
- dev_clear_fastroute(dev);
-#endif
-
/* Shutdown queueing discipline. */
dev_shutdown(dev);
return 0;
}
+/**
+ * unregister_netdev - remove device from the kernel
+ * @dev: device
+ *
+ * This function shuts down a device interface and removes it
+ * from the kernel tables. On success 0 is returned, on a failure
+ * a negative errno code is returned.
+ *
+ * This is just a wrapper for unregister_netdevice that takes
+ * the rtnl semaphore. In general you want to use this and not
+ * unregister_netdevice.
+ */
+void unregister_netdev(struct net_device *dev)
+{
+ rtnl_lock();
+ unregister_netdevice(dev);
+ rtnl_unlock();
+}
+
+EXPORT_SYMBOL(unregister_netdev);
+
#ifdef CONFIG_HOTPLUG_CPU
static int dev_cpu_callback(struct notifier_block *nfb,
unsigned long action,
BUG_ON(!dev_boot_phase);
+ net_random_init();
+
if (dev_proc_init())
goto out;
* Initialise the packet receive queues.
*/
- for (i = 0; i < NR_CPUS; i++) {
+ for_each_cpu(i) {
struct softnet_data *queue;
queue = &per_cpu(softnet_data, i);
skb_queue_head_init(&queue->input_pkt_queue);
- queue->throttle = 0;
- queue->cng_level = 0;
- queue->avg_blog = 10; /* arbitrary non-zero */
queue->completion_queue = NULL;
INIT_LIST_HEAD(&queue->poll_list);
set_bit(__LINK_STATE_START, &queue->backlog_dev.state);
atomic_set(&queue->backlog_dev.refcnt, 1);
}
-#ifdef OFFLINE_SAMPLE
- samp_timer.expires = jiffies + (10 * HZ);
- add_timer(&samp_timer);
-#endif
-
dev_boot_phase = 0;
open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);
subsys_initcall(net_dev_init);
-EXPORT_SYMBOL(__dev_get);
-EXPORT_SYMBOL(__dev_get_by_flags);
EXPORT_SYMBOL(__dev_get_by_index);
EXPORT_SYMBOL(__dev_get_by_name);
EXPORT_SYMBOL(__dev_remove_pack);
EXPORT_SYMBOL(__skb_linearize);
-EXPORT_SYMBOL(call_netdevice_notifiers);
+EXPORT_SYMBOL(dev_valid_name);
EXPORT_SYMBOL(dev_add_pack);
EXPORT_SYMBOL(dev_alloc_name);
EXPORT_SYMBOL(dev_close);
EXPORT_SYMBOL(dev_get_by_flags);
EXPORT_SYMBOL(dev_get_by_index);
EXPORT_SYMBOL(dev_get_by_name);
-EXPORT_SYMBOL(dev_getbyhwaddr);
-EXPORT_SYMBOL(dev_ioctl);
-EXPORT_SYMBOL(dev_new_index);
EXPORT_SYMBOL(dev_open);
EXPORT_SYMBOL(dev_queue_xmit);
+#if defined(CONFIG_VNET) || defined(CONFIG_VNET_MODULE)
EXPORT_SYMBOL(dev_queue_xmit_nit);
+#endif
EXPORT_SYMBOL(dev_remove_pack);
EXPORT_SYMBOL(dev_set_allmulti);
EXPORT_SYMBOL(dev_set_promiscuity);
+EXPORT_SYMBOL(dev_change_flags);
+EXPORT_SYMBOL(dev_set_mtu);
+EXPORT_SYMBOL(dev_set_mac_address);
EXPORT_SYMBOL(free_netdev);
EXPORT_SYMBOL(netdev_boot_setup_check);
EXPORT_SYMBOL(netdev_set_master);
EXPORT_SYMBOL(synchronize_net);
EXPORT_SYMBOL(unregister_netdevice);
EXPORT_SYMBOL(unregister_netdevice_notifier);
+EXPORT_SYMBOL(net_enable_timestamp);
+EXPORT_SYMBOL(net_disable_timestamp);
+EXPORT_SYMBOL(dev_get_flags);
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
EXPORT_SYMBOL(br_handle_frame_hook);
+EXPORT_SYMBOL(br_fdb_get_hook);
+EXPORT_SYMBOL(br_fdb_put_hook);
#endif
-/* for 801q VLAN support */
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-EXPORT_SYMBOL(dev_change_flags);
-#endif
+
#ifdef CONFIG_KMOD
EXPORT_SYMBOL(dev_load);
#endif
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-EXPORT_SYMBOL(netdev_dropping);
-EXPORT_SYMBOL(netdev_fc_xoff);
-EXPORT_SYMBOL(netdev_register_fc);
-EXPORT_SYMBOL(netdev_unregister_fc);
-#endif
-#ifdef CONFIG_NET_FASTROUTE
-EXPORT_SYMBOL(netdev_fastroute);
-EXPORT_SYMBOL(netdev_fastroute_obstacles);
-#endif
-
-#ifdef CONFIG_NET_CLS_ACT
-EXPORT_SYMBOL(ing_filter);
-#endif
-
EXPORT_PER_CPU_SYMBOL(softnet_data);