*/
static DEFINE_SPINLOCK(ptype_lock);
-static struct list_head ptype_base[16]; /* 16 way hashed list */
-static struct list_head ptype_all; /* Taps */
+static struct list_head ptype_base[16] __read_mostly; /* 16 way hashed list */
+static struct list_head ptype_all __read_mostly; /* Taps */
#ifdef CONFIG_NET_DMA
static struct dma_client *net_dma_client;
* is linked into kernel lists and may not be freed until it has been
* removed from the kernel lists.
*
- * This call does not sleep therefore it can not
+ * This call does not sleep therefore it can not
* guarantee all CPU's that are in middle of receiving packets
* will see the new packet type (until the next received packet).
*/
* Remove a protocol handler that was previously added to the kernel
* protocol handlers by dev_add_pack(). The passed &packet_type is removed
* from the kernel lists and can be freed or reused once this function
- * returns.
+ * returns.
*
* The packet type might still be in use by receivers
* and must not be freed until after all the CPU's have gone
void dev_remove_pack(struct packet_type *pt)
{
__dev_remove_pack(pt);
-
+
synchronize_net();
}
* @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 device returned has
+ * is not found or a pointer to the device. The device returned has
* had a reference added and the pointer is safe until the user calls
* dev_put to indicate they have finished with it.
*/
else
strlcpy(dev->name, newname, IFNAMSIZ);
- err = device_rename(&dev->dev, dev->name);
- if (!err) {
- hlist_del(&dev->name_hlist);
- hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name));
- raw_notifier_call_chain(&netdev_chain,
- NETDEV_CHANGENAME, dev);
- }
+ device_rename(&dev->dev, dev->name);
+ hlist_del(&dev->name_hlist);
+ hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name));
+ raw_notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
return err;
}
void dev_load(const char *name)
{
- struct net_device *dev;
+ struct net_device *dev;
read_lock(&dev_base_lock);
dev = __dev_get_by_name(name);
clear_bit(__LINK_STATE_START, &dev->state);
}
- /*
+ /*
* If it went open OK then:
*/
* is returned on a failure.
*
* When registered all registration and up events are replayed
- * to the new notifier to allow device to have a race free
+ * to the new notifier to allow device to have a race free
* view of the network device list.
*/
for (dev = dev_base; dev; dev = dev->next) {
nb->notifier_call(nb, NETDEV_REGISTER, dev);
- if (dev->flags & IFF_UP)
+ if (dev->flags & IFF_UP)
nb->notifier_call(nb, NETDEV_UP, dev);
}
}
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;
- }
+ else
+ skb->tstamp.tv64 = 0;
}
/*
set by sender, so that the second statement is
just protection against buggy protocols.
*/
- skb2->mac.raw = skb2->data;
+ skb_reset_mac_header(skb2);
- if (skb2->nh.raw < skb2->data ||
- skb2->nh.raw > skb2->tail) {
+ if (skb_network_header(skb2) < skb2->data ||
+ skb_network_header(skb2) > skb2->tail) {
if (net_ratelimit())
printk(KERN_CRIT "protocol %04x is "
"buggy, dev %s\n",
skb2->protocol, dev->name);
- skb2->nh.raw = skb2->data;
+ skb_reset_network_header(skb2);
}
- skb2->h.raw = skb2->nh.raw;
+ skb2->transport_header = skb2->network_header;
skb2->pkt_type = PACKET_OUTGOING;
ptype->func(skb2, skb->dev, ptype, skb->dev);
}
if (!test_and_set_bit(__LINK_STATE_PRESENT, &dev->state) &&
netif_running(dev)) {
netif_wake_queue(dev);
- __netdev_watchdog_up(dev);
+ __netdev_watchdog_up(dev);
}
}
EXPORT_SYMBOL(netif_device_attach);
int skb_checksum_help(struct sk_buff *skb)
{
__wsum csum;
- int ret = 0, offset = skb->h.raw - skb->data;
+ int ret = 0, offset = skb_transport_offset(skb);
if (skb->ip_summed == CHECKSUM_COMPLETE)
goto out_set_summed;
BUG_ON(offset > (int)skb->len);
csum = skb_checksum(skb, offset, skb->len-offset, 0);
- offset = skb->tail - skb->h.raw;
+ offset = skb->tail - skb_transport_header(skb);
BUG_ON(offset <= 0);
BUG_ON(skb->csum_offset + 2 > offset);
- *(__sum16*)(skb->h.raw + skb->csum_offset) = csum_fold(csum);
-
+ *(__sum16 *)(skb_transport_header(skb) +
+ skb->csum_offset) = csum_fold(csum);
out_set_summed:
skb->ip_summed = CHECKSUM_NONE;
-out:
+out:
return ret;
}
BUG_ON(skb_shinfo(skb)->frag_list);
- skb->mac.raw = skb->data;
- skb->mac_len = skb->nh.raw - skb->data;
+ skb_reset_mac_header(skb);
+ skb->mac_len = skb->network_header - skb->mac_header;
__skb_pull(skb, skb->mac_len);
if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL)) {
segs = ERR_PTR(err);
if (err || skb_gso_ok(skb, features))
break;
- __skb_push(skb, skb->data - skb->nh.raw);
+ __skb_push(skb, (skb->data -
+ skb_network_header(skb)));
}
segs = ptype->gso_segment(skb, features);
break;
}
rcu_read_unlock();
- __skb_push(skb, skb->data - skb->mac.raw);
+ __skb_push(skb, skb->data - skb_mac_header(skb));
return segs;
}
void netdev_rx_csum_fault(struct net_device *dev)
{
if (net_ratelimit()) {
- printk(KERN_ERR "%s: hw csum failure.\n",
+ printk(KERN_ERR "%s: hw csum failure.\n",
dev ? dev->name : "<unknown>");
dump_stack();
}
if (unlikely(netif_queue_stopped(dev) && skb->next))
return NETDEV_TX_BUSY;
} while (skb->next);
-
+
skb->destructor = DEV_GSO_CB(skb)->destructor;
out_kfree_skb:
(!(dev->features & NETIF_F_GEN_CSUM) &&
(!(dev->features & NETIF_F_IP_CSUM) ||
skb->protocol != htons(ETH_P_IP))))
- if (skb_checksum_help(skb))
- goto out_kfree_skb;
+ if (skb_checksum_help(skb))
+ goto out_kfree_skb;
gso:
spin_lock_prefetch(&dev->queue_lock);
- /* Disable soft irqs for various locks below. Also
- * stops preemption for RCU.
+ /* Disable soft irqs for various locks below. Also
+ * stops preemption for RCU.
*/
- rcu_read_lock_bh();
+ rcu_read_lock_bh();
- /* 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
+ /* 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
* a lock (but the structure may be stale.) The freeing of the
- * qdisc will be deferred until it's known that there are no
+ * qdisc will be deferred until it's known that there are no
* more references to it.
- *
- * If the qdisc has an enqueue function, we still need to
+ *
+ * If the qdisc has an enqueue function, we still need to
* hold the queue_lock before calling it, since queue_lock
* also serializes access to the device queue.
*/
Receiver routines
=======================================================================*/
-int netdev_max_backlog = 1000;
-int netdev_budget = 300;
-int weight_p = 64; /* old backlog weight */
+int netdev_max_backlog __read_mostly = 1000;
+int netdev_budget __read_mostly = 300;
+int weight_p __read_mostly = 64; /* old backlog weight */
DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, };
if (netpoll_rx(skb))
return NET_RX_DROP;
- if (!skb->tstamp.off_sec)
+ if (!skb->tstamp.tv64)
net_timestamp(skb);
/*
}
}
-static __inline__ int deliver_skb(struct sk_buff *skb,
- struct packet_type *pt_prev,
- struct net_device *orig_dev)
+static inline int deliver_skb(struct sk_buff *skb,
+ struct packet_type *pt_prev,
+ struct net_device *orig_dev)
{
atomic_inc(&skb->users);
return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
if (*pt_prev) {
*ret = deliver_skb(*pskb, *pt_prev, orig_dev);
*pt_prev = NULL;
- }
-
+ }
+
return br_handle_frame_hook(port, pskb);
}
#else
* when CONFIG_NET_CLS_ACT is? otherwise some useless instructions
* a compare and 2 stores extra right now if we dont have it on
* but have CONFIG_NET_CLS_ACT
- * NOTE: This doesnt stop any functionality; if you dont have
+ * NOTE: This doesnt stop any functionality; if you dont have
* the ingress scheduler, you just cant add policies on ingress.
*
*/
-static 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 result = TC_ACT_OK;
-
+
if (dev->qdisc_ingress) {
__u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd);
if (MAX_RED_LOOP < ttl++) {
- printk(KERN_WARNING "Redir loop detected Dropping packet (%s->%s)\n",
- skb->input_dev->name, skb->dev->name);
+ printk(KERN_WARNING "Redir loop detected Dropping packet (%d->%d)\n",
+ skb->iif, skb->dev->ifindex);
return TC_ACT_SHOT;
}
skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS);
- spin_lock(&dev->ingress_lock);
+ spin_lock(&dev->queue_lock);
if ((q = dev->qdisc_ingress) != NULL)
result = q->enqueue(skb, q);
- spin_unlock(&dev->ingress_lock);
+ spin_unlock(&dev->queue_lock);
}
if (skb->dev->poll && netpoll_rx(skb))
return NET_RX_DROP;
- if (!skb->tstamp.off_sec)
+ if (!skb->tstamp.tv64)
net_timestamp(skb);
- if (!skb->input_dev)
- skb->input_dev = skb->dev;
+ if (!skb->iif)
+ skb->iif = skb->dev->ifindex;
orig_dev = skb_bond(skb);
__get_cpu_var(netdev_rx_stat).total++;
- skb->h.raw = skb->nh.raw = skb->data;
- skb->mac_len = skb->nh.raw - skb->mac.raw;
+ skb_reset_network_header(skb);
+ skb_reset_transport_header(skb);
+ skb->mac_len = skb->network_header - skb->mac_header;
pt_prev = NULL;
list_for_each_entry_rcu(ptype, &ptype_all, list) {
if (!ptype->dev || ptype->dev == skb->dev) {
- if (pt_prev)
+ if (pt_prev)
ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = ptype;
}
list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) {
if (ptype->type == type &&
(!ptype->dev || ptype->dev == skb->dev)) {
- if (pt_prev)
+ if (pt_prev)
ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = ptype;
}
total += done;
}
}
- }
+ }
/*
* All done. Write the updated control block back to the caller.
* This is invoked by the /proc filesystem handler to display a device
* in detail.
*/
-static __inline__ struct net_device *dev_get_idx(loff_t pos)
+static struct net_device *dev_get_idx(loff_t pos)
{
struct net_device *dev;
loff_t i;
struct netif_rx_stats *rc = NULL;
while (*pos < NR_CPUS)
- if (cpu_online(*pos)) {
+ if (cpu_online(*pos)) {
rc = &per_cpu(netdev_rx_stat, *pos);
break;
} else
return 0;
}
-static struct seq_operations dev_seq_ops = {
+static const struct seq_operations dev_seq_ops = {
.start = dev_seq_start,
.next = dev_seq_next,
.stop = dev_seq_stop,
return seq_open(file, &dev_seq_ops);
}
-static struct file_operations dev_seq_fops = {
+static const struct file_operations dev_seq_fops = {
.owner = THIS_MODULE,
.open = dev_seq_open,
.read = seq_read,
.release = seq_release,
};
-static struct seq_operations softnet_seq_ops = {
+static const struct seq_operations softnet_seq_ops = {
.start = softnet_seq_start,
.next = softnet_seq_next,
.stop = softnet_seq_stop,
return seq_open(file, &softnet_seq_ops);
}
-static struct file_operations softnet_seq_fops = {
+static const struct file_operations softnet_seq_fops = {
.owner = THIS_MODULE,
.open = softnet_seq_open,
.read = seq_read,
.release = seq_release,
};
+static void *ptype_get_idx(loff_t pos)
+{
+ struct packet_type *pt = NULL;
+ loff_t i = 0;
+ int t;
+
+ list_for_each_entry_rcu(pt, &ptype_all, list) {
+ if (i == pos)
+ return pt;
+ ++i;
+ }
+
+ for (t = 0; t < 16; t++) {
+ list_for_each_entry_rcu(pt, &ptype_base[t], list) {
+ if (i == pos)
+ return pt;
+ ++i;
+ }
+ }
+ return NULL;
+}
+
+static void *ptype_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ rcu_read_lock();
+ return *pos ? ptype_get_idx(*pos - 1) : SEQ_START_TOKEN;
+}
+
+static void *ptype_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ struct packet_type *pt;
+ struct list_head *nxt;
+ int hash;
+
+ ++*pos;
+ if (v == SEQ_START_TOKEN)
+ return ptype_get_idx(0);
+
+ pt = v;
+ nxt = pt->list.next;
+ if (pt->type == htons(ETH_P_ALL)) {
+ if (nxt != &ptype_all)
+ goto found;
+ hash = 0;
+ nxt = ptype_base[0].next;
+ } else
+ hash = ntohs(pt->type) & 15;
+
+ while (nxt == &ptype_base[hash]) {
+ if (++hash >= 16)
+ return NULL;
+ nxt = ptype_base[hash].next;
+ }
+found:
+ return list_entry(nxt, struct packet_type, list);
+}
+
+static void ptype_seq_stop(struct seq_file *seq, void *v)
+{
+ rcu_read_unlock();
+}
+
+static void ptype_seq_decode(struct seq_file *seq, void *sym)
+{
+#ifdef CONFIG_KALLSYMS
+ unsigned long offset = 0, symsize;
+ const char *symname;
+ char *modname;
+ char namebuf[128];
+
+ symname = kallsyms_lookup((unsigned long)sym, &symsize, &offset,
+ &modname, namebuf);
+
+ if (symname) {
+ char *delim = ":";
+
+ if (!modname)
+ modname = delim = "";
+ seq_printf(seq, "%s%s%s%s+0x%lx", delim, modname, delim,
+ symname, offset);
+ return;
+ }
+#endif
+
+ seq_printf(seq, "[%p]", sym);
+}
+
+static int ptype_seq_show(struct seq_file *seq, void *v)
+{
+ struct packet_type *pt = v;
+
+ if (v == SEQ_START_TOKEN)
+ seq_puts(seq, "Type Device Function\n");
+ else {
+ if (pt->type == htons(ETH_P_ALL))
+ seq_puts(seq, "ALL ");
+ else
+ seq_printf(seq, "%04x", ntohs(pt->type));
+
+ seq_printf(seq, " %-8s ",
+ pt->dev ? pt->dev->name : "");
+ ptype_seq_decode(seq, pt->func);
+ seq_putc(seq, '\n');
+ }
+
+ return 0;
+}
+
+static const struct seq_operations ptype_seq_ops = {
+ .start = ptype_seq_start,
+ .next = ptype_seq_next,
+ .stop = ptype_seq_stop,
+ .show = ptype_seq_show,
+};
+
+static int ptype_seq_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &ptype_seq_ops);
+}
+
+static const struct file_operations ptype_seq_fops = {
+ .owner = THIS_MODULE,
+ .open = ptype_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+
#ifdef CONFIG_WIRELESS_EXT
extern int wireless_proc_init(void);
#else
goto out;
if (!proc_net_fops_create("softnet_stat", S_IRUGO, &softnet_seq_fops))
goto out_dev;
+ if (!proc_net_fops_create("ptype", S_IRUGO, &ptype_seq_fops))
+ goto out_dev2;
+
if (wireless_proc_init())
goto out_softnet;
rc = 0;
return rc;
out_softnet:
proc_net_remove("softnet_stat");
+out_dev2:
+ proc_net_remove("ptype");
out_dev:
proc_net_remove("dev");
goto out;
}
slave->master = master;
-
+
synchronize_net();
if (old)
dev_mc_upload(dev);
printk(KERN_INFO "device %s %s promiscuous mode\n",
dev->name, (dev->flags & IFF_PROMISC) ? "entered" :
- "left");
+ "left");
audit_log(current->audit_context, GFP_ATOMIC,
AUDIT_ANOM_PROMISCUOUS,
"dev=%s prom=%d old_prom=%d auid=%u",
dev->name, (dev->flags & IFF_PROMISC),
(old_flags & IFF_PROMISC),
- audit_get_loginuid(current->audit_context));
+ audit_get_loginuid(current->audit_context));
}
}
rtnl_unlock();
if (IW_IS_GET(cmd) &&
copy_to_user(arg, &ifr,
- sizeof(struct ifreq)))
+ sizeof(struct ifreq)))
ret = -EFAULT;
return ret;
}
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)
+static void net_set_todo(struct net_device *dev)
{
spin_lock(&net_todo_list_lock);
list_add_tail(&dev->todo_list, &net_todo_list);
goto out;
}
}
-
+
if (!dev_valid_name(dev->name)) {
ret = -EINVAL;
goto out;
= hlist_entry(p, struct net_device, name_hlist);
if (!strncmp(d->name, dev->name, IFNAMSIZ)) {
ret = -EEXIST;
- goto out;
+ goto out;
}
- }
+ }
/* Fix illegal SG+CSUM combinations. */
if ((dev->features & NETIF_F_SG) &&
if (err < 0)
goto out;
}
-
+
err = register_netdevice(dev);
out:
rtnl_unlock();
* for netdevice notification, and cleanup and put back the
* reference if they receive an UNREGISTER event.
* We can get stuck here if buggy protocols don't correctly
- * call dev_put.
+ * call dev_put.
*/
static void netdev_wait_allrefs(struct net_device *dev)
{
* free_netdev - free network device
* @dev: device
*
- * This function does the last stage of destroying an allocated device
- * interface. The reference to the device object is released.
+ * This function does the last stage of destroying an allocated device
+ * interface. The reference to the device object is released.
* If this is the last reference then it will be freed.
*/
void free_netdev(struct net_device *dev)
kfree((char *)dev - dev->padded);
#endif
}
-
+
/* Synchronize with packet receive processing. */
-void synchronize_net(void)
+void synchronize_net(void)
{
might_sleep();
synchronize_rcu();
/* Shutdown queueing discipline. */
dev_shutdown(dev);
-
+
/* Notify protocols, that we are about to destroy
this device. They should clean all the things.
*/
raw_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
-
+
/*
* Flush the multicast chain
*/
goto out;
INIT_LIST_HEAD(&ptype_all);
- for (i = 0; i < 16; i++)
+ for (i = 0; i < 16; i++)
INIT_LIST_HEAD(&ptype_base[i]);
for (i = 0; i < ARRAY_SIZE(dev_name_head); i++)