Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 14d3692f authored by David S. Miller's avatar David S. Miller
Browse files


Pablo Neira Ayuso says:

====================
The following patchset contains relevant updates for the Netfilter
tree, they are:

* Enhancements for ipset: Add the counter extension for sets, this
  information can be used from the iptables set match, to change
  the matching behaviour. Jozsef required to add the extension
  infrastructure and moved the existing timeout support upon it.
  This also includes a change in net/sched/em_ipset to adapt it to
  the new extension structure.

* Enhancements for performance boosting in nfnetlink_queue: Add new
  configuration flags that allows user-space to receive big packets (GRO)
  and to disable checksumming calculation. This were proposed by Eric
  Dumazet during the Netfilter Workshop 2013 in Copenhagen. Florian
  Westphal was kind enough to find the time to materialize the proposal.

* A sparse fix from Simon, he noticed it in the SCTP NAT helper, the fix
  required a change in the interface of sctp_end_cksum.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 674853b2 eee1d5a1
Loading
Loading
Loading
Loading
+119 −7
Original line number Original line Diff line number Diff line
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
 *                         Patrick Schaaf <bof@bof.de>
 *                         Patrick Schaaf <bof@bof.de>
 *                         Martin Josefsson <gandalf@wlug.westbo.se>
 *                         Martin Josefsson <gandalf@wlug.westbo.se>
 * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
 * Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * 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
 * it under the terms of the GNU General Public License version 2 as
@@ -47,10 +47,36 @@ enum ip_set_feature {
	IPSET_DUMP_LAST = (1 << IPSET_DUMP_LAST_FLAG),
	IPSET_DUMP_LAST = (1 << IPSET_DUMP_LAST_FLAG),
};
};


/* Set extensions */
enum ip_set_extension {
	IPSET_EXT_NONE = 0,
	IPSET_EXT_BIT_TIMEOUT = 1,
	IPSET_EXT_TIMEOUT = (1 << IPSET_EXT_BIT_TIMEOUT),
	IPSET_EXT_BIT_COUNTER = 2,
	IPSET_EXT_COUNTER = (1 << IPSET_EXT_BIT_COUNTER),
};

/* Extension offsets */
enum ip_set_offset {
	IPSET_OFFSET_TIMEOUT = 0,
	IPSET_OFFSET_COUNTER,
	IPSET_OFFSET_MAX,
};

#define SET_WITH_TIMEOUT(s)	((s)->extensions & IPSET_EXT_TIMEOUT)
#define SET_WITH_COUNTER(s)	((s)->extensions & IPSET_EXT_COUNTER)

struct ip_set_ext {
	unsigned long timeout;
	u64 packets;
	u64 bytes;
};

struct ip_set;
struct ip_set;


typedef int (*ipset_adtfn)(struct ip_set *set, void *value,
typedef int (*ipset_adtfn)(struct ip_set *set, void *value,
			   u32 timeout, u32 flags);
			   const struct ip_set_ext *ext,
			   struct ip_set_ext *mext, u32 cmdflags);


/* Kernel API function options */
/* Kernel API function options */
struct ip_set_adt_opt {
struct ip_set_adt_opt {
@@ -58,7 +84,7 @@ struct ip_set_adt_opt {
	u8 dim;			/* Dimension of match/target */
	u8 dim;			/* Dimension of match/target */
	u8 flags;		/* Direction and negation flags */
	u8 flags;		/* Direction and negation flags */
	u32 cmdflags;		/* Command-like flags */
	u32 cmdflags;		/* Command-like flags */
	u32 timeout;		/* Timeout value */
	struct ip_set_ext ext;	/* Extensions */
};
};


/* Set type, variant-specific part */
/* Set type, variant-specific part */
@@ -69,7 +95,7 @@ struct ip_set_type_variant {
	 *			positive for matching element */
	 *			positive for matching element */
	int (*kadt)(struct ip_set *set, const struct sk_buff *skb,
	int (*kadt)(struct ip_set *set, const struct sk_buff *skb,
		    const struct xt_action_param *par,
		    const struct xt_action_param *par,
		    enum ipset_adt adt, const struct ip_set_adt_opt *opt);
		    enum ipset_adt adt, struct ip_set_adt_opt *opt);


	/* Userspace: test/add/del entries
	/* Userspace: test/add/del entries
	 *		returns negative error code,
	 *		returns negative error code,
@@ -151,10 +177,76 @@ struct ip_set {
	u8 family;
	u8 family;
	/* The type revision */
	/* The type revision */
	u8 revision;
	u8 revision;
	/* Extensions */
	u8 extensions;
	/* The type specific data */
	/* The type specific data */
	void *data;
	void *data;
};
};


struct ip_set_counter {
	atomic64_t bytes;
	atomic64_t packets;
};

static inline void
ip_set_add_bytes(u64 bytes, struct ip_set_counter *counter)
{
	atomic64_add((long long)bytes, &(counter)->bytes);
}

static inline void
ip_set_add_packets(u64 packets, struct ip_set_counter *counter)
{
	atomic64_add((long long)packets, &(counter)->packets);
}

static inline u64
ip_set_get_bytes(const struct ip_set_counter *counter)
{
	return (u64)atomic64_read(&(counter)->bytes);
}

static inline u64
ip_set_get_packets(const struct ip_set_counter *counter)
{
	return (u64)atomic64_read(&(counter)->packets);
}

static inline void
ip_set_update_counter(struct ip_set_counter *counter,
		      const struct ip_set_ext *ext,
		      struct ip_set_ext *mext, u32 flags)
{
	if (ext->packets != ULLONG_MAX &&
	    !(flags & IPSET_FLAG_SKIP_COUNTER_UPDATE)) {
		ip_set_add_bytes(ext->bytes, counter);
		ip_set_add_packets(ext->packets, counter);
	}
	if (flags & IPSET_FLAG_MATCH_COUNTERS) {
		mext->packets = ip_set_get_packets(counter);
		mext->bytes = ip_set_get_bytes(counter);
	}
}

static inline bool
ip_set_put_counter(struct sk_buff *skb, struct ip_set_counter *counter)
{
	return nla_put_net64(skb, IPSET_ATTR_BYTES,
			     cpu_to_be64(ip_set_get_bytes(counter))) ||
	       nla_put_net64(skb, IPSET_ATTR_PACKETS,
			     cpu_to_be64(ip_set_get_packets(counter)));
}

static inline void
ip_set_init_counter(struct ip_set_counter *counter,
		    const struct ip_set_ext *ext)
{
	if (ext->bytes != ULLONG_MAX)
		atomic64_set(&(counter)->bytes, (long long)(ext->bytes));
	if (ext->packets != ULLONG_MAX)
		atomic64_set(&(counter)->packets, (long long)(ext->packets));
}

/* register and unregister set references */
/* register and unregister set references */
extern ip_set_id_t ip_set_get_byname(const char *name, struct ip_set **set);
extern ip_set_id_t ip_set_get_byname(const char *name, struct ip_set **set);
extern void ip_set_put_byindex(ip_set_id_t index);
extern void ip_set_put_byindex(ip_set_id_t index);
@@ -167,19 +259,21 @@ extern void ip_set_nfnl_put(ip_set_id_t index);


extern int ip_set_add(ip_set_id_t id, const struct sk_buff *skb,
extern int ip_set_add(ip_set_id_t id, const struct sk_buff *skb,
		      const struct xt_action_param *par,
		      const struct xt_action_param *par,
		      const struct ip_set_adt_opt *opt);
		      struct ip_set_adt_opt *opt);
extern int ip_set_del(ip_set_id_t id, const struct sk_buff *skb,
extern int ip_set_del(ip_set_id_t id, const struct sk_buff *skb,
		      const struct xt_action_param *par,
		      const struct xt_action_param *par,
		      const struct ip_set_adt_opt *opt);
		      struct ip_set_adt_opt *opt);
extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb,
extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb,
		       const struct xt_action_param *par,
		       const struct xt_action_param *par,
		       const struct ip_set_adt_opt *opt);
		       struct ip_set_adt_opt *opt);


/* Utility functions */
/* Utility functions */
extern void *ip_set_alloc(size_t size);
extern void *ip_set_alloc(size_t size);
extern void ip_set_free(void *members);
extern void ip_set_free(void *members);
extern int ip_set_get_ipaddr4(struct nlattr *nla,  __be32 *ipaddr);
extern int ip_set_get_ipaddr4(struct nlattr *nla,  __be32 *ipaddr);
extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr);
extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr);
extern int ip_set_get_extensions(struct ip_set *set, struct nlattr *tb[],
				 struct ip_set_ext *ext);


static inline int
static inline int
ip_set_get_hostipaddr4(struct nlattr *nla, u32 *ipaddr)
ip_set_get_hostipaddr4(struct nlattr *nla, u32 *ipaddr)
@@ -200,6 +294,14 @@ ip_set_eexist(int ret, u32 flags)
	return ret == -IPSET_ERR_EXIST && (flags & IPSET_FLAG_EXIST);
	return ret == -IPSET_ERR_EXIST && (flags & IPSET_FLAG_EXIST);
}
}


/* Match elements marked with nomatch */
static inline bool
ip_set_enomatch(int ret, u32 flags, enum ipset_adt adt)
{
	return adt == IPSET_TEST &&
	       ret == -ENOTEMPTY && ((flags >> 16) & IPSET_FLAG_NOMATCH);
}

/* Check the NLA_F_NET_BYTEORDER flag */
/* Check the NLA_F_NET_BYTEORDER flag */
static inline bool
static inline bool
ip_set_attr_netorder(struct nlattr *tb[], int type)
ip_set_attr_netorder(struct nlattr *tb[], int type)
@@ -284,4 +386,14 @@ bitmap_bytes(u32 a, u32 b)
	return 4 * ((((b - a + 8) / 8) + 3) / 4);
	return 4 * ((((b - a + 8) / 8) + 3) / 4);
}
}


#include <linux/netfilter/ipset/ip_set_timeout.h>

#define IP_SET_INIT_KEXT(skb, opt, map)			\
	{ .bytes = (skb)->len, .packets = 1,		\
	  .timeout = ip_set_adt_opt_timeout(opt, map) }

#define IP_SET_INIT_UEXT(map)				\
	{ .bytes = ULLONG_MAX, .packets = ULLONG_MAX,	\
	  .timeout = (map)->timeout }

#endif /*_IP_SET_H */
#endif /*_IP_SET_H */
+6 −0
Original line number Original line Diff line number Diff line
@@ -5,6 +5,12 @@


#define IPSET_BITMAP_MAX_RANGE	0x0000FFFF
#define IPSET_BITMAP_MAX_RANGE	0x0000FFFF


enum {
	IPSET_ADD_FAILED = 1,
	IPSET_ADD_STORE_PLAIN_TIMEOUT,
	IPSET_ADD_START_STORED_TIMEOUT,
};

/* Common functions */
/* Common functions */


static inline u32
static inline u32
+22 −80
Original line number Original line Diff line number Diff line
#ifndef _IP_SET_TIMEOUT_H
#ifndef _IP_SET_TIMEOUT_H
#define _IP_SET_TIMEOUT_H
#define _IP_SET_TIMEOUT_H


/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
/* Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * 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
 * it under the terms of the GNU General Public License version 2 as
@@ -17,13 +17,14 @@
#define IPSET_GC_PERIOD(timeout) \
#define IPSET_GC_PERIOD(timeout) \
	((timeout/3) ? min_t(u32, (timeout)/3, IPSET_GC_TIME) : 1)
	((timeout/3) ? min_t(u32, (timeout)/3, IPSET_GC_TIME) : 1)


/* Set is defined without timeout support: timeout value may be 0 */
/* Entry is set with no timeout value */
#define IPSET_NO_TIMEOUT	UINT_MAX
#define IPSET_ELEM_PERMANENT	0


#define with_timeout(timeout)	((timeout) != IPSET_NO_TIMEOUT)
/* Set is defined with timeout support: timeout value may be 0 */
#define IPSET_NO_TIMEOUT	UINT_MAX


#define opt_timeout(opt, map)	\
#define ip_set_adt_opt_timeout(opt, map)	\
	(with_timeout((opt)->timeout) ? (opt)->timeout : (map)->timeout)
((opt)->ext.timeout != IPSET_NO_TIMEOUT ? (opt)->ext.timeout : (map)->timeout)


static inline unsigned int
static inline unsigned int
ip_set_timeout_uget(struct nlattr *tb)
ip_set_timeout_uget(struct nlattr *tb)
@@ -38,61 +39,6 @@ ip_set_timeout_uget(struct nlattr *tb)
	return timeout == IPSET_NO_TIMEOUT ? IPSET_NO_TIMEOUT - 1 : timeout;
	return timeout == IPSET_NO_TIMEOUT ? IPSET_NO_TIMEOUT - 1 : timeout;
}
}


#ifdef IP_SET_BITMAP_TIMEOUT

/* Bitmap specific timeout constants and macros for the entries */

/* Bitmap entry is unset */
#define IPSET_ELEM_UNSET	0
/* Bitmap entry is set with no timeout value */
#define IPSET_ELEM_PERMANENT	(UINT_MAX/2)

static inline bool
ip_set_timeout_test(unsigned long timeout)
{
	return timeout != IPSET_ELEM_UNSET &&
	       (timeout == IPSET_ELEM_PERMANENT ||
		time_is_after_jiffies(timeout));
}

static inline bool
ip_set_timeout_expired(unsigned long timeout)
{
	return timeout != IPSET_ELEM_UNSET &&
	       timeout != IPSET_ELEM_PERMANENT &&
	       time_is_before_jiffies(timeout);
}

static inline unsigned long
ip_set_timeout_set(u32 timeout)
{
	unsigned long t;

	if (!timeout)
		return IPSET_ELEM_PERMANENT;

	t = msecs_to_jiffies(timeout * 1000) + jiffies;
	if (t == IPSET_ELEM_UNSET || t == IPSET_ELEM_PERMANENT)
		/* Bingo! */
		t++;

	return t;
}

static inline u32
ip_set_timeout_get(unsigned long timeout)
{
	return timeout == IPSET_ELEM_PERMANENT ? 0 :
		jiffies_to_msecs(timeout - jiffies)/1000;
}

#else

/* Hash specific timeout constants and macros for the entries */

/* Hash entry is set with no timeout value */
#define IPSET_ELEM_PERMANENT	0

static inline bool
static inline bool
ip_set_timeout_test(unsigned long timeout)
ip_set_timeout_test(unsigned long timeout)
{
{
@@ -101,36 +47,32 @@ ip_set_timeout_test(unsigned long timeout)
}
}


static inline bool
static inline bool
ip_set_timeout_expired(unsigned long timeout)
ip_set_timeout_expired(unsigned long *timeout)
{
{
	return timeout != IPSET_ELEM_PERMANENT &&
	return *timeout != IPSET_ELEM_PERMANENT &&
	       time_is_before_jiffies(timeout);
	       time_is_before_jiffies(*timeout);
}
}


static inline unsigned long
static inline void
ip_set_timeout_set(u32 timeout)
ip_set_timeout_set(unsigned long *timeout, u32 t)
{
{
	unsigned long t;
	if (!t) {

		*timeout = IPSET_ELEM_PERMANENT;
	if (!timeout)
		return;
		return IPSET_ELEM_PERMANENT;
	}


	t = msecs_to_jiffies(timeout * 1000) + jiffies;
	*timeout = msecs_to_jiffies(t * 1000) + jiffies;
	if (t == IPSET_ELEM_PERMANENT)
	if (*timeout == IPSET_ELEM_PERMANENT)
		/* Bingo! :-) */
		/* Bingo! :-) */
		t++;
		(*timeout)--;

	return t;
}
}


static inline u32
static inline u32
ip_set_timeout_get(unsigned long timeout)
ip_set_timeout_get(unsigned long *timeout)
{
{
	return timeout == IPSET_ELEM_PERMANENT ? 0 :
	return *timeout == IPSET_ELEM_PERMANENT ? 0 :
		jiffies_to_msecs(timeout - jiffies)/1000;
		jiffies_to_msecs(*timeout - jiffies)/1000;
}
}
#endif /* ! IP_SET_BITMAP_TIMEOUT */


#endif	/* __KERNEL__ */
#endif	/* __KERNEL__ */

#endif /* _IP_SET_TIMEOUT_H */
#endif /* _IP_SET_TIMEOUT_H */
+9 −0
Original line number Original line Diff line number Diff line
@@ -41,4 +41,13 @@ do { \
	to = from | ~ip_set_hostmask(cidr);	\
	to = from | ~ip_set_hostmask(cidr);	\
} while (0)
} while (0)


static inline void
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
{
	ip->ip6[0] &= ip_set_netmask6(prefix)[0];
	ip->ip6[1] &= ip_set_netmask6(prefix)[1];
	ip->ip6[2] &= ip_set_netmask6(prefix)[2];
	ip->ip6[3] &= ip_set_netmask6(prefix)[3];
}

#endif /*_PFXLEN_H */
#endif /*_PFXLEN_H */
+6 −0
Original line number Original line Diff line number Diff line
@@ -9,10 +9,13 @@ struct nf_queue_entry {


	struct nf_hook_ops	*elem;
	struct nf_hook_ops	*elem;
	u_int8_t		pf;
	u_int8_t		pf;
	u16			size; /* sizeof(entry) + saved route keys */
	unsigned int		hook;
	unsigned int		hook;
	struct net_device	*indev;
	struct net_device	*indev;
	struct net_device	*outdev;
	struct net_device	*outdev;
	int			(*okfn)(struct sk_buff *);
	int			(*okfn)(struct sk_buff *);

	/* extra space to store route keys */
};
};


#define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry))
#define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry))
@@ -27,4 +30,7 @@ void nf_register_queue_handler(const struct nf_queue_handler *qh);
void nf_unregister_queue_handler(void);
void nf_unregister_queue_handler(void);
extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);


bool nf_queue_entry_get_refs(struct nf_queue_entry *entry);
void nf_queue_entry_release_refs(struct nf_queue_entry *entry);

#endif /* _NF_QUEUE_H */
#endif /* _NF_QUEUE_H */
Loading