Commit e89970aa authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6:
  netfilter: nf_conntrack_sctp: fix sparse warnings
  netfilter: nf_nat_sip: c= is optional for session
  netfilter: xt_TCPMSS: collapse tcpmss_reverse_mtu{4,6} into one function
  netfilter: nfnetlink_log: send complete hardware header
  netfilter: xt_time: fix time's time_mt()'s use of do_div()
  netfilter: accounting rework: ct_extend + 64bit counters (v4)
  netlink: add NLA_PUT_BE64 macro
  netfilter: nf_nat_core: eliminate useless find_appropriate_src for IP_NAT_RANGE_PROTO_RANDOM
  hdlcdrv: Fix CRC calculation.
  Revert "pkt_sched: Make default qdisc nonshared-multiqueue safe."
  net: In __netif_schedule() use WARN_ON instead of BUG_ON
  net: Improve simple_tx_hash().
  pkt_sched: Remove unused variable skb in dev_deactivate_queue function.
  sunhme: Remove stop/wake TX queue calls in set-multicast-list handler.
  ucc_geth: do not touch net queue in adjust_link phylib callback
  gianfar: do not touch net queue in adjust_link phylib callback
  atl1: Do not wake queue before queue has been started.
parents 443bd1c4 5547cd0a
...@@ -336,3 +336,13 @@ When: After the only user (hal) has seen a release with the patches ...@@ -336,3 +336,13 @@ When: After the only user (hal) has seen a release with the patches
Why: Over 1K .text/.data size reduction, data is available in other Why: Over 1K .text/.data size reduction, data is available in other
ways (ioctls) ways (ioctls)
Who: Johannes Berg <johannes@sipsolutions.net> Who: Johannes Berg <johannes@sipsolutions.net>
---------------------------
What: CONFIG_NF_CT_ACCT
When: 2.6.29
Why: Accounting can now be enabled/disabled without kernel recompilation.
Currently used only to set a default value for a feature that is also
controlled by a kernel/module/sysfs/sysctl parameter.
Who: Krzysztof Piotr Oledzki <ole@ans.pl>
...@@ -1279,6 +1279,13 @@ and is between 256 and 4096 characters. It is defined in the file ...@@ -1279,6 +1279,13 @@ and is between 256 and 4096 characters. It is defined in the file
This usage is only documented in each driver source This usage is only documented in each driver source
file if at all. file if at all.
nf_conntrack.acct=
[NETFILTER] Enable connection tracking flow accounting
0 to disable accounting
1 to enable accounting
Default value depends on CONFIG_NF_CT_ACCT that is
going to be removed in 2.6.29.
nfsaddrs= [NFS] nfsaddrs= [NFS]
See Documentation/filesystems/nfsroot.txt. See Documentation/filesystems/nfsroot.txt.
......
...@@ -1308,7 +1308,6 @@ static u32 atl1_check_link(struct atl1_adapter *adapter) ...@@ -1308,7 +1308,6 @@ static u32 atl1_check_link(struct atl1_adapter *adapter)
dev_info(&adapter->pdev->dev, "link is down\n"); dev_info(&adapter->pdev->dev, "link is down\n");
adapter->link_speed = SPEED_0; adapter->link_speed = SPEED_0;
netif_carrier_off(netdev); netif_carrier_off(netdev);
netif_stop_queue(netdev);
} }
return 0; return 0;
} }
...@@ -1358,7 +1357,6 @@ static u32 atl1_check_link(struct atl1_adapter *adapter) ...@@ -1358,7 +1357,6 @@ static u32 atl1_check_link(struct atl1_adapter *adapter)
if (!netif_carrier_ok(netdev)) { if (!netif_carrier_ok(netdev)) {
/* Link down -> Up */ /* Link down -> Up */
netif_carrier_on(netdev); netif_carrier_on(netdev);
netif_wake_queue(netdev);
} }
return 0; return 0;
} }
...@@ -2627,6 +2625,7 @@ static s32 atl1_up(struct atl1_adapter *adapter) ...@@ -2627,6 +2625,7 @@ static s32 atl1_up(struct atl1_adapter *adapter)
mod_timer(&adapter->watchdog_timer, jiffies); mod_timer(&adapter->watchdog_timer, jiffies);
atlx_irq_enable(adapter); atlx_irq_enable(adapter);
atl1_check_link(adapter); atl1_check_link(adapter);
netif_start_queue(netdev);
return 0; return 0;
err_up: err_up:
......
...@@ -1725,7 +1725,6 @@ static void adjust_link(struct net_device *dev) ...@@ -1725,7 +1725,6 @@ static void adjust_link(struct net_device *dev)
if (!priv->oldlink) { if (!priv->oldlink) {
new_state = 1; new_state = 1;
priv->oldlink = 1; priv->oldlink = 1;
netif_tx_schedule_all(dev);
} }
} else if (priv->oldlink) { } else if (priv->oldlink) {
new_state = 1; new_state = 1;
......
...@@ -88,6 +88,7 @@ ...@@ -88,6 +88,7 @@
static inline void append_crc_ccitt(unsigned char *buffer, int len) static inline void append_crc_ccitt(unsigned char *buffer, int len)
{ {
unsigned int crc = crc_ccitt(0xffff, buffer, len) ^ 0xffff; unsigned int crc = crc_ccitt(0xffff, buffer, len) ^ 0xffff;
buffer += len;
*buffer++ = crc; *buffer++ = crc;
*buffer++ = crc >> 8; *buffer++ = crc >> 8;
} }
......
...@@ -2377,8 +2377,6 @@ static void happy_meal_set_multicast(struct net_device *dev) ...@@ -2377,8 +2377,6 @@ static void happy_meal_set_multicast(struct net_device *dev)
spin_lock_irq(&hp->happy_lock); spin_lock_irq(&hp->happy_lock);
netif_stop_queue(dev);
if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) { if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
hme_write32(hp, bregs + BMAC_HTABLE0, 0xffff); hme_write32(hp, bregs + BMAC_HTABLE0, 0xffff);
hme_write32(hp, bregs + BMAC_HTABLE1, 0xffff); hme_write32(hp, bregs + BMAC_HTABLE1, 0xffff);
...@@ -2410,8 +2408,6 @@ static void happy_meal_set_multicast(struct net_device *dev) ...@@ -2410,8 +2408,6 @@ static void happy_meal_set_multicast(struct net_device *dev)
hme_write32(hp, bregs + BMAC_HTABLE3, hash_table[3]); hme_write32(hp, bregs + BMAC_HTABLE3, hash_table[3]);
} }
netif_wake_queue(dev);
spin_unlock_irq(&hp->happy_lock); spin_unlock_irq(&hp->happy_lock);
} }
......
...@@ -1588,7 +1588,6 @@ static void adjust_link(struct net_device *dev) ...@@ -1588,7 +1588,6 @@ static void adjust_link(struct net_device *dev)
if (!ugeth->oldlink) { if (!ugeth->oldlink) {
new_state = 1; new_state = 1;
ugeth->oldlink = 1; ugeth->oldlink = 1;
netif_tx_schedule_all(dev);
} }
} else if (ugeth->oldlink) { } else if (ugeth->oldlink) {
new_state = 1; new_state = 1;
......
...@@ -122,7 +122,7 @@ enum ip_conntrack_events ...@@ -122,7 +122,7 @@ enum ip_conntrack_events
IPCT_NATINFO_BIT = 10, IPCT_NATINFO_BIT = 10,
IPCT_NATINFO = (1 << IPCT_NATINFO_BIT), IPCT_NATINFO = (1 << IPCT_NATINFO_BIT),
/* Counter highest bit has been set */ /* Counter highest bit has been set, unused */
IPCT_COUNTER_FILLING_BIT = 11, IPCT_COUNTER_FILLING_BIT = 11,
IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT), IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT),
...@@ -145,12 +145,6 @@ enum ip_conntrack_expect_events { ...@@ -145,12 +145,6 @@ enum ip_conntrack_expect_events {
}; };
#ifdef __KERNEL__ #ifdef __KERNEL__
struct ip_conntrack_counter
{
u_int32_t packets;
u_int32_t bytes;
};
struct ip_conntrack_stat struct ip_conntrack_stat
{ {
unsigned int searched; unsigned int searched;
......
...@@ -115,10 +115,10 @@ enum ctattr_protoinfo_sctp { ...@@ -115,10 +115,10 @@ enum ctattr_protoinfo_sctp {
enum ctattr_counters { enum ctattr_counters {
CTA_COUNTERS_UNSPEC, CTA_COUNTERS_UNSPEC,
CTA_COUNTERS_PACKETS, /* old 64bit counters */ CTA_COUNTERS_PACKETS, /* 64bit counters */
CTA_COUNTERS_BYTES, /* old 64bit counters */ CTA_COUNTERS_BYTES, /* 64bit counters */
CTA_COUNTERS32_PACKETS, CTA_COUNTERS32_PACKETS, /* old 32bit counters, unused */
CTA_COUNTERS32_BYTES, CTA_COUNTERS32_BYTES, /* old 32bit counters, unused */
__CTA_COUNTERS_MAX __CTA_COUNTERS_MAX
}; };
#define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1) #define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)
......
...@@ -48,6 +48,9 @@ enum nfulnl_attr_type { ...@@ -48,6 +48,9 @@ enum nfulnl_attr_type {
NFULA_SEQ, /* instance-local sequence number */ NFULA_SEQ, /* instance-local sequence number */
NFULA_SEQ_GLOBAL, /* global sequence number */ NFULA_SEQ_GLOBAL, /* global sequence number */
NFULA_GID, /* group id of socket */ NFULA_GID, /* group id of socket */
NFULA_HWTYPE, /* hardware type */
NFULA_HWHEADER, /* hardware header */
NFULA_HWLEN, /* hardware header length */
__NFULA_MAX __NFULA_MAX
}; };
......
...@@ -88,7 +88,6 @@ struct nf_conn_help { ...@@ -88,7 +88,6 @@ struct nf_conn_help {
u8 expecting[NF_CT_MAX_EXPECT_CLASSES]; u8 expecting[NF_CT_MAX_EXPECT_CLASSES];
}; };
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h> #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h> #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
...@@ -111,11 +110,6 @@ struct nf_conn ...@@ -111,11 +110,6 @@ struct nf_conn
/* Timer function; drops refcnt when it goes off. */ /* Timer function; drops refcnt when it goes off. */
struct timer_list timeout; struct timer_list timeout;
#ifdef CONFIG_NF_CT_ACCT
/* Accounting Information (same cache line as other written members) */
struct ip_conntrack_counter counters[IP_CT_DIR_MAX];
#endif
#if defined(CONFIG_NF_CONNTRACK_MARK) #if defined(CONFIG_NF_CONNTRACK_MARK)
u_int32_t mark; u_int32_t mark;
#endif #endif
......
/*
* (C) 2008 Krzysztof Piotr Oledzki <ole@ans.pl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _NF_CONNTRACK_ACCT_H
#define _NF_CONNTRACK_ACCT_H
#include <linux/netfilter/nf_conntrack_common.h>
#include <linux/netfilter/nf_conntrack_tuple_common.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_extend.h>
struct nf_conn_counter {
u_int64_t packets;
u_int64_t bytes;
};
extern int nf_ct_acct;
static inline
struct nf_conn_counter *nf_conn_acct_find(const struct nf_conn *ct)
{
return nf_ct_ext_find(ct, NF_CT_EXT_ACCT);
}
static inline
struct nf_conn_counter *nf_ct_acct_ext_add(struct nf_conn *ct, gfp_t gfp)
{
struct nf_conn_counter *acct;
if (!nf_ct_acct)
return NULL;
acct = nf_ct_ext_add(ct, NF_CT_EXT_ACCT, gfp);
if (!acct)
pr_debug("failed to add accounting extension area");
return acct;
};
extern unsigned int
seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir);
extern int nf_conntrack_acct_init(void);
extern void nf_conntrack_acct_fini(void);
#endif /* _NF_CONNTRACK_ACCT_H */
...@@ -7,11 +7,13 @@ enum nf_ct_ext_id ...@@ -7,11 +7,13 @@ enum nf_ct_ext_id
{ {
NF_CT_EXT_HELPER, NF_CT_EXT_HELPER,
NF_CT_EXT_NAT, NF_CT_EXT_NAT,
NF_CT_EXT_ACCT,
NF_CT_EXT_NUM, NF_CT_EXT_NUM,
}; };
#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help #define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat #define NF_CT_EXT_NAT_TYPE struct nf_conn_nat
#define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter
/* Extensions: optional stuff which isn't permanently in struct. */ /* Extensions: optional stuff which isn't permanently in struct. */
struct nf_ct_ext { struct nf_ct_ext {
......
...@@ -896,6 +896,9 @@ static inline int nla_put_msecs(struct sk_buff *skb, int attrtype, ...@@ -896,6 +896,9 @@ static inline int nla_put_msecs(struct sk_buff *skb, int attrtype,
#define NLA_PUT_U64(skb, attrtype, value) \ #define NLA_PUT_U64(skb, attrtype, value) \
NLA_PUT_TYPE(skb, u64, attrtype, value) NLA_PUT_TYPE(skb, u64, attrtype, value)
#define NLA_PUT_BE64(skb, attrtype, value) \
NLA_PUT_TYPE(skb, __be64, attrtype, value)
#define NLA_PUT_STRING(skb, attrtype, value) \ #define NLA_PUT_STRING(skb, attrtype, value) \
NLA_PUT(skb, attrtype, strlen(value) + 1, value) NLA_PUT(skb, attrtype, strlen(value) + 1, value)
......
...@@ -124,6 +124,8 @@ ...@@ -124,6 +124,8 @@
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/ipv6.h> #include <linux/ipv6.h>
#include <linux/in.h> #include <linux/in.h>
#include <linux/jhash.h>
#include <linux/random.h>
#include "net-sysfs.h" #include "net-sysfs.h"
...@@ -1325,7 +1327,8 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) ...@@ -1325,7 +1327,8 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
void __netif_schedule(struct Qdisc *q) void __netif_schedule(struct Qdisc *q)
{ {
BUG_ON(q == &noop_qdisc); if (WARN_ON_ONCE(q == &noop_qdisc))
return;
if (!test_and_set_bit(__QDISC_STATE_SCHED, &q->state)) { if (!test_and_set_bit(__QDISC_STATE_SCHED, &q->state)) {
struct softnet_data *sd; struct softnet_data *sd;
...@@ -1668,34 +1671,37 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, ...@@ -1668,34 +1671,37 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
* --BLG * --BLG
*/ */
static u32 simple_tx_hashrnd;
static int simple_tx_hashrnd_initialized = 0;
static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb) static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb)
{ {
u32 *addr, *ports, hash, ihl; u32 addr1, addr2, ports;
u32 hash, ihl;
u8 ip_proto; u8 ip_proto;
int alen;
if (unlikely(!simple_tx_hashrnd_initialized)) {
get_random_bytes(&simple_tx_hashrnd, 4);
simple_tx_hashrnd_initialized = 1;
}
switch (skb->protocol) { switch (skb->protocol) {
case __constant_htons(ETH_P_IP): case __constant_htons(ETH_P_IP):
ip_proto = ip_hdr(skb)->protocol; ip_proto = ip_hdr(skb)->protocol;
addr = &ip_hdr(skb)->saddr; addr1 = ip_hdr(skb)->saddr;
addr2 = ip_hdr(skb)->daddr;
ihl = ip_hdr(skb)->ihl; ihl = ip_hdr(skb)->ihl;
alen = 2;
break; break;
case __constant_htons(ETH_P_IPV6): case __constant_htons(ETH_P_IPV6):
ip_proto = ipv6_hdr(skb)->nexthdr; ip_proto = ipv6_hdr(skb)->nexthdr;
addr = &ipv6_hdr(skb)->saddr.s6_addr32[0]; addr1 = ipv6_hdr(skb)->saddr.s6_addr32[3];
addr2 = ipv6_hdr(skb)->daddr.s6_addr32[3];
ihl = (40 >> 2); ihl = (40 >> 2);
alen = 8;
break; break;
default: default:
return 0; return 0;
} }
ports = (u32 *) (skb_network_header(skb) + (ihl * 4));
hash = 0;
while (alen--)
hash ^= *addr++;
switch (ip_proto) { switch (ip_proto) {
case IPPROTO_TCP: case IPPROTO_TCP:
...@@ -1705,14 +1711,17 @@ static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb) ...@@ -1705,14 +1711,17 @@ static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb)
case IPPROTO_AH: case IPPROTO_AH:
case IPPROTO_SCTP: case IPPROTO_SCTP:
case IPPROTO_UDPLITE: case IPPROTO_UDPLITE:
hash ^= *ports; ports = *((u32 *) (skb_network_header(skb) + (ihl * 4)));
break; break;
default: default:
ports = 0;
break; break;
} }
return hash % dev->real_num_tx_queues; hash = jhash_3words(addr1, addr2, ports, simple_tx_hashrnd);
return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32);
} }
static struct netdev_queue *dev_pick_tx(struct net_device *dev, static struct netdev_queue *dev_pick_tx(struct net_device *dev,
......
...@@ -18,19 +18,7 @@ ...@@ -18,19 +18,7 @@
#include <net/netfilter/nf_conntrack_l3proto.h> #include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_expect.h> #include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_acct.h>
#ifdef CONFIG_NF_CT_ACCT
static unsigned int
seq_print_counters(struct seq_file *s,
const struct ip_conntrack_counter *counter)
{
return seq_printf(s, "packets=%llu bytes=%llu ",
(unsigned long long)counter->packets,
(unsigned long long)counter->bytes);
}
#else
#define seq_print_counters(x, y) 0
#endif
struct ct_iter_state { struct ct_iter_state {
unsigned int bucket; unsigned int bucket;
...@@ -127,7 +115,7 @@ static int ct_seq_show(struct seq_file *s, void *v) ...@@ -127,7 +115,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
l3proto, l4proto)) l3proto, l4proto))
return -ENOSPC; return -ENOSPC;
if (seq_print_counters(s, &ct->counters[IP_CT_DIR_ORIGINAL])) if (seq_print_acct(s, ct, IP_CT_DIR_ORIGINAL))
return -ENOSPC; return -ENOSPC;
if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status))) 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,7 +126,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
l3proto, l4proto)) l3proto, l4proto))
return -ENOSPC; return -ENOSPC;
if (seq_print_counters(s, &ct->counters[IP_CT_DIR_REPLY])) if (seq_print_acct(s, ct, IP_CT_DIR_REPLY))
return -ENOSPC; return -ENOSPC;
if (test_bit(IPS_ASSURED_BIT, &ct->status)) if (test_bit(IPS_ASSURED_BIT, &ct->status))
......
...@@ -240,12 +240,12 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, ...@@ -240,12 +240,12 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
This is only required for source (ie. NAT/masq) mappings. This is only required for source (ie. NAT/masq) mappings.
So far, we don't do local source mappings, so multiple So far, we don't do local source mappings, so multiple
manips not an issue. */ manips not an issue. */
if (maniptype == IP_NAT_MANIP_SRC) { if (maniptype == IP_NAT_MANIP_SRC &&
!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) {
if (find_appropriate_src(orig_tuple, tuple, range)) { if (find_appropriate_src(orig_tuple, tuple, range)) {
pr_debug("get_unique_tuple: Found current src map\n"); pr_debug("get_unique_tuple: Found current src map\n");
if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) if (!nf_nat_used_tuple(tuple, ct))
if (!nf_nat_used_tuple(tuple, ct)) return;
return;
} }
} }
......
...@@ -318,11 +318,11 @@ static int mangle_content_len(struct sk_buff *skb, ...@@ -318,11 +318,11 @@ static int mangle_content_len(struct sk_buff *skb,
buffer, buflen); buffer, buflen);
} }
static unsigned mangle_sdp_packet(struct sk_buff *skb, const char **dptr, static int mangle_sdp_packet(struct sk_buff *skb, const char **dptr,
unsigned int dataoff, unsigned int *datalen, unsigned int dataoff, unsigned int *datalen,
enum sdp_header_types type, enum sdp_header_types type,
enum sdp_header_types term, enum sdp_header_types term,
char *buffer, int buflen) char *buffer, int buflen)
{ {
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 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,9 +330,9 @@ static unsigned mangle_sdp_packet(struct sk_buff *skb, const char **dptr,
if (ct_sip_get_sdp_header(ct, *dptr, dataoff, *datalen, type, term, if (ct_sip_get_sdp_header(ct, *dptr, dataoff, *datalen, type, term,
&matchoff, &matchlen) <= 0) &matchoff, &matchlen) <= 0)
return 0; return -ENOENT;
return mangle_packet(skb, dptr, datalen, matchoff, matchlen, return mangle_packet(skb, dptr, datalen, matchoff, matchlen,
buffer, buflen); buffer, buflen) ? 0 : -EINVAL;
} }
static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr, static 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,8 +346,8 @@ static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr,
unsigned int buflen; unsigned int buflen;
buflen = sprintf(buffer, NIPQUAD_FMT, NIPQUAD(addr->ip)); buflen = sprintf(buffer, NIPQUAD_FMT, NIPQUAD(addr->ip));
if (!mangle_sdp_packet(skb, dptr, dataoff, datalen, type, term, if (mangle_sdp_packet(skb, dptr, dataoff, datalen, type, term,
buffer, buflen)) buffer, buflen))
return 0; return 0;
return mangle_content_len(skb, dptr, datalen); 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,15 +381,27 @@ static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr,
/* Mangle session description owner and contact addresses */ /* Mangle session description owner and contact addresses */
buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(addr->ip)); buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(addr->ip));
if (!mangle_sdp_packet(skb, dptr, dataoff, datalen, if (mangle_sdp_packet(skb, dptr, dataoff, datalen,
SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA, SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA,
buffer, buflen)) buffer, buflen))
return 0; return 0;
if (!mangle_sdp_packet(skb, dptr, dataoff, datalen, switch (mangle_sdp_packet(skb, dptr, dataoff, datalen,
SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA, SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA,
buffer, buflen)) buffer, buflen)) {
case 0:
/*
* RFC 2327:
*
* Session description
*
* c=* (connection information - not required if included in all media)
*/
case -ENOENT:
break;
default:
return 0; return 0;
}
return mangle_content_len(skb, dptr, datalen); return mangle_content_len(skb, dptr, datalen);
} }
......
...@@ -49,6 +49,15 @@ config NF_CT_ACCT ...@@ -49,6 +49,15 @@ config NF_CT_ACCT
Those counters can be used for flow-based accounting or the Those counters can be used for flow-based accounting or the
`connbytes' match. `connbytes' match.
Please note that currently this option only sets a default state.
You may change it at boot time with nf_conntrack.acct=0/1 kernel
paramater or by loading the nf_conntrack module with acct=0/1.
You may also disable/enable it on a running system with:
sysctl net.netfilter.nf_conntrack_acct=0/1
This option will be removed in 2.6.29.
If unsure, say `N'. If unsure, say `N'.
config NF_CONNTRACK_MARK config NF_CONNTRACK_MARK
......
netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
nf_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-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
nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
obj-$(CONFIG_NETFILTER) = netfilter.o obj-$(CONFIG_NETFILTER) = netfilter.o
......
/* Accouting handling for netfilter. */
/*
* (C) 2008 Krzysztof Piotr Oledzki <ole@ans.pl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/netfilter.h>
#include <linux/kernel.h>
#include <linux/moduleparam.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_extend.h>
#include <net/netfilter/nf_conntrack_acct.h>
#ifdef CONFIG_NF_CT_ACCT
#define NF_CT_ACCT_DEFAULT 1
#else
#define NF_CT_ACCT_DEFAULT 0
#endif
int nf_ct_acct __read_mostly = NF_CT_ACCT_DEFAULT;
EXPORT_SYMBOL_GPL(nf_ct_acct);
module_param_named(acct, nf_ct_acct, bool, 0644);
MODULE_PARM_DESC(acct, "Enable connection tracking flow accounting.");
#ifdef CONFIG_SYSCTL
static struct ctl_table_header *acct_sysctl_header;
static struct ctl_table acct_sysctl_table[] = {
{
.ctl_name = CTL_UNNUMBERED,
.procname = "nf_conntrack_acct",
.data = &nf_ct_acct,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{}
};
#endif /* CONFIG_SYSCTL */
unsigned int
seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir)
{
struct nf_conn_counter *acct;
acct = nf_conn_acct_find(ct);
if (!acct)
return 0;
return seq_printf(s, "packets=%llu bytes=%llu ",
(unsigned long long)acct[dir].packets,
(unsigned long long)acct[dir].bytes);
};
EXPORT_SYMBOL_GPL(seq_print_acct);
static struct nf_ct_ext_type acct_extend __read_mostly = {
.len = sizeof(struct nf_conn_counter[IP_CT_DIR_MAX]),
.align = __alignof__(struct nf_conn_counter[IP_CT_DIR_MAX]),
.id = NF_CT_EXT_ACCT,
};
int nf_conntrack_acct_init(void)
{
int ret;
#ifdef CONFIG_NF_CT_ACCT
printk(KERN_WARNING "CONFIG_NF_CT_ACCT is deprecated and will be removed soon. Plase use\n");
printk(KERN_WARNING "nf_conntrack.acct=1 kernel paramater, acct=1 nf_conntrack module option or\n");
printk(KERN_WARNING "sysctl net.netfilter.nf_conntrack_acct=1 to enable it.\n");
#endif
ret = nf_ct_extend_register(&acct_extend);
if (ret < 0) {
printk(KERN_ERR "nf_conntrack_acct: Unable to register extension\n");
return ret;
}
#ifdef CONFIG_SYSCTL
acct_sysctl_header = register_sysctl_paths(nf_net_netfilter_sysctl_path,
acct_sysctl_table);
if (!acct_sysctl_header) {
nf_ct_extend_unregister(&acct_extend);
printk(KERN_ERR "nf_conntrack_acct: can't register to sysctl.\n");
return -ENOMEM;
}
#endif
return 0;
}
void nf_conntrack_acct_fini(void)
{
#ifdef CONFIG_SYSCTL
unregister_sysctl_table(acct_sysctl_header);
#endif
nf_ct_extend_unregister(&acct_extend);
}
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_extend.h> #include <net/netfilter/nf_conntrack_extend.h>
#include <net/netfilter/nf_conntrack_acct.h>
#define NF_CONNTRACK_VERSION "0.5.0" #define NF_CONNTRACK_VERSION "0.5.0"
...@@ -555,6 +556,8 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, ...@@ -555,6 +556,8 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
return NULL; return NULL;
} }
nf_ct_acct_ext_add(ct, GFP_ATOMIC);
spin_lock_bh(&nf_conntrack_lock); spin_lock_bh(&nf_conntrack_lock);
exp = nf_ct_find_expectation(tuple); exp = nf_ct_find_expectation(tuple);
if (exp) { if (exp) {
...@@ -828,17 +831,16 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, ...@@ -828,17 +831,16 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
} }
acct: acct:
#ifdef CONFIG_NF_CT_ACCT
if (do_acct) { if (do_acct) {
ct->counters[CTINFO2DIR(ctinfo)].packets++; struct nf_conn_counter *acct;
ct->counters[CTINFO2DIR(ctinfo)].bytes +=
skb->len - skb_network_offset(skb);
if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000) acct = nf_conn_acct_find(ct);
|| (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000)) if (acct) {
event |= IPCT_COUNTER_FILLING; acct[CTINFO2DIR(ctinfo)].packets++;
acct[CTINFO2DIR(ctinfo)].bytes +=
skb->len - skb_network_offset(skb);
}
} }
#endif
spin_unlock_bh(&nf_conntrack_lock); spin_unlock_bh(&nf_conntrack_lock);
...@@ -853,15 +855,19 @@ bool __nf_ct_kill_acct(struct nf_conn *ct, ...@@ -853,15 +855,19 @@ bool __nf_ct_kill_acct(struct nf_conn *ct,
const struct sk_buff *skb, const struct sk_buff *skb,
int do_acct) int do_acct)
{ {
#ifdef CONFIG_NF_CT_ACCT
if (do_acct) { if (do_acct) {
struct nf_conn_counter *acct;
spin_lock_bh(&nf_conntrack_lock); spin_lock_bh(&nf_conntrack_lock);
ct->counters[CTINFO2DIR(ctinfo)].packets++; acct = nf_conn_acct_find(ct);
ct->counters[CTINFO2DIR(ctinfo)].bytes += if (acct) {
skb->len - skb_network_offset(skb); acct[CTINFO2DIR(ctinfo)].packets++;
acct[CTINFO2DIR(ctinfo)].bytes +=
skb->len - skb_network_offset(skb);
}
spin_unlock_bh(&nf_conntrack_lock); spin_unlock_bh(&nf_conntrack_lock);
} }
#endif
if (del_timer(&ct->timeout)) { if (del_timer(&ct->timeout)) {
ct->timeout.function((unsigned long)ct); ct->timeout.function((unsigned long)ct);
return true; return true;
...@@ -1029,6 +1035,7 @@ void nf_conntrack_cleanup(void) ...@@ -1029,6 +1035,7 @@ void nf_conntrack_cleanup(void)
nf_conntrack_proto_fini(); nf_conntrack_proto_fini();
nf_conntrack_helper_fini(); nf_conntrack_helper_fini();
nf_conntrack_expect_fini(); nf_conntrack_expect_fini();
nf_conntrack_acct_fini();
} }
struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced) struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced)
...@@ -1168,6 +1175,10 @@ int __init nf_conntrack_init(void) ...@@ -1168,6 +1175,10 @@ int __init nf_conntrack_init(void)
if (ret < 0) if (ret < 0)
goto out_fini_expect; goto out_fini_expect;
ret = nf_conntrack_acct_init();
if (ret < 0)
goto out_fini_helper;
/* For use by REJECT target */ /* For use by REJECT target */
rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach); rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach);
rcu_assign_pointer(nf_ct_destroy, destroy_conntrack); rcu_assign_pointer(nf_ct_destroy, destroy_conntrack);
...@@ -1180,6 +1191,8 @@ int __init nf_conntrack_init(void) ...@@ -1180,6 +1191,8 @@ int __init nf_conntrack_init(void)
return ret; return ret;
out_fini_helper:
nf_conntrack_helper_fini();
out_fini_expect: out_fini_expect:
nf_conntrack_expect_fini(); nf_conntrack_expect_fini();
out_fini_proto: out_fini_proto:
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <net/netfilter/nf_conntrack_l3proto.h> #include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_tuple.h> #include <net/netfilter/nf_conntrack_tuple.h>
#include <net/netfilter/nf_conntrack_acct.h>
#ifdef CONFIG_NF_NAT_NEEDED #ifdef CONFIG_NF_NAT_NEEDED
#include <net/netfilter/nf_nat_core.h> #include <net/netfilter/nf_nat_core.h>
#include <net/netfilter/nf_nat_protocol.h> #include <net/netfilter/nf_nat_protocol.h>
...@@ -206,22 +207,26 @@ ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct) ...@@ -206,22 +207,26 @@ ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct)
return -1; return -1;
} }
#ifdef CONFIG_NF_CT_ACCT
static int static int
ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct, ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
enum ip_conntrack_dir dir) enum ip_conntrack_dir dir)
{ {
enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
struct nlattr *nest_count; struct nlattr *nest_count;
const struct nf_conn_counter *acct;
acct = nf_conn_acct_find(ct);
if (!acct)
return 0;
nest_count = nla_nest_start(skb, type | NLA_F_NESTED); nest_count = nla_nest_start(skb, type | NLA_F_NESTED);
if (!nest_count) if (!nest_count)
goto nla_put_failure; goto nla_put_failure;
NLA_PUT_BE32(skb, CTA_COUNTERS32_PACKETS, NLA_PUT_BE64(skb, CTA_COUNTERS_PACKETS,
htonl(ct->counters[dir].packets)); cpu_to_be64(acct[dir].packets));
NLA_PUT_BE32(skb, CTA_COUNTERS32_BYTES, NLA_PUT_BE64(skb, CTA_COUNTERS_BYTES,
htonl(ct->counters[dir].bytes)); cpu_to_be64(acct[dir].bytes));
nla_nest_end(skb, nest_count); nla_nest_end(skb, nest_count);
...@@ -230,9 +235,6 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct, ...@@ -230,9 +235,6 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
nla_put_failure: nla_put_failure:
return -1; return -1;
} }
#else
#define ctnetlink_dump_counters(a, b, c) (0)
#endif
#ifdef CONFIG_NF_CONNTRACK_MARK #ifdef CONFIG_NF_CONNTRACK_MARK
static inline int static inline int
...@@ -501,11 +503,6 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, ...@@ -501,11 +503,6 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
goto nla_put_failure; goto nla_put_failure;
#endif #endif
if (events & IPCT_COUNTER_FILLING &&
(ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0))
goto nla_put_failure;
if (events & IPCT_RELATED && if (events & IPCT_RELATED &&
ctnetlink_dump_master(skb, ct) < 0) ctnetlink_dump_master(skb, ct) < 0)
goto nla_put_failure; goto nla_put_failure;
...@@ -576,11 +573,15 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -576,11 +573,15 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
cb->args[1] = (unsigned long)ct; cb->args[1] = (unsigned long)ct;
goto out; goto out;
} }
#ifdef CONFIG_NF_CT_ACCT
if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) ==
IPCTNL_MSG_CT_GET_CTRZERO) IPCTNL_MSG_CT_GET_CTRZERO) {
memset(&ct->counters, 0, sizeof(ct->counters)); struct nf_conn_counter *acct;
#endif
acct = nf_conn_acct_find(ct);
if (acct)
memset(acct, 0, sizeof(struct nf_conn_counter[IP_CT_DIR_MAX]));
}
} }
if (cb->args[1]) { if (cb->args[1]) {
cb->args[1] = 0; cb->args[1] = 0;
...@@ -832,14 +833,9 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, ...@@ -832,14 +833,9 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
u_int8_t u3 = nfmsg->nfgen_family; u_int8_t u3 = nfmsg->nfgen_family;
int err = 0; int err = 0;
if (nlh->nlmsg_flags & NLM_F_DUMP) { if (nlh->nlmsg_flags & NLM_F_DUMP)
#ifndef CONFIG_NF_CT_ACCT
if (NFNL_MSG_TYPE(nlh->nlmsg_type) == IPCTNL_MSG_CT_GET_CTRZERO)
return -ENOTSUPP;
#endif
return netlink_dump_start(ctnl, skb, nlh, ctnetlink_dump_table, return netlink_dump_start(ctnl, skb, nlh, ctnetlink_dump_table,
ctnetlink_done); ctnetlink_done);
}
if (cda[CTA_TUPLE_ORIG]) if (cda[CTA_TUPLE_ORIG])
err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3); err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3);
...@@ -1152,6 +1148,8 @@ ctnetlink_create_conntrack(struct nlattr *cda[], ...@@ -1152,6 +1148,8 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
goto err; goto err;
} }
nf_ct_acct_ext_add(ct, GFP_KERNEL);
#if defined(CONFIG_NF_CONNTRACK_MARK) #if defined(CONFIG_NF_CONNTRACK_MARK)
if (cda[CTA_MARK]) if (cda[CTA_MARK])
ct->mark = ntohl(nla_get_be32(cda[CTA_MARK])); ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
......
...@@ -482,11 +482,11 @@ static int sctp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, ...@@ -482,11 +482,11 @@ static int sctp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
NLA_PUT_BE32(skb, NLA_PUT_BE32(skb,
CTA_PROTOINFO_SCTP_VTAG_ORIGINAL, CTA_PROTOINFO_SCTP_VTAG_ORIGINAL,
htonl(ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL])); ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL]);
NLA_PUT_BE32(skb, NLA_PUT_BE32(skb,
CTA_PROTOINFO_SCTP_VTAG_REPLY, CTA_PROTOINFO_SCTP_VTAG_REPLY,
htonl(ct->proto.sctp.vtag[IP_CT_DIR_REPLY])); ct->proto.sctp.vtag[IP_CT_DIR_REPLY]);
read_unlock_bh(&sctp_lock); read_unlock_bh(&sctp_lock);
...@@ -530,9 +530,9 @@ static int nlattr_to_sctp(struct nlattr *cda[], struct nf_conn *ct) ...@@ -530,9 +530,9 @@ static int nlattr_to_sctp(struct nlattr *cda[], struct nf_conn *ct)
write_lock_bh(&sctp_lock); write_lock_bh(&sctp_lock);
ct->proto.sctp.state = nla_get_u8(tb[CTA_PROTOINFO_SCTP_STATE]); ct->proto.sctp.state = nla_get_u8(tb[CTA_PROTOINFO_SCTP_STATE]);
ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] =
ntohl(nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL])); nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]);
ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = ct->proto.sctp.vtag[IP_CT_DIR_REPLY] =
ntohl(nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_REPLY])); nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]);
write_unlock_bh(&sctp_lock); write_unlock_bh(&sctp_lock);
return 0; return 0;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_expect.h> #include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_acct.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -38,19 +39,6 @@ print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, ...@@ -38,19 +39,6 @@ print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
} }
EXPORT_SYMBOL_GPL(print_tuple); EXPORT_SYMBOL_GPL(print_tuple);
#ifdef CONFIG_NF_CT_ACCT
static unsigned int
seq_print_counters(struct seq_file *s,
const struct ip_conntrack_counter *counter)
{
return seq_printf(s, "packets=%llu bytes=%llu ",
(unsigned long long)counter->packets,
(unsigned long long)counter->bytes);
}
#else
#define seq_print_counters(x, y) 0
#endif
struct ct_iter_state { struct ct_iter_state {
unsigned int bucket; unsigned int bucket;
}; };
...@@ -146,7 +134,7 @@ static int ct_seq_show(struct seq_file *s, void *v) ...@@ -146,7 +134,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
l3proto, l4proto)) l3proto, l4proto))
return -ENOSPC; return -ENOSPC;
if (seq_print_counters(s, &ct->counters[IP_CT_DIR_ORIGINAL])) if (seq_print_acct(s, ct, IP_CT_DIR_ORIGINAL))
return -ENOSPC; return -ENOSPC;
if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status))) 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,7 +145,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
l3proto, l4proto)) l3proto, l4proto))
return -ENOSPC; return -ENOSPC;
if (seq_print_counters(s, &ct->counters[IP_CT_DIR_REPLY])) if (seq_print_acct(s, ct, IP_CT_DIR_REPLY))
return -ENOSPC; return -ENOSPC;
if (test_bit(IPS_ASSURED_BIT, &ct->status)) if (test_bit(IPS_ASSURED_BIT, &ct->status))
......
...@@ -453,6 +453,14 @@ __build_packet_message(struct nfulnl_instance *inst, ...@@ -453,6 +453,14 @@ __build_packet_message(struct nfulnl_instance *inst,
} }
} }
if (indev && skb_mac_header_was_set(skb)) {
NLA_PUT_BE16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type));
NLA_PUT_BE16(inst->skb, NFULA_HWLEN,
htons(skb->dev->hard_header_len));
NLA_PUT(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len,
skb_mac_header(skb));
}
if (skb->tstamp.tv64) { if (skb->tstamp.tv64) {
struct nfulnl_msg_packet_timestamp ts; struct nfulnl_msg_packet_timestamp ts;
struct timeval tv = ktime_to_timeval(skb->tstamp); struct timeval tv = ktime_to_timeval(skb->tstamp);
......
...@@ -147,17 +147,21 @@ tcpmss_mangle_packet(struct sk_buff *skb, ...@@ -147,17 +147,21 @@ tcpmss_mangle_packet(struct sk_buff *skb,
return TCPOLEN_MSS; return TCPOLEN_MSS;
} }
static u_int32_t tcpmss_reverse_mtu4(const struct iphdr *iph) static u_int32_t tcpmss_reverse_mtu(const struct sk_buff *skb,
unsigned int family)
{ {
struct flowi fl = { struct flowi fl = {};
.fl4_dst = iph->saddr,
};
const struct nf_afinfo *ai; const struct nf_afinfo *ai;
struct rtable *rt = NULL; struct rtable *rt = NULL;
u_int32_t mtu = ~0U; u_int32_t mtu = ~0U;
if (family == PF_INET)
fl.fl4_dst = ip_hdr(skb)->saddr;
else
fl.fl6_dst = ipv6_hdr(skb)->saddr;
rcu_read_lock(); rcu_read_lock();
ai = nf_get_afinfo(AF_INET); ai = nf_get_afinfo(family);
if (ai != NULL) if (ai != NULL)
ai->route((struct dst_entry **)&rt, &fl); ai->route((struct dst_entry **)&rt, &fl);
rcu_read_unlock(); rcu_read_unlock();
...@@ -178,7 +182,8 @@ tcpmss_tg4(struct sk_buff *skb, const struct net_device *in, ...@@ -178,7 +182,8 @@ tcpmss_tg4(struct sk_buff *skb, const struct net_device *in,
__be16 newlen; __be16 newlen;
int ret; int ret;
ret = tcpmss_mangle_packet(skb, targinfo, tcpmss_reverse_mtu4(iph), ret = tcpmss_mangle_packet(skb, targinfo,
tcpmss_reverse_mtu(skb, PF_INET),
iph->ihl * 4, iph->ihl * 4,
sizeof(*iph) + sizeof(struct tcphdr)); sizeof(*iph) + sizeof(struct tcphdr));
if (ret < 0) if (ret < 0)
...@@ -193,28 +198,6 @@ tcpmss_tg4(struct sk_buff *skb, const struct net_device *in, ...@@ -193,28 +198,6 @@ tcpmss_tg4(struct sk_buff *skb, const struct net_device *in,
} }
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
static u_int32_t tcpmss_reverse_mtu6(const struct ipv6hdr *iph)
{
struct flowi fl = {
.fl6_dst = iph->saddr,
};
const struct nf_afinfo *ai;
struct rtable *rt = NULL;
u_int32_t mtu = ~0U;
rcu_read_lock();
ai = nf_get_afinfo(AF_INET6);
if (ai != NULL)
ai->route((struct dst_entry **)&rt, &fl);
rcu_read_unlock();
if (rt != NULL) {
mtu = dst_mtu(&rt->u.dst);
dst_release(&rt->u.dst);
}
return mtu;
}
static unsigned int static unsigned int
tcpmss_tg6(struct sk_buff *skb, const struct net_device *in, tcpmss_tg6(struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, unsigned int hooknum, const struct net_device *out, unsigned int hooknum,
...@@ -229,7 +212,8 @@ tcpmss_tg6(struct sk_buff *skb, const struct net_device *in, ...@@ -229,7 +212,8 @@ tcpmss_tg6(struct sk_buff *skb, const struct net_device *in,
tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr); tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr);
if (tcphoff < 0) if (tcphoff < 0)
return NF_DROP; return NF_DROP;
ret = tcpmss_mangle_packet(skb, targinfo, tcpmss_reverse_mtu6(ipv6h), ret = tcpmss_mangle_packet(skb, targinfo,
tcpmss_reverse_mtu(skb, PF_INET6),
tcphoff, tcphoff,
sizeof(*ipv6h) + sizeof(struct tcphdr)); sizeof(*ipv6h) + sizeof(struct tcphdr));
if (ret < 0) if (ret < 0)
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/netfilter/x_tables.h> #include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_connbytes.h> #include <linux/netfilter/xt_connbytes.h>
#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_acct.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
...@@ -27,12 +28,15 @@ connbytes_mt(const struct sk_buff *skb, const struct net_device *in, ...@@ -27,12 +28,15 @@ connbytes_mt(const struct sk_buff *skb, const struct net_device *in,
u_int64_t what = 0; /* initialize to make gcc happy */ u_int64_t what = 0; /* initialize to make gcc happy */
u_int64_t bytes = 0; u_int64_t bytes = 0;
u_int64_t pkts = 0; u_int64_t pkts = 0;
const struct ip_conntrack_counter *counters; const struct nf_conn_counter *counters;
ct = nf_ct_get(skb, &ctinfo); ct = nf_ct_get(skb, &ctinfo);
if (!ct) if (!ct)
return false; return false;
counters = ct->counters;
counters = nf_conn_acct_find(ct);
if (!counters)
return false;
switch (sinfo->what) { switch (sinfo->what) {
case XT_CONNBYTES_PKTS: case XT_CONNBYTES_PKTS:
......
...@@ -173,7 +173,7 @@ time_mt(const struct sk_buff *skb, const struct net_device *in, ...@@ -173,7 +173,7 @@ time_mt(const struct sk_buff *skb, const struct net_device *in,
__net_timestamp((struct sk_buff *)skb); __net_timestamp((struct sk_buff *)skb);
stamp = ktime_to_ns(skb->tstamp); stamp = ktime_to_ns(skb->tstamp);
do_div(stamp, NSEC_PER_SEC); stamp = div_s64(stamp, NSEC_PER_SEC);
if (info->flags & XT_TIME_LOCAL_TZ) if (info->flags & XT_TIME_LOCAL_TZ)
/* Adjust for local timezone */ /* Adjust for local timezone */
......
...@@ -356,44 +356,99 @@ static struct Qdisc noqueue_qdisc = { ...@@ -356,44 +356,99 @@ static struct Qdisc noqueue_qdisc = {
}; };
static int fifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc) static const u8 prio2band[TC_PRIO_MAX+1] =
{ 1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1 };
/* 3-band FIFO queue: old style, but should be a bit faster than
generic prio+fifo combination.
*/
#define PFIFO_FAST_BANDS 3
static inline struct sk_buff_head *prio2list(struct sk_buff *skb,
struct Qdisc *qdisc)
{
struct sk_buff_head *list = qdisc_priv(qdisc);
return list + prio2band[skb->priority & TC_PRIO_MAX];
}
static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
{ {
struct sk_buff_head *list = &qdisc->q; struct sk_buff_head *list = prio2list(skb, qdisc);
if (skb_queue_len(list) < qdisc_dev(qdisc)->tx_queue_len) if (skb_queue_len(list) < qdisc_dev(qdisc)->tx_queue_len) {
qdisc->q.qlen++;
return __qdisc_enqueue_tail(skb, qdisc, list); return __qdisc_enqueue_tail(skb, qdisc, list);
}
return qdisc_drop(skb, qdisc); return qdisc_drop(skb, qdisc);
} }
static struct sk_buff *fifo_fast_dequeue(struct Qdisc* qdisc) static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc)
{ {
struct sk_buff_head *list = &qdisc->q; int prio;
struct sk_buff_head *list = qdisc_priv(qdisc);
if (!skb_queue_empty(list)) for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) {
return __qdisc_dequeue_head(qdisc, list); if (!skb_queue_empty(list + prio)) {
qdisc->q.qlen--;
return __qdisc_dequeue_head(qdisc, list + prio);
}
}
return NULL; return NULL;
} }
static int fifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc) static int pfifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
{ {
return __qdisc_requeue(skb, qdisc, &qdisc->q); qdisc->q.qlen++;
return __qdisc_requeue(skb, qdisc, prio2list(skb, qdisc));
} }
static void fifo_fast_reset(struct Qdisc* qdisc) static void pfifo_fast_reset(struct Qdisc* qdisc)
{ {
__qdisc_reset_queue(qdisc, &qdisc->q); int prio;
struct sk_buff_head *list = qdisc_priv(qdisc);
for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
__qdisc_reset_queue(qdisc, list + prio);
qdisc->qstats.backlog = 0; qdisc->qstats.backlog = 0;
qdisc->q.qlen = 0;
} }
static struct Qdisc_ops fifo_fast_ops __read_mostly = { static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb)
.id = "fifo_fast", {
.priv_size = 0, struct tc_prio_qopt opt = { .bands = PFIFO_FAST_BANDS };
.enqueue = fifo_fast_enqueue,
.dequeue = fifo_fast_dequeue, memcpy(&opt.priomap, prio2band, TC_PRIO_MAX+1);
.requeue = fifo_fast_requeue, NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
.reset = fifo_fast_reset, return skb->len;
nla_put_failure:
return -1;
}
static int pfifo_fast_init(struct Qdisc *qdisc, struct nlattr *opt)
{
int prio;
struct sk_buff_head *list = qdisc_priv(qdisc);
for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
skb_queue_head_init(list + prio);
return 0;
}
static struct Qdisc_ops pfifo_fast_ops __read_mostly = {
.id = "pfifo_fast",
.priv_size = PFIFO_FAST_BANDS * sizeof(struct sk_buff_head),
.enqueue = pfifo_fast_enqueue,
.dequeue = pfifo_fast_dequeue,
.requeue = pfifo_fast_requeue,
.init = pfifo_fast_init,
.reset = pfifo_fast_reset,
.dump = pfifo_fast_dump,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
...@@ -522,7 +577,7 @@ static void attach_one_default_qdisc(struct net_device *dev, ...@@ -522,7 +577,7 @@ static void attach_one_default_qdisc(struct net_device *dev,
if (dev->tx_queue_len) { if (dev->tx_queue_len) {
qdisc = qdisc_create_dflt(dev, dev_queue, qdisc = qdisc_create_dflt(dev, dev_queue,
&fifo_fast_ops, TC_H_ROOT); &pfifo_fast_ops, TC_H_ROOT);
if (!qdisc) { if (!qdisc) {
printk(KERN_INFO "%s: activation failed\n", dev->name); printk(KERN_INFO "%s: activation failed\n", dev->name);
return; return;
...@@ -550,9 +605,9 @@ void dev_activate(struct net_device *dev) ...@@ -550,9 +605,9 @@ void dev_activate(struct net_device *dev)
int need_watchdog; int need_watchdog;
/* No queueing discipline is attached to device; /* No queueing discipline is attached to device;
* create default one i.e. fifo_fast for devices, create default one i.e. pfifo_fast for devices,
* which need queueing and noqueue_qdisc for which need queueing and noqueue_qdisc for
* virtual interfaces. virtual interfaces
*/ */
if (dev_all_qdisc_sleeping_noop(dev)) if (dev_all_qdisc_sleeping_noop(dev))
...@@ -576,7 +631,6 @@ static void dev_deactivate_queue(struct net_device *dev, ...@@ -576,7 +631,6 @@ static void dev_deactivate_queue(struct net_device *dev,
void *_qdisc_default) void *_qdisc_default)
{ {
struct Qdisc *qdisc_default = _qdisc_default; struct Qdisc *qdisc_default = _qdisc_default;
struct sk_buff *skb = NULL;
struct Qdisc *qdisc; struct Qdisc *qdisc;
qdisc = dev_queue->qdisc; qdisc = dev_queue->qdisc;
...@@ -588,8 +642,6 @@ static void dev_deactivate_queue(struct net_device *dev, ...@@ -588,8 +642,6 @@ static void dev_deactivate_queue(struct net_device *dev,
spin_unlock_bh(qdisc_lock(qdisc)); spin_unlock_bh(qdisc_lock(qdisc));
} }
kfree_skb(skb);
} }
static bool some_qdisc_is_running(struct net_device *dev, int lock) static bool some_qdisc_is_running(struct net_device *dev, int lock)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment