aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/feature-removal-schedule.txt10
-rw-r--r--Documentation/kernel-parameters.txt7
-rw-r--r--drivers/net/atlx/atl1.c3
-rw-r--r--drivers/net/gianfar.c1
-rw-r--r--drivers/net/hamradio/hdlcdrv.c1
-rw-r--r--drivers/net/sunhme.c4
-rw-r--r--drivers/net/ucc_geth.c1
-rw-r--r--include/linux/netfilter/nf_conntrack_common.h8
-rw-r--r--include/linux/netfilter/nfnetlink_conntrack.h8
-rw-r--r--include/linux/netfilter/nfnetlink_log.h3
-rw-r--r--include/net/netfilter/nf_conntrack.h6
-rw-r--r--include/net/netfilter/nf_conntrack_acct.h51
-rw-r--r--include/net/netfilter/nf_conntrack_extend.h2
-rw-r--r--include/net/netlink.h3
-rw-r--r--net/core/dev.c37
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c18
-rw-r--r--net/ipv4/netfilter/nf_nat_core.c8
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c38
-rw-r--r--net/netfilter/Kconfig9
-rw-r--r--net/netfilter/Makefile2
-rw-r--r--net/netfilter/nf_conntrack_acct.c104
-rw-r--r--net/netfilter/nf_conntrack_core.c39
-rw-r--r--net/netfilter/nf_conntrack_netlink.c44
-rw-r--r--net/netfilter/nf_conntrack_proto_sctp.c8
-rw-r--r--net/netfilter/nf_conntrack_standalone.c18
-rw-r--r--net/netfilter/nfnetlink_log.c8
-rw-r--r--net/netfilter/xt_TCPMSS.c42
-rw-r--r--net/netfilter/xt_connbytes.c8
-rw-r--r--net/netfilter/xt_time.c2
-rw-r--r--net/sched/sch_generic.c102
30 files changed, 411 insertions, 184 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 86334b6f8238..9f73587219e8 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -336,3 +336,13 @@ When: After the only user (hal) has seen a release with the patches
336Why: Over 1K .text/.data size reduction, data is available in other 336Why: Over 1K .text/.data size reduction, data is available in other
337 ways (ioctls) 337 ways (ioctls)
338Who: Johannes Berg <johannes@sipsolutions.net> 338Who: Johannes Berg <johannes@sipsolutions.net>
339
340---------------------------
341
342What: CONFIG_NF_CT_ACCT
343When: 2.6.29
344Why: Accounting can now be enabled/disabled without kernel recompilation.
345 Currently used only to set a default value for a feature that is also
346 controlled by a kernel/module/sysfs/sysctl parameter.
347Who: Krzysztof Piotr Oledzki <ole@ans.pl>
348
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 25e88cf5d84e..30d44b78171a 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1279,6 +1279,13 @@ and is between 256 and 4096 characters. It is defined in the file
1279 This usage is only documented in each driver source 1279 This usage is only documented in each driver source
1280 file if at all. 1280 file if at all.
1281 1281
1282 nf_conntrack.acct=
1283 [NETFILTER] Enable connection tracking flow accounting
1284 0 to disable accounting
1285 1 to enable accounting
1286 Default value depends on CONFIG_NF_CT_ACCT that is
1287 going to be removed in 2.6.29.
1288
1282 nfsaddrs= [NFS] 1289 nfsaddrs= [NFS]
1283 See Documentation/filesystems/nfsroot.txt. 1290 See Documentation/filesystems/nfsroot.txt.
1284 1291
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
index 3e22e7817bc3..f12e3d12474b 100644
--- a/drivers/net/atlx/atl1.c
+++ b/drivers/net/atlx/atl1.c
@@ -1308,7 +1308,6 @@ static u32 atl1_check_link(struct atl1_adapter *adapter)
1308 dev_info(&adapter->pdev->dev, "link is down\n"); 1308 dev_info(&adapter->pdev->dev, "link is down\n");
1309 adapter->link_speed = SPEED_0; 1309 adapter->link_speed = SPEED_0;
1310 netif_carrier_off(netdev); 1310 netif_carrier_off(netdev);
1311 netif_stop_queue(netdev);
1312 } 1311 }
1313 return 0; 1312 return 0;
1314 } 1313 }
@@ -1358,7 +1357,6 @@ static u32 atl1_check_link(struct atl1_adapter *adapter)
1358 if (!netif_carrier_ok(netdev)) { 1357 if (!netif_carrier_ok(netdev)) {
1359 /* Link down -> Up */ 1358 /* Link down -> Up */
1360 netif_carrier_on(netdev); 1359 netif_carrier_on(netdev);
1361 netif_wake_queue(netdev);
1362 } 1360 }
1363 return 0; 1361 return 0;
1364 } 1362 }
@@ -2627,6 +2625,7 @@ static s32 atl1_up(struct atl1_adapter *adapter)
2627 mod_timer(&adapter->watchdog_timer, jiffies); 2625 mod_timer(&adapter->watchdog_timer, jiffies);
2628 atlx_irq_enable(adapter); 2626 atlx_irq_enable(adapter);
2629 atl1_check_link(adapter); 2627 atl1_check_link(adapter);
2628 netif_start_queue(netdev);
2630 return 0; 2629 return 0;
2631 2630
2632err_up: 2631err_up:
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 45a63172852f..39b45e901be6 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -1725,7 +1725,6 @@ static void adjust_link(struct net_device *dev)
1725 if (!priv->oldlink) { 1725 if (!priv->oldlink) {
1726 new_state = 1; 1726 new_state = 1;
1727 priv->oldlink = 1; 1727 priv->oldlink = 1;
1728 netif_tx_schedule_all(dev);
1729 } 1728 }
1730 } else if (priv->oldlink) { 1729 } else if (priv->oldlink) {
1731 new_state = 1; 1730 new_state = 1;
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index ae9629fa6882..c258a0586e61 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -88,6 +88,7 @@
88static inline void append_crc_ccitt(unsigned char *buffer, int len) 88static inline void append_crc_ccitt(unsigned char *buffer, int len)
89{ 89{
90 unsigned int crc = crc_ccitt(0xffff, buffer, len) ^ 0xffff; 90 unsigned int crc = crc_ccitt(0xffff, buffer, len) ^ 0xffff;
91 buffer += len;
91 *buffer++ = crc; 92 *buffer++ = crc;
92 *buffer++ = crc >> 8; 93 *buffer++ = crc >> 8;
93} 94}
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 1aa425be3067..b79d5f018f79 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2377,8 +2377,6 @@ static void happy_meal_set_multicast(struct net_device *dev)
2377 2377
2378 spin_lock_irq(&hp->happy_lock); 2378 spin_lock_irq(&hp->happy_lock);
2379 2379
2380 netif_stop_queue(dev);
2381
2382 if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) { 2380 if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
2383 hme_write32(hp, bregs + BMAC_HTABLE0, 0xffff); 2381 hme_write32(hp, bregs + BMAC_HTABLE0, 0xffff);
2384 hme_write32(hp, bregs + BMAC_HTABLE1, 0xffff); 2382 hme_write32(hp, bregs + BMAC_HTABLE1, 0xffff);
@@ -2410,8 +2408,6 @@ static void happy_meal_set_multicast(struct net_device *dev)
2410 hme_write32(hp, bregs + BMAC_HTABLE3, hash_table[3]); 2408 hme_write32(hp, bregs + BMAC_HTABLE3, hash_table[3]);
2411 } 2409 }
2412 2410
2413 netif_wake_queue(dev);
2414
2415 spin_unlock_irq(&hp->happy_lock); 2411 spin_unlock_irq(&hp->happy_lock);
2416} 2412}
2417 2413
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 756ba10b79d6..8f944e57fd55 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -1588,7 +1588,6 @@ static void adjust_link(struct net_device *dev)
1588 if (!ugeth->oldlink) { 1588 if (!ugeth->oldlink) {
1589 new_state = 1; 1589 new_state = 1;
1590 ugeth->oldlink = 1; 1590 ugeth->oldlink = 1;
1591 netif_tx_schedule_all(dev);
1592 } 1591 }
1593 } else if (ugeth->oldlink) { 1592 } else if (ugeth->oldlink) {
1594 new_state = 1; 1593 new_state = 1;
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h
index bad1eb760f61..885cbe282260 100644
--- a/include/linux/netfilter/nf_conntrack_common.h
+++ b/include/linux/netfilter/nf_conntrack_common.h
@@ -122,7 +122,7 @@ enum ip_conntrack_events
122 IPCT_NATINFO_BIT = 10, 122 IPCT_NATINFO_BIT = 10,
123 IPCT_NATINFO = (1 << IPCT_NATINFO_BIT), 123 IPCT_NATINFO = (1 << IPCT_NATINFO_BIT),
124 124
125 /* Counter highest bit has been set */ 125 /* Counter highest bit has been set, unused */
126 IPCT_COUNTER_FILLING_BIT = 11, 126 IPCT_COUNTER_FILLING_BIT = 11,
127 IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT), 127 IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT),
128 128
@@ -145,12 +145,6 @@ enum ip_conntrack_expect_events {
145}; 145};
146 146
147#ifdef __KERNEL__ 147#ifdef __KERNEL__
148struct ip_conntrack_counter
149{
150 u_int32_t packets;
151 u_int32_t bytes;
152};
153
154struct ip_conntrack_stat 148struct ip_conntrack_stat
155{ 149{
156 unsigned int searched; 150 unsigned int searched;
diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h
index 759bc043dc65..c19595c89304 100644
--- a/include/linux/netfilter/nfnetlink_conntrack.h
+++ b/include/linux/netfilter/nfnetlink_conntrack.h
@@ -115,10 +115,10 @@ enum ctattr_protoinfo_sctp {
115 115
116enum ctattr_counters { 116enum ctattr_counters {
117 CTA_COUNTERS_UNSPEC, 117 CTA_COUNTERS_UNSPEC,
118 CTA_COUNTERS_PACKETS, /* old 64bit counters */ 118 CTA_COUNTERS_PACKETS, /* 64bit counters */
119 CTA_COUNTERS_BYTES, /* old 64bit counters */ 119 CTA_COUNTERS_BYTES, /* 64bit counters */
120 CTA_COUNTERS32_PACKETS, 120 CTA_COUNTERS32_PACKETS, /* old 32bit counters, unused */
121 CTA_COUNTERS32_BYTES, 121 CTA_COUNTERS32_BYTES, /* old 32bit counters, unused */
122 __CTA_COUNTERS_MAX 122 __CTA_COUNTERS_MAX
123}; 123};
124#define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1) 124#define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)
diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h
index a85721332924..f661731f3cb1 100644
--- a/include/linux/netfilter/nfnetlink_log.h
+++ b/include/linux/netfilter/nfnetlink_log.h
@@ -48,6 +48,9 @@ enum nfulnl_attr_type {
48 NFULA_SEQ, /* instance-local sequence number */ 48 NFULA_SEQ, /* instance-local sequence number */
49 NFULA_SEQ_GLOBAL, /* global sequence number */ 49 NFULA_SEQ_GLOBAL, /* global sequence number */
50 NFULA_GID, /* group id of socket */ 50 NFULA_GID, /* group id of socket */
51 NFULA_HWTYPE, /* hardware type */
52 NFULA_HWHEADER, /* hardware header */
53 NFULA_HWLEN, /* hardware header length */
51 54
52 __NFULA_MAX 55 __NFULA_MAX
53}; 56};
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 8f5b75734dd0..0741ad592da0 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -88,7 +88,6 @@ struct nf_conn_help {
88 u8 expecting[NF_CT_MAX_EXPECT_CLASSES]; 88 u8 expecting[NF_CT_MAX_EXPECT_CLASSES];
89}; 89};
90 90
91
92#include <net/netfilter/ipv4/nf_conntrack_ipv4.h> 91#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
93#include <net/netfilter/ipv6/nf_conntrack_ipv6.h> 92#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
94 93
@@ -111,11 +110,6 @@ struct nf_conn
111 /* Timer function; drops refcnt when it goes off. */ 110 /* Timer function; drops refcnt when it goes off. */
112 struct timer_list timeout; 111 struct timer_list timeout;
113 112
114#ifdef CONFIG_NF_CT_ACCT
115 /* Accounting Information (same cache line as other written members) */
116 struct ip_conntrack_counter counters[IP_CT_DIR_MAX];
117#endif
118
119#if defined(CONFIG_NF_CONNTRACK_MARK) 113#if defined(CONFIG_NF_CONNTRACK_MARK)
120 u_int32_t mark; 114 u_int32_t mark;
121#endif 115#endif
diff --git a/include/net/netfilter/nf_conntrack_acct.h b/include/net/netfilter/nf_conntrack_acct.h
new file mode 100644
index 000000000000..5d5ae55d54c4
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_acct.h
@@ -0,0 +1,51 @@
1/*
2 * (C) 2008 Krzysztof Piotr Oledzki <ole@ans.pl>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _NF_CONNTRACK_ACCT_H
10#define _NF_CONNTRACK_ACCT_H
11#include <linux/netfilter/nf_conntrack_common.h>
12#include <linux/netfilter/nf_conntrack_tuple_common.h>
13#include <net/netfilter/nf_conntrack.h>
14#include <net/netfilter/nf_conntrack_extend.h>
15
16struct nf_conn_counter {
17 u_int64_t packets;
18 u_int64_t bytes;
19};
20
21extern int nf_ct_acct;
22
23static inline
24struct nf_conn_counter *nf_conn_acct_find(const struct nf_conn *ct)
25{
26 return nf_ct_ext_find(ct, NF_CT_EXT_ACCT);
27}
28
29static inline
30struct nf_conn_counter *nf_ct_acct_ext_add(struct nf_conn *ct, gfp_t gfp)
31{
32 struct nf_conn_counter *acct;
33
34 if (!nf_ct_acct)
35 return NULL;
36
37 acct = nf_ct_ext_add(ct, NF_CT_EXT_ACCT, gfp);
38 if (!acct)
39 pr_debug("failed to add accounting extension area");
40
41
42 return acct;
43};
44
45extern unsigned int
46seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir);
47
48extern int nf_conntrack_acct_init(void);
49extern void nf_conntrack_acct_fini(void);
50
51#endif /* _NF_CONNTRACK_ACCT_H */
diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h
index f80c0ed6d870..da8ee52613a5 100644
--- a/include/net/netfilter/nf_conntrack_extend.h
+++ b/include/net/netfilter/nf_conntrack_extend.h
@@ -7,11 +7,13 @@ enum nf_ct_ext_id
7{ 7{
8 NF_CT_EXT_HELPER, 8 NF_CT_EXT_HELPER,
9 NF_CT_EXT_NAT, 9 NF_CT_EXT_NAT,
10 NF_CT_EXT_ACCT,
10 NF_CT_EXT_NUM, 11 NF_CT_EXT_NUM,
11}; 12};
12 13
13#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help 14#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
14#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat 15#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat
16#define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter
15 17
16/* Extensions: optional stuff which isn't permanently in struct. */ 18/* Extensions: optional stuff which isn't permanently in struct. */
17struct nf_ct_ext { 19struct nf_ct_ext {
diff --git a/include/net/netlink.h b/include/net/netlink.h
index dfc3701dfcc3..18024b8cecb8 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -896,6 +896,9 @@ static inline int nla_put_msecs(struct sk_buff *skb, int attrtype,
896#define NLA_PUT_U64(skb, attrtype, value) \ 896#define NLA_PUT_U64(skb, attrtype, value) \
897 NLA_PUT_TYPE(skb, u64, attrtype, value) 897 NLA_PUT_TYPE(skb, u64, attrtype, value)
898 898
899#define NLA_PUT_BE64(skb, attrtype, value) \
900 NLA_PUT_TYPE(skb, __be64, attrtype, value)
901
899#define NLA_PUT_STRING(skb, attrtype, value) \ 902#define NLA_PUT_STRING(skb, attrtype, value) \
900 NLA_PUT(skb, attrtype, strlen(value) + 1, value) 903 NLA_PUT(skb, attrtype, strlen(value) + 1, value)
901 904
diff --git a/net/core/dev.c b/net/core/dev.c
index 2eed17bcb2dd..cbc34c0db376 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -124,6 +124,8 @@
124#include <linux/ip.h> 124#include <linux/ip.h>
125#include <linux/ipv6.h> 125#include <linux/ipv6.h>
126#include <linux/in.h> 126#include <linux/in.h>
127#include <linux/jhash.h>
128#include <linux/random.h>
127 129
128#include "net-sysfs.h" 130#include "net-sysfs.h"
129 131
@@ -1325,7 +1327,8 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
1325 1327
1326void __netif_schedule(struct Qdisc *q) 1328void __netif_schedule(struct Qdisc *q)
1327{ 1329{
1328 BUG_ON(q == &noop_qdisc); 1330 if (WARN_ON_ONCE(q == &noop_qdisc))
1331 return;
1329 1332
1330 if (!test_and_set_bit(__QDISC_STATE_SCHED, &q->state)) { 1333 if (!test_and_set_bit(__QDISC_STATE_SCHED, &q->state)) {
1331 struct softnet_data *sd; 1334 struct softnet_data *sd;
@@ -1668,34 +1671,37 @@ out_kfree_skb:
1668 * --BLG 1671 * --BLG
1669 */ 1672 */
1670 1673
1674static u32 simple_tx_hashrnd;
1675static int simple_tx_hashrnd_initialized = 0;
1676
1671static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb) 1677static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb)
1672{ 1678{
1673 u32 *addr, *ports, hash, ihl; 1679 u32 addr1, addr2, ports;
1680 u32 hash, ihl;
1674 u8 ip_proto; 1681 u8 ip_proto;
1675 int alen; 1682
1683 if (unlikely(!simple_tx_hashrnd_initialized)) {
1684 get_random_bytes(&simple_tx_hashrnd, 4);
1685 simple_tx_hashrnd_initialized = 1;
1686 }
1676 1687
1677 switch (skb->protocol) { 1688 switch (skb->protocol) {
1678 case __constant_htons(ETH_P_IP): 1689 case __constant_htons(ETH_P_IP):
1679 ip_proto = ip_hdr(skb)->protocol; 1690 ip_proto = ip_hdr(skb)->protocol;
1680 addr = &ip_hdr(skb)->saddr; 1691 addr1 = ip_hdr(skb)->saddr;
1692 addr2 = ip_hdr(skb)->daddr;
1681 ihl = ip_hdr(skb)->ihl; 1693 ihl = ip_hdr(skb)->ihl;
1682 alen = 2;
1683 break; 1694 break;
1684 case __constant_htons(ETH_P_IPV6): 1695 case __constant_htons(ETH_P_IPV6):
1685 ip_proto = ipv6_hdr(skb)->nexthdr; 1696 ip_proto = ipv6_hdr(skb)->nexthdr;
1686 addr = &ipv6_hdr(skb)->saddr.s6_addr32[0]; 1697 addr1 = ipv6_hdr(skb)->saddr.s6_addr32[3];
1698 addr2 = ipv6_hdr(skb)->daddr.s6_addr32[3];
1687 ihl = (40 >> 2); 1699 ihl = (40 >> 2);
1688 alen = 8;
1689 break; 1700 break;
1690 default: 1701 default:
1691 return 0; 1702 return 0;
1692 } 1703 }
1693 1704
1694 ports = (u32 *) (skb_network_header(skb) + (ihl * 4));
1695
1696 hash = 0;
1697 while (alen--)
1698 hash ^= *addr++;
1699 1705
1700 switch (ip_proto) { 1706 switch (ip_proto) {
1701 case IPPROTO_TCP: 1707 case IPPROTO_TCP:
@@ -1705,14 +1711,17 @@ static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb)
1705 case IPPROTO_AH: 1711 case IPPROTO_AH:
1706 case IPPROTO_SCTP: 1712 case IPPROTO_SCTP:
1707 case IPPROTO_UDPLITE: 1713 case IPPROTO_UDPLITE:
1708 hash ^= *ports; 1714 ports = *((u32 *) (skb_network_header(skb) + (ihl * 4)));
1709 break; 1715 break;
1710 1716
1711 default: 1717 default:
1718 ports = 0;
1712 break; 1719 break;
1713 } 1720 }
1714 1721
1715 return hash % dev->real_num_tx_queues; 1722 hash = jhash_3words(addr1, addr2, ports, simple_tx_hashrnd);
1723
1724 return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32);
1716} 1725}
1717 1726
1718static struct netdev_queue *dev_pick_tx(struct net_device *dev, 1727static struct netdev_queue *dev_pick_tx(struct net_device *dev,
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
index 40a46d482490..3a020720e40b 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -18,19 +18,7 @@
18#include <net/netfilter/nf_conntrack_l3proto.h> 18#include <net/netfilter/nf_conntrack_l3proto.h>
19#include <net/netfilter/nf_conntrack_l4proto.h> 19#include <net/netfilter/nf_conntrack_l4proto.h>
20#include <net/netfilter/nf_conntrack_expect.h> 20#include <net/netfilter/nf_conntrack_expect.h>
21 21#include <net/netfilter/nf_conntrack_acct.h>
22#ifdef CONFIG_NF_CT_ACCT
23static unsigned int
24seq_print_counters(struct seq_file *s,
25 const struct ip_conntrack_counter *counter)
26{
27 return seq_printf(s, "packets=%llu bytes=%llu ",
28 (unsigned long long)counter->packets,
29 (unsigned long long)counter->bytes);
30}
31#else
32#define seq_print_counters(x, y) 0
33#endif
34 22
35struct ct_iter_state { 23struct ct_iter_state {
36 unsigned int bucket; 24 unsigned int bucket;
@@ -127,7 +115,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
127 l3proto, l4proto)) 115 l3proto, l4proto))
128 return -ENOSPC; 116 return -ENOSPC;
129 117
130 if (seq_print_counters(s, &ct->counters[IP_CT_DIR_ORIGINAL])) 118 if (seq_print_acct(s, ct, IP_CT_DIR_ORIGINAL))
131 return -ENOSPC; 119 return -ENOSPC;
132 120
133 if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status))) 121 if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status)))
@@ -138,7 +126,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
138 l3proto, l4proto)) 126 l3proto, l4proto))
139 return -ENOSPC; 127 return -ENOSPC;
140 128
141 if (seq_print_counters(s, &ct->counters[IP_CT_DIR_REPLY])) 129 if (seq_print_acct(s, ct, IP_CT_DIR_REPLY))
142 return -ENOSPC; 130 return -ENOSPC;
143 131
144 if (test_bit(IPS_ASSURED_BIT, &ct->status)) 132 if (test_bit(IPS_ASSURED_BIT, &ct->status))
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index d2a887fc8d9b..6c6a3cba8d50 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -240,12 +240,12 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
240 This is only required for source (ie. NAT/masq) mappings. 240 This is only required for source (ie. NAT/masq) mappings.
241 So far, we don't do local source mappings, so multiple 241 So far, we don't do local source mappings, so multiple
242 manips not an issue. */ 242 manips not an issue. */
243 if (maniptype == IP_NAT_MANIP_SRC) { 243 if (maniptype == IP_NAT_MANIP_SRC &&
244 !(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) {
244 if (find_appropriate_src(orig_tuple, tuple, range)) { 245 if (find_appropriate_src(orig_tuple, tuple, range)) {
245 pr_debug("get_unique_tuple: Found current src map\n"); 246 pr_debug("get_unique_tuple: Found current src map\n");
246 if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) 247 if (!nf_nat_used_tuple(tuple, ct))
247 if (!nf_nat_used_tuple(tuple, ct)) 248 return;
248 return;
249 } 249 }
250 } 250 }
251 251
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index 4334d5cabc5b..14544320c545 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -318,11 +318,11 @@ static int mangle_content_len(struct sk_buff *skb,
318 buffer, buflen); 318 buffer, buflen);
319} 319}
320 320
321static unsigned mangle_sdp_packet(struct sk_buff *skb, const char **dptr, 321static int mangle_sdp_packet(struct sk_buff *skb, const char **dptr,
322 unsigned int dataoff, unsigned int *datalen, 322 unsigned int dataoff, unsigned int *datalen,
323 enum sdp_header_types type, 323 enum sdp_header_types type,
324 enum sdp_header_types term, 324 enum sdp_header_types term,
325 char *buffer, int buflen) 325 char *buffer, int buflen)
326{ 326{
327 enum ip_conntrack_info ctinfo; 327 enum ip_conntrack_info ctinfo;
328 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 328 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
@@ -330,9 +330,9 @@ static unsigned mangle_sdp_packet(struct sk_buff *skb, const char **dptr,
330 330
331 if (ct_sip_get_sdp_header(ct, *dptr, dataoff, *datalen, type, term, 331 if (ct_sip_get_sdp_header(ct, *dptr, dataoff, *datalen, type, term,
332 &matchoff, &matchlen) <= 0) 332 &matchoff, &matchlen) <= 0)
333 return 0; 333 return -ENOENT;
334 return mangle_packet(skb, dptr, datalen, matchoff, matchlen, 334 return mangle_packet(skb, dptr, datalen, matchoff, matchlen,
335 buffer, buflen); 335 buffer, buflen) ? 0 : -EINVAL;
336} 336}
337 337
338static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr, 338static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr,
@@ -346,8 +346,8 @@ static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr,
346 unsigned int buflen; 346 unsigned int buflen;
347 347
348 buflen = sprintf(buffer, NIPQUAD_FMT, NIPQUAD(addr->ip)); 348 buflen = sprintf(buffer, NIPQUAD_FMT, NIPQUAD(addr->ip));
349 if (!mangle_sdp_packet(skb, dptr, dataoff, datalen, type, term, 349 if (mangle_sdp_packet(skb, dptr, dataoff, datalen, type, term,
350 buffer, buflen)) 350 buffer, buflen))
351 return 0; 351 return 0;
352 352
353 return mangle_content_len(skb, dptr, datalen); 353 return mangle_content_len(skb, dptr, datalen);
@@ -381,15 +381,27 @@ static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr,
381 381
382 /* Mangle session description owner and contact addresses */ 382 /* Mangle session description owner and contact addresses */
383 buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(addr->ip)); 383 buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(addr->ip));
384 if (!mangle_sdp_packet(skb, dptr, dataoff, datalen, 384 if (mangle_sdp_packet(skb, dptr, dataoff, datalen,
385 SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA, 385 SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA,
386 buffer, buflen)) 386 buffer, buflen))
387 return 0; 387 return 0;
388 388
389 if (!mangle_sdp_packet(skb, dptr, dataoff, datalen, 389 switch (mangle_sdp_packet(skb, dptr, dataoff, datalen,
390 SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA, 390 SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA,
391 buffer, buflen)) 391 buffer, buflen)) {
392 case 0:
393 /*
394 * RFC 2327:
395 *
396 * Session description
397 *
398 * c=* (connection information - not required if included in all media)
399 */
400 case -ENOENT:
401 break;
402 default:
392 return 0; 403 return 0;
404 }
393 405
394 return mangle_content_len(skb, dptr, datalen); 406 return mangle_content_len(skb, dptr, datalen);
395} 407}
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 316c7af1d2b1..ee898e74808d 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -49,6 +49,15 @@ config NF_CT_ACCT
49 Those counters can be used for flow-based accounting or the 49 Those counters can be used for flow-based accounting or the
50 `connbytes' match. 50 `connbytes' match.
51 51
52 Please note that currently this option only sets a default state.
53 You may change it at boot time with nf_conntrack.acct=0/1 kernel
54 paramater or by loading the nf_conntrack module with acct=0/1.
55
56 You may also disable/enable it on a running system with:
57 sysctl net.netfilter.nf_conntrack_acct=0/1
58
59 This option will be removed in 2.6.29.
60
52 If unsure, say `N'. 61 If unsure, say `N'.
53 62
54config NF_CONNTRACK_MARK 63config NF_CONNTRACK_MARK
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 5c4b183f6422..3bd2cc556aea 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,6 +1,6 @@
1netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o 1netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
2 2
3nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o 3nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o nf_conntrack_acct.o
4nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o 4nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
5 5
6obj-$(CONFIG_NETFILTER) = netfilter.o 6obj-$(CONFIG_NETFILTER) = netfilter.o
diff --git a/net/netfilter/nf_conntrack_acct.c b/net/netfilter/nf_conntrack_acct.c
new file mode 100644
index 000000000000..59bd8b903a19
--- /dev/null
+++ b/net/netfilter/nf_conntrack_acct.c
@@ -0,0 +1,104 @@
1/* Accouting handling for netfilter. */
2
3/*
4 * (C) 2008 Krzysztof Piotr Oledzki <ole@ans.pl>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/netfilter.h>
12#include <linux/kernel.h>
13#include <linux/moduleparam.h>
14
15#include <net/netfilter/nf_conntrack.h>
16#include <net/netfilter/nf_conntrack_extend.h>
17#include <net/netfilter/nf_conntrack_acct.h>
18
19#ifdef CONFIG_NF_CT_ACCT
20#define NF_CT_ACCT_DEFAULT 1
21#else
22#define NF_CT_ACCT_DEFAULT 0
23#endif
24
25int nf_ct_acct __read_mostly = NF_CT_ACCT_DEFAULT;
26EXPORT_SYMBOL_GPL(nf_ct_acct);
27
28module_param_named(acct, nf_ct_acct, bool, 0644);
29MODULE_PARM_DESC(acct, "Enable connection tracking flow accounting.");
30
31#ifdef CONFIG_SYSCTL
32static struct ctl_table_header *acct_sysctl_header;
33static struct ctl_table acct_sysctl_table[] = {
34 {
35 .ctl_name = CTL_UNNUMBERED,
36 .procname = "nf_conntrack_acct",
37 .data = &nf_ct_acct,
38 .maxlen = sizeof(unsigned int),
39 .mode = 0644,
40 .proc_handler = &proc_dointvec,
41 },
42 {}
43};
44#endif /* CONFIG_SYSCTL */
45
46unsigned int
47seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir)
48{
49 struct nf_conn_counter *acct;
50
51 acct = nf_conn_acct_find(ct);
52 if (!acct)
53 return 0;
54
55 return seq_printf(s, "packets=%llu bytes=%llu ",
56 (unsigned long long)acct[dir].packets,
57 (unsigned long long)acct[dir].bytes);
58};
59EXPORT_SYMBOL_GPL(seq_print_acct);
60
61static struct nf_ct_ext_type acct_extend __read_mostly = {
62 .len = sizeof(struct nf_conn_counter[IP_CT_DIR_MAX]),
63 .align = __alignof__(struct nf_conn_counter[IP_CT_DIR_MAX]),
64 .id = NF_CT_EXT_ACCT,
65};
66
67int nf_conntrack_acct_init(void)
68{
69 int ret;
70
71#ifdef CONFIG_NF_CT_ACCT
72 printk(KERN_WARNING "CONFIG_NF_CT_ACCT is deprecated and will be removed soon. Plase use\n");
73 printk(KERN_WARNING "nf_conntrack.acct=1 kernel paramater, acct=1 nf_conntrack module option or\n");
74 printk(KERN_WARNING "sysctl net.netfilter.nf_conntrack_acct=1 to enable it.\n");
75#endif
76
77 ret = nf_ct_extend_register(&acct_extend);
78 if (ret < 0) {
79 printk(KERN_ERR "nf_conntrack_acct: Unable to register extension\n");
80 return ret;
81 }
82
83#ifdef CONFIG_SYSCTL
84 acct_sysctl_header = register_sysctl_paths(nf_net_netfilter_sysctl_path,
85 acct_sysctl_table);
86
87 if (!acct_sysctl_header) {
88 nf_ct_extend_unregister(&acct_extend);
89
90 printk(KERN_ERR "nf_conntrack_acct: can't register to sysctl.\n");
91 return -ENOMEM;
92 }
93#endif
94
95 return 0;
96}
97
98void nf_conntrack_acct_fini(void)
99{
100#ifdef CONFIG_SYSCTL
101 unregister_sysctl_table(acct_sysctl_header);
102#endif
103 nf_ct_extend_unregister(&acct_extend);
104}
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 28d03e64200b..c519d090bdb9 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -37,6 +37,7 @@
37#include <net/netfilter/nf_conntrack_helper.h> 37#include <net/netfilter/nf_conntrack_helper.h>
38#include <net/netfilter/nf_conntrack_core.h> 38#include <net/netfilter/nf_conntrack_core.h>
39#include <net/netfilter/nf_conntrack_extend.h> 39#include <net/netfilter/nf_conntrack_extend.h>
40#include <net/netfilter/nf_conntrack_acct.h>
40 41
41#define NF_CONNTRACK_VERSION "0.5.0" 42#define NF_CONNTRACK_VERSION "0.5.0"
42 43
@@ -555,6 +556,8 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
555 return NULL; 556 return NULL;
556 } 557 }
557 558
559 nf_ct_acct_ext_add(ct, GFP_ATOMIC);
560
558 spin_lock_bh(&nf_conntrack_lock); 561 spin_lock_bh(&nf_conntrack_lock);
559 exp = nf_ct_find_expectation(tuple); 562 exp = nf_ct_find_expectation(tuple);
560 if (exp) { 563 if (exp) {
@@ -828,17 +831,16 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
828 } 831 }
829 832
830acct: 833acct:
831#ifdef CONFIG_NF_CT_ACCT
832 if (do_acct) { 834 if (do_acct) {
833 ct->counters[CTINFO2DIR(ctinfo)].packets++; 835 struct nf_conn_counter *acct;
834 ct->counters[CTINFO2DIR(ctinfo)].bytes +=
835 skb->len - skb_network_offset(skb);
836 836
837 if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000) 837 acct = nf_conn_acct_find(ct);
838 || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000)) 838 if (acct) {
839 event |= IPCT_COUNTER_FILLING; 839 acct[CTINFO2DIR(ctinfo)].packets++;
840 acct[CTINFO2DIR(ctinfo)].bytes +=
841 skb->len - skb_network_offset(skb);
842 }
840 } 843 }
841#endif
842 844
843 spin_unlock_bh(&nf_conntrack_lock); 845 spin_unlock_bh(&nf_conntrack_lock);
844 846
@@ -853,15 +855,19 @@ bool __nf_ct_kill_acct(struct nf_conn *ct,
853 const struct sk_buff *skb, 855 const struct sk_buff *skb,
854 int do_acct) 856 int do_acct)
855{ 857{
856#ifdef CONFIG_NF_CT_ACCT
857 if (do_acct) { 858 if (do_acct) {
859 struct nf_conn_counter *acct;
860
858 spin_lock_bh(&nf_conntrack_lock); 861 spin_lock_bh(&nf_conntrack_lock);
859 ct->counters[CTINFO2DIR(ctinfo)].packets++; 862 acct = nf_conn_acct_find(ct);
860 ct->counters[CTINFO2DIR(ctinfo)].bytes += 863 if (acct) {
861 skb->len - skb_network_offset(skb); 864 acct[CTINFO2DIR(ctinfo)].packets++;
865 acct[CTINFO2DIR(ctinfo)].bytes +=
866 skb->len - skb_network_offset(skb);
867 }
862 spin_unlock_bh(&nf_conntrack_lock); 868 spin_unlock_bh(&nf_conntrack_lock);
863 } 869 }
864#endif 870
865 if (del_timer(&ct->timeout)) { 871 if (del_timer(&ct->timeout)) {
866 ct->timeout.function((unsigned long)ct); 872 ct->timeout.function((unsigned long)ct);
867 return true; 873 return true;
@@ -1029,6 +1035,7 @@ void nf_conntrack_cleanup(void)
1029 nf_conntrack_proto_fini(); 1035 nf_conntrack_proto_fini();
1030 nf_conntrack_helper_fini(); 1036 nf_conntrack_helper_fini();
1031 nf_conntrack_expect_fini(); 1037 nf_conntrack_expect_fini();
1038 nf_conntrack_acct_fini();
1032} 1039}
1033 1040
1034struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced) 1041struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced)
@@ -1168,6 +1175,10 @@ int __init nf_conntrack_init(void)
1168 if (ret < 0) 1175 if (ret < 0)
1169 goto out_fini_expect; 1176 goto out_fini_expect;
1170 1177
1178 ret = nf_conntrack_acct_init();
1179 if (ret < 0)
1180 goto out_fini_helper;
1181
1171 /* For use by REJECT target */ 1182 /* For use by REJECT target */
1172 rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach); 1183 rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach);
1173 rcu_assign_pointer(nf_ct_destroy, destroy_conntrack); 1184 rcu_assign_pointer(nf_ct_destroy, destroy_conntrack);
@@ -1180,6 +1191,8 @@ int __init nf_conntrack_init(void)
1180 1191
1181 return ret; 1192 return ret;
1182 1193
1194out_fini_helper:
1195 nf_conntrack_helper_fini();
1183out_fini_expect: 1196out_fini_expect:
1184 nf_conntrack_expect_fini(); 1197 nf_conntrack_expect_fini();
1185out_fini_proto: 1198out_fini_proto:
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 95a7967731f9..105a616c5c78 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -37,6 +37,7 @@
37#include <net/netfilter/nf_conntrack_l3proto.h> 37#include <net/netfilter/nf_conntrack_l3proto.h>
38#include <net/netfilter/nf_conntrack_l4proto.h> 38#include <net/netfilter/nf_conntrack_l4proto.h>
39#include <net/netfilter/nf_conntrack_tuple.h> 39#include <net/netfilter/nf_conntrack_tuple.h>
40#include <net/netfilter/nf_conntrack_acct.h>
40#ifdef CONFIG_NF_NAT_NEEDED 41#ifdef CONFIG_NF_NAT_NEEDED
41#include <net/netfilter/nf_nat_core.h> 42#include <net/netfilter/nf_nat_core.h>
42#include <net/netfilter/nf_nat_protocol.h> 43#include <net/netfilter/nf_nat_protocol.h>
@@ -206,22 +207,26 @@ nla_put_failure:
206 return -1; 207 return -1;
207} 208}
208 209
209#ifdef CONFIG_NF_CT_ACCT
210static int 210static int
211ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct, 211ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
212 enum ip_conntrack_dir dir) 212 enum ip_conntrack_dir dir)
213{ 213{
214 enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; 214 enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
215 struct nlattr *nest_count; 215 struct nlattr *nest_count;
216 const struct nf_conn_counter *acct;
217
218 acct = nf_conn_acct_find(ct);
219 if (!acct)
220 return 0;
216 221
217 nest_count = nla_nest_start(skb, type | NLA_F_NESTED); 222 nest_count = nla_nest_start(skb, type | NLA_F_NESTED);
218 if (!nest_count) 223 if (!nest_count)
219 goto nla_put_failure; 224 goto nla_put_failure;
220 225
221 NLA_PUT_BE32(skb, CTA_COUNTERS32_PACKETS, 226 NLA_PUT_BE64(skb, CTA_COUNTERS_PACKETS,
222 htonl(ct->counters[dir].packets)); 227 cpu_to_be64(acct[dir].packets));
223 NLA_PUT_BE32(skb, CTA_COUNTERS32_BYTES, 228 NLA_PUT_BE64(skb, CTA_COUNTERS_BYTES,
224 htonl(ct->counters[dir].bytes)); 229 cpu_to_be64(acct[dir].bytes));
225 230
226 nla_nest_end(skb, nest_count); 231 nla_nest_end(skb, nest_count);
227 232
@@ -230,9 +235,6 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
230nla_put_failure: 235nla_put_failure:
231 return -1; 236 return -1;
232} 237}
233#else
234#define ctnetlink_dump_counters(a, b, c) (0)
235#endif
236 238
237#ifdef CONFIG_NF_CONNTRACK_MARK 239#ifdef CONFIG_NF_CONNTRACK_MARK
238static inline int 240static inline int
@@ -501,11 +503,6 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
501 goto nla_put_failure; 503 goto nla_put_failure;
502#endif 504#endif
503 505
504 if (events & IPCT_COUNTER_FILLING &&
505 (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
506 ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0))
507 goto nla_put_failure;
508
509 if (events & IPCT_RELATED && 506 if (events & IPCT_RELATED &&
510 ctnetlink_dump_master(skb, ct) < 0) 507 ctnetlink_dump_master(skb, ct) < 0)
511 goto nla_put_failure; 508 goto nla_put_failure;
@@ -576,11 +573,15 @@ restart:
576 cb->args[1] = (unsigned long)ct; 573 cb->args[1] = (unsigned long)ct;
577 goto out; 574 goto out;
578 } 575 }
579#ifdef CONFIG_NF_CT_ACCT 576
580 if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == 577 if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) ==
581 IPCTNL_MSG_CT_GET_CTRZERO) 578 IPCTNL_MSG_CT_GET_CTRZERO) {
582 memset(&ct->counters, 0, sizeof(ct->counters)); 579 struct nf_conn_counter *acct;
583#endif 580
581 acct = nf_conn_acct_find(ct);
582 if (acct)
583 memset(acct, 0, sizeof(struct nf_conn_counter[IP_CT_DIR_MAX]));
584 }
584 } 585 }
585 if (cb->args[1]) { 586 if (cb->args[1]) {
586 cb->args[1] = 0; 587 cb->args[1] = 0;
@@ -832,14 +833,9 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
832 u_int8_t u3 = nfmsg->nfgen_family; 833 u_int8_t u3 = nfmsg->nfgen_family;
833 int err = 0; 834 int err = 0;
834 835
835 if (nlh->nlmsg_flags & NLM_F_DUMP) { 836 if (nlh->nlmsg_flags & NLM_F_DUMP)
836#ifndef CONFIG_NF_CT_ACCT
837 if (NFNL_MSG_TYPE(nlh->nlmsg_type) == IPCTNL_MSG_CT_GET_CTRZERO)
838 return -ENOTSUPP;
839#endif
840 return netlink_dump_start(ctnl, skb, nlh, ctnetlink_dump_table, 837 return netlink_dump_start(ctnl, skb, nlh, ctnetlink_dump_table,
841 ctnetlink_done); 838 ctnetlink_done);
842 }
843 839
844 if (cda[CTA_TUPLE_ORIG]) 840 if (cda[CTA_TUPLE_ORIG])
845 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3); 841 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3);
@@ -1152,6 +1148,8 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
1152 goto err; 1148 goto err;
1153 } 1149 }
1154 1150
1151 nf_ct_acct_ext_add(ct, GFP_KERNEL);
1152
1155#if defined(CONFIG_NF_CONNTRACK_MARK) 1153#if defined(CONFIG_NF_CONNTRACK_MARK)
1156 if (cda[CTA_MARK]) 1154 if (cda[CTA_MARK])
1157 ct->mark = ntohl(nla_get_be32(cda[CTA_MARK])); 1155 ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 41183a4d2d62..30aa5b94a771 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -482,11 +482,11 @@ static int sctp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
482 482
483 NLA_PUT_BE32(skb, 483 NLA_PUT_BE32(skb,
484 CTA_PROTOINFO_SCTP_VTAG_ORIGINAL, 484 CTA_PROTOINFO_SCTP_VTAG_ORIGINAL,
485 htonl(ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL])); 485 ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL]);
486 486
487 NLA_PUT_BE32(skb, 487 NLA_PUT_BE32(skb,
488 CTA_PROTOINFO_SCTP_VTAG_REPLY, 488 CTA_PROTOINFO_SCTP_VTAG_REPLY,
489 htonl(ct->proto.sctp.vtag[IP_CT_DIR_REPLY])); 489 ct->proto.sctp.vtag[IP_CT_DIR_REPLY]);
490 490
491 read_unlock_bh(&sctp_lock); 491 read_unlock_bh(&sctp_lock);
492 492
@@ -530,9 +530,9 @@ static int nlattr_to_sctp(struct nlattr *cda[], struct nf_conn *ct)
530 write_lock_bh(&sctp_lock); 530 write_lock_bh(&sctp_lock);
531 ct->proto.sctp.state = nla_get_u8(tb[CTA_PROTOINFO_SCTP_STATE]); 531 ct->proto.sctp.state = nla_get_u8(tb[CTA_PROTOINFO_SCTP_STATE]);
532 ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = 532 ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] =
533 ntohl(nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL])); 533 nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]);
534 ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = 534 ct->proto.sctp.vtag[IP_CT_DIR_REPLY] =
535 ntohl(nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_REPLY])); 535 nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]);
536 write_unlock_bh(&sctp_lock); 536 write_unlock_bh(&sctp_lock);
537 537
538 return 0; 538 return 0;
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 46ea542d0df9..869ef9349d0f 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -25,6 +25,7 @@
25#include <net/netfilter/nf_conntrack_l4proto.h> 25#include <net/netfilter/nf_conntrack_l4proto.h>
26#include <net/netfilter/nf_conntrack_expect.h> 26#include <net/netfilter/nf_conntrack_expect.h>
27#include <net/netfilter/nf_conntrack_helper.h> 27#include <net/netfilter/nf_conntrack_helper.h>
28#include <net/netfilter/nf_conntrack_acct.h>
28 29
29MODULE_LICENSE("GPL"); 30MODULE_LICENSE("GPL");
30 31
@@ -38,19 +39,6 @@ print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
38} 39}
39EXPORT_SYMBOL_GPL(print_tuple); 40EXPORT_SYMBOL_GPL(print_tuple);
40 41
41#ifdef CONFIG_NF_CT_ACCT
42static unsigned int
43seq_print_counters(struct seq_file *s,
44 const struct ip_conntrack_counter *counter)
45{
46 return seq_printf(s, "packets=%llu bytes=%llu ",
47 (unsigned long long)counter->packets,
48 (unsigned long long)counter->bytes);
49}
50#else
51#define seq_print_counters(x, y) 0
52#endif
53
54struct ct_iter_state { 42struct ct_iter_state {
55 unsigned int bucket; 43 unsigned int bucket;
56}; 44};
@@ -146,7 +134,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
146 l3proto, l4proto)) 134 l3proto, l4proto))
147 return -ENOSPC; 135 return -ENOSPC;
148 136
149 if (seq_print_counters(s, &ct->counters[IP_CT_DIR_ORIGINAL])) 137 if (seq_print_acct(s, ct, IP_CT_DIR_ORIGINAL))
150 return -ENOSPC; 138 return -ENOSPC;
151 139
152 if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status))) 140 if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status)))
@@ -157,7 +145,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
157 l3proto, l4proto)) 145 l3proto, l4proto))
158 return -ENOSPC; 146 return -ENOSPC;
159 147
160 if (seq_print_counters(s, &ct->counters[IP_CT_DIR_REPLY])) 148 if (seq_print_acct(s, ct, IP_CT_DIR_REPLY))
161 return -ENOSPC; 149 return -ENOSPC;
162 150
163 if (test_bit(IPS_ASSURED_BIT, &ct->status)) 151 if (test_bit(IPS_ASSURED_BIT, &ct->status))
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index b8173af8c24a..9a35b57ab76d 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -453,6 +453,14 @@ __build_packet_message(struct nfulnl_instance *inst,
453 } 453 }
454 } 454 }
455 455
456 if (indev && skb_mac_header_was_set(skb)) {
457 NLA_PUT_BE16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type));
458 NLA_PUT_BE16(inst->skb, NFULA_HWLEN,
459 htons(skb->dev->hard_header_len));
460 NLA_PUT(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len,
461 skb_mac_header(skb));
462 }
463
456 if (skb->tstamp.tv64) { 464 if (skb->tstamp.tv64) {
457 struct nfulnl_msg_packet_timestamp ts; 465 struct nfulnl_msg_packet_timestamp ts;
458 struct timeval tv = ktime_to_timeval(skb->tstamp); 466 struct timeval tv = ktime_to_timeval(skb->tstamp);
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index 217e2b686322..beb5094703cb 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -147,17 +147,21 @@ tcpmss_mangle_packet(struct sk_buff *skb,
147 return TCPOLEN_MSS; 147 return TCPOLEN_MSS;
148} 148}
149 149
150static u_int32_t tcpmss_reverse_mtu4(const struct iphdr *iph) 150static u_int32_t tcpmss_reverse_mtu(const struct sk_buff *skb,
151 unsigned int family)
151{ 152{
152 struct flowi fl = { 153 struct flowi fl = {};
153 .fl4_dst = iph->saddr,
154 };
155 const struct nf_afinfo *ai; 154 const struct nf_afinfo *ai;
156 struct rtable *rt = NULL; 155 struct rtable *rt = NULL;
157 u_int32_t mtu = ~0U; 156 u_int32_t mtu = ~0U;
158 157
158 if (family == PF_INET)
159 fl.fl4_dst = ip_hdr(skb)->saddr;
160 else
161 fl.fl6_dst = ipv6_hdr(skb)->saddr;
162
159 rcu_read_lock(); 163 rcu_read_lock();
160 ai = nf_get_afinfo(AF_INET); 164 ai = nf_get_afinfo(family);
161 if (ai != NULL) 165 if (ai != NULL)
162 ai->route((struct dst_entry **)&rt, &fl); 166 ai->route((struct dst_entry **)&rt, &fl);
163 rcu_read_unlock(); 167 rcu_read_unlock();
@@ -178,7 +182,8 @@ tcpmss_tg4(struct sk_buff *skb, const struct net_device *in,
178 __be16 newlen; 182 __be16 newlen;
179 int ret; 183 int ret;
180 184
181 ret = tcpmss_mangle_packet(skb, targinfo, tcpmss_reverse_mtu4(iph), 185 ret = tcpmss_mangle_packet(skb, targinfo,
186 tcpmss_reverse_mtu(skb, PF_INET),
182 iph->ihl * 4, 187 iph->ihl * 4,
183 sizeof(*iph) + sizeof(struct tcphdr)); 188 sizeof(*iph) + sizeof(struct tcphdr));
184 if (ret < 0) 189 if (ret < 0)
@@ -193,28 +198,6 @@ tcpmss_tg4(struct sk_buff *skb, const struct net_device *in,
193} 198}
194 199
195#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) 200#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
196static u_int32_t tcpmss_reverse_mtu6(const struct ipv6hdr *iph)
197{
198 struct flowi fl = {
199 .fl6_dst = iph->saddr,
200 };
201 const struct nf_afinfo *ai;
202 struct rtable *rt = NULL;
203 u_int32_t mtu = ~0U;
204
205 rcu_read_lock();
206 ai = nf_get_afinfo(AF_INET6);
207 if (ai != NULL)
208 ai->route((struct dst_entry **)&rt, &fl);
209 rcu_read_unlock();
210
211 if (rt != NULL) {
212 mtu = dst_mtu(&rt->u.dst);
213 dst_release(&rt->u.dst);
214 }
215 return mtu;
216}
217
218static unsigned int 201static unsigned int
219tcpmss_tg6(struct sk_buff *skb, const struct net_device *in, 202tcpmss_tg6(struct sk_buff *skb, const struct net_device *in,
220 const struct net_device *out, unsigned int hooknum, 203 const struct net_device *out, unsigned int hooknum,
@@ -229,7 +212,8 @@ tcpmss_tg6(struct sk_buff *skb, const struct net_device *in,
229 tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr); 212 tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr);
230 if (tcphoff < 0) 213 if (tcphoff < 0)
231 return NF_DROP; 214 return NF_DROP;
232 ret = tcpmss_mangle_packet(skb, targinfo, tcpmss_reverse_mtu6(ipv6h), 215 ret = tcpmss_mangle_packet(skb, targinfo,
216 tcpmss_reverse_mtu(skb, PF_INET6),
233 tcphoff, 217 tcphoff,
234 sizeof(*ipv6h) + sizeof(struct tcphdr)); 218 sizeof(*ipv6h) + sizeof(struct tcphdr));
235 if (ret < 0) 219 if (ret < 0)
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index d7e8983cd37f..3e39c4fe1931 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -8,6 +8,7 @@
8#include <linux/netfilter/x_tables.h> 8#include <linux/netfilter/x_tables.h>
9#include <linux/netfilter/xt_connbytes.h> 9#include <linux/netfilter/xt_connbytes.h>
10#include <net/netfilter/nf_conntrack.h> 10#include <net/netfilter/nf_conntrack.h>
11#include <net/netfilter/nf_conntrack_acct.h>
11 12
12MODULE_LICENSE("GPL"); 13MODULE_LICENSE("GPL");
13MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); 14MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
@@ -27,12 +28,15 @@ connbytes_mt(const struct sk_buff *skb, const struct net_device *in,
27 u_int64_t what = 0; /* initialize to make gcc happy */ 28 u_int64_t what = 0; /* initialize to make gcc happy */
28 u_int64_t bytes = 0; 29 u_int64_t bytes = 0;
29 u_int64_t pkts = 0; 30 u_int64_t pkts = 0;
30 const struct ip_conntrack_counter *counters; 31 const struct nf_conn_counter *counters;
31 32
32 ct = nf_ct_get(skb, &ctinfo); 33 ct = nf_ct_get(skb, &ctinfo);
33 if (!ct) 34 if (!ct)
34 return false; 35 return false;
35 counters = ct->counters; 36
37 counters = nf_conn_acct_find(ct);
38 if (!counters)
39 return false;
36 40
37 switch (sinfo->what) { 41 switch (sinfo->what) {
38 case XT_CONNBYTES_PKTS: 42 case XT_CONNBYTES_PKTS:
diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c
index ed76baab4734..9f328593287e 100644
--- a/net/netfilter/xt_time.c
+++ b/net/netfilter/xt_time.c
@@ -173,7 +173,7 @@ time_mt(const struct sk_buff *skb, const struct net_device *in,
173 __net_timestamp((struct sk_buff *)skb); 173 __net_timestamp((struct sk_buff *)skb);
174 174
175 stamp = ktime_to_ns(skb->tstamp); 175 stamp = ktime_to_ns(skb->tstamp);
176 do_div(stamp, NSEC_PER_SEC); 176 stamp = div_s64(stamp, NSEC_PER_SEC);
177 177
178 if (info->flags & XT_TIME_LOCAL_TZ) 178 if (info->flags & XT_TIME_LOCAL_TZ)
179 /* Adjust for local timezone */ 179 /* Adjust for local timezone */
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 0ddf69286f92..cb625b4d6da5 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -356,44 +356,99 @@ static struct Qdisc noqueue_qdisc = {
356}; 356};
357 357
358 358
359static int fifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc) 359static const u8 prio2band[TC_PRIO_MAX+1] =
360 { 1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1 };
361
362/* 3-band FIFO queue: old style, but should be a bit faster than
363 generic prio+fifo combination.
364 */
365
366#define PFIFO_FAST_BANDS 3
367
368static inline struct sk_buff_head *prio2list(struct sk_buff *skb,
369 struct Qdisc *qdisc)
370{
371 struct sk_buff_head *list = qdisc_priv(qdisc);
372 return list + prio2band[skb->priority & TC_PRIO_MAX];
373}
374
375static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
360{ 376{
361 struct sk_buff_head *list = &qdisc->q; 377 struct sk_buff_head *list = prio2list(skb, qdisc);
362 378
363 if (skb_queue_len(list) < qdisc_dev(qdisc)->tx_queue_len) 379 if (skb_queue_len(list) < qdisc_dev(qdisc)->tx_queue_len) {
380 qdisc->q.qlen++;
364 return __qdisc_enqueue_tail(skb, qdisc, list); 381 return __qdisc_enqueue_tail(skb, qdisc, list);
382 }
365 383
366 return qdisc_drop(skb, qdisc); 384 return qdisc_drop(skb, qdisc);
367} 385}
368 386
369static struct sk_buff *fifo_fast_dequeue(struct Qdisc* qdisc) 387static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc)
370{ 388{
371 struct sk_buff_head *list = &qdisc->q; 389 int prio;
390 struct sk_buff_head *list = qdisc_priv(qdisc);
372 391
373 if (!skb_queue_empty(list)) 392 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) {
374 return __qdisc_dequeue_head(qdisc, list); 393 if (!skb_queue_empty(list + prio)) {
394 qdisc->q.qlen--;
395 return __qdisc_dequeue_head(qdisc, list + prio);
396 }
397 }
375 398
376 return NULL; 399 return NULL;
377} 400}
378 401
379static int fifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc) 402static int pfifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
380{ 403{
381 return __qdisc_requeue(skb, qdisc, &qdisc->q); 404 qdisc->q.qlen++;
405 return __qdisc_requeue(skb, qdisc, prio2list(skb, qdisc));
382} 406}
383 407
384static void fifo_fast_reset(struct Qdisc* qdisc) 408static void pfifo_fast_reset(struct Qdisc* qdisc)
385{ 409{
386 __qdisc_reset_queue(qdisc, &qdisc->q); 410 int prio;
411 struct sk_buff_head *list = qdisc_priv(qdisc);
412
413 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
414 __qdisc_reset_queue(qdisc, list + prio);
415
387 qdisc->qstats.backlog = 0; 416 qdisc->qstats.backlog = 0;
417 qdisc->q.qlen = 0;
388} 418}
389 419
390static struct Qdisc_ops fifo_fast_ops __read_mostly = { 420static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb)
391 .id = "fifo_fast", 421{
392 .priv_size = 0, 422 struct tc_prio_qopt opt = { .bands = PFIFO_FAST_BANDS };
393 .enqueue = fifo_fast_enqueue, 423
394 .dequeue = fifo_fast_dequeue, 424 memcpy(&opt.priomap, prio2band, TC_PRIO_MAX+1);
395 .requeue = fifo_fast_requeue, 425 NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
396 .reset = fifo_fast_reset, 426 return skb->len;
427
428nla_put_failure:
429 return -1;
430}
431
432static int pfifo_fast_init(struct Qdisc *qdisc, struct nlattr *opt)
433{
434 int prio;
435 struct sk_buff_head *list = qdisc_priv(qdisc);
436
437 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
438 skb_queue_head_init(list + prio);
439
440 return 0;
441}
442
443static struct Qdisc_ops pfifo_fast_ops __read_mostly = {
444 .id = "pfifo_fast",
445 .priv_size = PFIFO_FAST_BANDS * sizeof(struct sk_buff_head),
446 .enqueue = pfifo_fast_enqueue,
447 .dequeue = pfifo_fast_dequeue,
448 .requeue = pfifo_fast_requeue,
449 .init = pfifo_fast_init,
450 .reset = pfifo_fast_reset,
451 .dump = pfifo_fast_dump,
397 .owner = THIS_MODULE, 452 .owner = THIS_MODULE,
398}; 453};
399 454
@@ -522,7 +577,7 @@ static void attach_one_default_qdisc(struct net_device *dev,
522 577
523 if (dev->tx_queue_len) { 578 if (dev->tx_queue_len) {
524 qdisc = qdisc_create_dflt(dev, dev_queue, 579 qdisc = qdisc_create_dflt(dev, dev_queue,
525 &fifo_fast_ops, TC_H_ROOT); 580 &pfifo_fast_ops, TC_H_ROOT);
526 if (!qdisc) { 581 if (!qdisc) {
527 printk(KERN_INFO "%s: activation failed\n", dev->name); 582 printk(KERN_INFO "%s: activation failed\n", dev->name);
528 return; 583 return;
@@ -550,9 +605,9 @@ void dev_activate(struct net_device *dev)
550 int need_watchdog; 605 int need_watchdog;
551 606
552 /* No queueing discipline is attached to device; 607 /* No queueing discipline is attached to device;
553 * create default one i.e. fifo_fast for devices, 608 create default one i.e. pfifo_fast for devices,
554 * which need queueing and noqueue_qdisc for 609 which need queueing and noqueue_qdisc for
555 * virtual interfaces. 610 virtual interfaces
556 */ 611 */
557 612
558 if (dev_all_qdisc_sleeping_noop(dev)) 613 if (dev_all_qdisc_sleeping_noop(dev))
@@ -576,7 +631,6 @@ static void dev_deactivate_queue(struct net_device *dev,
576 void *_qdisc_default) 631 void *_qdisc_default)
577{ 632{
578 struct Qdisc *qdisc_default = _qdisc_default; 633 struct Qdisc *qdisc_default = _qdisc_default;
579 struct sk_buff *skb = NULL;
580 struct Qdisc *qdisc; 634 struct Qdisc *qdisc;
581 635
582 qdisc = dev_queue->qdisc; 636 qdisc = dev_queue->qdisc;
@@ -588,8 +642,6 @@ static void dev_deactivate_queue(struct net_device *dev,
588 642
589 spin_unlock_bh(qdisc_lock(qdisc)); 643 spin_unlock_bh(qdisc_lock(qdisc));
590 } 644 }
591
592 kfree_skb(skb);
593} 645}
594 646
595static bool some_qdisc_is_running(struct net_device *dev, int lock) 647static bool some_qdisc_is_running(struct net_device *dev, int lock)