* 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 <linux/kallsyms.h>
#include <linux/netpoll.h>
#include <linux/rcupdate.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>
+#include <linux/vs_network.h>
/* This define, if set, will randomly drop a packet when congestion
* is more than moderate. It helps fairness in the multi-interface
* 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 */
* 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);
* 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;
* Network device names need to be valid file names to
* to allow sysfs to work
*/
-int dev_valid_name(const char *name)
+static int dev_valid_name(const char *name)
{
return !(*name == '\0'
|| !strcmp(name, ".")
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
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;
* 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)
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);
preempt_disable();
err = netif_rx(skb);
- if (softirq_pending(smp_processor_id()))
+ if (local_softirq_pending())
do_softirq();
preempt_enable();
#if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE)
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 **pskb,
struct packet_type **pt_prev, int *ret)
* 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;
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);
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;
dev = list_entry(queue->poll_list.next,
struct net_device, poll_list);
+ netpoll_poll_lock(dev);
if (dev->quota <= 0 || dev->poll(dev, &budget)) {
+ netpoll_poll_unlock(dev);
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(dev);
dev_put(dev);
local_irq_disable();
}
total = 0;
for (dev = dev_base; dev; dev = dev->next) {
+ 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]) {
int done;
static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev)
{
+ struct nx_info *nxi = current->nx_info;
+
+ 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);
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 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)
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:
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.
*
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: "
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.
*/
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,
EXPORT_SYMBOL(dev_ioctl);
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_change_name);
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(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
#ifdef CONFIG_KMOD
EXPORT_SYMBOL(dev_load);
#endif
-#ifdef CONFIG_NET_CLS_ACT
-EXPORT_SYMBOL(ing_filter);
-#endif
-
-
EXPORT_PER_CPU_SYMBOL(softnet_data);