#include <net/iw_handler.h>
#endif /* CONFIG_NET_RADIO */
#include <asm/current.h>
+#include <linux/vs_base.h>
#include <linux/vs_network.h>
/* This define, if set, will randomly drop a packet when congestion
}
-/*
- * 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:
*/
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(*pskb)) {
+ ret = pskb_expand_head(*pskb, 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)
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); \
} \
}
if (skb_checksum_help(&skb, 0))
goto out_kfree_skb;
- rcu_read_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);
+ spin_lock(&dev->queue_lock);
rc = q->enqueue(skb, q);
qdisc_run(dev);
- spin_unlock_bh(&dev->queue_lock);
- rcu_read_unlock();
+ spin_unlock(&dev->queue_lock);
rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc;
goto out;
}
- 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())
out_kfree_skb:
kfree_skb(skb);
out:
+ local_bh_enable();
return rc;
}
struct softnet_data *queue;
unsigned long flags;
-#ifdef CONFIG_NETPOLL_RX
+#ifdef CONFIG_NETPOLL
if (skb->dev->netpoll_rx && netpoll_rx(skb)) {
kfree_skb(skb);
return NET_RX_DROP;
}
static __inline__ int deliver_skb(struct sk_buff *skb,
- struct packet_type *pt_prev, int last)
+ struct packet_type *pt_prev)
{
atomic_inc(&skb->users);
return pt_prev->func(skb, skb->dev, pt_prev);
}
-
#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);
-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)
{
- 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);
*pt_prev = NULL;
- }
-#endif
- return 0;
+ }
+
+ return br_handle_frame_hook(port, pskb);
}
-
+#else
+#define handle_bridge(skb, pt_prev, ret) (0)
+#endif
#ifdef CONFIG_NET_CLS_ACT
/* TODO: Maybe we should just force sch_ingress to be compiled in
int ret = NET_RX_DROP;
unsigned short type;
-#ifdef CONFIG_NETPOLL_RX
+#ifdef CONFIG_NETPOLL
if (skb->dev->netpoll_rx && skb->dev->poll && netpoll_rx(skb)) {
kfree_skb(skb);
return NET_RX_DROP;
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);
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);
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))
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);
pt_prev = ptype;
}
}
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);
BUG_ON(!dev_boot_phase);
+ net_random_init();
+
if (dev_proc_init())
goto out;
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(free_netdev);
EXPORT_SYMBOL(netdev_boot_setup_check);