diff options
Diffstat (limited to 'net/core/dev.c')
-rw-r--r-- | net/core/dev.c | 328 |
1 files changed, 218 insertions, 110 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 4dc93cc4d5b7..d5e42d13bd67 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -109,7 +109,7 @@ | |||
109 | #include <linux/netpoll.h> | 109 | #include <linux/netpoll.h> |
110 | #include <linux/rcupdate.h> | 110 | #include <linux/rcupdate.h> |
111 | #include <linux/delay.h> | 111 | #include <linux/delay.h> |
112 | #include <linux/wireless.h> | 112 | #include <net/wext.h> |
113 | #include <net/iw_handler.h> | 113 | #include <net/iw_handler.h> |
114 | #include <asm/current.h> | 114 | #include <asm/current.h> |
115 | #include <linux/audit.h> | 115 | #include <linux/audit.h> |
@@ -146,8 +146,8 @@ | |||
146 | */ | 146 | */ |
147 | 147 | ||
148 | static DEFINE_SPINLOCK(ptype_lock); | 148 | static DEFINE_SPINLOCK(ptype_lock); |
149 | static struct list_head ptype_base[16]; /* 16 way hashed list */ | 149 | static struct list_head ptype_base[16] __read_mostly; /* 16 way hashed list */ |
150 | static struct list_head ptype_all; /* Taps */ | 150 | static struct list_head ptype_all __read_mostly; /* Taps */ |
151 | 151 | ||
152 | #ifdef CONFIG_NET_DMA | 152 | #ifdef CONFIG_NET_DMA |
153 | static struct dma_client *net_dma_client; | 153 | static struct dma_client *net_dma_client; |
@@ -226,12 +226,6 @@ extern void netdev_unregister_sysfs(struct net_device *); | |||
226 | *******************************************************************************/ | 226 | *******************************************************************************/ |
227 | 227 | ||
228 | /* | 228 | /* |
229 | * For efficiency | ||
230 | */ | ||
231 | |||
232 | static int netdev_nit; | ||
233 | |||
234 | /* | ||
235 | * Add a protocol ID to the list. Now that the input handler is | 229 | * Add a protocol ID to the list. Now that the input handler is |
236 | * smarter we can dispense with all the messy stuff that used to be | 230 | * smarter we can dispense with all the messy stuff that used to be |
237 | * here. | 231 | * here. |
@@ -265,10 +259,9 @@ void dev_add_pack(struct packet_type *pt) | |||
265 | int hash; | 259 | int hash; |
266 | 260 | ||
267 | spin_lock_bh(&ptype_lock); | 261 | spin_lock_bh(&ptype_lock); |
268 | if (pt->type == htons(ETH_P_ALL)) { | 262 | if (pt->type == htons(ETH_P_ALL)) |
269 | netdev_nit++; | ||
270 | list_add_rcu(&pt->list, &ptype_all); | 263 | list_add_rcu(&pt->list, &ptype_all); |
271 | } else { | 264 | else { |
272 | hash = ntohs(pt->type) & 15; | 265 | hash = ntohs(pt->type) & 15; |
273 | list_add_rcu(&pt->list, &ptype_base[hash]); | 266 | list_add_rcu(&pt->list, &ptype_base[hash]); |
274 | } | 267 | } |
@@ -295,10 +288,9 @@ void __dev_remove_pack(struct packet_type *pt) | |||
295 | 288 | ||
296 | spin_lock_bh(&ptype_lock); | 289 | spin_lock_bh(&ptype_lock); |
297 | 290 | ||
298 | if (pt->type == htons(ETH_P_ALL)) { | 291 | if (pt->type == htons(ETH_P_ALL)) |
299 | netdev_nit--; | ||
300 | head = &ptype_all; | 292 | head = &ptype_all; |
301 | } else | 293 | else |
302 | head = &ptype_base[ntohs(pt->type) & 15]; | 294 | head = &ptype_base[ntohs(pt->type) & 15]; |
303 | 295 | ||
304 | list_for_each_entry(pt1, head, list) { | 296 | list_for_each_entry(pt1, head, list) { |
@@ -817,7 +809,6 @@ static int default_rebuild_header(struct sk_buff *skb) | |||
817 | return 1; | 809 | return 1; |
818 | } | 810 | } |
819 | 811 | ||
820 | |||
821 | /** | 812 | /** |
822 | * dev_open - prepare an interface for use. | 813 | * dev_open - prepare an interface for use. |
823 | * @dev: device to open | 814 | * @dev: device to open |
@@ -1031,23 +1022,12 @@ void net_disable_timestamp(void) | |||
1031 | atomic_dec(&netstamp_needed); | 1022 | atomic_dec(&netstamp_needed); |
1032 | } | 1023 | } |
1033 | 1024 | ||
1034 | void __net_timestamp(struct sk_buff *skb) | ||
1035 | { | ||
1036 | struct timeval tv; | ||
1037 | |||
1038 | do_gettimeofday(&tv); | ||
1039 | skb_set_timestamp(skb, &tv); | ||
1040 | } | ||
1041 | EXPORT_SYMBOL(__net_timestamp); | ||
1042 | |||
1043 | static inline void net_timestamp(struct sk_buff *skb) | 1025 | static inline void net_timestamp(struct sk_buff *skb) |
1044 | { | 1026 | { |
1045 | if (atomic_read(&netstamp_needed)) | 1027 | if (atomic_read(&netstamp_needed)) |
1046 | __net_timestamp(skb); | 1028 | __net_timestamp(skb); |
1047 | else { | 1029 | else |
1048 | skb->tstamp.off_sec = 0; | 1030 | skb->tstamp.tv64 = 0; |
1049 | skb->tstamp.off_usec = 0; | ||
1050 | } | ||
1051 | } | 1031 | } |
1052 | 1032 | ||
1053 | /* | 1033 | /* |
@@ -1077,18 +1057,18 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) | |||
1077 | set by sender, so that the second statement is | 1057 | set by sender, so that the second statement is |
1078 | just protection against buggy protocols. | 1058 | just protection against buggy protocols. |
1079 | */ | 1059 | */ |
1080 | skb2->mac.raw = skb2->data; | 1060 | skb_reset_mac_header(skb2); |
1081 | 1061 | ||
1082 | if (skb2->nh.raw < skb2->data || | 1062 | if (skb_network_header(skb2) < skb2->data || |
1083 | skb2->nh.raw > skb2->tail) { | 1063 | skb2->network_header > skb2->tail) { |
1084 | if (net_ratelimit()) | 1064 | if (net_ratelimit()) |
1085 | printk(KERN_CRIT "protocol %04x is " | 1065 | printk(KERN_CRIT "protocol %04x is " |
1086 | "buggy, dev %s\n", | 1066 | "buggy, dev %s\n", |
1087 | skb2->protocol, dev->name); | 1067 | skb2->protocol, dev->name); |
1088 | skb2->nh.raw = skb2->data; | 1068 | skb_reset_network_header(skb2); |
1089 | } | 1069 | } |
1090 | 1070 | ||
1091 | skb2->h.raw = skb2->nh.raw; | 1071 | skb2->transport_header = skb2->network_header; |
1092 | skb2->pkt_type = PACKET_OUTGOING; | 1072 | skb2->pkt_type = PACKET_OUTGOING; |
1093 | ptype->func(skb2, skb->dev, ptype, skb->dev); | 1073 | ptype->func(skb2, skb->dev, ptype, skb->dev); |
1094 | } | 1074 | } |
@@ -1167,7 +1147,7 @@ EXPORT_SYMBOL(netif_device_attach); | |||
1167 | int skb_checksum_help(struct sk_buff *skb) | 1147 | int skb_checksum_help(struct sk_buff *skb) |
1168 | { | 1148 | { |
1169 | __wsum csum; | 1149 | __wsum csum; |
1170 | int ret = 0, offset = skb->h.raw - skb->data; | 1150 | int ret = 0, offset; |
1171 | 1151 | ||
1172 | if (skb->ip_summed == CHECKSUM_COMPLETE) | 1152 | if (skb->ip_summed == CHECKSUM_COMPLETE) |
1173 | goto out_set_summed; | 1153 | goto out_set_summed; |
@@ -1183,15 +1163,16 @@ int skb_checksum_help(struct sk_buff *skb) | |||
1183 | goto out; | 1163 | goto out; |
1184 | } | 1164 | } |
1185 | 1165 | ||
1166 | offset = skb->csum_start - skb_headroom(skb); | ||
1186 | BUG_ON(offset > (int)skb->len); | 1167 | BUG_ON(offset > (int)skb->len); |
1187 | csum = skb_checksum(skb, offset, skb->len-offset, 0); | 1168 | csum = skb_checksum(skb, offset, skb->len-offset, 0); |
1188 | 1169 | ||
1189 | offset = skb->tail - skb->h.raw; | 1170 | offset = skb_headlen(skb) - offset; |
1190 | BUG_ON(offset <= 0); | 1171 | BUG_ON(offset <= 0); |
1191 | BUG_ON(skb->csum_offset + 2 > offset); | 1172 | BUG_ON(skb->csum_offset + 2 > offset); |
1192 | 1173 | ||
1193 | *(__sum16*)(skb->h.raw + skb->csum_offset) = csum_fold(csum); | 1174 | *(__sum16 *)(skb->head + skb->csum_start + skb->csum_offset) = |
1194 | 1175 | csum_fold(csum); | |
1195 | out_set_summed: | 1176 | out_set_summed: |
1196 | skb->ip_summed = CHECKSUM_NONE; | 1177 | skb->ip_summed = CHECKSUM_NONE; |
1197 | out: | 1178 | out: |
@@ -1217,11 +1198,11 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features) | |||
1217 | 1198 | ||
1218 | BUG_ON(skb_shinfo(skb)->frag_list); | 1199 | BUG_ON(skb_shinfo(skb)->frag_list); |
1219 | 1200 | ||
1220 | skb->mac.raw = skb->data; | 1201 | skb_reset_mac_header(skb); |
1221 | skb->mac_len = skb->nh.raw - skb->data; | 1202 | skb->mac_len = skb->network_header - skb->mac_header; |
1222 | __skb_pull(skb, skb->mac_len); | 1203 | __skb_pull(skb, skb->mac_len); |
1223 | 1204 | ||
1224 | if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL)) { | 1205 | if (WARN_ON(skb->ip_summed != CHECKSUM_PARTIAL)) { |
1225 | if (skb_header_cloned(skb) && | 1206 | if (skb_header_cloned(skb) && |
1226 | (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) | 1207 | (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) |
1227 | return ERR_PTR(err); | 1208 | return ERR_PTR(err); |
@@ -1235,7 +1216,8 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features) | |||
1235 | segs = ERR_PTR(err); | 1216 | segs = ERR_PTR(err); |
1236 | if (err || skb_gso_ok(skb, features)) | 1217 | if (err || skb_gso_ok(skb, features)) |
1237 | break; | 1218 | break; |
1238 | __skb_push(skb, skb->data - skb->nh.raw); | 1219 | __skb_push(skb, (skb->data - |
1220 | skb_network_header(skb))); | ||
1239 | } | 1221 | } |
1240 | segs = ptype->gso_segment(skb, features); | 1222 | segs = ptype->gso_segment(skb, features); |
1241 | break; | 1223 | break; |
@@ -1243,7 +1225,7 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features) | |||
1243 | } | 1225 | } |
1244 | rcu_read_unlock(); | 1226 | rcu_read_unlock(); |
1245 | 1227 | ||
1246 | __skb_push(skb, skb->data - skb->mac.raw); | 1228 | __skb_push(skb, skb->data - skb_mac_header(skb)); |
1247 | 1229 | ||
1248 | return segs; | 1230 | return segs; |
1249 | } | 1231 | } |
@@ -1340,7 +1322,7 @@ static int dev_gso_segment(struct sk_buff *skb) | |||
1340 | int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | 1322 | int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) |
1341 | { | 1323 | { |
1342 | if (likely(!skb->next)) { | 1324 | if (likely(!skb->next)) { |
1343 | if (netdev_nit) | 1325 | if (!list_empty(&ptype_all)) |
1344 | dev_queue_xmit_nit(skb, dev); | 1326 | dev_queue_xmit_nit(skb, dev); |
1345 | 1327 | ||
1346 | if (netif_needs_gso(dev, skb)) { | 1328 | if (netif_needs_gso(dev, skb)) { |
@@ -1442,12 +1424,16 @@ int dev_queue_xmit(struct sk_buff *skb) | |||
1442 | /* If packet is not checksummed and device does not support | 1424 | /* If packet is not checksummed and device does not support |
1443 | * checksumming for this protocol, complete checksumming here. | 1425 | * checksumming for this protocol, complete checksumming here. |
1444 | */ | 1426 | */ |
1445 | if (skb->ip_summed == CHECKSUM_PARTIAL && | 1427 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
1446 | (!(dev->features & NETIF_F_GEN_CSUM) && | 1428 | skb_set_transport_header(skb, skb->csum_start - |
1447 | (!(dev->features & NETIF_F_IP_CSUM) || | 1429 | skb_headroom(skb)); |
1448 | skb->protocol != htons(ETH_P_IP)))) | 1430 | |
1449 | if (skb_checksum_help(skb)) | 1431 | if (!(dev->features & NETIF_F_GEN_CSUM) && |
1450 | goto out_kfree_skb; | 1432 | (!(dev->features & NETIF_F_IP_CSUM) || |
1433 | skb->protocol != htons(ETH_P_IP))) | ||
1434 | if (skb_checksum_help(skb)) | ||
1435 | goto out_kfree_skb; | ||
1436 | } | ||
1451 | 1437 | ||
1452 | gso: | 1438 | gso: |
1453 | spin_lock_prefetch(&dev->queue_lock); | 1439 | spin_lock_prefetch(&dev->queue_lock); |
@@ -1543,9 +1529,9 @@ out: | |||
1543 | Receiver routines | 1529 | Receiver routines |
1544 | =======================================================================*/ | 1530 | =======================================================================*/ |
1545 | 1531 | ||
1546 | int netdev_max_backlog = 1000; | 1532 | int netdev_max_backlog __read_mostly = 1000; |
1547 | int netdev_budget = 300; | 1533 | int netdev_budget __read_mostly = 300; |
1548 | int weight_p = 64; /* old backlog weight */ | 1534 | int weight_p __read_mostly = 64; /* old backlog weight */ |
1549 | 1535 | ||
1550 | DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, }; | 1536 | DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, }; |
1551 | 1537 | ||
@@ -1577,7 +1563,7 @@ int netif_rx(struct sk_buff *skb) | |||
1577 | if (netpoll_rx(skb)) | 1563 | if (netpoll_rx(skb)) |
1578 | return NET_RX_DROP; | 1564 | return NET_RX_DROP; |
1579 | 1565 | ||
1580 | if (!skb->tstamp.off_sec) | 1566 | if (!skb->tstamp.tv64) |
1581 | net_timestamp(skb); | 1567 | net_timestamp(skb); |
1582 | 1568 | ||
1583 | /* | 1569 | /* |
@@ -1684,40 +1670,46 @@ static void net_tx_action(struct softirq_action *h) | |||
1684 | } | 1670 | } |
1685 | } | 1671 | } |
1686 | 1672 | ||
1687 | static __inline__ int deliver_skb(struct sk_buff *skb, | 1673 | static inline int deliver_skb(struct sk_buff *skb, |
1688 | struct packet_type *pt_prev, | 1674 | struct packet_type *pt_prev, |
1689 | struct net_device *orig_dev) | 1675 | struct net_device *orig_dev) |
1690 | { | 1676 | { |
1691 | atomic_inc(&skb->users); | 1677 | atomic_inc(&skb->users); |
1692 | return pt_prev->func(skb, skb->dev, pt_prev, orig_dev); | 1678 | return pt_prev->func(skb, skb->dev, pt_prev, orig_dev); |
1693 | } | 1679 | } |
1694 | 1680 | ||
1695 | #if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE) | 1681 | #if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE) |
1696 | int (*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff **pskb); | 1682 | /* These hooks defined here for ATM */ |
1697 | struct net_bridge; | 1683 | struct net_bridge; |
1698 | struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br, | 1684 | struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br, |
1699 | unsigned char *addr); | 1685 | unsigned char *addr); |
1700 | void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent); | 1686 | void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) __read_mostly; |
1701 | 1687 | ||
1702 | static __inline__ int handle_bridge(struct sk_buff **pskb, | 1688 | /* |
1703 | struct packet_type **pt_prev, int *ret, | 1689 | * If bridge module is loaded call bridging hook. |
1704 | struct net_device *orig_dev) | 1690 | * returns NULL if packet was consumed. |
1691 | */ | ||
1692 | struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p, | ||
1693 | struct sk_buff *skb) __read_mostly; | ||
1694 | static inline struct sk_buff *handle_bridge(struct sk_buff *skb, | ||
1695 | struct packet_type **pt_prev, int *ret, | ||
1696 | struct net_device *orig_dev) | ||
1705 | { | 1697 | { |
1706 | struct net_bridge_port *port; | 1698 | struct net_bridge_port *port; |
1707 | 1699 | ||
1708 | if ((*pskb)->pkt_type == PACKET_LOOPBACK || | 1700 | if (skb->pkt_type == PACKET_LOOPBACK || |
1709 | (port = rcu_dereference((*pskb)->dev->br_port)) == NULL) | 1701 | (port = rcu_dereference(skb->dev->br_port)) == NULL) |
1710 | return 0; | 1702 | return skb; |
1711 | 1703 | ||
1712 | if (*pt_prev) { | 1704 | if (*pt_prev) { |
1713 | *ret = deliver_skb(*pskb, *pt_prev, orig_dev); | 1705 | *ret = deliver_skb(skb, *pt_prev, orig_dev); |
1714 | *pt_prev = NULL; | 1706 | *pt_prev = NULL; |
1715 | } | 1707 | } |
1716 | 1708 | ||
1717 | return br_handle_frame_hook(port, pskb); | 1709 | return br_handle_frame_hook(port, skb); |
1718 | } | 1710 | } |
1719 | #else | 1711 | #else |
1720 | #define handle_bridge(skb, pt_prev, ret, orig_dev) (0) | 1712 | #define handle_bridge(skb, pt_prev, ret, orig_dev) (skb) |
1721 | #endif | 1713 | #endif |
1722 | 1714 | ||
1723 | #ifdef CONFIG_NET_CLS_ACT | 1715 | #ifdef CONFIG_NET_CLS_ACT |
@@ -1747,10 +1739,10 @@ static int ing_filter(struct sk_buff *skb) | |||
1747 | 1739 | ||
1748 | skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS); | 1740 | skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS); |
1749 | 1741 | ||
1750 | spin_lock(&dev->queue_lock); | 1742 | spin_lock(&dev->ingress_lock); |
1751 | if ((q = dev->qdisc_ingress) != NULL) | 1743 | if ((q = dev->qdisc_ingress) != NULL) |
1752 | result = q->enqueue(skb, q); | 1744 | result = q->enqueue(skb, q); |
1753 | spin_unlock(&dev->queue_lock); | 1745 | spin_unlock(&dev->ingress_lock); |
1754 | 1746 | ||
1755 | } | 1747 | } |
1756 | 1748 | ||
@@ -1769,7 +1761,7 @@ int netif_receive_skb(struct sk_buff *skb) | |||
1769 | if (skb->dev->poll && netpoll_rx(skb)) | 1761 | if (skb->dev->poll && netpoll_rx(skb)) |
1770 | return NET_RX_DROP; | 1762 | return NET_RX_DROP; |
1771 | 1763 | ||
1772 | if (!skb->tstamp.off_sec) | 1764 | if (!skb->tstamp.tv64) |
1773 | net_timestamp(skb); | 1765 | net_timestamp(skb); |
1774 | 1766 | ||
1775 | if (!skb->iif) | 1767 | if (!skb->iif) |
@@ -1782,8 +1774,9 @@ int netif_receive_skb(struct sk_buff *skb) | |||
1782 | 1774 | ||
1783 | __get_cpu_var(netdev_rx_stat).total++; | 1775 | __get_cpu_var(netdev_rx_stat).total++; |
1784 | 1776 | ||
1785 | skb->h.raw = skb->nh.raw = skb->data; | 1777 | skb_reset_network_header(skb); |
1786 | skb->mac_len = skb->nh.raw - skb->mac.raw; | 1778 | skb_reset_transport_header(skb); |
1779 | skb->mac_len = skb->network_header - skb->mac_header; | ||
1787 | 1780 | ||
1788 | pt_prev = NULL; | 1781 | pt_prev = NULL; |
1789 | 1782 | ||
@@ -1823,7 +1816,8 @@ int netif_receive_skb(struct sk_buff *skb) | |||
1823 | ncls: | 1816 | ncls: |
1824 | #endif | 1817 | #endif |
1825 | 1818 | ||
1826 | if (handle_bridge(&skb, &pt_prev, &ret, orig_dev)) | 1819 | skb = handle_bridge(skb, &pt_prev, &ret, orig_dev); |
1820 | if (!skb) | ||
1827 | goto out; | 1821 | goto out; |
1828 | 1822 | ||
1829 | type = skb->protocol; | 1823 | type = skb->protocol; |
@@ -2076,7 +2070,7 @@ static int dev_ifconf(char __user *arg) | |||
2076 | * This is invoked by the /proc filesystem handler to display a device | 2070 | * This is invoked by the /proc filesystem handler to display a device |
2077 | * in detail. | 2071 | * in detail. |
2078 | */ | 2072 | */ |
2079 | static __inline__ struct net_device *dev_get_idx(loff_t pos) | 2073 | static struct net_device *dev_get_idx(loff_t pos) |
2080 | { | 2074 | { |
2081 | struct net_device *dev; | 2075 | struct net_device *dev; |
2082 | loff_t i; | 2076 | loff_t i; |
@@ -2105,9 +2099,9 @@ void dev_seq_stop(struct seq_file *seq, void *v) | |||
2105 | 2099 | ||
2106 | static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev) | 2100 | static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev) |
2107 | { | 2101 | { |
2108 | if (dev->get_stats) { | 2102 | struct net_device_stats *stats = dev->get_stats(dev); |
2109 | struct net_device_stats *stats = dev->get_stats(dev); | ||
2110 | 2103 | ||
2104 | if (stats) { | ||
2111 | seq_printf(seq, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu " | 2105 | seq_printf(seq, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu " |
2112 | "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", | 2106 | "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", |
2113 | dev->name, stats->rx_bytes, stats->rx_packets, | 2107 | dev->name, stats->rx_bytes, stats->rx_packets, |
@@ -2185,7 +2179,7 @@ static int softnet_seq_show(struct seq_file *seq, void *v) | |||
2185 | return 0; | 2179 | return 0; |
2186 | } | 2180 | } |
2187 | 2181 | ||
2188 | static struct seq_operations dev_seq_ops = { | 2182 | static const struct seq_operations dev_seq_ops = { |
2189 | .start = dev_seq_start, | 2183 | .start = dev_seq_start, |
2190 | .next = dev_seq_next, | 2184 | .next = dev_seq_next, |
2191 | .stop = dev_seq_stop, | 2185 | .stop = dev_seq_stop, |
@@ -2205,7 +2199,7 @@ static const struct file_operations dev_seq_fops = { | |||
2205 | .release = seq_release, | 2199 | .release = seq_release, |
2206 | }; | 2200 | }; |
2207 | 2201 | ||
2208 | static struct seq_operations softnet_seq_ops = { | 2202 | static const struct seq_operations softnet_seq_ops = { |
2209 | .start = softnet_seq_start, | 2203 | .start = softnet_seq_start, |
2210 | .next = softnet_seq_next, | 2204 | .next = softnet_seq_next, |
2211 | .stop = softnet_seq_stop, | 2205 | .stop = softnet_seq_stop, |
@@ -2225,12 +2219,135 @@ static const struct file_operations softnet_seq_fops = { | |||
2225 | .release = seq_release, | 2219 | .release = seq_release, |
2226 | }; | 2220 | }; |
2227 | 2221 | ||
2228 | #ifdef CONFIG_WIRELESS_EXT | 2222 | static void *ptype_get_idx(loff_t pos) |
2229 | extern int wireless_proc_init(void); | 2223 | { |
2230 | #else | 2224 | struct packet_type *pt = NULL; |
2231 | #define wireless_proc_init() 0 | 2225 | loff_t i = 0; |
2226 | int t; | ||
2227 | |||
2228 | list_for_each_entry_rcu(pt, &ptype_all, list) { | ||
2229 | if (i == pos) | ||
2230 | return pt; | ||
2231 | ++i; | ||
2232 | } | ||
2233 | |||
2234 | for (t = 0; t < 16; t++) { | ||
2235 | list_for_each_entry_rcu(pt, &ptype_base[t], list) { | ||
2236 | if (i == pos) | ||
2237 | return pt; | ||
2238 | ++i; | ||
2239 | } | ||
2240 | } | ||
2241 | return NULL; | ||
2242 | } | ||
2243 | |||
2244 | static void *ptype_seq_start(struct seq_file *seq, loff_t *pos) | ||
2245 | { | ||
2246 | rcu_read_lock(); | ||
2247 | return *pos ? ptype_get_idx(*pos - 1) : SEQ_START_TOKEN; | ||
2248 | } | ||
2249 | |||
2250 | static void *ptype_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
2251 | { | ||
2252 | struct packet_type *pt; | ||
2253 | struct list_head *nxt; | ||
2254 | int hash; | ||
2255 | |||
2256 | ++*pos; | ||
2257 | if (v == SEQ_START_TOKEN) | ||
2258 | return ptype_get_idx(0); | ||
2259 | |||
2260 | pt = v; | ||
2261 | nxt = pt->list.next; | ||
2262 | if (pt->type == htons(ETH_P_ALL)) { | ||
2263 | if (nxt != &ptype_all) | ||
2264 | goto found; | ||
2265 | hash = 0; | ||
2266 | nxt = ptype_base[0].next; | ||
2267 | } else | ||
2268 | hash = ntohs(pt->type) & 15; | ||
2269 | |||
2270 | while (nxt == &ptype_base[hash]) { | ||
2271 | if (++hash >= 16) | ||
2272 | return NULL; | ||
2273 | nxt = ptype_base[hash].next; | ||
2274 | } | ||
2275 | found: | ||
2276 | return list_entry(nxt, struct packet_type, list); | ||
2277 | } | ||
2278 | |||
2279 | static void ptype_seq_stop(struct seq_file *seq, void *v) | ||
2280 | { | ||
2281 | rcu_read_unlock(); | ||
2282 | } | ||
2283 | |||
2284 | static void ptype_seq_decode(struct seq_file *seq, void *sym) | ||
2285 | { | ||
2286 | #ifdef CONFIG_KALLSYMS | ||
2287 | unsigned long offset = 0, symsize; | ||
2288 | const char *symname; | ||
2289 | char *modname; | ||
2290 | char namebuf[128]; | ||
2291 | |||
2292 | symname = kallsyms_lookup((unsigned long)sym, &symsize, &offset, | ||
2293 | &modname, namebuf); | ||
2294 | |||
2295 | if (symname) { | ||
2296 | char *delim = ":"; | ||
2297 | |||
2298 | if (!modname) | ||
2299 | modname = delim = ""; | ||
2300 | seq_printf(seq, "%s%s%s%s+0x%lx", delim, modname, delim, | ||
2301 | symname, offset); | ||
2302 | return; | ||
2303 | } | ||
2232 | #endif | 2304 | #endif |
2233 | 2305 | ||
2306 | seq_printf(seq, "[%p]", sym); | ||
2307 | } | ||
2308 | |||
2309 | static int ptype_seq_show(struct seq_file *seq, void *v) | ||
2310 | { | ||
2311 | struct packet_type *pt = v; | ||
2312 | |||
2313 | if (v == SEQ_START_TOKEN) | ||
2314 | seq_puts(seq, "Type Device Function\n"); | ||
2315 | else { | ||
2316 | if (pt->type == htons(ETH_P_ALL)) | ||
2317 | seq_puts(seq, "ALL "); | ||
2318 | else | ||
2319 | seq_printf(seq, "%04x", ntohs(pt->type)); | ||
2320 | |||
2321 | seq_printf(seq, " %-8s ", | ||
2322 | pt->dev ? pt->dev->name : ""); | ||
2323 | ptype_seq_decode(seq, pt->func); | ||
2324 | seq_putc(seq, '\n'); | ||
2325 | } | ||
2326 | |||
2327 | return 0; | ||
2328 | } | ||
2329 | |||
2330 | static const struct seq_operations ptype_seq_ops = { | ||
2331 | .start = ptype_seq_start, | ||
2332 | .next = ptype_seq_next, | ||
2333 | .stop = ptype_seq_stop, | ||
2334 | .show = ptype_seq_show, | ||
2335 | }; | ||
2336 | |||
2337 | static int ptype_seq_open(struct inode *inode, struct file *file) | ||
2338 | { | ||
2339 | return seq_open(file, &ptype_seq_ops); | ||
2340 | } | ||
2341 | |||
2342 | static const struct file_operations ptype_seq_fops = { | ||
2343 | .owner = THIS_MODULE, | ||
2344 | .open = ptype_seq_open, | ||
2345 | .read = seq_read, | ||
2346 | .llseek = seq_lseek, | ||
2347 | .release = seq_release, | ||
2348 | }; | ||
2349 | |||
2350 | |||
2234 | static int __init dev_proc_init(void) | 2351 | static int __init dev_proc_init(void) |
2235 | { | 2352 | { |
2236 | int rc = -ENOMEM; | 2353 | int rc = -ENOMEM; |
@@ -2239,13 +2356,18 @@ static int __init dev_proc_init(void) | |||
2239 | goto out; | 2356 | goto out; |
2240 | if (!proc_net_fops_create("softnet_stat", S_IRUGO, &softnet_seq_fops)) | 2357 | if (!proc_net_fops_create("softnet_stat", S_IRUGO, &softnet_seq_fops)) |
2241 | goto out_dev; | 2358 | goto out_dev; |
2242 | if (wireless_proc_init()) | 2359 | if (!proc_net_fops_create("ptype", S_IRUGO, &ptype_seq_fops)) |
2360 | goto out_dev2; | ||
2361 | |||
2362 | if (wext_proc_init()) | ||
2243 | goto out_softnet; | 2363 | goto out_softnet; |
2244 | rc = 0; | 2364 | rc = 0; |
2245 | out: | 2365 | out: |
2246 | return rc; | 2366 | return rc; |
2247 | out_softnet: | 2367 | out_softnet: |
2248 | proc_net_remove("softnet_stat"); | 2368 | proc_net_remove("softnet_stat"); |
2369 | out_dev2: | ||
2370 | proc_net_remove("ptype"); | ||
2249 | out_dev: | 2371 | out_dev: |
2250 | proc_net_remove("dev"); | 2372 | proc_net_remove("dev"); |
2251 | goto out; | 2373 | goto out; |
@@ -2795,29 +2917,9 @@ int dev_ioctl(unsigned int cmd, void __user *arg) | |||
2795 | ret = -EFAULT; | 2917 | ret = -EFAULT; |
2796 | return ret; | 2918 | return ret; |
2797 | } | 2919 | } |
2798 | #ifdef CONFIG_WIRELESS_EXT | ||
2799 | /* Take care of Wireless Extensions */ | 2920 | /* Take care of Wireless Extensions */ |
2800 | if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { | 2921 | if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) |
2801 | /* If command is `set a parameter', or | 2922 | return wext_handle_ioctl(&ifr, cmd, arg); |
2802 | * `get the encoding parameters', check if | ||
2803 | * the user has the right to do it */ | ||
2804 | if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE | ||
2805 | || cmd == SIOCGIWENCODEEXT) { | ||
2806 | if (!capable(CAP_NET_ADMIN)) | ||
2807 | return -EPERM; | ||
2808 | } | ||
2809 | dev_load(ifr.ifr_name); | ||
2810 | rtnl_lock(); | ||
2811 | /* Follow me in net/core/wireless.c */ | ||
2812 | ret = wireless_process_ioctl(&ifr, cmd); | ||
2813 | rtnl_unlock(); | ||
2814 | if (IW_IS_GET(cmd) && | ||
2815 | copy_to_user(arg, &ifr, | ||
2816 | sizeof(struct ifreq))) | ||
2817 | ret = -EFAULT; | ||
2818 | return ret; | ||
2819 | } | ||
2820 | #endif /* CONFIG_WIRELESS_EXT */ | ||
2821 | return -EINVAL; | 2923 | return -EINVAL; |
2822 | } | 2924 | } |
2823 | } | 2925 | } |
@@ -2847,7 +2949,7 @@ static int dev_boot_phase = 1; | |||
2847 | static DEFINE_SPINLOCK(net_todo_list_lock); | 2949 | static DEFINE_SPINLOCK(net_todo_list_lock); |
2848 | static struct list_head net_todo_list = LIST_HEAD_INIT(net_todo_list); | 2950 | static struct list_head net_todo_list = LIST_HEAD_INIT(net_todo_list); |
2849 | 2951 | ||
2850 | static inline void net_set_todo(struct net_device *dev) | 2952 | static void net_set_todo(struct net_device *dev) |
2851 | { | 2953 | { |
2852 | spin_lock(&net_todo_list_lock); | 2954 | spin_lock(&net_todo_list_lock); |
2853 | list_add_tail(&dev->todo_list, &net_todo_list); | 2955 | list_add_tail(&dev->todo_list, &net_todo_list); |
@@ -2888,9 +2990,7 @@ int register_netdevice(struct net_device *dev) | |||
2888 | spin_lock_init(&dev->queue_lock); | 2990 | spin_lock_init(&dev->queue_lock); |
2889 | spin_lock_init(&dev->_xmit_lock); | 2991 | spin_lock_init(&dev->_xmit_lock); |
2890 | dev->xmit_lock_owner = -1; | 2992 | dev->xmit_lock_owner = -1; |
2891 | #ifdef CONFIG_NET_CLS_ACT | ||
2892 | spin_lock_init(&dev->ingress_lock); | 2993 | spin_lock_init(&dev->ingress_lock); |
2893 | #endif | ||
2894 | 2994 | ||
2895 | dev->iflink = -1; | 2995 | dev->iflink = -1; |
2896 | 2996 | ||
@@ -3002,7 +3102,7 @@ out: | |||
3002 | * chain. 0 is returned on success. A negative errno code is returned | 3102 | * chain. 0 is returned on success. A negative errno code is returned |
3003 | * on a failure to set up the device, or if the name is a duplicate. | 3103 | * on a failure to set up the device, or if the name is a duplicate. |
3004 | * | 3104 | * |
3005 | * This is a wrapper around register_netdev that takes the rtnl semaphore | 3105 | * This is a wrapper around register_netdevice that takes the rtnl semaphore |
3006 | * and expands the device name if you passed a format string to | 3106 | * and expands the device name if you passed a format string to |
3007 | * alloc_netdev. | 3107 | * alloc_netdev. |
3008 | */ | 3108 | */ |
@@ -3157,6 +3257,13 @@ out: | |||
3157 | mutex_unlock(&net_todo_run_mutex); | 3257 | mutex_unlock(&net_todo_run_mutex); |
3158 | } | 3258 | } |
3159 | 3259 | ||
3260 | static struct net_device_stats *maybe_internal_stats(struct net_device *dev) | ||
3261 | { | ||
3262 | if (dev->features & NETIF_F_INTERNAL_STATS) | ||
3263 | return &dev->stats; | ||
3264 | return NULL; | ||
3265 | } | ||
3266 | |||
3160 | /** | 3267 | /** |
3161 | * alloc_netdev - allocate network device | 3268 | * alloc_netdev - allocate network device |
3162 | * @sizeof_priv: size of private data to allocate space for | 3269 | * @sizeof_priv: size of private data to allocate space for |
@@ -3192,6 +3299,7 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name, | |||
3192 | if (sizeof_priv) | 3299 | if (sizeof_priv) |
3193 | dev->priv = netdev_priv(dev); | 3300 | dev->priv = netdev_priv(dev); |
3194 | 3301 | ||
3302 | dev->get_stats = maybe_internal_stats; | ||
3195 | setup(dev); | 3303 | setup(dev); |
3196 | strcpy(dev->name, name); | 3304 | strcpy(dev->name, name); |
3197 | return dev; | 3305 | return dev; |