Netfilter/IPVS updates for net-next
Subsystems (7)
Pablo Neira Ayuso
maintainercover Netfilter/IPVS updates for net-next
Hi David,
The following patchset contains Netfilter/IPVS updates for your net-next tree, more relevant updates in this batch are:
1) Add Maglev support to IPVS. Moreover, store lastest server weight in IPVS since this is needed by maglev, patches from from Inju Song.
2) Preparation works to add iptables flowtable support, patches from Felix Fietkau.
3) Hand over flows back to conntrack slow path in case of TCP RST/FIN packet is seen via new teardown state, also from Felix.
4) Add support for extended netlink error reporting for nf_tables.
5) Support for larger timeouts that 23 days in nf_tables, patch from Florian Westphal.
6) Always set an upper limit to dynamic sets, also from Florian.
7) Allow number generator to make map lookups, from Laura Garcia.
8) Use hash_32() instead of opencode hashing in IPVS, from Vicent Bernat.
9) Extend ip6tables SRH match to support previous, next and last SID, from Ahmed Abdelsalam.
10) Move Passive OS fingerprint nf_osf.c, from Fernando Fernandez.
11) Expose nf_conntrack_max through ctnetlink, from Florent Fourcot.
12) Several housekeeping patches for xt_NFLOG, x_tables and ebtables, from Taehee Yoo.
13) Unify meta bridge with core nft_meta, then make nft_meta built-in. Make rt and exthdr built-in too, again from Florian.
14) Missing initialization of tbl->entries in IPVS, from Cong Wang.
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git
Thanks.
----------------------------------------------------------------
The following changes since commit 415787d7799f4fccbe8d49cb0b8e5811be6b0389:
ipv6: frags: fix a lockdep false positive (2018-04-18 23:19:39 -0400)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git HEAD
for you to fetch changes up to b13468dc577498002cf4e62978359ff97ffcd187:
netfilter: nft_dynset: fix timeout updates on 32bit (2018-05-07 00:05:22 +0200)
----------------------------------------------------------------
Ahmed Abdelsalam (1):
netfilter: ip6t_srh: extend SRH matching for previous, next and last SID
Arvind Yadav (1):
netfilter: ipvs: Fix space before '[' error.
Cong Wang (2):
ipvs: initialize tbl->entries after allocation
ipvs: initialize tbl->entries in ip_vs_lblc_init_svc()Felix Fietkau (19):
netfilter: nf_flow_table: use IP_CT_DIR_* values for FLOW_OFFLOAD_DIR_*
netfilter: nf_flow_table: clean up flow_offload_alloc
ipv6: make ip6_dst_mtu_forward inline
netfilter: nf_flow_table: cache mtu in struct flow_offload_tuple
netfilter: nf_flow_table: rename nf_flow_table.c to nf_flow_table_core.c
netfilter: nf_flow_table: move ipv4 offload hook code to nf_flow_table
netfilter: nf_flow_table: move ip header check out of nf_flow_exceeds_mtu
netfilter: nf_flow_table: move ipv6 offload hook code to nf_flow_table
netfilter: nf_flow_table: relax mixed ipv4/ipv6 flowtable dependencies
netfilter: nf_flow_table: move init code to nf_flow_table_core.c
netfilter: nf_flow_table: fix priv pointer for netdev hook
netfilter: nf_flow_table: track flow tables in nf_flow_table directly
netfilter: nf_flow_table: make flow_offload_dead inline
netfilter: nf_flow_table: add a new flow state for tearing down offloading
netfilter: nf_flow_table: in flow_offload_lookup, skip entries being deleted
netfilter: nf_flow_table: add support for sending flows back to the slow path
netfilter: nf_flow_table: tear down TCP flows if RST or FIN was seen
netfilter: nf_flow_table: add missing condition for TCP state check
netfilter: nf_flow_table: fix offloading connections with SNAT+DNAT
Fernando Fernandez Mancera (1):
netfilter: extract Passive OS fingerprint infrastructure from xt_osf
Florent Fourcot (1):
netfilter: ctnetlink: export nf_conntrack_max
Florian Westphal (8):
netfilter: nf_tables: support timeouts larger than 23 days
netfilter: nf_tables: always use an upper set size for dynsets
netfilter: merge meta_bridge into nft_meta
netfilter: nf_tables: make meta expression builtin
netfilter: nf_tables: merge rt expression into nft core
netfilter: nf_tables: merge exthdr expression into nft core
netfilter: nf_nat: remove unused ct arg from lookup functions
netfilter: nft_dynset: fix timeout updates on 32bit
Inju Song (3):
netfilter: ipvs: Keep latest weight of destination
netfilter: ipvs: Add Maglev hashing scheduler
netfilter: ipvs: Add configurations of Maglev hashing
Laura Garcia Liebana (2):
netfilter: nft_numgen: add map lookups for numgen statements
netfilter: nft_numgen: enable hashing of one element
Pablo Neira Ayuso (3):
netfilter: nf_tables: simplify lookup functions
netfilter: nf_tables: initial support for extended ACK reporting Merge tag 'ipvs-for-v4.18' of http://git.kernel.org/.../horms/ipvs-next
Phil Sutter (2):
netfilter: nf_tables: Simplify set backend selection
netfilter: nf_tables: Provide NFT_{RT,CT}_MAX for userspace
Taehee Yoo (7):
netfilter: xt_NFLOG: use nf_log_packet instead of nfulnl_log_packet.
netfilter: add __exit mark to helper modules
netfilter: ebtables: add ebt_free_table_info function
netfilter: ebtables: remove EBT_MATCH and EBT_NOMATCH
netfilter: x_tables: remove duplicate ip6t_get_target function call
netfilter: ebtables: add ebt_get_target and ebt_get_target_c
netfilter: xtables: use ipt_get_target_c instead of ipt_get_target
Thierry Du Tre (1):
netfilter: add NAT support for shifted portmap ranges
Vincent Bernat (1):
ipvs: fix multiplicative hashing in sh/dh/lblc/lblcr algorithms
include/linux/netfilter/nf_osf.h | 27 +
include/linux/netfilter_bridge/ebtables.h | 4 -
include/net/ip6_route.h | 21 +
include/net/ip_vs.h | 1 +
include/net/ipv6.h | 2 -
include/net/netfilter/ipv4/nf_nat_masquerade.h | 2 +-
include/net/netfilter/ipv6/nf_nat_masquerade.h | 2 +-
include/net/netfilter/nf_flow_table.h | 24 +-
include/net/netfilter/nf_nat.h | 2 +-
include/net/netfilter/nf_nat_l3proto.h | 28 +-
include/net/netfilter/nf_nat_l4proto.h | 8 +-
include/net/netfilter/nf_nat_redirect.h | 2 +-
include/net/netfilter/nf_tables.h | 53 +-
include/net/netfilter/nf_tables_core.h | 3 +
include/net/netfilter/nfnetlink_log.h | 17 -
include/net/netfilter/nft_meta.h | 44 --
include/uapi/linux/netfilter/nf_nat.h | 12 +-
include/uapi/linux/netfilter/nf_osf.h | 90 +++
include/uapi/linux/netfilter/nf_tables.h | 8 +
include/uapi/linux/netfilter/nfnetlink_conntrack.h | 1 +
include/uapi/linux/netfilter/xt_osf.h | 106 +---
include/uapi/linux/netfilter_bridge/ebtables.h | 6 +
include/uapi/linux/netfilter_ipv6/ip6t_srh.h | 43 +-
net/bridge/netfilter/Kconfig | 7 -
net/bridge/netfilter/Makefile | 1 -
net/bridge/netfilter/ebtables.c | 63 +--
net/bridge/netfilter/nft_meta_bridge.c | 135 -----
net/ipv4/netfilter/ip_tables.c | 2 +-
net/ipv4/netfilter/ipt_MASQUERADE.c | 2 +-
net/ipv4/netfilter/iptable_nat.c | 3 +-
net/ipv4/netfilter/nf_flow_table_ipv4.c | 255 +--------
net/ipv4/netfilter/nf_nat_h323.c | 4 +-
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 18 +-
net/ipv4/netfilter/nf_nat_masquerade_ipv4.c | 4 +-
net/ipv4/netfilter/nf_nat_pptp.c | 2 +-
net/ipv4/netfilter/nf_nat_proto_gre.c | 2 +-
net/ipv4/netfilter/nf_nat_proto_icmp.c | 2 +-
net/ipv4/netfilter/nft_chain_nat_ipv4.c | 3 +-
net/ipv4/netfilter/nft_masq_ipv4.c | 2 +-
net/ipv6/ip6_output.c | 22 -
net/ipv6/netfilter/ip6_tables.c | 1 -
net/ipv6/netfilter/ip6t_MASQUERADE.c | 2 +-
net/ipv6/netfilter/ip6t_srh.c | 173 +++++-
net/ipv6/netfilter/ip6table_nat.c | 3 +-
net/ipv6/netfilter/nf_flow_table_ipv6.c | 246 +-------
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 18 +-
net/ipv6/netfilter/nf_nat_masquerade_ipv6.c | 4 +-
net/ipv6/netfilter/nf_nat_proto_icmpv6.c | 2 +-
net/ipv6/netfilter/nft_chain_nat_ipv6.c | 3 +-
net/ipv6/netfilter/nft_masq_ipv6.c | 2 +-
net/ipv6/netfilter/nft_redir_ipv6.c | 2 +-
net/netfilter/Kconfig | 25 +-
net/netfilter/Makefile | 8 +-
net/netfilter/ipvs/Kconfig | 37 ++
net/netfilter/ipvs/Makefile | 1 +
net/netfilter/ipvs/ip_vs_ctl.c | 4 +
net/netfilter/ipvs/ip_vs_dh.c | 3 +-
net/netfilter/ipvs/ip_vs_lblc.c | 4 +-
net/netfilter/ipvs/ip_vs_lblcr.c | 4 +-
net/netfilter/ipvs/ip_vs_mh.c | 540 ++++++++++++++++++
net/netfilter/ipvs/ip_vs_proto_tcp.c | 4 +-
net/netfilter/ipvs/ip_vs_sh.c | 3 +-
net/netfilter/nf_conntrack_core.c | 1 +
net/netfilter/nf_conntrack_ftp.c | 3 +-
net/netfilter/nf_conntrack_irc.c | 6 +-
net/netfilter/nf_conntrack_netlink.c | 3 +
net/netfilter/nf_conntrack_sane.c | 3 +-
net/netfilter/nf_conntrack_sip.c | 2 +-
net/netfilter/nf_conntrack_tftp.c | 2 +-
.../{nf_flow_table.c => nf_flow_table_core.c} | 309 ++++++----
net/netfilter/nf_flow_table_inet.c | 3 +-
net/netfilter/nf_flow_table_ip.c | 487 ++++++++++++++++
net/netfilter/nf_nat_core.c | 27 +-
net/netfilter/nf_nat_helper.c | 2 +-
net/netfilter/nf_nat_proto_common.c | 9 +-
net/netfilter/nf_nat_proto_dccp.c | 2 +-
net/netfilter/nf_nat_proto_sctp.c | 2 +-
net/netfilter/nf_nat_proto_tcp.c | 2 +-
net/netfilter/nf_nat_proto_udp.c | 4 +-
net/netfilter/nf_nat_proto_unknown.c | 2 +-
net/netfilter/nf_nat_redirect.c | 6 +-
net/netfilter/nf_nat_sip.c | 2 +-
net/netfilter/nf_osf.c | 218 +++++++
net/netfilter/nf_tables_api.c | 624 +++++++++++----------
net/netfilter/nf_tables_core.c | 3 +
net/netfilter/nfnetlink_log.c | 8 +-
net/netfilter/nft_dynset.c | 7 +-
net/netfilter/nft_exthdr.c | 23 +-
net/netfilter/nft_flow_offload.c | 5 +-
net/netfilter/nft_hash.c | 2 +-
net/netfilter/nft_meta.c | 112 ++--
net/netfilter/nft_nat.c | 2 +-
net/netfilter/nft_numgen.c | 85 ++-
net/netfilter/nft_objref.c | 4 +-
net/netfilter/nft_rt.c | 22 +-
net/netfilter/nft_set_bitmap.c | 34 +-
net/netfilter/nft_set_hash.c | 153 ++---
net/netfilter/nft_set_rbtree.c | 36 +-
net/netfilter/xt_NETMAP.c | 8 +-
net/netfilter/xt_NFLOG.c | 15 +-
net/netfilter/xt_REDIRECT.c | 2 +-
net/netfilter/xt_nat.c | 72 ++-
net/netfilter/xt_osf.c | 202 +------
net/openvswitch/conntrack.c | 4 +-
104 files changed, 2753 insertions(+), 1887 deletions(-)
create mode 100644 include/linux/netfilter/nf_osf.h
delete mode 100644 include/net/netfilter/nft_meta.h
create mode 100644 include/uapi/linux/netfilter/nf_osf.h
delete mode 100644 net/bridge/netfilter/nft_meta_bridge.c
create mode 100644 net/netfilter/ipvs/ip_vs_mh.c
rename net/netfilter/{nf_flow_table.c => nf_flow_table_core.c} (67%)
create mode 100644 net/netfilter/nf_flow_table_ip.c
create mode 100644 net/netfilter/nf_osf.cPablo Neira Ayuso
maintainerPATCH 1/51 netfilter: ipvs: Fix space before '[' error.
From: Arvind Yadav <[email protected]>
Fix checkpatch.pl error:
ERROR: space prohibited before open square bracket '['.
--- net/netfilter/ipvs/ip_vs_proto_tcp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/netfilter/ipvs/ip_vs_proto_tcp.c +2 -2
@@ -436,7 +436,7 @@ static bool tcp_state_active(int state)return tcp_state_active_table[state]; } -static struct tcp_states_t tcp_states [] = { +static struct tcp_states_t tcp_states[] = {/* INPUT */ /* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA */ /*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR }},
@@ -459,7 +459,7 @@ static struct tcp_states_t tcp_states [] = { /*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sCL }}, }; -static struct tcp_states_t tcp_states_dos [] = { +static struct tcp_states_t tcp_states_dos[] = { /* INPUT */ /* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA */ /*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSA }},
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 2/51 netfilter: ipvs: Keep latest weight of destination
In reply to Pablo Neira AyusoFrom: Inju Song <[email protected]>
The hashing table in scheduler such as source hash or maglev hash should ignore the changed weight to 0 and allow changing the weight from/to non-0 values. So, struct ip_vs_dest needs to keep weight with latest non-0 weight.
--- include/net/ip_vs.h | 1 + net/netfilter/ipvs/ip_vs_ctl.c | 4 ++++ 2 files changed, 5 insertions(+)
include/net/ip_vs.h +1 -0
@@ -668,6 +668,7 @@ struct ip_vs_dest {volatile unsigned int flags;/* dest status flags */ atomic_t conn_flags;/* flags to copy to conn */ atomic_t weight;/* server weight */ +atomic_t last_weight;/* server latest weight */ refcount_t refcnt;/* reference counter */ struct ip_vs_stats stats;/* statistics */
net/netfilter/ipvs/ip_vs_ctl.c +4 -0
@@ -821,6 +821,10 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,if (add && udest->af != svc->af) ipvs->mixed_address_family_dests++; +/* keep the last_weight with latest non-0 weight */ +if (add || udest->weight !=0 ) +atomic_set (&dest->last_weight, udest->weight); +/* set the weight and the flags */ atomic_set (&dest->weight, udest->weight); conn_flags = udest->conn_flags &IP_VS_CONN_F_DEST_MASK ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 3/51 netfilter: ipvs: Add Maglev hashing scheduler
In reply to Pablo Neira AyusoFrom: Inju Song <[email protected]>
Implements the Google's Maglev hashing algorithm as a IPVS scheduler.
Basically it provides consistent hashing but offers some special features about disruption and load balancing.
1) minimal disruption: when the set of destinations changes,
a connection will likely be sent to the same destination as it was before.
2) load balancing: each destination will receive an almost
equal number of connections.
Seel also for detail: [3.4 Consistent Hasing] in
https://www.usenix.org/system/files/conference/nsdi16/nsdi16-paper-eisenbud.pdf
--- net/netfilter/ipvs/ip_vs_mh.c | 540 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 540 insertions(+) create mode 100644 net/netfilter/ipvs/ip_vs_mh.c
net/netfilter/ipvs/ip_vs_mh.c new file +540 -0
@@ -0,0 +1,540 @@ +// SPDX-License-Identifier: GPL-2.0 +/* IPVS: Maglev Hashing scheduling module +* +* Authors: Inju Song <[email protected]> +* +*/ + +/* The mh algorithm is to assign�a preference list of all the lookup +* table positions to each destination and populate the table with +* the most-preferred position of destinations. Then it is to select +* destination with the hash key of source IP address�through looking +* up a the lookup table. +* +* The algorithm is detailed in: +* [3.4 Consistent Hasing] +https://www.usenix.org/system/files/conference/nsdi16/nsdi16-paper-eisenbud.pdf +* +*/ + +#define KMSG_COMPONENT "IPVS" +#define pr_fmt (fmt) KMSG_COMPONENT ": " fmt + +#include <linux/ip.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/skbuff.h> + +#include <net/ip_vs.h> + +#include <linux/siphash.h> +#include <linux/bitops.h> +#include <linux/gcd.h> + +#define IP_VS_SVC_F_SCHED_MH_FALLBACK IP_VS_SVC_F_SCHED1/* MH fallback */ +#define IP_VS_SVC_F_SCHED_MH_PORT IP_VS_SVC_F_SCHED2/* MH use port */ + +struct ip_vs_mh_lookup { +struct ip_vs_dest __rcu *dest;/* real server (cache) */ +}; + +struct ip_vs_mh_dest_setup { +unsigned int offset;/* starting offset */ +unsigned int skip;/* skip */ +unsigned int perm;/* next_offset */ +int turns;/* weight / gcd() and rshift */ +}; + +/* Available prime numbers for MH table */ +static int primes[] = {251 ,509 ,1021 ,2039 ,4093 , +8191 ,16381 ,32749 ,65521 ,131071 }; + +/* For IPVS MH entry hash table */ +#ifndef CONFIG_IP_VS_MH_TAB_INDEX +#define CONFIG_IP_VS_MH_TAB_INDEX 12 +#endif +#define IP_VS_MH_TAB_BITS (CONFIG_IP_VS_MH_TAB_INDEX / 2) +#define IP_VS_MH_TAB_INDEX (CONFIG_IP_VS_MH_TAB_INDEX - 8) +#define IP_VS_MH_TAB_SIZE primes[IP_VS_MH_TAB_INDEX] + +struct ip_vs_mh_state { +struct rcu_head rcu_head; +struct ip_vs_mh_lookup *lookup; +struct ip_vs_mh_dest_setup *dest_setup; +hsiphash_key_t hash1, hash2; +int gcd; +int rshift; +}; + +static inline void generate_hash_secret (hsiphash_key_t *hash1, +hsiphash_key_t *hash2) +{ + hash1->key[0 ] =2654435761UL ; + hash1->key[1 ] =2654435761UL ; + + hash2->key[0 ] =2654446892UL ; + hash2->key[1 ] =2654446892UL ; +} + +/* Helper function to determine if server is unavailable */ +static inline bool is_unavailable (struct ip_vs_dest *dest) +{ +return atomic_read (&dest->weight) <=0 || + dest->flags &IP_VS_DEST_F_OVERLOAD ; +} + +/* Returns hash value for IPVS MH entry */ +static inline unsigned int +ip_vs_mh_hashkey (int af,const union nf_inet_addr *addr, +__be16 port,hsiphash_key_t *key,unsigned int offset) +{ +unsigned int v; +__be32 addr_fold = addr->ip; + +#ifdef CONFIG_IP_VS_IPV6 +if (af ==AF_INET6 ) + addr_fold = addr->ip6[0 ] ^ addr->ip6[1 ] ^ + addr->ip6[2 ] ^ addr->ip6[3 ]; +#endif + v = (offset +ntohs (port) +ntohl (addr_fold)); +return hsiphash (&v,sizeof (v), key); +} + +/* Reset all the hash buckets of the specified table. */ +static void ip_vs_mh_reset (struct ip_vs_mh_state *s) +{ +int i; +struct ip_vs_mh_lookup *l; +struct ip_vs_dest *dest; + + l = &s->lookup[0 ]; +for (i =0 ; i <IP_VS_MH_TAB_SIZE ; i++) { + dest =rcu_dereference_protected (l->dest,1 ); +if (dest) { +ip_vs_dest_put (dest); +RCU_INIT_POINTER (l->dest,NULL ); + } + l++; + } +} + +static int ip_vs_mh_permutate (struct ip_vs_mh_state *s, +struct ip_vs_service *svc) +{ +struct list_head *p; +struct ip_vs_mh_dest_setup *ds; +struct ip_vs_dest *dest; +int lw; + +/* If gcd is smaller then 1, number of dests or +* all last_weight of dests are zero. So, skip +* permutation for the dests. +*/ +if (s->gcd <1 ) +return 0 ; + +/* Set dest_setup for the dests permutation */ + p = &svc->destinations; + ds = &s->dest_setup[0 ]; +while ((p = p->next) != &svc->destinations) { + dest = list_entry(p, struct ip_vs_dest, n_list); + + ds->offset =ip_vs_mh_hashkey (svc->af, &dest->addr, + dest->port, &s->hash1,0 ) % +IP_VS_MH_TAB_SIZE ; + ds->skip =ip_vs_mh_hashkey (svc->af, &dest->addr, + dest->port, &s->hash2,0 ) % + (IP_VS_MH_TAB_SIZE -1 ) +1 ; + ds->perm = ds->offset; + + lw =atomic_read (&dest->last_weight); + ds->turns = ((lw / s->gcd) >> s->rshift) ? : (lw !=0 ); + ds++; + } + +return 0 ; +} + +static int ip_vs_mh_populate (struct ip_vs_mh_state *s, +struct ip_vs_service *svc) +{ +int n, c, dt_count; +unsigned long *table; +struct list_head *p; +struct ip_vs_mh_dest_setup *ds; +struct ip_vs_dest *dest, *new_dest; + +/* If gcd is smaller then 1, number of dests or +* all last_weight of dests are zero. So, skip +* the population for the dests and reset lookup table. +*/ +if (s->gcd <1 ) { +ip_vs_mh_reset (s); +return 0 ; + } + + table =kcalloc (BITS_TO_LONGS (IP_VS_MH_TAB_SIZE ), +sizeof (unsigned long ),GFP_KERNEL ); +if (!table) +return -ENOMEM ; + + p = &svc->destinations; + n =0 ; + dt_count =0 ; +while (n <IP_VS_MH_TAB_SIZE ) { +if (p == &svc->destinations) + p = p->next; + + ds = &s->dest_setup[0 ]; +while (p != &svc->destinations) { +/* Ignore added server with zero weight */ +if (ds->turns <1 ) { + p = p->next; + ds++; +continue ; + } + + c = ds->perm; +while (test_bit (c, table)) { +/* Add skip, mod IP_VS_MH_TAB_SIZE */ + ds->perm += ds->skip; +if (ds->perm >=IP_VS_MH_TAB_SIZE ) + ds->perm -=IP_VS_MH_TAB_SIZE ; + c = ds->perm; + } + +__set_bit (c, table); + + dest =rcu_dereference_protected (s->lookup[c].dest,1 ); + new_dest = list_entry(p, struct ip_vs_dest, n_list); +if (dest != new_dest) { +if (dest) +ip_vs_dest_put (dest); +ip_vs_dest_hold (new_dest); +RCU_INIT_POINTER (s->lookup[c].dest, new_dest); + } + +if (++n ==IP_VS_MH_TAB_SIZE ) + goto out; + +if (++dt_count >= ds->turns) { + dt_count =0 ; + p = p->next; + ds++; + } + } + } + +out: +kfree (table); +return 0 ; +} + +/* Get ip_vs_dest associated with supplied parameters. */ +static inline struct ip_vs_dest * +ip_vs_mh_get (struct ip_vs_service *svc,struct ip_vs_mh_state *s, +const union nf_inet_addr *addr,__be16 port) +{ +unsigned int hash =ip_vs_mh_hashkey (svc->af, addr, port, &s->hash1,0 ) + %IP_VS_MH_TAB_SIZE ; +struct ip_vs_dest *dest =rcu_dereference (s->lookup[hash].dest); + +return (!dest ||is_unavailable (dest)) ?NULL : dest; +} + +/* As ip_vs_mh_get, but with fallback if selected server is unavailable */ +static inline struct ip_vs_dest * +ip_vs_mh_get_fallback (struct ip_vs_service *svc,struct ip_vs_mh_state *s, +const union nf_inet_addr *addr,__be16 port) +{ +unsigned int offset, roffset; +unsigned int hash, ihash; +struct ip_vs_dest *dest; + +/* First try the dest it's supposed to go to */ + ihash =ip_vs_mh_hashkey (svc->af, addr, port, + &s->hash1,0 ) %IP_VS_MH_TAB_SIZE ; + dest =rcu_dereference (s->lookup[ihash].dest); +if (!dest) +return NULL ; +if (!is_unavailable (dest)) +return dest; + +IP_VS_DBG_BUF (6 ,"MH: selected unavailable server %s:%u, reselecting" , +IP_VS_DBG_ADDR (dest->af, &dest->addr),ntohs (dest->port)); + +/* If the original dest is unavailable, loop around the table +* starting from ihash to find a new dest +*/ +for (offset =0 ; offset <IP_VS_MH_TAB_SIZE ; offset++) { + roffset = (offset + ihash) %IP_VS_MH_TAB_SIZE ; + hash =ip_vs_mh_hashkey (svc->af, addr, port, &s->hash1, + roffset) %IP_VS_MH_TAB_SIZE ; + dest =rcu_dereference (s->lookup[hash].dest); +if (!dest) +break ; +if (!is_unavailable (dest)) +return dest; +IP_VS_DBG_BUF (6 , +"MH: selected unavailable server %s:%u (offset %u), reselecting" , +IP_VS_DBG_ADDR (dest->af, &dest->addr), +ntohs (dest->port), roffset); + } + +return NULL ; +} + +/* Assign all the hash buckets of the specified table with the service. */ +static int ip_vs_mh_reassign (struct ip_vs_mh_state *s, +struct ip_vs_service *svc) +{ +int ret; + +if (svc->num_dests >IP_VS_MH_TAB_SIZE ) +return -EINVAL ; + +if (svc->num_dests >=1 ) { + s->dest_setup =kcalloc (svc->num_dests, +sizeof (struct ip_vs_mh_dest_setup ), +GFP_KERNEL ); +if (!s->dest_setup) +return -ENOMEM ; + } + +ip_vs_mh_permutate (s, svc); + + ret =ip_vs_mh_populate (s, svc); +if (ret <0 ) + goto out; + +IP_VS_DBG_BUF (6 ,"MH: reassign lookup table of %s:%u\n" , +IP_VS_DBG_ADDR (svc->af, &svc->addr), +ntohs (svc->port)); + +out: +if (svc->num_dests >=1 ) { +kfree (s->dest_setup); + s->dest_setup =NULL ; + } +return ret; +} + +static int ip_vs_mh_gcd_weight (struct ip_vs_service *svc) +{ +struct ip_vs_dest *dest; +int weight; +int g =0 ; + +list_for_each_entry (dest, &svc->destinations, n_list) { + weight =atomic_read (&dest->last_weight); +if (weight >0 ) { +if (g >0 ) + g =gcd (weight, g); +else + g = weight; + } + } +return g; +} + +/* To avoid assigning huge weight for the MH table, +* calculate shift value with gcd. +*/ +static int ip_vs_mh_shift_weight (struct ip_vs_service *svc,int gcd) +{ +struct ip_vs_dest *dest; +int new_weight, weight =0 ; +int mw, shift; + +/* If gcd is smaller then 1, number of dests or +* all last_weight of dests are zero. So, return +* shift value as zero. +*/ +if (gcd <1 ) +return 0 ; + +list_for_each_entry (dest, &svc->destinations, n_list) { + new_weight =atomic_read (&dest->last_weight); +if (new_weight > weight) + weight = new_weight; + } + +/* Because gcd is greater than zero, +* the maximum weight and gcd are always greater than zero +*/ + mw = weight / gcd; + +/* shift = occupied bits of weight/gcd - MH highest bits */ + shift =fls (mw) -IP_VS_MH_TAB_BITS ; +return (shift >=0 ) ? shift :0 ; +} + +static void ip_vs_mh_state_free (struct rcu_head *head) +{ +struct ip_vs_mh_state *s; + + s = container_of(head, struct ip_vs_mh_state, rcu_head); +kfree (s->lookup); +kfree (s); +} + +static int ip_vs_mh_init_svc (struct ip_vs_service *svc) +{ +int ret; +struct ip_vs_mh_state *s; + +/* Allocate the MH table for this service */ + s =kzalloc (sizeof (*s),GFP_KERNEL ); +if (!s) +return -ENOMEM ; + + s->lookup =kcalloc (IP_VS_MH_TAB_SIZE ,sizeof (struct ip_vs_mh_lookup ), +GFP_KERNEL ); +if (!s->lookup) { +kfree (s); +return -ENOMEM ; + } + +generate_hash_secret (&s->hash1, &s->hash2); + s->gcd =ip_vs_mh_gcd_weight (svc); + s->rshift =ip_vs_mh_shift_weight (svc, s->gcd); + +IP_VS_DBG (6 , +"MH lookup table (memory=%zdbytes) allocated for current service\n" , +sizeof (struct ip_vs_mh_lookup ) *IP_VS_MH_TAB_SIZE ); + +/* Assign the lookup table with current dests */ + ret =ip_vs_mh_reassign (s, svc); +if (ret <0 ) { +ip_vs_mh_reset (s); +ip_vs_mh_state_free (&s->rcu_head); +return ret; + } + +/* No more failures, attach state */ + svc->sched_data = s; +return 0 ; +} + +static void ip_vs_mh_done_svc (struct ip_vs_service *svc) +{ +struct ip_vs_mh_state *s = svc->sched_data; + +/* Got to clean up lookup entry here */ +ip_vs_mh_reset (s); + +call_rcu (&s->rcu_head, ip_vs_mh_state_free); +IP_VS_DBG (6 ,"MH lookup table (memory=%zdbytes) released\n" , +sizeof (struct ip_vs_mh_lookup ) *IP_VS_MH_TAB_SIZE ); +} + +static int ip_vs_mh_dest_changed (struct ip_vs_service *svc, +struct ip_vs_dest *dest) +{ +struct ip_vs_mh_state *s = svc->sched_data; + + s->gcd =ip_vs_mh_gcd_weight (svc); + s->rshift =ip_vs_mh_shift_weight (svc, s->gcd); + +/* Assign the lookup table with the updated service */ +return ip_vs_mh_reassign (s, svc); +} + +/* Helper function to get port number */ +static inline __be16 +ip_vs_mh_get_port (const struct sk_buff *skb,struct ip_vs_iphdr *iph) +{ +__be16 _ports[2 ], *ports; + +/* At this point we know that we have a valid packet of some kind. +* Because ICMP packets are only guaranteed to have the first 8 +* bytes, let's just grab the ports. Fortunately they're in the +* same position for all three of the protocols we care about. +*/ +switch (iph->protocol) { +case IPPROTO_TCP : +case IPPROTO_UDP : +case IPPROTO_SCTP : + ports =skb_header_pointer (skb, iph->len,sizeof (_ports), + &_ports); +if (unlikely (!ports)) +return 0 ; + +if (likely (!ip_vs_iph_inverse (iph))) +return ports[0 ]; +else +return ports[1 ]; +default : +return 0 ; + } +} + +/* Maglev Hashing scheduling */ +static struct ip_vs_dest * +ip_vs_mh_schedule (struct ip_vs_service *svc,const struct sk_buff *skb, +struct ip_vs_iphdr *iph) +{ +struct ip_vs_dest *dest; +struct ip_vs_mh_state *s; +__be16 port =0 ; +const union nf_inet_addr *hash_addr; + + hash_addr =ip_vs_iph_inverse (iph) ? &iph->daddr : &iph->saddr; + +IP_VS_DBG (6 ,"%s : Scheduling...\n" , __func__); + +if (svc->flags &IP_VS_SVC_F_SCHED_MH_PORT ) + port =ip_vs_mh_get_port (skb, iph); + + s = (struct ip_vs_mh_state *)svc->sched_data; + +if (svc->flags &IP_VS_SVC_F_SCHED_MH_FALLBACK ) + dest =ip_vs_mh_get_fallback (svc, s, hash_addr, port); +else + dest =ip_vs_mh_get (svc, s, hash_addr, port); + +if (!dest) { +ip_vs_scheduler_err (svc,"no destination available" ); +return NULL ; + } + +IP_VS_DBG_BUF (6 ,"MH: source IP address %s:%u --> server %s:%u\n" , +IP_VS_DBG_ADDR (svc->af, hash_addr), +ntohs (port), +IP_VS_DBG_ADDR (dest->af, &dest->addr), +ntohs (dest->port)); + +return dest; +} + +/* IPVS MH Scheduler structure */ +static struct ip_vs_scheduler ip_vs_mh_scheduler = { + .name ="mh" , + .refcnt =ATOMIC_INIT (0 ), + .module =THIS_MODULE , + .n_list =LIST_HEAD_INIT (ip_vs_mh_scheduler.n_list), + .init_service = ip_vs_mh_init_svc, + .done_service = ip_vs_mh_done_svc, + .add_dest = ip_vs_mh_dest_changed, + .del_dest = ip_vs_mh_dest_changed, + .upd_dest = ip_vs_mh_dest_changed, + .schedule = ip_vs_mh_schedule, +}; + +static int __init ip_vs_mh_init (void ) +{ +return register_ip_vs_scheduler (&ip_vs_mh_scheduler); +} + +static void __exit ip_vs_mh_cleanup(void) +{ +unregister_ip_vs_scheduler (&ip_vs_mh_scheduler); +rcu_barrier (); +} + +module_init (ip_vs_mh_init); +module_exit (ip_vs_mh_cleanup); +MODULE_DESCRIPTION ("Maglev hashing ipvs scheduler" ); +MODULE_LICENSE ("GPL v2" ); +MODULE_AUTHOR ("Inju Song <[email protected]>" );
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 4/51 netfilter: ipvs: Add configurations of Maglev hashing
In reply to Pablo Neira AyusoFrom: Inju Song <[email protected]>
To build the maglev hashing scheduler, add some configuration to Kconfig and Makefile.
- The compile configurations of MH are added to the Kconfig.
- The MH build rule is added to the Makefile.
--- net/netfilter/ipvs/Kconfig | 37 +++++++++++++++++++++++++++++++++++++ net/netfilter/ipvs/Makefile | 1 + 2 files changed, 38 insertions(+)
net/netfilter/ipvs/Kconfig +37 -0
@@ -225,6 +225,25 @@ config IP_VS_SH If you want to compile it in kernel, say Y. To compile it as a module, choose M here. If unsure, say N. +config IP_VS_MH + tristate "maglev hashing scheduling" + ---help--- + The maglev consistent hashing scheduling algorithm provides the + Google's Maglev hashing algorithm as a IPVS scheduler. It assigns + network connections to the servers through looking up a statically + assigned special hash table called the lookup table. Maglev hashing + is to assign a preference list of all the lookup table positions + to each destination. + + Through this operation, The maglev hashing gives an almost equal + share of the lookup table to each of the destinations and provides + minimal disruption by using the lookup table. When the set of + destinations changes, a connection will likely be sent to the same + destination as it was before. + + If you want to compile it in kernel, say Y. To compile it as a + module, choose M here. If unsure, say N. + config IP_VS_SED tristate "shortest expected delay scheduling" ---help---
@@ -266,6 +285,24 @@ config IP_VS_SH_TAB_BITS needs to be large enough to effectively fit all the destinations multiplied by their respective weights. +comment 'IPVS MH scheduler' + +config IP_VS_MH_TAB_INDEX + int "IPVS maglev hashing table index of size (the prime numbers)" + range 8 17 + default 12 + ---help--- + The maglev hashing scheduler maps source IPs to destinations + stored in a hash table. This table is assigned by a preference + list of the positions to each destination until all slots in + the table are filled. The index determines the prime for size of + the table as�251, 509, 1021, 2039, 4093, 8191, 16381, 32749, + 65521 or 131071.�When using weights to allow destinations to + receive more connections,�the table is assigned an amount + proportional to the weights specified.�The table needs to be large + enough to effectively fit all the destinations multiplied by their + respective weights. + comment 'IPVS application helper' config IP_VS_FTP
net/netfilter/ipvs/Makefile +1 -0
@@ -33,6 +33,7 @@ obj-$(CONFIG_IP_VS_LBLC) += ip_vs_lblc.o obj-$(CONFIG_IP_VS_LBLCR) += ip_vs_lblcr.o obj-$(CONFIG_IP_VS_DH) += ip_vs_dh.o obj-$(CONFIG_IP_VS_SH) += ip_vs_sh.o +obj-$(CONFIG_IP_VS_MH) += ip_vs_mh.o obj-$(CONFIG_IP_VS_SED) += ip_vs_sed.o obj-$(CONFIG_IP_VS_NQ) += ip_vs_nq.o
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 5/51 ipvs: fix multiplicative hashing in sh/dh/lblc/lblcr algorithms
In reply to Pablo Neira AyusoFrom: Vincent Bernat <[email protected]>
The sh/dh/lblc/lblcr algorithms are using Knuth's multiplicative hashing incorrectly. Replace its use by the hash_32() macro, which correctly implements this algorithm. It doesn't use the same constant, but it shouldn't matter.
--- net/netfilter/ipvs/ip_vs_dh.c | 3 ++- net/netfilter/ipvs/ip_vs_lblc.c | 3 ++- net/netfilter/ipvs/ip_vs_lblcr.c | 3 ++- net/netfilter/ipvs/ip_vs_sh.c | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-)
net/netfilter/ipvs/ip_vs_dh.c +2 -1
@@ -43,6 +43,7 @@#include <linux/module.h> #include <linux/kernel.h> #include <linux/skbuff.h> +#include <linux/hash.h> #include <net/ip_vs.h>
@@ -81,7 +82,7 @@ static inline unsigned int ip_vs_dh_hashkey(int af, const union nf_inet_addr *ad addr_fold = addr->ip6[0 ]^addr->ip6[1 ]^ addr->ip6[2 ]^addr->ip6[3 ];#endif -return (ntohl (addr_fold)*2654435761UL ) &IP_VS_DH_TAB_MASK ; +return hash_32 (ntohl (addr_fold),IP_VS_DH_TAB_BITS ); }
net/netfilter/ipvs/ip_vs_lblc.c +2 -1
@@ -48,6 +48,7 @@#include <linux/kernel.h> #include <linux/skbuff.h> #include <linux/jiffies.h> +#include <linux/hash.h> /* for sysctl */ #include <linux/fs.h>
@@ -160,7 +161,7 @@ ip_vs_lblc_hashkey(int af, const union nf_inet_addr *addr) addr_fold = addr->ip6[0 ]^addr->ip6[1 ]^ addr->ip6[2 ]^addr->ip6[3 ];#endif -return (ntohl (addr_fold)*2654435761UL ) &IP_VS_LBLC_TAB_MASK ; +return hash_32 (ntohl (addr_fold),IP_VS_LBLC_TAB_BITS ); }
net/netfilter/ipvs/ip_vs_lblcr.c +2 -1
@@ -47,6 +47,7 @@#include <linux/jiffies.h> #include <linux/list.h> #include <linux/slab.h> +#include <linux/hash.h> /* for sysctl */ #include <linux/fs.h>
@@ -323,7 +324,7 @@ ip_vs_lblcr_hashkey(int af, const union nf_inet_addr *addr) addr_fold = addr->ip6[0 ]^addr->ip6[1 ]^ addr->ip6[2 ]^addr->ip6[3 ];#endif -return (ntohl (addr_fold)*2654435761UL ) &IP_VS_LBLCR_TAB_MASK ; +return hash_32 (ntohl (addr_fold),IP_VS_LBLCR_TAB_BITS ); }
net/netfilter/ipvs/ip_vs_sh.c +2 -1
@@ -96,7 +96,8 @@ ip_vs_sh_hashkey(int af, const union nf_inet_addr *addr, addr_fold = addr->ip6[0 ]^addr->ip6[1 ]^ addr->ip6[2 ]^addr->ip6[3 ];#endif -return (offset + (ntohs (port) +ntohl (addr_fold))*2654435761UL ) & +return (offset +hash_32 (ntohs (port) +ntohl (addr_fold), +IP_VS_SH_TAB_BITS )) &IP_VS_SH_TAB_MASK ; }
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 6/51 netfilter: xt_NFLOG: use nf_log_packet instead of nfulnl_log_packet.
In reply to Pablo Neira AyusoFrom: Taehee Yoo <[email protected]>
The nfulnl_log_packet() is added to make sure that the NFLOG target works as only user-space logger. but now, nf_log_packet() can find proper log function using NF_LOG_TYPE_ULOG and NF_LOG_TYPE_LOG.
--- include/net/netfilter/nfnetlink_log.h | 17 ----------------- net/netfilter/nfnetlink_log.c | 8 +++----- net/netfilter/xt_NFLOG.c | 15 +++++++++++---- 3 files changed, 14 insertions(+), 26 deletions(-)
include/net/netfilter/nfnetlink_log.h +0 -17
@@ -1,18 +1 @@/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _KER_NFNETLINK_LOG_H -#define _KER_NFNETLINK_LOG_H - -void -nfulnl_log_packet (struct net *net, -u_int8_t pf, -unsigned int hooknum, -const struct sk_buff *skb, -const struct net_device *in, -const struct net_device *out, -const struct nf_loginfo *li_user, -const char *prefix); - -#define NFULNL_COPY_DISABLED 0xff - -#endif /* _KER_NFNETLINK_LOG_H */ -
net/netfilter/nfnetlink_log.c +3 -5
@@ -37,7 +37,6 @@#include <net/sock.h> #include <net/netfilter/nf_log.h> #include <net/netns/generic.h> -#include <net/netfilter/nfnetlink_log.h> #include <linux/atomic.h> #include <linux/refcount.h>
@@ -47,6 +46,7 @@#include "../bridge/br_private.h" #endif +#define NFULNL_COPY_DISABLED 0xff#define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE#define NFULNL_TIMEOUT_DEFAULT 100/* every second */ #define NFULNL_QTHRESH_DEFAULT 100/* 100 packets */
@@ -618,7 +618,7 @@ static const struct nf_loginfo default_loginfo = { };/* log handler for internal netfilter logging api */ -void +static void nfulnl_log_packet(struct net *net, u_int8_t pf, unsigned int hooknum,
@@ -633,7 +633,7 @@ nfulnl_log_packet(struct net *net,struct nfulnl_instance *inst;const struct nf_loginfo *li;unsigned int qthreshold; -unsigned int plen; +unsigned int plen =0 ;struct nfnl_log_net *log =nfnl_log_pernet (net);const struct nfnl_ct_hook *nfnl_ct =NULL ;struct nf_conn *ct =NULL ;
@@ -648,7 +648,6 @@ nfulnl_log_packet(struct net *net,if (!inst)return ; - plen =0 ;if (prefix) plen =strlen (prefix) +1 ;
@@ -760,7 +759,6 @@ nfulnl_log_packet(struct net *net,/* FIXME: statistics */ goto unlock_and_release; } -EXPORT_SYMBOL_GPL (nfulnl_log_packet); static int nfulnl_rcv_nl_event(struct notifier_block *this,
net/netfilter/xt_NFLOG.c +11 -4
@@ -13,7 +13,6 @@#include <linux/netfilter/x_tables.h> #include <linux/netfilter/xt_NFLOG.h> #include <net/netfilter/nf_log.h> -#include <net/netfilter/nfnetlink_log.h> MODULE_AUTHOR ("Patrick McHardy <[email protected]>" );MODULE_DESCRIPTION ("Xtables: packet logging to netlink using NFLOG" );
@@ -37,8 +36,9 @@ nflog_tg(struct sk_buff *skb, const struct xt_action_param *par)if (info->flags &XT_NFLOG_F_COPY_LEN ) li.u.ulog.flags |=NF_LOG_F_COPY_LEN ; -nfulnl_log_packet (net,xt_family (par),xt_hooknum (par), skb, -xt_in (par),xt_out (par), &li, info->prefix); +nf_log_packet (net,xt_family (par),xt_hooknum (par), skb,xt_in (par), +xt_out (par), &li,"%s" , info->prefix); +return XT_CONTINUE ; }
@@ -50,7 +50,13 @@ static int nflog_tg_check(const struct xt_tgchk_param *par)return -EINVAL ;if (info->prefix[sizeof (info->prefix) -1 ] !='\0' )return -EINVAL ; -return 0 ; + +return nf_logger_find_get (par->family,NF_LOG_TYPE_ULOG ); +} + +static void nflog_tg_destroy (const struct xt_tgdtor_param *par) +{ +nf_logger_put (par->family,NF_LOG_TYPE_ULOG ); }static struct xt_target nflog_tg_reg__read_mostly = {
@@ -58,6 +64,7 @@ static struct xt_target nflog_tg_reg __read_mostly = { .revision = 0, .family = NFPROTO_UNSPEC, .checkentry = nflog_tg_check, + .destroy = nflog_tg_destroy, .target = nflog_tg, .targetsize = sizeof(struct xt_nflog_info), .me = THIS_MODULE,
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 7/51 netfilter: nf_flow_table: use IP_CT_DIR_* values for FLOW_OFFLOAD_DIR_*
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
Simplifies further code cleanups
--- include/net/netfilter/nf_flow_table.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
include/net/netfilter/nf_flow_table.h +4 -4
@@ -6,6 +6,7 @@#include <linux/netdevice.h> #include <linux/rhashtable.h> #include <linux/rcupdate.h> +#include <linux/netfilter/nf_conntrack_tuple_common.h> #include <net/dst.h> struct nf_flowtable ;
@@ -27,11 +28,10 @@ struct nf_flowtable { };enum flow_offload_tuple_dir { -FLOW_OFFLOAD_DIR_ORIGINAL , -FLOW_OFFLOAD_DIR_REPLY , - __FLOW_OFFLOAD_DIR_MAX =FLOW_OFFLOAD_DIR_REPLY , +FLOW_OFFLOAD_DIR_ORIGINAL =IP_CT_DIR_ORIGINAL , +FLOW_OFFLOAD_DIR_REPLY =IP_CT_DIR_REPLY , +FLOW_OFFLOAD_DIR_MAX =IP_CT_DIR_MAX }; -#define FLOW_OFFLOAD_DIR_MAX (__FLOW_OFFLOAD_DIR_MAX + 1) struct flow_offload_tuple { union {
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 8/51 netfilter: nf_flow_table: clean up flow_offload_alloc
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
Reduce code duplication and make it much easier to read
--- net/netfilter/nf_flow_table.c | 93 ++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 59 deletions(-)
net/netfilter/nf_flow_table.c +34 -59
@@ -16,6 +16,38 @@ struct flow_offload_entry {struct rcu_head rcu_head; }; +static void +flow_offload_fill_dir (struct flow_offload *flow,struct nf_conn *ct, +struct nf_flow_route *route, +enum flow_offload_tuple_dir dir) +{ +struct flow_offload_tuple *ft = &flow->tuplehash[dir].tuple; +struct nf_conntrack_tuple *ctt = &ct->tuplehash[dir].tuple; + + ft->dir = dir; + +switch (ctt->src.l3num) { +case NFPROTO_IPV4 : + ft->src_v4 = ctt->src.u3.in; + ft->dst_v4 = ctt->dst.u3.in; +break ; +case NFPROTO_IPV6 : + ft->src_v6 = ctt->src.u3.in6; + ft->dst_v6 = ctt->dst.u3.in6; +break ; + } + + ft->l3proto = ctt->src.l3num; + ft->l4proto = ctt->dst.protonum; + ft->src_port = ctt->src.u.tcp.port; + ft->dst_port = ctt->dst.u.tcp.port; + + ft->iifidx = route->tuple[dir].ifindex; + ft->oifidx = route->tuple[!dir].ifindex; + + ft->dst_cache = route->tuple[dir].dst; +} +struct flow_offload *flow_offload_alloc (struct nf_conn *ct,struct nf_flow_route *route) {
@@ -40,65 +72,8 @@ flow_offload_alloc(struct nf_conn *ct, struct nf_flow_route *route) entry->ct = ct; -switch (ct->tuplehash[IP_CT_DIR_ORIGINAL ].tuple.src.l3num) { -case NFPROTO_IPV4 : - flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL ].tuple.src_v4 = - ct->tuplehash[IP_CT_DIR_ORIGINAL ].tuple.src.u3.in; - flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL ].tuple.dst_v4 = - ct->tuplehash[IP_CT_DIR_ORIGINAL ].tuple.dst.u3.in; - flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY ].tuple.src_v4 = - ct->tuplehash[IP_CT_DIR_REPLY ].tuple.src.u3.in; - flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY ].tuple.dst_v4 = - ct->tuplehash[IP_CT_DIR_REPLY ].tuple.dst.u3.in; -break ; -case NFPROTO_IPV6 : - flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL ].tuple.src_v6 = - ct->tuplehash[IP_CT_DIR_ORIGINAL ].tuple.src.u3.in6; - flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL ].tuple.dst_v6 = - ct->tuplehash[IP_CT_DIR_ORIGINAL ].tuple.dst.u3.in6; - flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY ].tuple.src_v6 = - ct->tuplehash[IP_CT_DIR_REPLY ].tuple.src.u3.in6; - flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY ].tuple.dst_v6 = - ct->tuplehash[IP_CT_DIR_REPLY ].tuple.dst.u3.in6; -break ; - } - - flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL ].tuple.l3proto = - ct->tuplehash[IP_CT_DIR_ORIGINAL ].tuple.src.l3num; - flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL ].tuple.l4proto = - ct->tuplehash[IP_CT_DIR_ORIGINAL ].tuple.dst.protonum; - flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY ].tuple.l3proto = - ct->tuplehash[IP_CT_DIR_ORIGINAL ].tuple.src.l3num; - flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY ].tuple.l4proto = - ct->tuplehash[IP_CT_DIR_ORIGINAL ].tuple.dst.protonum; - - flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL ].tuple.dst_cache = - route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL ].dst; - flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY ].tuple.dst_cache = - route->tuple[FLOW_OFFLOAD_DIR_REPLY ].dst; - - flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL ].tuple.src_port = - ct->tuplehash[IP_CT_DIR_ORIGINAL ].tuple.src.u.tcp.port; - flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL ].tuple.dst_port = - ct->tuplehash[IP_CT_DIR_ORIGINAL ].tuple.dst.u.tcp.port; - flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY ].tuple.src_port = - ct->tuplehash[IP_CT_DIR_REPLY ].tuple.src.u.tcp.port; - flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY ].tuple.dst_port = - ct->tuplehash[IP_CT_DIR_REPLY ].tuple.dst.u.tcp.port; - - flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL ].tuple.dir = -FLOW_OFFLOAD_DIR_ORIGINAL ; - flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY ].tuple.dir = -FLOW_OFFLOAD_DIR_REPLY ; - - flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL ].tuple.iifidx = - route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL ].ifindex; - flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL ].tuple.oifidx = - route->tuple[FLOW_OFFLOAD_DIR_REPLY ].ifindex; - flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY ].tuple.iifidx = - route->tuple[FLOW_OFFLOAD_DIR_REPLY ].ifindex; - flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY ].tuple.oifidx = - route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL ].ifindex; +flow_offload_fill_dir (flow, ct, route,FLOW_OFFLOAD_DIR_ORIGINAL ); +flow_offload_fill_dir (flow, ct, route,FLOW_OFFLOAD_DIR_REPLY );if (ct->status &IPS_SRC_NAT ) flow->flags |=FLOW_OFFLOAD_SNAT ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 9/51 ipv6: make ip6_dst_mtu_forward inline
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
Just like ip_dst_mtu_maybe_forward(), to avoid a dependency with ipv6.ko.
--- include/net/ip6_route.h | 21 +++++++++++++++++++++ include/net/ipv6.h | 2 -- net/ipv6/ip6_output.c | 22 ---------------------- 3 files changed, 21 insertions(+), 24 deletions(-)
include/net/ip6_route.h +21 -0
@@ -279,6 +279,27 @@ static inline bool rt6_duplicate_nexthop(struct fib6_info *a, struct fib6_info * !lwtunnel_cmp_encap (a->fib6_nh.nh_lwtstate, b->fib6_nh.nh_lwtstate); } +static inline unsigned int ip6_dst_mtu_forward (const struct dst_entry *dst) +{ +struct inet6_dev *idev; +unsigned int mtu; + +if (dst_metric_locked (dst,RTAX_MTU )) { + mtu =dst_metric_raw (dst,RTAX_MTU ); +if (mtu) +return mtu; + } + + mtu =IPV6_MIN_MTU ; +rcu_read_lock (); + idev =__in6_dev_get (dst->dev); +if (idev) + mtu = idev->cnf.mtu6; +rcu_read_unlock (); + +return mtu; +} +struct neighbour *ip6_neigh_lookup (const struct in6_addr *gw,struct net_device *dev,struct sk_buff *skb,const void *daddr);
include/net/ipv6.h +0 -2
@@ -958,8 +958,6 @@ static inline struct sk_buff *ip6_finish_skb(struct sock *sk) &inet6_sk(sk)->cork); } -unsigned int ip6_dst_mtu_forward (const struct dst_entry *dst); -int ip6_dst_lookup (struct net *net,struct sock *sk,struct dst_entry **dst,struct flowi6 *fl6); struct dst_entry *ip6_dst_lookup_flow(const struct sock *sk, struct flowi6 *fl6,
net/ipv6/ip6_output.c +0 -22
@@ -383,28 +383,6 @@ static inline int ip6_forward_finish(struct net *net, struct sock *sk,return dst_output (net, sk, skb); } -unsigned int ip6_dst_mtu_forward (const struct dst_entry *dst) -{ -unsigned int mtu; -struct inet6_dev *idev; - -if (dst_metric_locked (dst,RTAX_MTU )) { - mtu =dst_metric_raw (dst,RTAX_MTU ); -if (mtu) -return mtu; - } - - mtu =IPV6_MIN_MTU ; -rcu_read_lock (); - idev =__in6_dev_get (dst->dev); -if (idev) - mtu = idev->cnf.mtu6; -rcu_read_unlock (); - -return mtu; -} -EXPORT_SYMBOL_GPL (ip6_dst_mtu_forward); -static bool ip6_pkt_too_big (const struct sk_buff *skb,unsigned int mtu) {if (skb->len <= mtu)
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 10/51 netfilter: nf_flow_table: cache mtu in struct flow_offload_tuple
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
Reduces the number of cache lines touched in the offload forwarding path. This is safe because PMTU limits are bypassed for the forwarding path (see commit f87c10a8aa1e for more details).
--- include/net/netfilter/nf_flow_table.h | 2 ++ net/ipv4/netfilter/nf_flow_table_ipv4.c | 17 +++-------------- net/ipv6/netfilter/nf_flow_table_ipv6.c | 17 +++-------------- net/netfilter/nf_flow_table.c | 8 ++++++-- 4 files changed, 14 insertions(+), 30 deletions(-)
include/net/netfilter/nf_flow_table.h +2 -0
@@ -55,6 +55,8 @@ struct flow_offload_tuple {int oifidx; +u16 mtu; +struct dst_entry *dst_cache; };
net/ipv4/netfilter/nf_flow_table_ipv4.c +3 -14
@@ -178,7 +178,7 @@ static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev, }/* Based on ip_exceeds_mtu(). */ -static bool __nf_flow_exceeds_mtu (const struct sk_buff *skb,unsigned int mtu) +static bool nf_flow_exceeds_mtu (const struct sk_buff *skb,unsigned int mtu) {if (skb->len <= mtu)return false;
@@ -192,17 +192,6 @@ static bool __nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)return true; } -static bool nf_flow_exceeds_mtu (struct sk_buff *skb,const struct rtable *rt) -{ -u32 mtu; - - mtu =ip_dst_mtu_maybe_forward (&rt->dst, true); -if (__nf_flow_exceeds_mtu (skb, mtu)) -return true; - -return false; -} -unsigned int nf_flow_offload_ip_hook (void *priv,struct sk_buff *skb,const struct nf_hook_state *state)
@@ -233,9 +222,9 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, dir = tuplehash->tuple.dir; flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); - rt = (const struct rtable *)flow->tuplehash[dir].tuple.dst_cache; -if (unlikely (nf_flow_exceeds_mtu (skb, rt))) + +if (unlikely (nf_flow_exceeds_mtu (skb, flow->tuplehash[dir].tuple.mtu)))return NF_ACCEPT ;if (skb_try_make_writable (skb,sizeof (*iph)))
net/ipv6/netfilter/nf_flow_table_ipv6.c +3 -14
@@ -173,7 +173,7 @@ static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev, }/* Based on ip_exceeds_mtu(). */ -static bool __nf_flow_exceeds_mtu (const struct sk_buff *skb,unsigned int mtu) +static bool nf_flow_exceeds_mtu (const struct sk_buff *skb,unsigned int mtu) {if (skb->len <= mtu)return false;
@@ -184,17 +184,6 @@ static bool __nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)return true; } -static bool nf_flow_exceeds_mtu (struct sk_buff *skb,const struct rt6_info *rt) -{ -u32 mtu; - - mtu =ip6_dst_mtu_forward (&rt->dst); -if (__nf_flow_exceeds_mtu (skb, mtu)) -return true; - -return false; -} -unsigned int nf_flow_offload_ipv6_hook (void *priv,struct sk_buff *skb,const struct nf_hook_state *state)
@@ -225,9 +214,9 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, dir = tuplehash->tuple.dir; flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); - rt = (struct rt6_info *)flow->tuplehash[dir].tuple.dst_cache; -if (unlikely (nf_flow_exceeds_mtu (skb, rt))) + +if (unlikely (nf_flow_exceeds_mtu (skb, flow->tuplehash[dir].tuple.mtu)))return NF_ACCEPT ;if (skb_try_make_writable (skb,sizeof (*ip6h)))
net/netfilter/nf_flow_table.c +6 -2
@@ -4,6 +4,8 @@#include <linux/netfilter.h> #include <linux/rhashtable.h> #include <linux/netdevice.h> +#include <net/ip.h> +#include <net/ip6_route.h> #include <net/netfilter/nf_tables.h> #include <net/netfilter/nf_flow_table.h> #include <net/netfilter/nf_conntrack.h>
@@ -23,6 +25,7 @@ flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct, {struct flow_offload_tuple *ft = &flow->tuplehash[dir].tuple;struct nf_conntrack_tuple *ctt = &ct->tuplehash[dir].tuple; +struct dst_entry *dst = route->tuple[dir].dst; ft->dir = dir;
@@ -30,10 +33,12 @@ flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct,case NFPROTO_IPV4 : ft->src_v4 = ctt->src.u3.in; ft->dst_v4 = ctt->dst.u3.in; + ft->mtu =ip_dst_mtu_maybe_forward (dst, true);break ;case NFPROTO_IPV6 : ft->src_v6 = ctt->src.u3.in6; ft->dst_v6 = ctt->dst.u3.in6; + ft->mtu =ip6_dst_mtu_forward (dst);break ; }
@@ -44,8 +49,7 @@ flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct, ft->iifidx = route->tuple[dir].ifindex; ft->oifidx = route->tuple[!dir].ifindex; - - ft->dst_cache = route->tuple[dir].dst; + ft->dst_cache = dst; } struct flow_offload *
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 11/51 netfilter: nf_flow_table: rename nf_flow_table.c to nf_flow_table_core.c
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
Preparation for adding more code to the same module
---
net/netfilter/Makefile | 2 ++
net/netfilter/{nf_flow_table.c => nf_flow_table_core.c} | 0
2 files changed, 2 insertions(+)
rename net/netfilter/{nf_flow_table.c => nf_flow_table_core.c} (100%)net/netfilter/Makefile +2 -0
@@ -111,6 +111,8 @@ obj-$(CONFIG_NFT_FWD_NETDEV) += nft_fwd_netdev.o # flow table infrastructure obj-$(CONFIG_NF_FLOW_TABLE) += nf_flow_table.o +nf_flow_table-objs := nf_flow_table_core.o + obj-$(CONFIG_NF_FLOW_TABLE_INET) += nf_flow_table_inet.o # generic X tables
net/netfilter/nf_flow_table_core.c renamed from net/netfilter/nf_flow_table.c +0 -0
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 12/51 netfilter: nf_flow_table: move ipv4 offload hook code to nf_flow_table
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
Allows some minor code sharing with the ipv6 hook code and is also useful as preparation for adding iptables support for offload
--- net/ipv4/netfilter/nf_flow_table_ipv4.c | 241 ------------------------------- net/netfilter/Makefile | 2 +- net/netfilter/nf_flow_table_ip.c | 246 ++++++++++++++++++++++++++++++++ 3 files changed, 247 insertions(+), 242 deletions(-) create mode 100644 net/netfilter/nf_flow_table_ip.c
net/ipv4/netfilter/nf_flow_table_ipv4.c +0 -241
@@ -2,249 +2,8 @@#include <linux/init.h> #include <linux/module.h> #include <linux/netfilter.h> -#include <linux/rhashtable.h> -#include <linux/ip.h> -#include <linux/netdevice.h> -#include <net/ip.h> -#include <net/neighbour.h> #include <net/netfilter/nf_flow_table.h> #include <net/netfilter/nf_tables.h> -/* For layer 4 checksum field offset. */ -#include <linux/tcp.h> -#include <linux/udp.h> - -static int nf_flow_nat_ip_tcp (struct sk_buff *skb,unsigned int thoff, -__be32 addr,__be32 new_addr) -{ -struct tcphdr *tcph; - -if (!pskb_may_pull (skb, thoff +sizeof (*tcph)) || -skb_try_make_writable (skb, thoff +sizeof (*tcph))) -return -1 ; - - tcph = (void *)(skb_network_header (skb) + thoff); -inet_proto_csum_replace4 (&tcph->check, skb, addr, new_addr, true); - -return 0 ; -} - -static int nf_flow_nat_ip_udp (struct sk_buff *skb,unsigned int thoff, -__be32 addr,__be32 new_addr) -{ -struct udphdr *udph; - -if (!pskb_may_pull (skb, thoff +sizeof (*udph)) || -skb_try_make_writable (skb, thoff +sizeof (*udph))) -return -1 ; - - udph = (void *)(skb_network_header (skb) + thoff); -if (udph->check || skb->ip_summed ==CHECKSUM_PARTIAL ) { -inet_proto_csum_replace4 (&udph->check, skb, addr, - new_addr, true); -if (!udph->check) - udph->check =CSUM_MANGLED_0 ; - } - -return 0 ; -} - -static int nf_flow_nat_ip_l4proto (struct sk_buff *skb,struct iphdr *iph, -unsigned int thoff,__be32 addr, -__be32 new_addr) -{ -switch (iph->protocol) { -case IPPROTO_TCP : -if (nf_flow_nat_ip_tcp (skb, thoff, addr, new_addr) <0 ) -return NF_DROP ; -break ; -case IPPROTO_UDP : -if (nf_flow_nat_ip_udp (skb, thoff, addr, new_addr) <0 ) -return NF_DROP ; -break ; - } - -return 0 ; -} - -static int nf_flow_snat_ip (const struct flow_offload *flow,struct sk_buff *skb, -struct iphdr *iph,unsigned int thoff, -enum flow_offload_tuple_dir dir) -{ -__be32 addr, new_addr; - -switch (dir) { -case FLOW_OFFLOAD_DIR_ORIGINAL : - addr = iph->saddr; - new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY ].tuple.dst_v4.s_addr; - iph->saddr = new_addr; -break ; -case FLOW_OFFLOAD_DIR_REPLY : - addr = iph->daddr; - new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL ].tuple.src_v4.s_addr; - iph->daddr = new_addr; -break ; -default : -return -1 ; - } -csum_replace4 (&iph->check, addr, new_addr); - -return nf_flow_nat_ip_l4proto (skb, iph, thoff, addr, new_addr); -} - -static int nf_flow_dnat_ip (const struct flow_offload *flow,struct sk_buff *skb, -struct iphdr *iph,unsigned int thoff, -enum flow_offload_tuple_dir dir) -{ -__be32 addr, new_addr; - -switch (dir) { -case FLOW_OFFLOAD_DIR_ORIGINAL : - addr = iph->daddr; - new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY ].tuple.src_v4.s_addr; - iph->daddr = new_addr; -break ; -case FLOW_OFFLOAD_DIR_REPLY : - addr = iph->saddr; - new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL ].tuple.dst_v4.s_addr; - iph->saddr = new_addr; -break ; -default : -return -1 ; - } -csum_replace4 (&iph->check, addr, new_addr); - -return nf_flow_nat_ip_l4proto (skb, iph, thoff, addr, new_addr); -} - -static int nf_flow_nat_ip (const struct flow_offload *flow,struct sk_buff *skb, -enum flow_offload_tuple_dir dir) -{ -struct iphdr *iph =ip_hdr (skb); -unsigned int thoff = iph->ihl *4 ; - -if (flow->flags &FLOW_OFFLOAD_SNAT && - (nf_flow_snat_port (flow, skb, thoff, iph->protocol, dir) <0 || -nf_flow_snat_ip (flow, skb, iph, thoff, dir) <0 )) -return -1 ; -if (flow->flags &FLOW_OFFLOAD_DNAT && - (nf_flow_dnat_port (flow, skb, thoff, iph->protocol, dir) <0 || -nf_flow_dnat_ip (flow, skb, iph, thoff, dir) <0 )) -return -1 ; - -return 0 ; -} - -static bool ip_has_options (unsigned int thoff) -{ -return thoff !=sizeof (struct iphdr ); -} - -static int nf_flow_tuple_ip (struct sk_buff *skb,const struct net_device *dev, -struct flow_offload_tuple *tuple) -{ -struct flow_ports *ports; -unsigned int thoff; -struct iphdr *iph; - -if (!pskb_may_pull (skb,sizeof (*iph))) -return -1 ; - - iph =ip_hdr (skb); - thoff = iph->ihl *4 ; - -if (ip_is_fragment (iph) || -unlikely (ip_has_options (thoff))) -return -1 ; - -if (iph->protocol !=IPPROTO_TCP && - iph->protocol !=IPPROTO_UDP ) -return -1 ; - - thoff = iph->ihl *4 ; -if (!pskb_may_pull (skb, thoff +sizeof (*ports))) -return -1 ; - - ports = (struct flow_ports *)(skb_network_header (skb) + thoff); - - tuple->src_v4.s_addr = iph->saddr; - tuple->dst_v4.s_addr = iph->daddr; - tuple->src_port = ports->source; - tuple->dst_port = ports->dest; - tuple->l3proto =AF_INET ; - tuple->l4proto = iph->protocol; - tuple->iifidx = dev->ifindex; - -return 0 ; -} - -/* Based on ip_exceeds_mtu(). */ -static bool nf_flow_exceeds_mtu (const struct sk_buff *skb,unsigned int mtu) -{ -if (skb->len <= mtu) -return false; - -if ((ip_hdr (skb)->frag_off &htons (IP_DF )) ==0 ) -return false; - -if (skb_is_gso (skb) &&skb_gso_validate_network_len (skb, mtu)) -return false; - -return true; -} - -unsigned int -nf_flow_offload_ip_hook (void *priv,struct sk_buff *skb, -const struct nf_hook_state *state) -{ -struct flow_offload_tuple_rhash *tuplehash; -struct nf_flowtable *flow_table = priv; -struct flow_offload_tuple tuple = {}; -enum flow_offload_tuple_dir dir; -struct flow_offload *flow; -struct net_device *outdev; -const struct rtable *rt; -struct iphdr *iph; -__be32 nexthop; - -if (skb->protocol !=htons (ETH_P_IP )) -return NF_ACCEPT ; - -if (nf_flow_tuple_ip (skb, state->in, &tuple) <0 ) -return NF_ACCEPT ; - - tuplehash =flow_offload_lookup (flow_table, &tuple); -if (tuplehash ==NULL ) -return NF_ACCEPT ; - - outdev =dev_get_by_index_rcu (state->net, tuplehash->tuple.oifidx); -if (!outdev) -return NF_ACCEPT ; - - dir = tuplehash->tuple.dir; - flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); - rt = (const struct rtable *)flow->tuplehash[dir].tuple.dst_cache; - -if (unlikely (nf_flow_exceeds_mtu (skb, flow->tuplehash[dir].tuple.mtu))) -return NF_ACCEPT ; - -if (skb_try_make_writable (skb,sizeof (*iph))) -return NF_DROP ; - -if (flow->flags & (FLOW_OFFLOAD_SNAT |FLOW_OFFLOAD_DNAT ) && -nf_flow_nat_ip (flow, skb, dir) <0 ) -return NF_DROP ; - - flow->timeout = (u32 )jiffies +NF_FLOW_TIMEOUT ; - iph =ip_hdr (skb); -ip_decrease_ttl (iph); - - skb->dev = outdev; - nexthop =rt_nexthop (rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); -neigh_xmit (NEIGH_ARP_TABLE , outdev, &nexthop, skb); - -return NF_STOLEN ; -} -EXPORT_SYMBOL_GPL (nf_flow_offload_ip_hook);static struct nf_flowtable_type flowtable_ipv4 = { .family =NFPROTO_IPV4 ,
net/netfilter/Makefile +1 -1
@@ -111,7 +111,7 @@ obj-$(CONFIG_NFT_FWD_NETDEV) += nft_fwd_netdev.o # flow table infrastructure obj-$(CONFIG_NF_FLOW_TABLE) += nf_flow_table.o -nf_flow_table-objs := nf_flow_table_core.o +nf_flow_table-objs := nf_flow_table_core.o nf_flow_table_ip.o obj-$(CONFIG_NF_FLOW_TABLE_INET) += nf_flow_table_inet.o
net/netfilter/nf_flow_table_ip.c new file +246 -0
246 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 13/51 netfilter: nf_flow_table: move ip header check out of nf_flow_exceeds_mtu
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
Allows the function to be shared with the IPv6 hook code
--- net/netfilter/nf_flow_table_ip.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
net/netfilter/nf_flow_table_ip.c +2 -4
@@ -182,9 +182,6 @@ static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)if (skb->len <= mtu)return false; -if ((ip_hdr (skb)->frag_off &htons (IP_DF )) ==0 ) -return false; -if (skb_is_gso (skb) &&skb_gso_validate_network_len (skb, mtu))return false;
@@ -223,7 +220,8 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); rt = (const struct rtable *)flow->tuplehash[dir].tuple.dst_cache; -if (unlikely (nf_flow_exceeds_mtu (skb, flow->tuplehash[dir].tuple.mtu))) +if (unlikely (nf_flow_exceeds_mtu (skb, flow->tuplehash[dir].tuple.mtu)) && + (ip_hdr (skb)->frag_off &htons (IP_DF )) !=0 )return NF_ACCEPT ;if (skb_try_make_writable (skb,sizeof (*iph)))
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 14/51 netfilter: nf_flow_table: move ipv6 offload hook code to nf_flow_table
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
Useful as preparation for adding iptables support for offload.
--- net/ipv6/netfilter/nf_flow_table_ipv6.c | 232 -------------------------------- net/netfilter/nf_flow_table_ip.c | 215 +++++++++++++++++++++++++++++ 2 files changed, 215 insertions(+), 232 deletions(-)
net/ipv6/netfilter/nf_flow_table_ipv6.c +0 -232
@@ -3,240 +3,8 @@#include <linux/module.h> #include <linux/netfilter.h> #include <linux/rhashtable.h> -#include <linux/ipv6.h> -#include <linux/netdevice.h> -#include <net/ipv6.h> -#include <net/ip6_route.h> -#include <net/neighbour.h> #include <net/netfilter/nf_flow_table.h> #include <net/netfilter/nf_tables.h> -/* For layer 4 checksum field offset. */ -#include <linux/tcp.h> -#include <linux/udp.h> - -static int nf_flow_nat_ipv6_tcp (struct sk_buff *skb,unsigned int thoff, -struct in6_addr *addr, -struct in6_addr *new_addr) -{ -struct tcphdr *tcph; - -if (!pskb_may_pull (skb, thoff +sizeof (*tcph)) || -skb_try_make_writable (skb, thoff +sizeof (*tcph))) -return -1 ; - - tcph = (void *)(skb_network_header (skb) + thoff); -inet_proto_csum_replace16 (&tcph->check, skb, addr->s6_addr32, - new_addr->s6_addr32, true); - -return 0 ; -} - -static int nf_flow_nat_ipv6_udp (struct sk_buff *skb,unsigned int thoff, -struct in6_addr *addr, -struct in6_addr *new_addr) -{ -struct udphdr *udph; - -if (!pskb_may_pull (skb, thoff +sizeof (*udph)) || -skb_try_make_writable (skb, thoff +sizeof (*udph))) -return -1 ; - - udph = (void *)(skb_network_header (skb) + thoff); -if (udph->check || skb->ip_summed ==CHECKSUM_PARTIAL ) { -inet_proto_csum_replace16 (&udph->check, skb, addr->s6_addr32, - new_addr->s6_addr32, true); -if (!udph->check) - udph->check =CSUM_MANGLED_0 ; - } - -return 0 ; -} - -static int nf_flow_nat_ipv6_l4proto (struct sk_buff *skb,struct ipv6hdr *ip6h, -unsigned int thoff,struct in6_addr *addr, -struct in6_addr *new_addr) -{ -switch (ip6h->nexthdr) { -case IPPROTO_TCP : -if (nf_flow_nat_ipv6_tcp (skb, thoff, addr, new_addr) <0 ) -return NF_DROP ; -break ; -case IPPROTO_UDP : -if (nf_flow_nat_ipv6_udp (skb, thoff, addr, new_addr) <0 ) -return NF_DROP ; -break ; - } - -return 0 ; -} - -static int nf_flow_snat_ipv6 (const struct flow_offload *flow, -struct sk_buff *skb,struct ipv6hdr *ip6h, -unsigned int thoff, -enum flow_offload_tuple_dir dir) -{ -struct in6_addr addr, new_addr; - -switch (dir) { -case FLOW_OFFLOAD_DIR_ORIGINAL : - addr = ip6h->saddr; - new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY ].tuple.dst_v6; - ip6h->saddr = new_addr; -break ; -case FLOW_OFFLOAD_DIR_REPLY : - addr = ip6h->daddr; - new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL ].tuple.src_v6; - ip6h->daddr = new_addr; -break ; -default : -return -1 ; - } - -return nf_flow_nat_ipv6_l4proto (skb, ip6h, thoff, &addr, &new_addr); -} - -static int nf_flow_dnat_ipv6 (const struct flow_offload *flow, -struct sk_buff *skb,struct ipv6hdr *ip6h, -unsigned int thoff, -enum flow_offload_tuple_dir dir) -{ -struct in6_addr addr, new_addr; - -switch (dir) { -case FLOW_OFFLOAD_DIR_ORIGINAL : - addr = ip6h->daddr; - new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY ].tuple.src_v6; - ip6h->daddr = new_addr; -break ; -case FLOW_OFFLOAD_DIR_REPLY : - addr = ip6h->saddr; - new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL ].tuple.dst_v6; - ip6h->saddr = new_addr; -break ; -default : -return -1 ; - } - -return nf_flow_nat_ipv6_l4proto (skb, ip6h, thoff, &addr, &new_addr); -} - -static int nf_flow_nat_ipv6 (const struct flow_offload *flow, -struct sk_buff *skb, -enum flow_offload_tuple_dir dir) -{ -struct ipv6hdr *ip6h =ipv6_hdr (skb); -unsigned int thoff =sizeof (*ip6h); - -if (flow->flags &FLOW_OFFLOAD_SNAT && - (nf_flow_snat_port (flow, skb, thoff, ip6h->nexthdr, dir) <0 || -nf_flow_snat_ipv6 (flow, skb, ip6h, thoff, dir) <0 )) -return -1 ; -if (flow->flags &FLOW_OFFLOAD_DNAT && - (nf_flow_dnat_port (flow, skb, thoff, ip6h->nexthdr, dir) <0 || -nf_flow_dnat_ipv6 (flow, skb, ip6h, thoff, dir) <0 )) -return -1 ; - -return 0 ; -} - -static int nf_flow_tuple_ipv6 (struct sk_buff *skb,const struct net_device *dev, -struct flow_offload_tuple *tuple) -{ -struct flow_ports *ports; -struct ipv6hdr *ip6h; -unsigned int thoff; - -if (!pskb_may_pull (skb,sizeof (*ip6h))) -return -1 ; - - ip6h =ipv6_hdr (skb); - -if (ip6h->nexthdr !=IPPROTO_TCP && - ip6h->nexthdr !=IPPROTO_UDP ) -return -1 ; - - thoff =sizeof (*ip6h); -if (!pskb_may_pull (skb, thoff +sizeof (*ports))) -return -1 ; - - ports = (struct flow_ports *)(skb_network_header (skb) + thoff); - - tuple->src_v6 = ip6h->saddr; - tuple->dst_v6 = ip6h->daddr; - tuple->src_port = ports->source; - tuple->dst_port = ports->dest; - tuple->l3proto =AF_INET6 ; - tuple->l4proto = ip6h->nexthdr; - tuple->iifidx = dev->ifindex; - -return 0 ; -} - -/* Based on ip_exceeds_mtu(). */ -static bool nf_flow_exceeds_mtu (const struct sk_buff *skb,unsigned int mtu) -{ -if (skb->len <= mtu) -return false; - -if (skb_is_gso (skb) &&skb_gso_validate_network_len (skb, mtu)) -return false; - -return true; -} - -unsigned int -nf_flow_offload_ipv6_hook (void *priv,struct sk_buff *skb, -const struct nf_hook_state *state) -{ -struct flow_offload_tuple_rhash *tuplehash; -struct nf_flowtable *flow_table = priv; -struct flow_offload_tuple tuple = {}; -enum flow_offload_tuple_dir dir; -struct flow_offload *flow; -struct net_device *outdev; -struct in6_addr *nexthop; -struct ipv6hdr *ip6h; -struct rt6_info *rt; - -if (skb->protocol !=htons (ETH_P_IPV6 )) -return NF_ACCEPT ; - -if (nf_flow_tuple_ipv6 (skb, state->in, &tuple) <0 ) -return NF_ACCEPT ; - - tuplehash =flow_offload_lookup (flow_table, &tuple); -if (tuplehash ==NULL ) -return NF_ACCEPT ; - - outdev =dev_get_by_index_rcu (state->net, tuplehash->tuple.oifidx); -if (!outdev) -return NF_ACCEPT ; - - dir = tuplehash->tuple.dir; - flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); - rt = (struct rt6_info *)flow->tuplehash[dir].tuple.dst_cache; - -if (unlikely (nf_flow_exceeds_mtu (skb, flow->tuplehash[dir].tuple.mtu))) -return NF_ACCEPT ; - -if (skb_try_make_writable (skb,sizeof (*ip6h))) -return NF_DROP ; - -if (flow->flags & (FLOW_OFFLOAD_SNAT |FLOW_OFFLOAD_DNAT ) && -nf_flow_nat_ipv6 (flow, skb, dir) <0 ) -return NF_DROP ; - - flow->timeout = (u32 )jiffies +NF_FLOW_TIMEOUT ; - ip6h =ipv6_hdr (skb); - ip6h->hop_limit--; - - skb->dev = outdev; - nexthop =rt6_nexthop (rt, &flow->tuplehash[!dir].tuple.src_v6); -neigh_xmit (NEIGH_ND_TABLE , outdev, nexthop, skb); - -return NF_STOLEN ; -} -EXPORT_SYMBOL_GPL (nf_flow_offload_ipv6_hook);static struct nf_flowtable_type flowtable_ipv6 = { .family =NFPROTO_IPV6 ,
net/netfilter/nf_flow_table_ip.c +215 -0
226 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 15/51 netfilter: nf_flow_table: relax mixed ipv4/ipv6 flowtable dependencies
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
Since the offload hook code was moved, this table no longer depends on the IPv4 and IPv6 flowtable modules
--- net/netfilter/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
net/netfilter/Kconfig +1 -2
@@ -666,8 +666,7 @@ endif # NF_TABLES config NF_FLOW_TABLE_INET tristate "Netfilter flow table mixed IPv4/IPv6 module" - depends on NF_FLOW_TABLE_IPV4 - depends on NF_FLOW_TABLE_IPV6 + depends on NF_FLOW_TABLE help This option adds the flow table mixed IPv4/IPv6 support.
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 16/51 netfilter: nf_flow_table: move init code to nf_flow_table_core.c
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
Reduces duplication of .gc and .params in flowtable type definitions and makes the API clearer
--- include/net/netfilter/nf_flow_table.h | 6 +- net/ipv4/netfilter/nf_flow_table_ipv4.c | 3 +- net/ipv6/netfilter/nf_flow_table_ipv6.c | 3 +- net/netfilter/nf_flow_table_core.c | 102 +++++++++++++++++++------------- net/netfilter/nf_flow_table_inet.c | 3 +- net/netfilter/nf_tables_api.c | 22 +++---- 6 files changed, 74 insertions(+), 65 deletions(-)
include/net/netfilter/nf_flow_table.h +2 -4
@@ -14,9 +14,8 @@ struct nf_flowtable;struct nf_flowtable_type {struct list_head list;int family; -void (*gc)(struct work_struct *work); +int (*init)(struct nf_flowtable *ft);void (*free)(struct nf_flowtable *ft); -const struct rhashtable_params *params;nf_hookfn *hook;struct module *owner; };
@@ -100,9 +99,8 @@ int nf_flow_table_iterate(struct nf_flowtable *flow_table,void nf_flow_table_cleanup (struct net *net,struct net_device *dev); +int nf_flow_table_init (struct nf_flowtable *flow_table);void nf_flow_table_free (struct nf_flowtable *flow_table); -void nf_flow_offload_work_gc (struct work_struct *work); -extern const struct rhashtable_params nf_flow_offload_rhash_params;void flow_offload_dead (struct flow_offload *flow);
net/ipv4/netfilter/nf_flow_table_ipv4.c +1 -2
@@ -7,8 +7,7 @@static struct nf_flowtable_type flowtable_ipv4 = { .family =NFPROTO_IPV4 , - .params = &nf_flow_offload_rhash_params, - .gc = nf_flow_offload_work_gc, + .init = nf_flow_table_init, .free = nf_flow_table_free, .hook = nf_flow_offload_ip_hook, .owner =THIS_MODULE ,
net/ipv6/netfilter/nf_flow_table_ipv6.c +1 -2
@@ -8,8 +8,7 @@static struct nf_flowtable_type flowtable_ipv6 = { .family =NFPROTO_IPV6 , - .params = &nf_flow_offload_rhash_params, - .gc = nf_flow_offload_work_gc, + .init = nf_flow_table_init, .free = nf_flow_table_free, .hook = nf_flow_offload_ipv6_hook, .owner =THIS_MODULE ,
net/netfilter/nf_flow_table_core.c +60 -42
156 lines not on this page · raw message
net/netfilter/nf_flow_table_inet.c +1 -2
@@ -22,8 +22,7 @@ nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb,static struct nf_flowtable_type flowtable_inet = { .family =NFPROTO_INET , - .params = &nf_flow_offload_rhash_params, - .gc = nf_flow_offload_work_gc, + .init = nf_flow_table_init, .free = nf_flow_table_free, .hook = nf_flow_offload_inet_hook, .owner =THIS_MODULE ,
net/netfilter/nf_tables_api.c +9 -13
@@ -5150,14 +5150,14 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk, } flowtable->data.type = type; - err =rhashtable_init (&flowtable->data.rhashtable, type->params); + err = type->init (&flowtable->data);if (err <0 ) goto err3; err =nf_tables_flowtable_parse_hook (&ctx, nla[NFTA_FLOWTABLE_HOOK ], flowtable);if (err <0 ) - goto err3; + goto err4;for (i =0 ; i < flowtable->ops_len; i++) {if (!flowtable->ops[i].dev)
@@ -5171,37 +5171,35 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk,if (flowtable->ops[i].dev == ft->ops[k].dev && flowtable->ops[i].pf == ft->ops[k].pf) { err = -EBUSY ; - goto err4; + goto err5; } } } err =nf_register_net_hook (net, &flowtable->ops[i]);if (err <0 ) - goto err4; + goto err5; } err =nft_trans_flowtable_add (&ctx,NFT_MSG_NEWFLOWTABLE , flowtable);if (err <0 ) - goto err5; - -INIT_DEFERRABLE_WORK (&flowtable->data.gc_work, type->gc); -queue_delayed_work (system_power_efficient_wq, - &flowtable->data.gc_work,HZ ); + goto err6;list_add_tail_rcu (&flowtable->list, &table->flowtables); table->use++;return 0 ; -err5: +err6: i = flowtable->ops_len; -err4: +err5:for (k = i -1 ; k >=0 ; k--) {kfree (flowtable->dev_name[k]);nf_unregister_net_hook (net, &flowtable->ops[k]); }kfree (flowtable->ops); +err4: + flowtable->data.type->free (&flowtable->data); err3:module_put (type->owner); err2:
@@ -5485,11 +5483,9 @@ static void nf_tables_flowtable_notify(struct nft_ctx *ctx,static void nf_tables_flowtable_destroy (struct nft_flowtable *flowtable) { -cancel_delayed_work_sync (&flowtable->data.gc_work);kfree (flowtable->ops);kfree (flowtable->name); flowtable->data.type->free (&flowtable->data); -rhashtable_destroy (&flowtable->data.rhashtable);module_put (flowtable->data.type->owner); }
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 17/51 netfilter: nf_flow_table: fix priv pointer for netdev hook
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
The offload ip hook expects a pointer to the flowtable, not to the rhashtable. Since the rhashtable is the first member, this is safe for the moment, but breaks as soon as the structure layout changes
--- net/netfilter/nf_tables_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/nf_tables_api.c +1 -1
@@ -5019,7 +5019,7 @@ static int nf_tables_flowtable_parse_hook(const struct nft_ctx *ctx, flowtable->ops[i].pf =NFPROTO_NETDEV ; flowtable->ops[i].hooknum = hooknum; flowtable->ops[i].priority = priority; - flowtable->ops[i].priv = &flowtable->data.rhashtable; + flowtable->ops[i].priv = &flowtable->data; flowtable->ops[i].hook = flowtable->data.type->hook; flowtable->ops[i].dev = dev_array[i]; flowtable->dev_name[i] = kstrdup(dev_array[i]->name,
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 18/51 netfilter: nf_flow_table: track flow tables in nf_flow_table directly
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
Avoids having nf_flow_table depend on nftables (useful for future iptables backport work)
--- include/net/netfilter/nf_flow_table.h | 1 + include/net/netfilter/nf_tables.h | 3 --- net/netfilter/nf_flow_table_core.c | 21 ++++++++++++++++++--- net/netfilter/nf_tables_api.c | 17 ----------------- 4 files changed, 19 insertions(+), 23 deletions(-)
include/net/netfilter/nf_flow_table.h +1 -0
@@ -21,6 +21,7 @@ struct nf_flowtable_type { };struct nf_flowtable { +struct list_head list;struct rhashtable rhashtable;const struct nf_flowtable_type *type;struct delayed_work gc_work;
include/net/netfilter/nf_tables.h +0 -3
@@ -1109,9 +1109,6 @@ struct nft_flowtable {struct nft_flowtable *nf_tables_flowtable_lookup (const struct nft_table *table,const struct nlattr *nla,u8 genmask); -void nft_flow_table_iterate (struct net *net, -void (*iter)(struct nf_flowtable *flowtable,void *data), -void *data);void nft_register_flowtable_type (struct nf_flowtable_type *type);void nft_unregister_flowtable_type (struct nf_flowtable_type *type);
net/netfilter/nf_flow_table_core.c +18 -3
@@ -18,6 +18,9 @@ struct flow_offload_entry {struct rcu_head rcu_head; }; +static DEFINE_MUTEX (flowtable_lock); +static LIST_HEAD (flowtables); + static void flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct, struct nf_flow_route *route,
@@ -410,6 +413,10 @@ int nf_flow_table_init(struct nf_flowtable *flowtable)queue_delayed_work (system_power_efficient_wq, &flowtable->gc_work,HZ ); +mutex_lock (&flowtable_lock); +list_add (&flowtable->list, &flowtables); +mutex_unlock (&flowtable_lock); +return 0 ; }EXPORT_SYMBOL_GPL (nf_flow_table_init);
@@ -425,20 +432,28 @@ static void nf_flow_table_do_cleanup(struct flow_offload *flow, void *data) }static void nf_flow_table_iterate_cleanup (struct nf_flowtable *flowtable, -void *data) +struct net_device *dev) { -nf_flow_table_iterate (flowtable, nf_flow_table_do_cleanup, data); +nf_flow_table_iterate (flowtable, nf_flow_table_do_cleanup, dev);flush_delayed_work (&flowtable->gc_work); }void nf_flow_table_cleanup (struct net *net,struct net_device *dev) { -nft_flow_table_iterate (net, nf_flow_table_iterate_cleanup, dev); +struct nf_flowtable *flowtable; + +mutex_lock (&flowtable_lock); +list_for_each_entry (flowtable, &flowtables, list) +nf_flow_table_iterate_cleanup (flowtable, dev); +mutex_unlock (&flowtable_lock); }EXPORT_SYMBOL_GPL (nf_flow_table_cleanup);void nf_flow_table_free (struct nf_flowtable *flow_table) { +mutex_lock (&flowtable_lock); +list_del (&flow_table->list); +mutex_unlock (&flowtable_lock);cancel_delayed_work_sync (&flow_table->gc_work);nf_flow_table_iterate (flow_table, nf_flow_table_do_cleanup,NULL );WARN_ON (!nf_flow_offload_gc_step (flow_table));
net/netfilter/nf_tables_api.c +0 -17
@@ -5060,23 +5060,6 @@ static const struct nf_flowtable_type *nft_flowtable_type_get(u8 family)return ERR_PTR (-ENOENT ); } -void nft_flow_table_iterate (struct net *net, -void (*iter)(struct nf_flowtable *flowtable,void *data), -void *data) -{ -struct nft_flowtable *flowtable; -const struct nft_table *table; - -nfnl_lock (NFNL_SUBSYS_NFTABLES ); -list_for_each_entry (table, &net->nft.tables, list) { -list_for_each_entry (flowtable, &table->flowtables, list) { -iter (&flowtable->data, data); - } - } -nfnl_unlock (NFNL_SUBSYS_NFTABLES ); -} -EXPORT_SYMBOL_GPL (nft_flow_table_iterate); -static void nft_unregister_flowtable_net_hooks (struct net *net,struct nft_flowtable *flowtable) {
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 19/51 netfilter: nf_flow_table: make flow_offload_dead inline
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
It is too trivial to keep as a separate exported function
--- include/net/netfilter/nf_flow_table.h | 5 ++++- net/netfilter/nf_flow_table_core.c | 6 ------ 2 files changed, 4 insertions(+), 7 deletions(-)
include/net/netfilter/nf_flow_table.h +4 -1
@@ -103,7 +103,10 @@ void nf_flow_table_cleanup(struct net *net, struct net_device *dev);int nf_flow_table_init (struct nf_flowtable *flow_table);void nf_flow_table_free (struct nf_flowtable *flow_table); -void flow_offload_dead (struct flow_offload *flow); +static inline void flow_offload_dead (struct flow_offload *flow) +{ + flow->flags |=FLOW_OFFLOAD_DYING ; +} int nf_flow_snat_port(const struct flow_offload *flow, struct sk_buff *skb, unsigned int thoff,
net/netfilter/nf_flow_table_core.c +0 -6
@@ -113,12 +113,6 @@ void flow_offload_free(struct flow_offload *flow) }EXPORT_SYMBOL_GPL (flow_offload_free); -void flow_offload_dead (struct flow_offload *flow) -{ - flow->flags |=FLOW_OFFLOAD_DYING ; -} -EXPORT_SYMBOL_GPL (flow_offload_dead); -static u32 flow_offload_hash (const void *data,u32 len,u32 seed) {const struct flow_offload_tuple *tuple = data;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 20/51 netfilter: nf_flow_table: add a new flow state for tearing down offloading
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
On cleanup, this will be treated differently from FLOW_OFFLOAD_DYING:
If FLOW_OFFLOAD_DYING is set, the connection is going away, so both the offload state and the connection tracking entry will be deleted.
If FLOW_OFFLOAD_TEARDOWN is set, the connection remains alive, but the offload state is torn down. This is useful for cases that require more complex state tracking / timeout handling on TCP, or if the connection has been idle for too long.
Support for sending flows back to the slow path will be implemented in a following patch
--- include/net/netfilter/nf_flow_table.h | 2 ++ net/netfilter/nf_flow_table_core.c | 22 ++++++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-)
include/net/netfilter/nf_flow_table.h +2 -0
@@ -68,6 +68,7 @@ struct flow_offload_tuple_rhash {#define FLOW_OFFLOAD_SNAT 0x1#define FLOW_OFFLOAD_DNAT 0x2#define FLOW_OFFLOAD_DYING 0x4 +#define FLOW_OFFLOAD_TEARDOWN 0x8struct flow_offload {struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX ];
@@ -103,6 +104,7 @@ void nf_flow_table_cleanup(struct net *net, struct net_device *dev);int nf_flow_table_init (struct nf_flowtable *flow_table);void nf_flow_table_free (struct nf_flowtable *flow_table); +void flow_offload_teardown (struct flow_offload *flow);static inline void flow_offload_dead (struct flow_offload *flow) { flow->flags |=FLOW_OFFLOAD_DYING ;
net/netfilter/nf_flow_table_core.c +14 -8
@@ -174,6 +174,12 @@ static void flow_offload_del(struct nf_flowtable *flow_table,flow_offload_free (flow); } +void flow_offload_teardown (struct flow_offload *flow) +{ + flow->flags |=FLOW_OFFLOAD_TEARDOWN ; +} +EXPORT_SYMBOL_GPL (flow_offload_teardown); +struct flow_offload_tuple_rhash *flow_offload_lookup (struct nf_flowtable *flow_table,struct flow_offload_tuple *tuple)
@@ -226,11 +232,6 @@ static inline bool nf_flow_has_expired(const struct flow_offload *flow)return (__s32)(flow->timeout - (u32 )jiffies) <=0 ; } -static inline bool nf_flow_is_dying (const struct flow_offload *flow) -{ -return flow->flags &FLOW_OFFLOAD_DYING ; -} -static int nf_flow_offload_gc_step (struct nf_flowtable *flow_table) {struct flow_offload_tuple_rhash *tuplehash;
@@ -258,7 +259,8 @@ static int nf_flow_offload_gc_step(struct nf_flowtable *flow_table) flow = container_of(tuplehash, struct flow_offload, tuplehash[0]);if (nf_flow_has_expired (flow) || -nf_flow_is_dying (flow)) + (flow->flags & (FLOW_OFFLOAD_DYING | +FLOW_OFFLOAD_TEARDOWN )))flow_offload_del (flow_table, flow); } out:
@@ -419,10 +421,14 @@ static void nf_flow_table_do_cleanup(struct flow_offload *flow, void *data) {struct net_device *dev = data; -if (dev && flow->tuplehash[0 ].tuple.iifidx != dev->ifindex) +if (!dev) { +flow_offload_teardown (flow);return ; + } -flow_offload_dead (flow); +if (flow->tuplehash[0 ].tuple.iifidx == dev->ifindex || + flow->tuplehash[1 ].tuple.iifidx == dev->ifindex) +flow_offload_dead (flow); } static void nf_flow_table_iterate_cleanup(struct nf_flowtable *flowtable,
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 21/51 netfilter: nf_flow_table: in flow_offload_lookup, skip entries being deleted
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
Preparation for sending flows back to the slow path
--- net/netfilter/nf_flow_table_core.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
net/netfilter/nf_flow_table_core.c +15 -2
@@ -184,8 +184,21 @@ struct flow_offload_tuple_rhash * flow_offload_lookup(struct nf_flowtable *flow_table, struct flow_offload_tuple *tuple) { - return rhashtable_lookup_fast(&flow_table->rhashtable, tuple, - nf_flow_offload_rhash_params); + struct flow_offload_tuple_rhash *tuplehash; +struct flow_offload *flow; +int dir; + + tuplehash =rhashtable_lookup_fast (&flow_table->rhashtable, tuple, + nf_flow_offload_rhash_params); +if (!tuplehash) +return NULL ; + + dir = tuplehash->tuple.dir; + flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); +if (flow->flags & (FLOW_OFFLOAD_DYING |FLOW_OFFLOAD_TEARDOWN )) +return NULL ; + +return tuplehash; }EXPORT_SYMBOL_GPL (flow_offload_lookup);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 22/51 netfilter: nf_flow_table: add support for sending flows back to the slow path
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
Since conntrack hasn't seen any packets from the offloaded flow in a while, and the timeout for offloaded flows is set to an extremely long value, we need to fix up the state before we can send a flow back to the slow path.
For TCP, reset td_maxwin in both directions, which makes it resync its state on the next packets.
Use the regular timeout for TCP and UDP established connections.
This allows the slow path to take over again once the offload state has been torn down
--- net/netfilter/nf_flow_table_core.c | 50 +++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-)
net/netfilter/nf_flow_table_core.c +49 -1
@@ -100,6 +100,43 @@ flow_offload_alloc(struct nf_conn *ct, struct nf_flow_route *route) }EXPORT_SYMBOL_GPL (flow_offload_alloc); +static void flow_offload_fixup_tcp (struct ip_ct_tcp *tcp) +{ + tcp->state =TCP_CONNTRACK_ESTABLISHED ; + tcp->seen[0 ].td_maxwin =0 ; + tcp->seen[1 ].td_maxwin =0 ; +} + +static void flow_offload_fixup_ct_state (struct nf_conn *ct) +{ +const struct nf_conntrack_l4proto *l4proto; +struct net *net =nf_ct_net (ct); +unsigned int *timeouts; +unsigned int timeout; +int l4num; + + l4num =nf_ct_protonum (ct); +if (l4num ==IPPROTO_TCP ) +flow_offload_fixup_tcp (&ct->proto.tcp); + + l4proto =__nf_ct_l4proto_find (nf_ct_l3num (ct), l4num); +if (!l4proto) +return ; + + timeouts = l4proto->get_timeouts (net); +if (!timeouts) +return ; + +if (l4num ==IPPROTO_TCP ) + timeout = timeouts[TCP_CONNTRACK_ESTABLISHED ]; +else if (l4num ==IPPROTO_UDP ) + timeout = timeouts[UDP_CT_REPLIED ]; +else +return ; + + ct->timeout = nfct_time_stamp + timeout; +} +void flow_offload_free (struct flow_offload *flow) {struct flow_offload_entry *e;
@@ -107,7 +144,8 @@ void flow_offload_free(struct flow_offload *flow)dst_release (flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL ].tuple.dst_cache);dst_release (flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY ].tuple.dst_cache); e = container_of(flow, struct flow_offload_entry, flow); -nf_ct_delete (e->ct,0 ,0 ); +if (flow->flags &FLOW_OFFLOAD_DYING ) +nf_ct_delete (e->ct,0 ,0 );nf_ct_put (e->ct);kfree_rcu (e, rcu_head); }
@@ -164,6 +202,8 @@ EXPORT_SYMBOL_GPL(flow_offload_add);static void flow_offload_del (struct nf_flowtable *flow_table,struct flow_offload *flow) { +struct flow_offload_entry *e; +rhashtable_remove_fast (&flow_table->rhashtable, &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL ].node, nf_flow_offload_rhash_params);
@@ -171,12 +211,20 @@ static void flow_offload_del(struct nf_flowtable *flow_table, &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY ].node, nf_flow_offload_rhash_params); + e = container_of(flow, struct flow_offload_entry, flow); +clear_bit (IPS_OFFLOAD_BIT , &e->ct->status); +flow_offload_free (flow); }void flow_offload_teardown (struct flow_offload *flow) { +struct flow_offload_entry *e; + flow->flags |=FLOW_OFFLOAD_TEARDOWN ; + + e = container_of(flow, struct flow_offload_entry, flow); +flow_offload_fixup_ct_state (e->ct); }EXPORT_SYMBOL_GPL (flow_offload_teardown);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 23/51 netfilter: nf_flow_table: tear down TCP flows if RST or FIN was seen
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
Allow the slow path to handle the shutdown of the connection with proper timeouts. The packet containing RST/FIN is also sent to the slow path and the TCP conntrack module will update its state.
--- net/netfilter/nf_flow_table_ip.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-)
net/netfilter/nf_flow_table_ip.c +27 -3
@@ -15,6 +15,23 @@#include <linux/tcp.h> #include <linux/udp.h> +static int nf_flow_tcp_state_check (struct flow_offload *flow, +struct sk_buff *skb,unsigned int thoff) +{ +struct tcphdr *tcph; + +if (!pskb_may_pull (skb, thoff +sizeof (*tcph))) +return -1 ; + + tcph = (void *)(skb_network_header (skb) + thoff); +if (unlikely (tcph->fin || tcph->rst)) { +flow_offload_teardown (flow); +return -1 ; + } + +return 0 ; +} +static int nf_flow_nat_ip_tcp (struct sk_buff *skb,unsigned int thoff,__be32 addr,__be32 new_addr) {
@@ -119,10 +136,9 @@ static int nf_flow_dnat_ip(const struct flow_offload *flow, struct sk_buff *skb, }static int nf_flow_nat_ip (const struct flow_offload *flow,struct sk_buff *skb, -enum flow_offload_tuple_dir dir) +unsigned int thoff,enum flow_offload_tuple_dir dir) {struct iphdr *iph =ip_hdr (skb); -unsigned int thoff = iph->ihl *4 ; if (flow->flags & FLOW_OFFLOAD_SNAT && (nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir) < 0 ||
@@ -202,6 +218,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,struct flow_offload *flow;struct net_device *outdev;const struct rtable *rt; +unsigned int thoff;struct iphdr *iph;__be32 nexthop;
@@ -230,8 +247,12 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,if (skb_try_make_writable (skb,sizeof (*iph)))return NF_DROP ; + thoff =ip_hdr (skb)->ihl *4 ; +if (nf_flow_tcp_state_check (flow, skb, thoff)) +return NF_ACCEPT ; +if (flow->flags & (FLOW_OFFLOAD_SNAT |FLOW_OFFLOAD_DNAT ) && -nf_flow_nat_ip (flow, skb, dir) <0 ) +nf_flow_nat_ip (flow, skb, thoff, dir) <0 )return NF_DROP ; flow->timeout = (u32 )jiffies +NF_FLOW_TIMEOUT ;
@@ -439,6 +460,9 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,if (unlikely (nf_flow_exceeds_mtu (skb, flow->tuplehash[dir].tuple.mtu)))return NF_ACCEPT ; +if (nf_flow_tcp_state_check (flow, skb,sizeof (*ip6h))) +return NF_ACCEPT ; +if (skb_try_make_writable (skb,sizeof (*ip6h)))return NF_DROP ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 24/51 netfilter: nf_flow_table: add missing condition for TCP state check
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
Avoid looking at unrelated fields in UDP packets
--- net/netfilter/nf_flow_table_ip.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
net/netfilter/nf_flow_table_ip.c +8 -4
@@ -15,11 +15,14 @@#include <linux/tcp.h> #include <linux/udp.h> -static int nf_flow_tcp_state_check (struct flow_offload *flow, -struct sk_buff *skb,unsigned int thoff) +static int nf_flow_state_check (struct flow_offload *flow,int proto, +struct sk_buff *skb,unsigned int thoff) {struct tcphdr *tcph; +if (proto !=IPPROTO_TCP ) +return 0 ; +if (!pskb_may_pull (skb, thoff +sizeof (*tcph)))return -1 ;
@@ -248,7 +251,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,return NF_DROP ; thoff =ip_hdr (skb)->ihl *4 ; -if (nf_flow_tcp_state_check (flow, skb, thoff)) +if (nf_flow_state_check (flow,ip_hdr (skb)->protocol, skb, thoff))return NF_ACCEPT ; if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) &&
@@ -460,7 +463,8 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,if (unlikely (nf_flow_exceeds_mtu (skb, flow->tuplehash[dir].tuple.mtu)))return NF_ACCEPT ; -if (nf_flow_tcp_state_check (flow, skb,sizeof (*ip6h))) +if (nf_flow_state_check (flow,ipv6_hdr (skb)->nexthdr, skb, +sizeof (*ip6h)))return NF_ACCEPT ;if (skb_try_make_writable (skb,sizeof (*ip6h)))
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 25/51 netfilter: nf_flow_table: fix offloading connections with SNAT+DNAT
In reply to Pablo Neira AyusoFrom: Felix Fietkau <[email protected]>
Pass all NAT types to the flow offload struct, otherwise parts of the address/port pair do not get translated properly, causing connection stalls
--- net/netfilter/nf_flow_table_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/nf_flow_table_core.c +1 -1
@@ -84,7 +84,7 @@ flow_offload_alloc(struct nf_conn *ct, struct nf_flow_route *route)if (ct->status &IPS_SRC_NAT ) flow->flags |=FLOW_OFFLOAD_SNAT ; -else if (ct->status &IPS_DST_NAT ) +if (ct->status &IPS_DST_NAT ) flow->flags |=FLOW_OFFLOAD_DNAT ;return flow;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 26/51 netfilter: nf_tables: simplify lookup functions
In reply to Pablo Neira AyusoReplace the nf_tables_ prefix by nft_ and merge code into single lookup function whenever possible. In many cases we go over the 80-chars boundary function names, this save us ~50 LoC.
--- include/net/netfilter/nf_tables.h | 12 +- net/netfilter/nf_tables_api.c | 249 +++++++++++++++----------------------- net/netfilter/nft_flow_offload.c | 5 +- net/netfilter/nft_objref.c | 4 +- 4 files changed, 110 insertions(+), 160 deletions(-)
include/net/netfilter/nf_tables.h +6 -6
@@ -1015,9 +1015,9 @@ static inline void *nft_obj_data(const struct nft_object *obj)#define nft_expr_obj (expr) *((struct nft_object **)nft_expr_priv(expr)) -struct nft_object *nf_tables_obj_lookup (const struct nft_table *table, -const struct nlattr *nla,u32 objtype, -u8 genmask); +struct nft_object *nft_obj_lookup (const struct nft_table *table, +const struct nlattr *nla,u32 objtype, +u8 genmask); void nft_obj_notify(struct net *net, struct nft_table *table, struct nft_object *obj, u32 portid, u32 seq,
@@ -1106,9 +1106,9 @@ struct nft_flowtable {struct nf_flowtable data; }; -struct nft_flowtable *nf_tables_flowtable_lookup (const struct nft_table *table, -const struct nlattr *nla, -u8 genmask); +struct nft_flowtable *nft_flowtable_lookup (const struct nft_table *table, +const struct nlattr *nla, +u8 genmask);void nft_register_flowtable_type (struct nf_flowtable_type *type);void nft_unregister_flowtable_type (struct nf_flowtable_type *type);
net/netfilter/nf_tables_api.c +100 -149
583 lines not on this page · raw message
net/netfilter/nft_flow_offload.c +2 -3
@@ -142,9 +142,8 @@ static int nft_flow_offload_init(const struct nft_ctx *ctx,if (!tb[NFTA_FLOW_TABLE_NAME ])return -EINVAL ; - flowtable =nf_tables_flowtable_lookup (ctx->table, - tb[NFTA_FLOW_TABLE_NAME ], - genmask); + flowtable =nft_flowtable_lookup (ctx->table, tb[NFTA_FLOW_TABLE_NAME ], + genmask);if (IS_ERR (flowtable))return PTR_ERR (flowtable);
net/netfilter/nft_objref.c +2 -2
@@ -38,8 +38,8 @@ static int nft_objref_init(const struct nft_ctx *ctx,return -EINVAL ; objtype =ntohl (nla_get_be32 (tb[NFTA_OBJREF_IMM_TYPE ])); - obj =nf_tables_obj_lookup (ctx->table, tb[NFTA_OBJREF_IMM_NAME ], objtype, - genmask); + obj =nft_obj_lookup (ctx->table, tb[NFTA_OBJREF_IMM_NAME ], objtype, + genmask);if (IS_ERR (obj))return -ENOENT ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 27/51 netfilter: nf_tables: initial support for extended ACK reporting
In reply to Pablo Neira AyusoKeep it simple to start with, just report attribute offsets that can be useful to userspace when representating errors to users.
--- net/netfilter/nf_tables_api.c | 299 +++++++++++++++++++++++++++++------------- 1 file changed, 206 insertions(+), 93 deletions(-)
net/netfilter/nf_tables_api.c +206 -93
@@ -582,8 +582,10 @@ static int nf_tables_gettable(struct net *net, struct sock *nlsk, } table =nft_table_lookup (net, nla[NFTA_TABLE_NAME ], family, genmask); -if (IS_ERR (table)) +if (IS_ERR (table)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_TABLE_NAME ]);return PTR_ERR (table); + } skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_KERNEL );if (!skb2)
@@ -699,21 +701,23 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk, {const struct nfgenmsg *nfmsg =nlmsg_data (nlh);u8 genmask =nft_genmask_next (net); -const struct nlattr *name; -struct nft_table *table;int family = nfmsg->nfgen_family; +const struct nlattr *attr; +struct nft_table *table;u32 flags =0 ;struct nft_ctx ctx;int err; - name = nla[NFTA_TABLE_NAME ]; - table =nft_table_lookup (net, name, family, genmask); + attr = nla[NFTA_TABLE_NAME ]; + table =nft_table_lookup (net, attr, family, genmask);if (IS_ERR (table)) {if (PTR_ERR (table) != -ENOENT )return PTR_ERR (table); }else { -if (nlh->nlmsg_flags &NLM_F_EXCL ) +if (nlh->nlmsg_flags &NLM_F_EXCL ) { +NL_SET_BAD_ATTR (extack, attr);return -EEXIST ; + }if (nlh->nlmsg_flags &NLM_F_REPLACE )return -EOPNOTSUPP ;
@@ -732,7 +736,7 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk,if (table ==NULL ) goto err_kzalloc; - table->name =nla_strdup (name,GFP_KERNEL ); + table->name =nla_strdup (attr,GFP_KERNEL );if (table->name ==NULL ) goto err_strdup;
@@ -855,8 +859,9 @@ static int nf_tables_deltable(struct net *net, struct sock *nlsk, {const struct nfgenmsg *nfmsg =nlmsg_data (nlh);u8 genmask =nft_genmask_next (net); -struct nft_table *table;int family = nfmsg->nfgen_family; +const struct nlattr *attr; +struct nft_table *table;struct nft_ctx ctx;nft_ctx_init (&ctx, net, skb, nlh,0 ,NULL ,NULL , nla);
@@ -864,15 +869,18 @@ static int nf_tables_deltable(struct net *net, struct sock *nlsk, (!nla[NFTA_TABLE_NAME] && !nla[NFTA_TABLE_HANDLE]))return nft_flush (&ctx, family); -if (nla[NFTA_TABLE_HANDLE ]) - table =nft_table_lookup_byhandle (net, nla[NFTA_TABLE_HANDLE ], - genmask); -else - table =nft_table_lookup (net, nla[NFTA_TABLE_NAME ], family, - genmask); +if (nla[NFTA_TABLE_HANDLE ]) { + attr = nla[NFTA_TABLE_HANDLE ]; + table =nft_table_lookup_byhandle (net, attr, genmask); + }else { + attr = nla[NFTA_TABLE_NAME ]; + table =nft_table_lookup (net, attr, family, genmask); + } -if (IS_ERR (table)) +if (IS_ERR (table)) { +NL_SET_BAD_ATTR (extack, attr);return PTR_ERR (table); + }if (nlh->nlmsg_flags &NLM_F_NONREC && table->use >0 )
@@ -1164,12 +1172,16 @@ static int nf_tables_getchain(struct net *net, struct sock *nlsk, } table =nft_table_lookup (net, nla[NFTA_CHAIN_TABLE ], family, genmask); -if (IS_ERR (table)) +if (IS_ERR (table)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_CHAIN_TABLE ]);return PTR_ERR (table); + } chain =nft_chain_lookup (table, nla[NFTA_CHAIN_NAME ], genmask); -if (IS_ERR (chain)) +if (IS_ERR (chain)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_CHAIN_NAME ]);return PTR_ERR (chain); + } skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_KERNEL );if (!skb2)
@@ -1531,9 +1543,9 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, struct netlink_ext_ack *extack) {const struct nfgenmsg *nfmsg =nlmsg_data (nlh); -const struct nlattr *uninitialized_var (name );u8 genmask =nft_genmask_next (net);int family = nfmsg->nfgen_family; +const struct nlattr *attr;struct nft_table *table;struct nft_chain *chain;u8 policy =NF_ACCEPT ;
@@ -1544,34 +1556,45 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, create = nlh->nlmsg_flags &NLM_F_CREATE ? true : false; table =nft_table_lookup (net, nla[NFTA_CHAIN_TABLE ], family, genmask); -if (IS_ERR (table)) +if (IS_ERR (table)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_CHAIN_TABLE ]);return PTR_ERR (table); + } chain =NULL ; - name = nla[NFTA_CHAIN_NAME ]; + attr = nla[NFTA_CHAIN_NAME ];if (nla[NFTA_CHAIN_HANDLE ]) { handle =be64_to_cpu (nla_get_be64 (nla[NFTA_CHAIN_HANDLE ])); chain =nft_chain_lookup_byhandle (table, handle, genmask); -if (IS_ERR (chain)) +if (IS_ERR (chain)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_CHAIN_HANDLE ]);return PTR_ERR (chain); + } + attr = nla[NFTA_CHAIN_HANDLE ]; }else { - chain =nft_chain_lookup (table, name, genmask); + chain =nft_chain_lookup (table, attr, genmask);if (IS_ERR (chain)) { -if (PTR_ERR (chain) != -ENOENT ) +if (PTR_ERR (chain) != -ENOENT ) { +NL_SET_BAD_ATTR (extack, attr);return PTR_ERR (chain); + } chain =NULL ; } }if (nla[NFTA_CHAIN_POLICY ]) {if (chain !=NULL && - !nft_is_base_chain (chain)) + !nft_is_base_chain (chain)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_CHAIN_POLICY ]);return -EOPNOTSUPP ; + }if (chain ==NULL && - nla[NFTA_CHAIN_HOOK ] ==NULL ) + nla[NFTA_CHAIN_HOOK ] ==NULL ) { +NL_SET_BAD_ATTR (extack, nla[NFTA_CHAIN_POLICY ]);return -EOPNOTSUPP ; + } policy =ntohl (nla_get_be32 (nla[NFTA_CHAIN_POLICY ]));switch (policy) {
@@ -1586,8 +1609,10 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,nft_ctx_init (&ctx, net, skb, nlh, family, table, chain, nla);if (chain !=NULL ) { -if (nlh->nlmsg_flags &NLM_F_EXCL ) +if (nlh->nlmsg_flags &NLM_F_EXCL ) { +NL_SET_BAD_ATTR (extack, attr);return -EEXIST ; + }if (nlh->nlmsg_flags &NLM_F_REPLACE )return -EOPNOTSUPP ;
@@ -1604,27 +1629,34 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk, {const struct nfgenmsg *nfmsg =nlmsg_data (nlh);u8 genmask =nft_genmask_next (net); +int family = nfmsg->nfgen_family; +const struct nlattr *attr;struct nft_table *table;struct nft_chain *chain;struct nft_rule *rule; -int family = nfmsg->nfgen_family;struct nft_ctx ctx;u64 handle;u32 use;int err; table =nft_table_lookup (net, nla[NFTA_CHAIN_TABLE ], family, genmask); -if (IS_ERR (table)) +if (IS_ERR (table)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_CHAIN_TABLE ]);return PTR_ERR (table); + }if (nla[NFTA_CHAIN_HANDLE ]) { - handle =be64_to_cpu (nla_get_be64 (nla[NFTA_CHAIN_HANDLE ])); + attr = nla[NFTA_CHAIN_HANDLE ]; + handle =be64_to_cpu (nla_get_be64 (attr)); chain =nft_chain_lookup_byhandle (table, handle, genmask); }else { - chain =nft_chain_lookup (table, nla[NFTA_CHAIN_NAME ], genmask); + attr = nla[NFTA_CHAIN_NAME ]; + chain =nft_chain_lookup (table, attr, genmask); } -if (IS_ERR (chain)) +if (IS_ERR (chain)) { +NL_SET_BAD_ATTR (extack, attr);return PTR_ERR (chain); + }if (nlh->nlmsg_flags &NLM_F_NONREC && chain->use >0 )
@@ -1646,8 +1678,10 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk,/* There are rules and elements that are still holding references to us, * we cannot do a recursive removal in this case. */ -if (use >0 ) +if (use >0 ) { +NL_SET_BAD_ATTR (extack, attr);return -EBUSY ; + }return nft_delchain (&ctx); }
@@ -2157,16 +2191,22 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk, } table =nft_table_lookup (net, nla[NFTA_RULE_TABLE ], family, genmask); -if (IS_ERR (table)) +if (IS_ERR (table)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_RULE_TABLE ]);return PTR_ERR (table); + } chain =nft_chain_lookup (table, nla[NFTA_RULE_CHAIN ], genmask); -if (IS_ERR (chain)) +if (IS_ERR (chain)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_RULE_CHAIN ]);return PTR_ERR (chain); + } rule =nft_rule_lookup (chain, nla[NFTA_RULE_HANDLE ]); -if (IS_ERR (rule)) +if (IS_ERR (rule)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_RULE_HANDLE ]);return PTR_ERR (rule); + } skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_KERNEL );if (!skb2)
@@ -2230,21 +2270,29 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, create = nlh->nlmsg_flags &NLM_F_CREATE ? true : false; table =nft_table_lookup (net, nla[NFTA_RULE_TABLE ], family, genmask); -if (IS_ERR (table)) +if (IS_ERR (table)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_RULE_TABLE ]);return PTR_ERR (table); + } chain =nft_chain_lookup (table, nla[NFTA_RULE_CHAIN ], genmask); -if (IS_ERR (chain)) +if (IS_ERR (chain)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_RULE_CHAIN ]);return PTR_ERR (chain); + }if (nla[NFTA_RULE_HANDLE ]) { handle =be64_to_cpu (nla_get_be64 (nla[NFTA_RULE_HANDLE ])); rule =__nft_rule_lookup (chain, handle); -if (IS_ERR (rule)) +if (IS_ERR (rule)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_RULE_HANDLE ]);return PTR_ERR (rule); + } -if (nlh->nlmsg_flags &NLM_F_EXCL ) +if (nlh->nlmsg_flags &NLM_F_EXCL ) { +NL_SET_BAD_ATTR (extack, nla[NFTA_RULE_HANDLE ]);return -EEXIST ; + }if (nlh->nlmsg_flags &NLM_F_REPLACE ) old_rule = rule;else
@@ -2264,8 +2312,10 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, pos_handle =be64_to_cpu (nla_get_be64 (nla[NFTA_RULE_POSITION ])); old_rule =__nft_rule_lookup (chain, pos_handle); -if (IS_ERR (old_rule)) +if (IS_ERR (old_rule)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_RULE_POSITION ]);return PTR_ERR (old_rule); + } }nft_ctx_init (&ctx, net, skb, nlh, family, table, chain, nla);
@@ -2399,13 +2449,17 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk,struct nft_ctx ctx; table =nft_table_lookup (net, nla[NFTA_RULE_TABLE ], family, genmask); -if (IS_ERR (table)) +if (IS_ERR (table)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_RULE_TABLE ]);return PTR_ERR (table); + }if (nla[NFTA_RULE_CHAIN ]) { chain =nft_chain_lookup (table, nla[NFTA_RULE_CHAIN ], genmask); -if (IS_ERR (chain)) +if (IS_ERR (chain)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_RULE_CHAIN ]);return PTR_ERR (chain); + } }nft_ctx_init (&ctx, net, skb, nlh, family, table, chain, nla);
@@ -2413,14 +2467,18 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk,if (chain) {if (nla[NFTA_RULE_HANDLE ]) { rule =nft_rule_lookup (chain, nla[NFTA_RULE_HANDLE ]); -if (IS_ERR (rule)) +if (IS_ERR (rule)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_RULE_HANDLE ]);return PTR_ERR (rule); + } err =nft_delrule (&ctx, rule); }else if (nla[NFTA_RULE_ID ]) { rule =nft_rule_lookup_byid (net, nla[NFTA_RULE_ID ]); -if (IS_ERR (rule)) +if (IS_ERR (rule)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_RULE_ID ]);return PTR_ERR (rule); + } err =nft_delrule (&ctx, rule); }else {
@@ -2588,6 +2646,7 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net,const struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const nla[], + struct netlink_ext_ack *extack, u8 genmask) { const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
@@ -2597,8 +2656,10 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net,if (nla[NFTA_SET_TABLE ] !=NULL ) { table =nft_table_lookup (net, nla[NFTA_SET_TABLE ], family, genmask); -if (IS_ERR (table)) +if (IS_ERR (table)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_SET_TABLE ]);return PTR_ERR (table); + } }nft_ctx_init (ctx, net, skb, nlh, family, table,NULL , nla);
@@ -2910,7 +2971,8 @@ static int nf_tables_getset(struct net *net, struct sock *nlsk,int err;/* Verify existence before starting dump */ - err =nft_ctx_init_from_setattr (&ctx, net, skb, nlh, nla, genmask); + err =nft_ctx_init_from_setattr (&ctx, net, skb, nlh, nla, extack, + genmask);if (err <0 )return err;
@@ -3090,20 +3152,27 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, create = nlh->nlmsg_flags &NLM_F_CREATE ? true : false; table =nft_table_lookup (net, nla[NFTA_SET_TABLE ], family, genmask); -if (IS_ERR (table)) +if (IS_ERR (table)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_SET_TABLE ]);return PTR_ERR (table); + }nft_ctx_init (&ctx, net, skb, nlh, family, table,NULL , nla); set =nft_set_lookup (table, nla[NFTA_SET_NAME ], genmask);if (IS_ERR (set)) { -if (PTR_ERR (set) != -ENOENT ) +if (PTR_ERR (set) != -ENOENT ) { +NL_SET_BAD_ATTR (extack, nla[NFTA_SET_NAME ]);return PTR_ERR (set); + } }else { -if (nlh->nlmsg_flags &NLM_F_EXCL ) +if (nlh->nlmsg_flags &NLM_F_EXCL ) { +NL_SET_BAD_ATTR (extack, nla[NFTA_SET_NAME ]);return -EEXIST ; + }if (nlh->nlmsg_flags &NLM_F_REPLACE )return -EOPNOTSUPP ; +return 0 ; }
@@ -3204,6 +3273,7 @@ static int nf_tables_delset(struct net *net, struct sock *nlsk, {const struct nfgenmsg *nfmsg =nlmsg_data (nlh);u8 genmask =nft_genmask_next (net); +const struct nlattr *attr;struct nft_set *set;struct nft_ctx ctx;int err;
@@ -3213,21 +3283,28 @@ static int nf_tables_delset(struct net *net, struct sock *nlsk,if (nla[NFTA_SET_TABLE ] ==NULL )return -EINVAL ; - err =nft_ctx_init_from_setattr (&ctx, net, skb, nlh, nla, genmask); + err =nft_ctx_init_from_setattr (&ctx, net, skb, nlh, nla, extack, + genmask);if (err <0 )return err; -if (nla[NFTA_SET_HANDLE ]) - set =nft_set_lookup_byhandle (ctx.table, nla[NFTA_SET_HANDLE ], - genmask); -else - set =nft_set_lookup (ctx.table, nla[NFTA_SET_NAME ], genmask); -if (IS_ERR (set)) -return PTR_ERR (set); +if (nla[NFTA_SET_HANDLE ]) { + attr = nla[NFTA_SET_HANDLE ]; + set =nft_set_lookup_byhandle (ctx.table, attr, genmask); + }else { + attr = nla[NFTA_SET_NAME ]; + set =nft_set_lookup (ctx.table, attr, genmask); + } +if (IS_ERR (set)) { +NL_SET_BAD_ATTR (extack, attr); +return PTR_ERR (set); + }if (!list_empty (&set->bindings) || - (nlh->nlmsg_flags &NLM_F_NONREC &&atomic_read (&set->nelems) >0 )) + (nlh->nlmsg_flags &NLM_F_NONREC &&atomic_read (&set->nelems) >0 )) { +NL_SET_BAD_ATTR (extack, attr);return -EBUSY ; + }return nft_delset (&ctx, set); }
@@ -3355,6 +3432,7 @@ static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net,const struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const nla[], + struct netlink_ext_ack *extack, u8 genmask) { const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
@@ -3363,8 +3441,10 @@ static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net, table =nft_table_lookup (net, nla[NFTA_SET_ELEM_LIST_TABLE ], family, genmask); -if (IS_ERR (table)) +if (IS_ERR (table)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_SET_ELEM_LIST_TABLE ]);return PTR_ERR (table); + }nft_ctx_init (ctx, net, skb, nlh, family, table,NULL , nla);return 0 ;
@@ -3694,7 +3774,8 @@ static int nf_tables_getsetelem(struct net *net, struct sock *nlsk,struct nft_ctx ctx;int rem, err =0 ; - err =nft_ctx_init_from_elemattr (&ctx, net, skb, nlh, nla, genmask); + err =nft_ctx_init_from_elemattr (&ctx, net, skb, nlh, nla, extack, + genmask);if (err <0 )return err;
@@ -4048,7 +4129,8 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk,if (nla[NFTA_SET_ELEM_LIST_ELEMENTS ] ==NULL )return -EINVAL ; - err =nft_ctx_init_from_elemattr (&ctx, net, skb, nlh, nla, genmask); + err =nft_ctx_init_from_elemattr (&ctx, net, skb, nlh, nla, extack, + genmask);if (err <0 )return err;
@@ -4236,7 +4318,8 @@ static int nf_tables_delsetelem(struct net *net, struct sock *nlsk,struct nft_ctx ctx;int rem, err =0 ; - err =nft_ctx_init_from_elemattr (&ctx, net, skb, nlh, nla, genmask); + err =nft_ctx_init_from_elemattr (&ctx, net, skb, nlh, nla, extack, + genmask);if (err <0 )return err;
@@ -4491,20 +4574,24 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,return -EINVAL ; table =nft_table_lookup (net, nla[NFTA_OBJ_TABLE ], family, genmask); -if (IS_ERR (table)) +if (IS_ERR (table)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_OBJ_TABLE ]);return PTR_ERR (table); + } objtype =ntohl (nla_get_be32 (nla[NFTA_OBJ_TYPE ])); obj =nft_obj_lookup (table, nla[NFTA_OBJ_NAME ], objtype, genmask);if (IS_ERR (obj)) { err =PTR_ERR (obj); -if (err != -ENOENT ) +if (err != -ENOENT ) { +NL_SET_BAD_ATTR (extack, nla[NFTA_OBJ_NAME ]);return err; - + } }else { -if (nlh->nlmsg_flags &NLM_F_EXCL ) +if (nlh->nlmsg_flags &NLM_F_EXCL ) { +NL_SET_BAD_ATTR (extack, nla[NFTA_OBJ_NAME ]);return -EEXIST ; - + }return 0 ; }
@@ -4716,13 +4803,17 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk,return -EINVAL ; table =nft_table_lookup (net, nla[NFTA_OBJ_TABLE ], family, genmask); -if (IS_ERR (table)) +if (IS_ERR (table)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_OBJ_TABLE ]);return PTR_ERR (table); + } objtype =ntohl (nla_get_be32 (nla[NFTA_OBJ_TYPE ])); obj =nft_obj_lookup (table, nla[NFTA_OBJ_NAME ], objtype, genmask); -if (IS_ERR (obj)) +if (IS_ERR (obj)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_OBJ_NAME ]);return PTR_ERR (obj); + } skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_KERNEL );if (!skb2)
@@ -4761,6 +4852,7 @@ static int nf_tables_delobj(struct net *net, struct sock *nlsk,const struct nfgenmsg *nfmsg =nlmsg_data (nlh);u8 genmask =nft_genmask_next (net);int family = nfmsg->nfgen_family; +const struct nlattr *attr;struct nft_table *table;struct nft_object *obj;struct nft_ctx ctx;
@@ -4771,20 +4863,28 @@ static int nf_tables_delobj(struct net *net, struct sock *nlsk,return -EINVAL ; table =nft_table_lookup (net, nla[NFTA_OBJ_TABLE ], family, genmask); -if (IS_ERR (table)) +if (IS_ERR (table)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_OBJ_TABLE ]);return PTR_ERR (table); + } objtype =ntohl (nla_get_be32 (nla[NFTA_OBJ_TYPE ])); -if (nla[NFTA_OBJ_HANDLE ]) - obj =nft_obj_lookup_byhandle (table, nla[NFTA_OBJ_HANDLE ], - objtype, genmask); -else - obj =nft_obj_lookup (table, nla[NFTA_OBJ_NAME ], objtype, - genmask); -if (IS_ERR (obj)) +if (nla[NFTA_OBJ_HANDLE ]) { + attr = nla[NFTA_OBJ_HANDLE ]; + obj =nft_obj_lookup_byhandle (table, attr, objtype, genmask); + }else { + attr = nla[NFTA_OBJ_NAME ]; + obj =nft_obj_lookup (table, attr, objtype, genmask); + } + +if (IS_ERR (obj)) { +NL_SET_BAD_ATTR (extack, attr);return PTR_ERR (obj); -if (obj->use >0 ) + } +if (obj->use >0 ) { +NL_SET_BAD_ATTR (extack, attr);return -EBUSY ; + }nft_ctx_init (&ctx, net, skb, nlh, family, table,NULL , nla);
@@ -5046,18 +5146,24 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk, table =nft_table_lookup (net, nla[NFTA_FLOWTABLE_TABLE ], family, genmask); -if (IS_ERR (table)) +if (IS_ERR (table)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_FLOWTABLE_TABLE ]);return PTR_ERR (table); + } flowtable =nft_flowtable_lookup (table, nla[NFTA_FLOWTABLE_NAME ], genmask);if (IS_ERR (flowtable)) { err =PTR_ERR (flowtable); -if (err != -ENOENT ) +if (err != -ENOENT ) { +NL_SET_BAD_ATTR (extack, nla[NFTA_FLOWTABLE_NAME ]);return err; + } }else { -if (nlh->nlmsg_flags &NLM_F_EXCL ) +if (nlh->nlmsg_flags &NLM_F_EXCL ) { +NL_SET_BAD_ATTR (extack, nla[NFTA_FLOWTABLE_NAME ]);return -EEXIST ; + }return 0 ; }
@@ -5153,6 +5259,7 @@ static int nf_tables_delflowtable(struct net *net, struct sock *nlsk,u8 genmask =nft_genmask_next (net);int family = nfmsg->nfgen_family;struct nft_flowtable *flowtable; +const struct nlattr *attr;struct nft_table *table;struct nft_ctx ctx;
@@ -5163,21 +5270,27 @@ static int nf_tables_delflowtable(struct net *net, struct sock *nlsk, table =nft_table_lookup (net, nla[NFTA_FLOWTABLE_TABLE ], family, genmask); -if (IS_ERR (table)) +if (IS_ERR (table)) { +NL_SET_BAD_ATTR (extack, nla[NFTA_FLOWTABLE_TABLE ]);return PTR_ERR (table); + } -if (nla[NFTA_FLOWTABLE_HANDLE ]) - flowtable =nft_flowtable_lookup_byhandle (table, - nla[NFTA_FLOWTABLE_HANDLE ], - genmask); -else - flowtable =nft_flowtable_lookup (table, - nla[NFTA_FLOWTABLE_NAME ], - genmask); -if (IS_ERR (flowtable)) -return PTR_ERR (flowtable); -if (flowtable->use >0 ) +if (nla[NFTA_FLOWTABLE_HANDLE ]) { + attr = nla[NFTA_FLOWTABLE_HANDLE ]; + flowtable =nft_flowtable_lookup_byhandle (table, attr, genmask); + }else { + attr = nla[NFTA_FLOWTABLE_NAME ]; + flowtable =nft_flowtable_lookup (table, attr, genmask); + } + +if (IS_ERR (flowtable)) { +NL_SET_BAD_ATTR (extack, attr); +return PTR_ERR (flowtable); + } +if (flowtable->use >0 ) { +NL_SET_BAD_ATTR (extack, attr);return -EBUSY ; + }nft_ctx_init (&ctx, net, skb, nlh, family, table,NULL , nla);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 28/51 netfilter: nf_tables: Simplify set backend selection
In reply to Pablo Neira AyusoFrom: Phil Sutter <[email protected]>
Drop nft_set_type's ability to act as a container of multiple backend implementations it chooses from. Instead consolidate the whole selection logic in nft_select_set_ops() and the actual backend provided estimate() callback.
This turns nf_tables_set_types into a list containing all available backends which is traversed when selecting one matching userspace requested criteria.
Also, this change allows to embed nft_set_ops structure into nft_set_type and pull flags field into the latter as it's only used during selection phase.
A crucial part of this change is to make sure the new layout respects hash backend constraints formerly enforced by nft_hash_select_ops()
function: This is achieved by introduction of a specific estimate() callback for nft_hash_fast_ops which returns false for key lengths != 4. In turn, nft_hash_estimate() is changed to return false for key lengths == 4 so it won't be chosen by accident. Also, both callbacks must return false for unbounded sets as their size estimate depends on a known maximum element count.
Note that this patch partially reverts commit 4f2921ca21b71 ("netfilter:nf_tables: meter: pick a set backend that supports updates") by making nft_set_ops_candidate() not explicitly look for an update callback but make NFT_SET_EVAL a regular backend feature flag which is checked along with the others. This way all feature requirements are checked in one go.
--- include/net/netfilter/nf_tables.h | 34 ++++----- net/netfilter/nf_tables_api.c | 25 +++---- net/netfilter/nft_set_bitmap.c | 34 ++++----- net/netfilter/nft_set_hash.c | 153 +++++++++++++++++++++----------------- net/netfilter/nft_set_rbtree.c | 36 ++++----- 5 files changed, 139 insertions(+), 143 deletions(-)
include/net/netfilter/nf_tables.h +15 -19
@@ -275,23 +275,6 @@ struct nft_set_estimate {enum nft_set_class space; }; -/** -* struct nft_set_type - nf_tables set type -* -* @select_ops: function to select nft_set_ops -* @ops: default ops, used when no select_ops functions is present -* @list: used internally -* @owner: module reference -*/ -struct nft_set_type { -const struct nft_set_ops *(*select_ops)(const struct nft_ctx *, -const struct nft_set_desc *desc, -u32 flags); -const struct nft_set_ops *ops; -struct list_head list; -struct module *owner; -}; -struct nft_set_ext ;struct nft_expr ;
@@ -310,7 +293,6 @@ struct nft_expr;* @init: initialize private data of new set instance * @destroy: destroy private data of set instance * @elemsize: element private size -* @features: features supported by the implementation */ struct nft_set_ops { bool (*lookup)(const struct net *net,
@@ -361,9 +343,23 @@ struct nft_set_ops {void (*destroy)(const struct nft_set *set);unsigned int elemsize; +}; + +/** +* struct nft_set_type - nf_tables set type +* +* @ops: set ops for this type +* @list: used internally +* @owner: module reference +* @features: features supported by the implementation +*/ +struct nft_set_type { +const struct nft_set_ops ops; +struct list_head list; +struct module *owner;u32 features; -const struct nft_set_type *type; }; +#define to_set_type (o) container_of(o, struct nft_set_type, ops)int nft_register_set (struct nft_set_type *type);void nft_unregister_set (struct nft_set_type *type);
net/netfilter/nf_tables_api.c +9 -16
@@ -2523,14 +2523,12 @@ void nft_unregister_set(struct nft_set_type *type)EXPORT_SYMBOL_GPL (nft_unregister_set);#define NFT_SET_FEATURES (NFT_SET_INTERVAL | NFT_SET_MAP | \ - NFT_SET_TIMEOUT | NFT_SET_OBJECT) + NFT_SET_TIMEOUT | NFT_SET_OBJECT | \ + NFT_SET_EVAL) -static bool nft_set_ops_candidate (const struct nft_set_ops *ops,u32 flags) +static bool nft_set_ops_candidate (const struct nft_set_type *type,u32 flags) { -if ((flags &NFT_SET_EVAL ) && !ops->update) -return false; - -return (flags & ops->features) == (flags &NFT_SET_FEATURES ); +return (flags & type->features) == (flags &NFT_SET_FEATURES ); }/*
@@ -2567,14 +2565,9 @@ nft_select_set_ops(const struct nft_ctx *ctx, best.space = ~0 ;list_for_each_entry (type, &nf_tables_set_types, list) { -if (!type->select_ops) - ops = type->ops; -else - ops = type->select_ops (ctx, desc, flags); -if (!ops) -continue ; + ops = &type->ops; -if (!nft_set_ops_candidate (ops, flags)) +if (!nft_set_ops_candidate (type, flags))continue ;if (!ops->estimate (desc, flags, &est))continue ;
@@ -2605,7 +2598,7 @@ nft_select_set_ops(const struct nft_ctx *ctx,if (!try_module_get (type->owner))continue ;if (bops !=NULL ) -module_put (bops->type->owner); +module_put (to_set_type (bops)->owner); bops = ops; best = est;
@@ -3247,14 +3240,14 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, err2:kvfree (set); err1: -module_put (ops->type->owner); +module_put (to_set_type (ops)->owner);return err; }static void nft_set_destroy (struct nft_set *set) { set->ops->destroy (set); -module_put (set->ops->type->owner); +module_put (to_set_type (set->ops)->owner);kfree (set->name);kvfree (set); }
net/netfilter/nft_set_bitmap.c +15 -19
@@ -296,27 +296,23 @@ static bool nft_bitmap_estimate(const struct nft_set_desc *desc, u32 features,return true; } -static struct nft_set_type nft_bitmap_type; -static struct nft_set_ops nft_bitmap_ops__read_mostly = { - .type = &nft_bitmap_type, - .privsize = nft_bitmap_privsize, - .elemsize = offsetof(struct nft_bitmap_elem , ext), - .estimate = nft_bitmap_estimate, - .init = nft_bitmap_init, - .destroy = nft_bitmap_destroy, - .insert = nft_bitmap_insert, - .remove = nft_bitmap_remove, - .deactivate = nft_bitmap_deactivate, - .flush = nft_bitmap_flush, - .activate = nft_bitmap_activate, - .lookup = nft_bitmap_lookup, - .walk = nft_bitmap_walk, - .get = nft_bitmap_get, -}; -static struct nft_set_type nft_bitmap_type__read_mostly = { - .ops = &nft_bitmap_ops, .owner =THIS_MODULE , + .ops = { + .privsize = nft_bitmap_privsize, + .elemsize = offsetof(struct nft_bitmap_elem , ext), + .estimate = nft_bitmap_estimate, + .init = nft_bitmap_init, + .destroy = nft_bitmap_destroy, + .insert = nft_bitmap_insert, + .remove = nft_bitmap_remove, + .deactivate = nft_bitmap_deactivate, + .flush = nft_bitmap_flush, + .activate = nft_bitmap_activate, + .lookup = nft_bitmap_lookup, + .walk = nft_bitmap_walk, + .get = nft_bitmap_get, + }, };static int __init nft_bitmap_module_init (void )
net/netfilter/nft_set_hash.c +84 -69
181 lines not on this page · raw message
net/netfilter/nft_set_rbtree.c +16 -20
@@ -393,28 +393,24 @@ static bool nft_rbtree_estimate(const struct nft_set_desc *desc, u32 features,return true; } -static struct nft_set_type nft_rbtree_type; -static struct nft_set_ops nft_rbtree_ops__read_mostly = { - .type = &nft_rbtree_type, - .privsize = nft_rbtree_privsize, - .elemsize = offsetof(struct nft_rbtree_elem , ext), - .estimate = nft_rbtree_estimate, - .init = nft_rbtree_init, - .destroy = nft_rbtree_destroy, - .insert = nft_rbtree_insert, - .remove = nft_rbtree_remove, - .deactivate = nft_rbtree_deactivate, - .flush = nft_rbtree_flush, - .activate = nft_rbtree_activate, - .lookup = nft_rbtree_lookup, - .walk = nft_rbtree_walk, - .get = nft_rbtree_get, - .features =NFT_SET_INTERVAL |NFT_SET_MAP |NFT_SET_OBJECT , -}; -static struct nft_set_type nft_rbtree_type__read_mostly = { - .ops = &nft_rbtree_ops, .owner =THIS_MODULE , + .features =NFT_SET_INTERVAL |NFT_SET_MAP |NFT_SET_OBJECT , + .ops = { + .privsize = nft_rbtree_privsize, + .elemsize = offsetof(struct nft_rbtree_elem , ext), + .estimate = nft_rbtree_estimate, + .init = nft_rbtree_init, + .destroy = nft_rbtree_destroy, + .insert = nft_rbtree_insert, + .remove = nft_rbtree_remove, + .deactivate = nft_rbtree_deactivate, + .flush = nft_rbtree_flush, + .activate = nft_rbtree_activate, + .lookup = nft_rbtree_lookup, + .walk = nft_rbtree_walk, + .get = nft_rbtree_get, + }, };static int __init nft_rbtree_module_init (void )
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 29/51 netfilter: add NAT support for shifted portmap ranges
In reply to Pablo Neira AyusoFrom: Thierry Du Tre <[email protected]>
This is a patch proposal to support shifted ranges in portmaps. (i.e. tcp/udp incoming port 5000-5100 on WAN redirected to LAN 192.168.1.5:2000-2100)
Currently DNAT only works for single port or identical port ranges. (i.e. ports 5000-5100 on WAN interface redirected to a LAN host while original destination port is not altered) When different port ranges are configured, either 'random' mode should be used, or else all incoming connections are mapped onto the first port in the redirect range. (in described example WAN:5000-5100 will all be mapped to 192.168.1.5:2000)
This patch introduces a new mode indicated by flag NF_NAT_RANGE_PROTO_OFFSET which uses a base port value to calculate an offset with the destination port present in the incoming stream. That offset is then applied as index within the redirect port range (index modulo rangewidth to handle range overflow).
In described example the base port would be 5000. An incoming stream with destination port 5004 would result in an offset value 4 which means that the NAT'ed stream will be using destination port 2004.
Other possibilities include deterministic mapping of larger or multiple ranges to a smaller range : WAN:5000-5999 -> LAN:5000-5099 (maps WAN port 5*xx to port 51xx)
This patch does not change any current behavior. It just adds new NAT proto range functionality which must be selected via the specific flag when intended to use.
A patch for iptables (libipt_DNAT.c + libip6t_DNAT.c) will also be proposed which makes this functionality immediately available.
--- include/net/netfilter/ipv4/nf_nat_masquerade.h | 2 +- include/net/netfilter/ipv6/nf_nat_masquerade.h | 2 +- include/net/netfilter/nf_nat.h | 2 +- include/net/netfilter/nf_nat_l3proto.h | 4 +- include/net/netfilter/nf_nat_l4proto.h | 8 +-- include/net/netfilter/nf_nat_redirect.h | 2 +- include/uapi/linux/netfilter/nf_nat.h | 12 ++++- net/ipv4/netfilter/ipt_MASQUERADE.c | 2 +- net/ipv4/netfilter/nf_nat_h323.c | 4 +- net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 4 +- net/ipv4/netfilter/nf_nat_masquerade_ipv4.c | 4 +- net/ipv4/netfilter/nf_nat_pptp.c | 2 +- net/ipv4/netfilter/nf_nat_proto_gre.c | 2 +- net/ipv4/netfilter/nf_nat_proto_icmp.c | 2 +- net/ipv4/netfilter/nft_masq_ipv4.c | 2 +- net/ipv6/netfilter/ip6t_MASQUERADE.c | 2 +- net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 4 +- net/ipv6/netfilter/nf_nat_masquerade_ipv6.c | 4 +- net/ipv6/netfilter/nf_nat_proto_icmpv6.c | 2 +- net/ipv6/netfilter/nft_masq_ipv6.c | 2 +- net/ipv6/netfilter/nft_redir_ipv6.c | 2 +- net/netfilter/nf_nat_core.c | 27 +++++----- net/netfilter/nf_nat_helper.c | 2 +- net/netfilter/nf_nat_proto_common.c | 9 ++-- net/netfilter/nf_nat_proto_dccp.c | 2 +- net/netfilter/nf_nat_proto_sctp.c | 2 +- net/netfilter/nf_nat_proto_tcp.c | 2 +- net/netfilter/nf_nat_proto_udp.c | 4 +- net/netfilter/nf_nat_proto_unknown.c | 2 +- net/netfilter/nf_nat_redirect.c | 6 +-- net/netfilter/nf_nat_sip.c | 2 +- net/netfilter/nft_nat.c | 2 +- net/netfilter/xt_NETMAP.c | 8 +-- net/netfilter/xt_REDIRECT.c | 2 +- net/netfilter/xt_nat.c | 72 +++++++++++++++++++++++--- net/openvswitch/conntrack.c | 4 +- 36 files changed, 145 insertions(+), 71 deletions(-)
include/net/netfilter/ipv4/nf_nat_masquerade.h +1 -1
@@ -6,7 +6,7 @@unsigned int nf_nat_masquerade_ipv4 (struct sk_buff *skb,unsigned int hooknum, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,const struct net_device *out);void nf_nat_masquerade_ipv4_register_notifier (void );
include/net/netfilter/ipv6/nf_nat_masquerade.h +1 -1
@@ -3,7 +3,7 @@#define _NF_NAT_MASQUERADE_IPV6_H_unsigned int -nf_nat_masquerade_ipv6 (struct sk_buff *skb,const struct nf_nat_range *range, +nf_nat_masquerade_ipv6 (struct sk_buff *skb,const struct nf_nat_range2 *range,const struct net_device *out);void nf_nat_masquerade_ipv6_register_notifier (void );void nf_nat_masquerade_ipv6_unregister_notifier (void );
include/net/netfilter/nf_nat.h +1 -1
@@ -39,7 +39,7 @@ struct nf_conn_nat {/* Set up the info structure to map into this range. */ unsigned int nf_nat_setup_info (struct nf_conn *ct, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,enum nf_nat_manip_type maniptype); extern unsigned int nf_nat_alloc_null_binding(struct nf_conn *ct,
include/net/netfilter/nf_nat_l3proto.h +2 -2
@@ -7,7 +7,7 @@ struct nf_nat_l3proto {u8 l3proto;bool (*in_range)(const struct nf_conntrack_tuple *t, -const struct nf_nat_range *range); +const struct nf_nat_range2 *range);u32 (*secure_port)(const struct nf_conntrack_tuple *t,__be16 );
@@ -33,7 +33,7 @@ struct nf_nat_l3proto { struct flowi *fl);int (*nlattr_to_range)(struct nlattr *tb[], -struct nf_nat_range *range); +struct nf_nat_range2 *range); };int nf_nat_l3proto_register (const struct nf_nat_l3proto *);
include/net/netfilter/nf_nat_l4proto.h +4 -4
@@ -34,12 +34,12 @@ struct nf_nat_l4proto {*/ void (*unique_tuple)(const struct nf_nat_l3proto *l3proto,struct nf_conntrack_tuple *tuple, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,enum nf_nat_manip_type maniptype,const struct nf_conn *ct);int (*nlattr_to_range)(struct nlattr *tb[], -struct nf_nat_range *range); +struct nf_nat_range2 *range); };/* Protocol registration. */
@@ -72,11 +72,11 @@ bool nf_nat_l4proto_in_range(const struct nf_conntrack_tuple *tuple,void nf_nat_l4proto_unique_tuple (const struct nf_nat_l3proto *l3proto,struct nf_conntrack_tuple *tuple, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,enum nf_nat_manip_type maniptype,const struct nf_conn *ct,u16 *rover);int nf_nat_l4proto_nlattr_to_range (struct nlattr *tb[], -struct nf_nat_range *range); +struct nf_nat_range2 *range);#endif /*_NF_NAT_L4PROTO_H*/
include/net/netfilter/nf_nat_redirect.h +1 -1
@@ -7,7 +7,7 @@ nf_nat_redirect_ipv4(struct sk_buff *skb,const struct nf_nat_ipv4_multi_range_compat *mr, unsigned int hooknum);unsigned int -nf_nat_redirect_ipv6 (struct sk_buff *skb,const struct nf_nat_range *range, +nf_nat_redirect_ipv6 (struct sk_buff *skb,const struct nf_nat_range2 *range,unsigned int hooknum);#endif /* _NF_NAT_REDIRECT_H_ */
include/uapi/linux/netfilter/nf_nat.h +11 -1
@@ -10,6 +10,7 @@#define NF_NAT_RANGE_PROTO_RANDOM (1 << 2)#define NF_NAT_RANGE_PERSISTENT (1 << 3)#define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4) +#define NF_NAT_RANGE_PROTO_OFFSET (1 << 5)#define NF_NAT_RANGE_PROTO_RANDOM_ALL \ (NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY)
@@ -17,7 +18,7 @@#define NF_NAT_RANGE_MASK \ (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED | \ NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PERSISTENT | \ - NF_NAT_RANGE_PROTO_RANDOM_FULLY) + NF_NAT_RANGE_PROTO_RANDOM_FULLY | NF_NAT_RANGE_PROTO_OFFSET)struct nf_nat_ipv4_range {unsigned int flags;
@@ -40,4 +41,13 @@ struct nf_nat_range { union nf_conntrack_man_proto max_proto; }; +struct nf_nat_range2 { +unsigned int flags; +union nf_inet_addr min_addr; +union nf_inet_addr max_addr; +union nf_conntrack_man_proto min_proto; +union nf_conntrack_man_proto max_proto; +union nf_conntrack_man_proto base_proto; +}; +#endif /* _NETFILTER_NF_NAT_H */
net/ipv4/netfilter/ipt_MASQUERADE.c +1 -1
@@ -47,7 +47,7 @@ static int masquerade_tg_check(const struct xt_tgchk_param *par)static unsigned int masquerade_tg (struct sk_buff *skb,const struct xt_action_param *par) { -struct nf_nat_range range; +struct nf_nat_range2 range;const struct nf_nat_ipv4_multi_range_compat *mr; mr = par->targinfo;
net/ipv4/netfilter/nf_nat_h323.c +2 -2
@@ -395,7 +395,7 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,static void ip_nat_q931_expect (struct nf_conn *new,struct nf_conntrack_expect *this) { -struct nf_nat_range range; +struct nf_nat_range2 range;if (this->tuple.src.u3.ip !=0 ) {/* Only accept calls from GK */ nf_nat_follow_master (new, this);
@@ -497,7 +497,7 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,static void ip_nat_callforwarding_expect (struct nf_conn *new,struct nf_conntrack_expect *this) { -struct nf_nat_range range; +struct nf_nat_range2 range;/* This must be a fresh one. */ BUG_ON (new->status &IPS_NAT_DONE_MASK );
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c +2 -2
@@ -63,7 +63,7 @@ static void nf_nat_ipv4_decode_session(struct sk_buff *skb,#endif /* CONFIG_XFRM */ static bool nf_nat_ipv4_in_range (const struct nf_conntrack_tuple *t, -const struct nf_nat_range *range) +const struct nf_nat_range2 *range) {return ntohl (t->src.u3.ip) >=ntohl (range->min_addr.ip) &&ntohl (t->src.u3.ip) <=ntohl (range->max_addr.ip);
@@ -143,7 +143,7 @@ static void nf_nat_ipv4_csum_recalc(struct sk_buff *skb,#if IS_ENABLED (CONFIG_NF_CT_NETLINK )static int nf_nat_ipv4_nlattr_to_range (struct nlattr *tb[], -struct nf_nat_range *range) +struct nf_nat_range2 *range) {if (tb[CTA_NAT_V4_MINIP ]) { range->min_addr.ip =nla_get_be32 (tb[CTA_NAT_V4_MINIP ]);
net/ipv4/netfilter/nf_nat_masquerade_ipv4.c +2 -2
@@ -24,13 +24,13 @@unsigned int nf_nat_masquerade_ipv4 (struct sk_buff *skb,unsigned int hooknum, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,const struct net_device *out) {struct nf_conn *ct;struct nf_conn_nat *nat;enum ip_conntrack_info ctinfo; -struct nf_nat_range newrange; +struct nf_nat_range2 newrange;const struct rtable *rt;__be32 newsrc, nh;
net/ipv4/netfilter/nf_nat_pptp.c +1 -1
@@ -48,7 +48,7 @@ static void pptp_nat_expected(struct nf_conn *ct,struct nf_conntrack_tuple t = {};const struct nf_ct_pptp_master *ct_pptp_info;const struct nf_nat_pptp *nat_pptp_info; -struct nf_nat_range range; +struct nf_nat_range2 range;struct nf_conn_nat *nat; nat =nf_ct_nat_ext_add (ct);
net/ipv4/netfilter/nf_nat_proto_gre.c +1 -1
@@ -41,7 +41,7 @@ MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");static void gre_unique_tuple (const struct nf_nat_l3proto *l3proto,struct nf_conntrack_tuple *tuple, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,enum nf_nat_manip_type maniptype,const struct nf_conn *ct) {
net/ipv4/netfilter/nf_nat_proto_icmp.c +1 -1
@@ -30,7 +30,7 @@ icmp_in_range(const struct nf_conntrack_tuple *tuple,static void icmp_unique_tuple (const struct nf_nat_l3proto *l3proto,struct nf_conntrack_tuple *tuple, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,enum nf_nat_manip_type maniptype,const struct nf_conn *ct) {
net/ipv4/netfilter/nft_masq_ipv4.c +1 -1
@@ -21,7 +21,7 @@ static void nft_masq_ipv4_eval(const struct nft_expr *expr, const struct nft_pktinfo *pkt) {struct nft_masq *priv =nft_expr_priv (expr); -struct nf_nat_range range; +struct nf_nat_range2 range;memset (&range,0 ,sizeof (range)); range.flags = priv->flags;
net/ipv6/netfilter/ip6t_MASQUERADE.c +1 -1
@@ -29,7 +29,7 @@ masquerade_tg6(struct sk_buff *skb, const struct xt_action_param *par)static int masquerade_tg6_checkentry (const struct xt_tgchk_param *par) { -const struct nf_nat_range *range = par->targinfo; +const struct nf_nat_range2 *range = par->targinfo;if (range->flags &NF_NAT_RANGE_MAP_IPS )return -EINVAL ;
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c +2 -2
@@ -62,7 +62,7 @@ static void nf_nat_ipv6_decode_session(struct sk_buff *skb,#endif static bool nf_nat_ipv6_in_range (const struct nf_conntrack_tuple *t, -const struct nf_nat_range *range) +const struct nf_nat_range2 *range) {return ipv6_addr_cmp (&t->src.u3.in6, &range->min_addr.in6) >=0 &&ipv6_addr_cmp (&t->src.u3.in6, &range->max_addr.in6) <=0 ;
@@ -151,7 +151,7 @@ static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb,#if IS_ENABLED (CONFIG_NF_CT_NETLINK )static int nf_nat_ipv6_nlattr_to_range (struct nlattr *tb[], -struct nf_nat_range *range) +struct nf_nat_range2 *range) {if (tb[CTA_NAT_V6_MINIP ]) { nla_memcpy(&range->min_addr.ip6, tb[CTA_NAT_V6_MINIP],
net/ipv6/netfilter/nf_nat_masquerade_ipv6.c +2 -2
@@ -26,14 +26,14 @@static atomic_t v6_worker_count;unsigned int -nf_nat_masquerade_ipv6 (struct sk_buff *skb,const struct nf_nat_range *range, +nf_nat_masquerade_ipv6 (struct sk_buff *skb,const struct nf_nat_range2 *range,const struct net_device *out) {enum ip_conntrack_info ctinfo;struct nf_conn_nat *nat;struct in6_addr src;struct nf_conn *ct; -struct nf_nat_range newrange; +struct nf_nat_range2 newrange; ct =nf_ct_get (skb, &ctinfo); WARN_ON(!(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
net/ipv6/netfilter/nf_nat_proto_icmpv6.c +1 -1
@@ -32,7 +32,7 @@ icmpv6_in_range(const struct nf_conntrack_tuple *tuple,static void icmpv6_unique_tuple (const struct nf_nat_l3proto *l3proto,struct nf_conntrack_tuple *tuple, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,enum nf_nat_manip_type maniptype,const struct nf_conn *ct) {
net/ipv6/netfilter/nft_masq_ipv6.c +1 -1
@@ -22,7 +22,7 @@ static void nft_masq_ipv6_eval(const struct nft_expr *expr, const struct nft_pktinfo *pkt) {struct nft_masq *priv =nft_expr_priv (expr); -struct nf_nat_range range; +struct nf_nat_range2 range;memset (&range,0 ,sizeof (range)); range.flags = priv->flags;
net/ipv6/netfilter/nft_redir_ipv6.c +1 -1
@@ -22,7 +22,7 @@ static void nft_redir_ipv6_eval(const struct nft_expr *expr, const struct nft_pktinfo *pkt) {struct nft_redir *priv =nft_expr_priv (expr); -struct nf_nat_range range; +struct nf_nat_range2 range;memset (&range,0 ,sizeof (range));if (priv->sreg_proto_min) {
net/netfilter/nf_nat_core.c +14 -13
@@ -157,7 +157,7 @@ EXPORT_SYMBOL(nf_nat_used_tuple);static int in_range (const struct nf_nat_l3proto *l3proto,const struct nf_nat_l4proto *l4proto,const struct nf_conntrack_tuple *tuple, -const struct nf_nat_range *range) +const struct nf_nat_range2 *range) {/* If we are supposed to map IPs, then we must be in the * range specified, otherwise let this drag us onto a new src IP.
@@ -194,7 +194,7 @@ find_appropriate_src(struct net *net,const struct nf_nat_l4proto *l4proto, const struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple *result, - const struct nf_nat_range *range) + const struct nf_nat_range2 *range) { unsigned int h = hash_by_src(net, tuple);const struct nf_conn *ct;
@@ -224,7 +224,7 @@ find_appropriate_src(struct net *net,static void find_best_ips_proto (const struct nf_conntrack_zone *zone,struct nf_conntrack_tuple *tuple, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,const struct nf_conn *ct,enum nf_nat_manip_type maniptype) {
@@ -298,7 +298,7 @@ find_best_ips_proto(const struct nf_conntrack_zone *zone,static void get_unique_tuple (struct nf_conntrack_tuple *tuple,const struct nf_conntrack_tuple *orig_tuple, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,struct nf_conn *ct,enum nf_nat_manip_type maniptype) {
@@ -349,9 +349,10 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,/* Only bother mapping if it's not already in range and unique */ if (!(range->flags &NF_NAT_RANGE_PROTO_RANDOM_ALL )) {if (range->flags &NF_NAT_RANGE_PROTO_SPECIFIED ) { -if (l4proto->in_range (tuple, maniptype, - &range->min_proto, - &range->max_proto) && +if (!(range->flags &NF_NAT_RANGE_PROTO_OFFSET ) && + l4proto->in_range (tuple, maniptype, + &range->min_proto, + &range->max_proto) && (range->min_proto.all == range->max_proto.all || !nf_nat_used_tuple (tuple, ct))) goto out;
@@ -360,7 +361,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, } } -/* Last change: get protocol to try to obtain unique tuple. */ +/* Last chance: get protocol to try to obtain unique tuple. */ l4proto->unique_tuple (l3proto, tuple, range, maniptype, ct); out:rcu_read_unlock ();
@@ -381,7 +382,7 @@ EXPORT_SYMBOL_GPL(nf_ct_nat_ext_add);unsigned int nf_nat_setup_info (struct nf_conn *ct, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,enum nf_nat_manip_type maniptype) {struct net *net =nf_ct_net (ct);
@@ -459,7 +460,7 @@ __nf_nat_alloc_null_binding(struct nf_conn *ct, enum nf_nat_manip_type manip) (manip ==NF_NAT_MANIP_SRC ? ct->tuplehash[IP_CT_DIR_REPLY ].tuple.dst.u3 : ct->tuplehash[IP_CT_DIR_REPLY ].tuple.src.u3); -struct nf_nat_range range = { +struct nf_nat_range2 range = { .flags =NF_NAT_RANGE_MAP_IPS , .min_addr = ip, .max_addr = ip,
@@ -702,7 +703,7 @@ static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = {static int nfnetlink_parse_nat_proto (struct nlattr *attr,const struct nf_conn *ct, -struct nf_nat_range *range) +struct nf_nat_range2 *range) {struct nlattr *tb[CTA_PROTONAT_MAX +1 ];const struct nf_nat_l4proto *l4proto;
@@ -730,7 +731,7 @@ static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = {static int nfnetlink_parse_nat (const struct nlattr *nat, -const struct nf_conn *ct,struct nf_nat_range *range, +const struct nf_conn *ct,struct nf_nat_range2 *range,const struct nf_nat_l3proto *l3proto) {struct nlattr *tb[CTA_NAT_MAX +1 ];
@@ -758,7 +759,7 @@ nfnetlink_parse_nat_setup(struct nf_conn *ct,enum nf_nat_manip_type manip, const struct nlattr *attr) { - struct nf_nat_range range; + struct nf_nat_range2 range;const struct nf_nat_l3proto *l3proto;int err;
net/netfilter/nf_nat_helper.c +1 -1
@@ -191,7 +191,7 @@ EXPORT_SYMBOL(nf_nat_mangle_udp_packet);void nf_nat_follow_master (struct nf_conn *ct,struct nf_conntrack_expect *exp) { -struct nf_nat_range range; +struct nf_nat_range2 range;/* This must be a fresh one. */ BUG_ON (ct->status &IPS_NAT_DONE_MASK );
net/netfilter/nf_nat_proto_common.c +6 -3
@@ -36,7 +36,7 @@ EXPORT_SYMBOL_GPL(nf_nat_l4proto_in_range);void nf_nat_l4proto_unique_tuple (const struct nf_nat_l3proto *l3proto,struct nf_conntrack_tuple *tuple, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,enum nf_nat_manip_type maniptype,const struct nf_conn *ct,u16 *rover)
@@ -83,6 +83,8 @@ void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto, : tuple->src.u.all); }else if (range->flags &NF_NAT_RANGE_PROTO_RANDOM_FULLY ) { off =prandom_u32 (); + }else if (range->flags &NF_NAT_RANGE_PROTO_OFFSET ) { + off = (ntohs (*portptr) -ntohs (range->base_proto.all)); }else { off = *rover; }
@@ -91,7 +93,8 @@ void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto, *portptr =htons (min + off % range_size);if (++i != range_size &&nf_nat_used_tuple (tuple, ct))continue ; -if (!(range->flags &NF_NAT_RANGE_PROTO_RANDOM_ALL )) +if (!(range->flags & (NF_NAT_RANGE_PROTO_RANDOM_ALL | +NF_NAT_RANGE_PROTO_OFFSET ))) *rover = off;return ; }
@@ -100,7 +103,7 @@ EXPORT_SYMBOL_GPL(nf_nat_l4proto_unique_tuple);#if IS_ENABLED (CONFIG_NF_CT_NETLINK )int nf_nat_l4proto_nlattr_to_range (struct nlattr *tb[], -struct nf_nat_range *range) +struct nf_nat_range2 *range) {if (tb[CTA_PROTONAT_PORT_MIN ]) { range->min_proto.all =nla_get_be16 (tb[CTA_PROTONAT_PORT_MIN ]);
net/netfilter/nf_nat_proto_dccp.c +1 -1
@@ -23,7 +23,7 @@ static u_int16_t dccp_port_rover;static void dccp_unique_tuple (const struct nf_nat_l3proto *l3proto,struct nf_conntrack_tuple *tuple, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,enum nf_nat_manip_type maniptype,const struct nf_conn *ct) {
net/netfilter/nf_nat_proto_sctp.c +1 -1
@@ -17,7 +17,7 @@ static u_int16_t nf_sctp_port_rover;static void sctp_unique_tuple (const struct nf_nat_l3proto *l3proto,struct nf_conntrack_tuple *tuple, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,enum nf_nat_manip_type maniptype,const struct nf_conn *ct) {
net/netfilter/nf_nat_proto_tcp.c +1 -1
@@ -23,7 +23,7 @@ static u16 tcp_port_rover;static void tcp_unique_tuple (const struct nf_nat_l3proto *l3proto,struct nf_conntrack_tuple *tuple, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,enum nf_nat_manip_type maniptype,const struct nf_conn *ct) {
net/netfilter/nf_nat_proto_udp.c +2 -2
@@ -22,7 +22,7 @@ static u16 udp_port_rover;static void udp_unique_tuple (const struct nf_nat_l3proto *l3proto,struct nf_conntrack_tuple *tuple, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,enum nf_nat_manip_type maniptype,const struct nf_conn *ct) {
@@ -100,7 +100,7 @@ static bool udplite_manip_pkt(struct sk_buff *skb,static void udplite_unique_tuple (const struct nf_nat_l3proto *l3proto,struct nf_conntrack_tuple *tuple, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,enum nf_nat_manip_type maniptype,const struct nf_conn *ct) {
net/netfilter/nf_nat_proto_unknown.c +1 -1
@@ -27,7 +27,7 @@ static bool unknown_in_range(const struct nf_conntrack_tuple *tuple,static void unknown_unique_tuple (const struct nf_nat_l3proto *l3proto,struct nf_conntrack_tuple *tuple, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,enum nf_nat_manip_type maniptype,const struct nf_conn *ct) {
net/netfilter/nf_nat_redirect.c +3 -3
@@ -36,7 +36,7 @@ nf_nat_redirect_ipv4(struct sk_buff *skb,struct nf_conn *ct;enum ip_conntrack_info ctinfo;__be32 newdst; -struct nf_nat_range newrange; +struct nf_nat_range2 newrange;WARN_ON (hooknum !=NF_INET_PRE_ROUTING && hooknum !=NF_INET_LOCAL_OUT );
@@ -82,10 +82,10 @@ EXPORT_SYMBOL_GPL(nf_nat_redirect_ipv4);static const struct in6_addr loopback_addr =IN6ADDR_LOOPBACK_INIT ;unsigned int -nf_nat_redirect_ipv6 (struct sk_buff *skb,const struct nf_nat_range *range, +nf_nat_redirect_ipv6 (struct sk_buff *skb,const struct nf_nat_range2 *range,unsigned int hooknum) { -struct nf_nat_range newrange; +struct nf_nat_range2 newrange;struct in6_addr newdst;enum ip_conntrack_info ctinfo;struct nf_conn *ct;
net/netfilter/nf_nat_sip.c +1 -1
@@ -316,7 +316,7 @@ static void nf_nat_sip_seq_adjust(struct sk_buff *skb, unsigned int protoff,static void nf_nat_sip_expected (struct nf_conn *ct,struct nf_conntrack_expect *exp) { -struct nf_nat_range range; +struct nf_nat_range2 range;/* This must be a fresh one. */ BUG_ON (ct->status &IPS_NAT_DONE_MASK );
net/netfilter/nft_nat.c +1 -1
@@ -43,7 +43,7 @@ static void nft_nat_eval(const struct nft_expr *expr,const struct nft_nat *priv =nft_expr_priv (expr);enum ip_conntrack_info ctinfo;struct nf_conn *ct =nf_ct_get (pkt->skb, &ctinfo); -struct nf_nat_range range; +struct nf_nat_range2 range;memset (&range,0 ,sizeof (range));if (priv->sreg_addr_min) {
net/netfilter/xt_NETMAP.c +4 -4
@@ -21,8 +21,8 @@static unsigned int netmap_tg6 (struct sk_buff *skb,const struct xt_action_param *par) { -const struct nf_nat_range *range = par->targinfo; -struct nf_nat_range newrange; +const struct nf_nat_range2 *range = par->targinfo; +struct nf_nat_range2 newrange;struct nf_conn *ct;enum ip_conntrack_info ctinfo;union nf_inet_addr new_addr, netmask;
@@ -56,7 +56,7 @@ netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par)static int netmap_tg6_checkentry (const struct xt_tgchk_param *par) { -const struct nf_nat_range *range = par->targinfo; +const struct nf_nat_range2 *range = par->targinfo;if (!(range->flags &NF_NAT_RANGE_MAP_IPS ))return -EINVAL ;
@@ -75,7 +75,7 @@ netmap_tg4(struct sk_buff *skb, const struct xt_action_param *par)enum ip_conntrack_info ctinfo;__be32 new_ip, netmask;const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; -struct nf_nat_range newrange; +struct nf_nat_range2 newrange; WARN_ON(xt_hooknum(par) != NF_INET_PRE_ROUTING && xt_hooknum(par) != NF_INET_POST_ROUTING &&
net/netfilter/xt_REDIRECT.c +1 -1
@@ -36,7 +36,7 @@ redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par)static int redirect_tg6_checkentry (const struct xt_tgchk_param *par) { -const struct nf_nat_range *range = par->targinfo; +const struct nf_nat_range2 *range = par->targinfo;if (range->flags &NF_NAT_RANGE_MAP_IPS )return -EINVAL ;
net/netfilter/xt_nat.c +66 -6
117 lines not on this page · raw message
net/openvswitch/conntrack.c +2 -2
@@ -72,7 +72,7 @@ struct ovs_conntrack_info {struct md_mark mark;struct md_labels labels;#ifdef CONFIG_NF_NAT_NEEDED -struct nf_nat_range range;/* Only present for SRC NAT and DST NAT. */ +struct nf_nat_range2 range;/* Only present for SRC NAT and DST NAT. */ #endif };
@@ -710,7 +710,7 @@ static bool skb_nfct_cached(struct net *net,*/ static int ovs_ct_nat_execute (struct sk_buff *skb,struct nf_conn *ct,enum ip_conntrack_info ctinfo, -const struct nf_nat_range *range, +const struct nf_nat_range2 *range,enum nf_nat_manip_type maniptype) {int hooknum, nh_off, err =NF_ACCEPT ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 30/51 netfilter: add __exit mark to helper modules
In reply to Pablo Neira AyusoFrom: Taehee Yoo <[email protected]>
There are no __exit mark in the helper modules. because these exit functions used to be called by init function but now that is not. so we can add __exit mark.
--- net/netfilter/nf_conntrack_ftp.c | 3 +-- net/netfilter/nf_conntrack_irc.c | 6 +----- net/netfilter/nf_conntrack_sane.c | 3 +-- net/netfilter/nf_conntrack_sip.c | 2 +- net/netfilter/nf_conntrack_tftp.c | 2 +- 5 files changed, 5 insertions(+), 11 deletions(-)
net/netfilter/nf_conntrack_ftp.c +1 -2
@@ -566,8 +566,7 @@ static const struct nf_conntrack_expect_policy ftp_exp_policy = { .timeout = 5 * 60, }; -/* don't make this __exit, since it's called from __init ! */ -static void nf_conntrack_ftp_fini (void ) +static void __exit nf_conntrack_ftp_fini(void) {nf_conntrack_helpers_unregister (ftp, ports_c *2 );kfree (ftp_buffer);
net/netfilter/nf_conntrack_irc.c +1 -5
@@ -232,8 +232,6 @@ static int help(struct sk_buff *skb, unsigned int protoff,static struct nf_conntrack_helper irc[MAX_PORTS ]__read_mostly ;static struct nf_conntrack_expect_policy irc_exp_policy; -static void nf_conntrack_irc_fini (void ); -static int __init nf_conntrack_irc_init (void ) {int i, ret;
@@ -276,9 +274,7 @@ static int __init nf_conntrack_irc_init(void)return 0 ; } -/* This function is intentionally _NOT_ defined as __exit, because -* it is needed by the init function */ -static void nf_conntrack_irc_fini (void ) +static void __exit nf_conntrack_irc_fini(void) {nf_conntrack_helpers_unregister (irc, ports_c);kfree (irc_buffer);
net/netfilter/nf_conntrack_sane.c +1 -2
@@ -173,8 +173,7 @@ static const struct nf_conntrack_expect_policy sane_exp_policy = { .timeout = 5 * 60, }; -/* don't make this __exit, since it's called from __init ! */ -static void nf_conntrack_sane_fini (void ) +static void __exit nf_conntrack_sane_fini(void) {nf_conntrack_helpers_unregister (sane, ports_c *2 );kfree (sane_buffer);
net/netfilter/nf_conntrack_sip.c +1 -1
@@ -1609,7 +1609,7 @@ static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1 }, }; -static void nf_conntrack_sip_fini (void ) +static void __exit nf_conntrack_sip_fini(void) {nf_conntrack_helpers_unregister (sip, ports_c *4 ); }
net/netfilter/nf_conntrack_tftp.c +1 -1
@@ -104,7 +104,7 @@ static const struct nf_conntrack_expect_policy tftp_exp_policy = { .timeout = 5 * 60, }; -static void nf_conntrack_tftp_fini (void ) +static void __exit nf_conntrack_tftp_fini(void) {nf_conntrack_helpers_unregister (tftp, ports_c *2 ); }
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 31/51 netfilter: ebtables: add ebt_free_table_info function
In reply to Pablo Neira AyusoFrom: Taehee Yoo <[email protected]>
A ebt_free_table_info frees all of chainstacks. It similar to xt_free_table_info. this inline function reduces code line.
--- net/bridge/netfilter/ebtables.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-)
net/bridge/netfilter/ebtables.c +15 -24
@@ -343,6 +343,16 @@ find_table_lock(struct net *net, const char *name, int *error, "ebtable_", error, mutex); } +static inline void ebt_free_table_info (struct ebt_table_info *info) +{ +int i; + +if (info->chainstack) { +for_each_possible_cpu (i) +vfree (info->chainstack[i]); +vfree (info->chainstack); + } +}static inline int ebt_check_match (struct ebt_entry_match *m,struct xt_mtchk_param *par,unsigned int *cnt)
@@ -975,7 +985,7 @@ static void get_counters(const struct ebt_counter *oldcounters,static int do_replace_finish (struct net *net,struct ebt_replace *repl,struct ebt_table_info *newinfo) { -int ret, i; +int ret;struct ebt_counter *counterstmp =NULL ;/* used to be able to unlock earlier */ struct ebt_table_info *table;
@@ -1051,13 +1061,8 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl, ebt_cleanup_entry, net, NULL);vfree (table->entries); -if (table->chainstack) { -for_each_possible_cpu (i) -vfree (table->chainstack[i]); -vfree (table->chainstack); - } +ebt_free_table_info (table);vfree (table); -vfree (counterstmp);#ifdef CONFIG_AUDIT
@@ -1078,11 +1083,7 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl, free_counterstmp:vfree (counterstmp);/* can be initialized in translate_table() */ -if (newinfo->chainstack) { -for_each_possible_cpu (i) -vfree (newinfo->chainstack[i]); -vfree (newinfo->chainstack); - } +ebt_free_table_info (newinfo);return ret; }
@@ -1147,8 +1148,6 @@ static int do_replace(struct net *net, const void __user *user,static void __ebt_unregister_table (struct net *net,struct ebt_table *table) { -int i; -mutex_lock (&ebt_mutex);list_del (&table->list);mutex_unlock (&ebt_mutex);
@@ -1157,11 +1156,7 @@ static void __ebt_unregister_table(struct net *net, struct ebt_table *table)if (table->private->nentries)module_put (table->me);vfree (table->private->entries); -if (table->private->chainstack) { -for_each_possible_cpu (i) -vfree (table->private->chainstack[i]); -vfree (table->private->chainstack); - } +ebt_free_table_info (table->private);vfree (table->private);kfree (table); }
@@ -1263,11 +1258,7 @@ int ebt_register_table(struct net *net, const struct ebt_table *input_table, free_unlock:mutex_unlock (&ebt_mutex); free_chainstack: -if (newinfo->chainstack) { -for_each_possible_cpu (i) -vfree (newinfo->chainstack[i]); -vfree (newinfo->chainstack); - } +ebt_free_table_info (newinfo);vfree (newinfo->entries); free_newinfo:vfree (newinfo);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 32/51 netfilter: ebtables: remove EBT_MATCH and EBT_NOMATCH
In reply to Pablo Neira AyusoFrom: Taehee Yoo <[email protected]>
EBT_MATCH and EBT_NOMATCH are used to change return value. match functions(ebt_xxx.c) return false when received frame is not matched and returns true when received frame is matched.
but, EBT_MATCH_ITERATE understands oppositely.
so, to change return value, EBT_MATCH and EBT_NOMATCH are used. but, we can use operation '!' simply.
--- include/linux/netfilter_bridge/ebtables.h | 4 ---- net/bridge/netfilter/ebtables.c | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-)
include/linux/netfilter_bridge/ebtables.h +0 -4
@@ -17,10 +17,6 @@#include <linux/if_ether.h> #include <uapi/linux/netfilter_bridge/ebtables.h> -/* return values for match() functions */ -#define EBT_MATCH 0 -#define EBT_NOMATCH 1 -struct ebt_match {struct list_head list;const char name[EBT_FUNCTION_MAXNAMELEN ];
net/bridge/netfilter/ebtables.c +1 -1
@@ -101,7 +101,7 @@ ebt_do_match(struct ebt_entry_match *m, const struct sk_buff *skb, { par->match = m->u.match; par->matchinfo = m->data; -return m->u.match->match (skb, par) ?EBT_MATCH :EBT_NOMATCH ; +return !m->u.match->match (skb, par); } static inline int
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 33/51 netfilter: x_tables: remove duplicate ip6t_get_target function call
In reply to Pablo Neira AyusoFrom: Taehee Yoo <[email protected]>
In the check_target, ip6t_get_target is called twice.
--- net/ipv6/netfilter/ip6_tables.c | 1 - 1 file changed, 1 deletion(-)
net/ipv6/netfilter/ip6_tables.c +0 -1
@@ -528,7 +528,6 @@ static int check_target(struct ip6t_entry *e, struct net *net, const char *name) .family = NFPROTO_IPV6, }; - t =ip6t_get_target (e);return xt_check_target (&par, t->u.target_size -sizeof (*t), e->ipv6.proto, e->ipv6.invflags &IP6T_INV_PROTO );
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 34/51 netfilter: ebtables: add ebt_get_target and ebt_get_target_c
In reply to Pablo Neira AyusoFrom: Taehee Yoo <[email protected]>
ebt_get_target similar to {ip/ip6/arp}t_get_target. and ebt_get_target_c similar to {ip/ip6/arp}t_get_target_c.
--- include/uapi/linux/netfilter_bridge/ebtables.h | 6 ++++++ net/bridge/netfilter/ebtables.c | 22 +++++++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-)
include/uapi/linux/netfilter_bridge/ebtables.h +6 -0
@@ -191,6 +191,12 @@ struct ebt_entry { unsigned char elems[0] __attribute__ ((aligned (__alignof__(struct ebt_replace)))); }; +static __inline__struct ebt_entry_target * +ebt_get_target (struct ebt_entry *e) +{ +return (void *)e + e->target_offset; +} +/* {g,s}etsockopt numbers */ #define EBT_BASE_CTL 128
net/bridge/netfilter/ebtables.c +13 -9
@@ -177,6 +177,12 @@ struct ebt_entry *ebt_next_entry(const struct ebt_entry *entry)return (void *)entry + entry->next_offset; } +static inline const struct ebt_entry_target * +ebt_get_target_c (const struct ebt_entry *e) +{ +return ebt_get_target ((struct ebt_entry *)e); +} +/* Do some firewalling */ unsigned int ebt_do_table(struct sk_buff *skb, const struct nf_hook_state *state,
@@ -230,8 +236,7 @@ unsigned int ebt_do_table(struct sk_buff *skb,*/ EBT_WATCHER_ITERATE (point, ebt_do_watcher, skb, &acpar); - t = (struct ebt_entry_target *) - (((char *)point) + point->target_offset); + t =ebt_get_target_c (point);/* standard target */ if (!t->u.target->target) verdict = ((struct ebt_standard_target *)t)->verdict;
@@ -637,7 +642,7 @@ ebt_cleanup_entry(struct ebt_entry *e, struct net *net, unsigned int *cnt)return 1 ;EBT_WATCHER_ITERATE (e, ebt_cleanup_watcher, net,NULL );EBT_MATCH_ITERATE (e, ebt_cleanup_match, net,NULL ); - t = (struct ebt_entry_target *)(((char *)e) + e->target_offset); + t =ebt_get_target (e); par.net = net; par.target = t->u.target;
@@ -716,7 +721,7 @@ ebt_check_entry(struct ebt_entry *e, struct net *net, ret =EBT_WATCHER_ITERATE (e, ebt_check_watcher, &tgpar, &j);if (ret !=0 ) goto cleanup_watchers; - t = (struct ebt_entry_target *)(((char *)e) + e->target_offset); + t =ebt_get_target (e); gap = e->next_offset - e->target_offset; target =xt_request_find_target (NFPROTO_BRIDGE , t->u.name,0 );
@@ -789,8 +794,7 @@ static int check_chainloops(const struct ebt_entries *chain, struct ebt_cl_stackif (pos == nentries)continue ; } - t = (struct ebt_entry_target *) - (((char *)e) + e->target_offset); + t =ebt_get_target_c (e);if (strcmp (t->u.name,EBT_STANDARD_TARGET )) goto letscontinue; if (e->target_offset + sizeof(struct ebt_standard_target) >
@@ -1396,7 +1400,7 @@ static inline int ebt_entry_to_user(struct ebt_entry *e, const char *base,return -EFAULT ; hlp = ubase + (((char *)e + e->target_offset) - base); - t = (struct ebt_entry_target *)(((char *)e) + e->target_offset); + t =ebt_get_target_c (e); ret =EBT_MATCH_ITERATE (e, ebt_match_to_user, base, ubase);if (ret !=0 )
@@ -1737,7 +1741,7 @@ static int compat_copy_entry_to_user(struct ebt_entry *e, void __user **dstptr,return ret; target_offset = e->target_offset - (origsize - *size); - t = (struct ebt_entry_target *) ((char *) e + e->target_offset); + t =ebt_get_target (e); ret =compat_target_to_user (t, dstptr, size);if (ret)
@@ -1785,7 +1789,7 @@ static int compat_calc_entry(const struct ebt_entry *e,EBT_MATCH_ITERATE (e, compat_calc_match, &off);EBT_WATCHER_ITERATE (e, compat_calc_watcher, &off); - t = (const struct ebt_entry_target *) ((char *) e + e->target_offset); + t =ebt_get_target_c (e); off +=xt_compat_target_offset (t->u.target); off +=ebt_compat_entry_padsize ();
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 35/51 netfilter: xtables: use ipt_get_target_c instead of ipt_get_target
In reply to Pablo Neira AyusoFrom: Taehee Yoo <[email protected]>
ipt_get_target is used to get struct xt_entry_target
and ipt_get_target_c is used to get const struct xt_entry_target. However in the ipt_do_table, ipt_get_target is used to get const struct xt_entry_target. it should be replaced by ipt_get_target_c.
--- net/ipv4/netfilter/ip_tables.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/netfilter/ip_tables.c +1 -1
@@ -300,7 +300,7 @@ ipt_do_table(struct sk_buff *skb, counter =xt_get_this_cpu_counter (&e->counters);ADD_COUNTER (*counter, skb->len,1 ); - t =ipt_get_target (e); + t =ipt_get_target_c (e);WARN_ON (!t->u.kernel.target);#if IS_ENABLED (CONFIG_NETFILTER_XT_TARGET_TRACE )
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 36/51 netfilter: nf_tables: support timeouts larger than 23 days
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
Marco De Benedetto says:
I would like to use a timeout of 30 days for elements in a set but it seems there is a some kind of problem above 24d20h31m23s.
Fix this by using 'jiffies64' for timeout handling to get same behaviour on 32 and 64bit systems.
nftables passes timeouts as u64 in milliseconds to the kernel, but on kernel side we used a mixture of 'long' and jiffies conversions rather than u64 and jiffies64.
Bugzilla: https://bugzilla.netfilter.org/show_bug.cgi?id=1237
--- include/net/netfilter/nf_tables.h | 4 ++-- net/netfilter/nf_tables_api.c | 50 +++++++++++++++++++++++++++++---------- 2 files changed, 39 insertions(+), 15 deletions(-)
include/net/netfilter/nf_tables.h +2 -2
@@ -585,7 +585,7 @@ static inline u64 *nft_set_ext_timeout(const struct nft_set_ext *ext)return nft_set_ext (ext,NFT_SET_EXT_TIMEOUT ); } -static inline unsigned long *nft_set_ext_expiration (const struct nft_set_ext *ext) +static inline u64 *nft_set_ext_expiration (const struct nft_set_ext *ext) {return nft_set_ext (ext,NFT_SET_EXT_EXPIRATION ); }
@@ -603,7 +603,7 @@ static inline struct nft_expr *nft_set_ext_expr(const struct nft_set_ext *ext)static inline bool nft_set_elem_expired (const struct nft_set_ext *ext) {return nft_set_ext_exists (ext,NFT_SET_EXT_EXPIRATION ) && -time_is_before_eq_jiffies (*nft_set_ext_expiration (ext)); +time_is_before_eq_jiffies64 (*nft_set_ext_expiration (ext)); } static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set,
net/netfilter/nf_tables_api.c +37 -13
103 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 37/51 netfilter: nf_tables: always use an upper set size for dynsets
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
nft rejects rules that lack a timeout and a size limit when they're used to add elements from packet path.
Pick a sane upperlimit instead of rejecting outright.
The upperlimit is visible to userspace, just as if it would have been given during set declaration.
--- net/netfilter/nft_dynset.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
net/netfilter/nft_dynset.c +4 -1
@@ -36,7 +36,7 @@ static void *nft_dynset_new(struct nft_set *set, const struct nft_expr *expr,u64 timeout;void *elem; -if (set->size && !atomic_add_unless (&set->nelems,1 , set->size)) +if (!atomic_add_unless (&set->nelems,1 , set->size))return NULL ; timeout = priv->timeout ? : set->timeout;
@@ -216,6 +216,9 @@ static int nft_dynset_init(const struct nft_ctx *ctx,if (err <0 ) goto err1; +if (set->size ==0 ) + set->size =0xffff ; + priv->set = set;return 0 ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 38/51 netfilter: merge meta_bridge into nft_meta
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
It overcomplicates things for no reason.nft_meta_bridge only offers retrieval of bridge port interface name.
Because of this being its own module, we had to export all nft_meta functions, which we can then make static again (which even reduces the size of nft_meta -- including bridge port retrieval...):
before:
text data bss dec hex filename
1838 832 0 2670 a6e net/bridge/netfilter/nft_meta_bridge.ko 6147 936 1 7084 1bac net/netfilter/nft_meta.ko
after:
5826 936 1 6763 1a6b net/netfilter/nft_meta.ko
--- include/net/netfilter/nft_meta.h | 44 ----------- net/bridge/netfilter/Kconfig | 7 -- net/bridge/netfilter/Makefile | 1 - net/bridge/netfilter/nft_meta_bridge.c | 135 --------------------------------- net/netfilter/nft_meta.c | 90 ++++++++++++++-------- 5 files changed, 58 insertions(+), 219 deletions(-) delete mode 100644 include/net/netfilter/nft_meta.h delete mode 100644 net/bridge/netfilter/nft_meta_bridge.c
include/net/netfilter/nft_meta.h deleted +0 -44
@@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _NFT_META_H_ -#define _NFT_META_H_ - -struct nft_meta { -enum nft_meta_keys key:8 ; -union { -enum nft_registers dreg:8 ; -enum nft_registers sreg:8 ; - }; -}; - -extern const struct nla_policy nft_meta_policy[]; - -int nft_meta_get_init (const struct nft_ctx *ctx, -const struct nft_expr *expr, -const struct nlattr *const tb[]); - -int nft_meta_set_init (const struct nft_ctx *ctx, -const struct nft_expr *expr, -const struct nlattr *const tb[]); - -int nft_meta_get_dump (struct sk_buff *skb, -const struct nft_expr *expr); - -int nft_meta_set_dump (struct sk_buff *skb, -const struct nft_expr *expr); - -void nft_meta_get_eval (const struct nft_expr *expr, -struct nft_regs *regs, -const struct nft_pktinfo *pkt); - -void nft_meta_set_eval (const struct nft_expr *expr, -struct nft_regs *regs, -const struct nft_pktinfo *pkt); - -void nft_meta_set_destroy (const struct nft_ctx *ctx, -const struct nft_expr *expr); - -int nft_meta_set_validate (const struct nft_ctx *ctx, -const struct nft_expr *expr, -const struct nft_data **data); - -#endif
net/bridge/netfilter/Kconfig +0 -7
@@ -8,13 +8,6 @@ menuconfig NF_TABLES_BRIDGE bool "Ethernet Bridge nf_tables support" if NF_TABLES_BRIDGE - -config NFT_BRIDGE_META - tristate "Netfilter nf_table bridge meta support" - depends on NFT_META - help - Add support for bridge dedicated meta key. - config NFT_BRIDGE_REJECT tristate "Netfilter nf_tables bridge reject support" depends on NFT_REJECT && NFT_REJECT_IPV4 && NFT_REJECT_IPV6
net/bridge/netfilter/Makefile +0 -1
@@ -3,7 +3,6 @@ # Makefile for the netfilter modules for Link Layer filtering on a bridge. # -obj-$(CONFIG_NFT_BRIDGE_META) += nft_meta_bridge.o obj-$(CONFIG_NFT_BRIDGE_REJECT) += nft_reject_bridge.o # packet logging
net/bridge/netfilter/nft_meta_bridge.c deleted +0 -135
135 lines not on this page · raw message
net/netfilter/nft_meta.c +58 -32
189 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 39/51 netfilter: nf_tables: make meta expression builtin
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
size net/netfilter/nft_meta.ko
text data bss dec hex filename
5826 936 1 6763 1a6b net/netfilter/nft_meta.ko
96407 2064 400 98871 18237 net/netfilter/nf_tables.ko
after:
100826 2240 401 103467 1942b net/netfilter/nf_tables.ko
--- include/net/netfilter/nf_tables_core.h | 1 + net/netfilter/Kconfig | 6 ------ net/netfilter/Makefile | 3 +-- net/netfilter/nf_tables_core.c | 1 + net/netfilter/nft_meta.c | 22 +--------------------- 5 files changed, 4 insertions(+), 29 deletions(-)
include/net/netfilter/nf_tables_core.h +1 -0
@@ -10,6 +10,7 @@ extern struct nft_expr_type nft_byteorder_type;extern struct nft_expr_type nft_payload_type;extern struct nft_expr_type nft_dynset_type;extern struct nft_expr_type nft_range_type; +extern struct nft_expr_type nft_meta_type;int nf_tables_core_module_init (void );void nf_tables_core_module_exit (void );
net/netfilter/Kconfig +0 -6
@@ -480,12 +480,6 @@ config NFT_EXTHDR This option adds the "exthdr" expression that you can use to match IPv6 extension headers and tcp options. -config NFT_META - tristate "Netfilter nf_tables meta module" - help - This option adds the "meta" expression that you can use to match and - to set packet metainformation such as the packet mark. - config NFT_RT tristate "Netfilter nf_tables routing module" help
net/netfilter/Makefile +1 -2
@@ -76,12 +76,11 @@ obj-$(CONFIG_NF_DUP_NETDEV) += nf_dup_netdev.o nf_tables-objs := nf_tables_core.o nf_tables_api.o nft_chain_filter.o \ nf_tables_trace.o nft_immediate.o nft_cmp.o nft_range.o \ nft_bitwise.o nft_byteorder.o nft_payload.o nft_lookup.o \ - nft_dynset.o + nft_dynset.o nft_meta.o obj-$(CONFIG_NF_TABLES) += nf_tables.o obj-$(CONFIG_NFT_COMPAT) += nft_compat.o obj-$(CONFIG_NFT_EXTHDR) += nft_exthdr.o -obj-$(CONFIG_NFT_META) += nft_meta.o obj-$(CONFIG_NFT_RT) += nft_rt.o obj-$(CONFIG_NFT_NUMGEN) += nft_numgen.o obj-$(CONFIG_NFT_CT) += nft_ct.o
net/netfilter/nf_tables_core.c +1 -0
@@ -251,6 +251,7 @@ static struct nft_expr_type *nft_basic_types[] = { &nft_payload_type, &nft_dynset_type, &nft_range_type, + &nft_meta_type, };int __init nf_tables_core_module_init (void )
net/netfilter/nft_meta.c +1 -21
@@ -11,8 +11,6 @@*/ #include <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> #include <linux/netlink.h> #include <linux/netfilter.h> #include <linux/netfilter/nf_tables.h>
@@ -495,7 +493,6 @@ static void nft_meta_set_destroy(const struct nft_ctx *ctx,static_branch_dec (&nft_trace_enabled); } -static struct nft_expr_type nft_meta_type;static const struct nft_expr_ops nft_meta_get_ops = { .type = &nft_meta_type, .size =NFT_EXPR_SIZE (sizeof (struct nft_meta )),
@@ -534,27 +531,10 @@ nft_meta_select_ops(const struct nft_ctx *ctx,return ERR_PTR (-EINVAL ); } -static struct nft_expr_type nft_meta_type__read_mostly = { +struct nft_expr_type nft_meta_type__read_mostly = { .name ="meta" , .select_ops = nft_meta_select_ops, .policy = nft_meta_policy, .maxattr =NFTA_META_MAX , .owner =THIS_MODULE , }; - -static int __init nft_meta_module_init (void ) -{ -return nft_register_expr (&nft_meta_type); -} - -static void __exit nft_meta_module_exit(void) -{ -nft_unregister_expr (&nft_meta_type); -} - -module_init (nft_meta_module_init); -module_exit (nft_meta_module_exit); - -MODULE_LICENSE ("GPL" ); -MODULE_AUTHOR ("Patrick McHardy <[email protected]>" ); -MODULE_ALIAS_NFT_EXPR ("meta" );
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 40/51 netfilter: nf_tables: merge rt expression into nft core
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
before:
text data bss dec hex filename
2657 844 0 3501 dad net/netfilter/nft_rt.ko
100826 2240 401 103467 1942b net/netfilter/nf_tables.ko
after:
2657 844 0 3501 dad net/netfilter/nft_rt.ko
102456 2316 401 105173 19ad5 net/netfilter/nf_tables.ko
--- include/net/netfilter/nf_tables_core.h | 1 + net/netfilter/Kconfig | 6 ------ net/netfilter/Makefile | 3 +-- net/netfilter/nf_tables_core.c | 1 + net/netfilter/nft_rt.c | 22 +--------------------- 5 files changed, 4 insertions(+), 29 deletions(-)
include/net/netfilter/nf_tables_core.h +1 -0
@@ -11,6 +11,7 @@ extern struct nft_expr_type nft_payload_type;extern struct nft_expr_type nft_dynset_type;extern struct nft_expr_type nft_range_type;extern struct nft_expr_type nft_meta_type; +extern struct nft_expr_type nft_rt_type;int nf_tables_core_module_init (void );void nf_tables_core_module_exit (void );
net/netfilter/Kconfig +0 -6
@@ -480,12 +480,6 @@ config NFT_EXTHDR This option adds the "exthdr" expression that you can use to match IPv6 extension headers and tcp options. -config NFT_RT - tristate "Netfilter nf_tables routing module" - help - This option adds the "rt" expression that you can use to match - packet routing information such as the packet nexthop. - config NFT_NUMGEN tristate "Netfilter nf_tables number generator module" help
net/netfilter/Makefile +1 -2
@@ -76,12 +76,11 @@ obj-$(CONFIG_NF_DUP_NETDEV) += nf_dup_netdev.o nf_tables-objs := nf_tables_core.o nf_tables_api.o nft_chain_filter.o \ nf_tables_trace.o nft_immediate.o nft_cmp.o nft_range.o \ nft_bitwise.o nft_byteorder.o nft_payload.o nft_lookup.o \ - nft_dynset.o nft_meta.o + nft_dynset.o nft_meta.o nft_rt.o obj-$(CONFIG_NF_TABLES) += nf_tables.o obj-$(CONFIG_NFT_COMPAT) += nft_compat.o obj-$(CONFIG_NFT_EXTHDR) += nft_exthdr.o -obj-$(CONFIG_NFT_RT) += nft_rt.o obj-$(CONFIG_NFT_NUMGEN) += nft_numgen.o obj-$(CONFIG_NFT_CT) += nft_ct.o obj-$(CONFIG_NFT_FLOW_OFFLOAD) += nft_flow_offload.o
net/netfilter/nf_tables_core.c +1 -0
@@ -252,6 +252,7 @@ static struct nft_expr_type *nft_basic_types[] = { &nft_dynset_type, &nft_range_type, &nft_meta_type, + &nft_rt_type, };int __init nf_tables_core_module_init (void )
net/netfilter/nft_rt.c +1 -21
@@ -7,8 +7,6 @@*/ #include <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> #include <linux/netlink.h> #include <linux/netfilter.h> #include <linux/netfilter/nf_tables.h>
@@ -179,7 +177,6 @@ static int nft_rt_validate(const struct nft_ctx *ctx, const struct nft_expr *expreturn nft_chain_validate_hooks (ctx->chain, hooks); } -static struct nft_expr_type nft_rt_type;static const struct nft_expr_ops nft_rt_get_ops = { .type = &nft_rt_type, .size =NFT_EXPR_SIZE (sizeof (struct nft_rt )),
@@ -189,27 +186,10 @@ static const struct nft_expr_ops nft_rt_get_ops = { .validate = nft_rt_validate, }; -static struct nft_expr_type nft_rt_type__read_mostly = { +struct nft_expr_type nft_rt_type__read_mostly = { .name ="rt" , .ops = &nft_rt_get_ops, .policy = nft_rt_policy, .maxattr =NFTA_RT_MAX , .owner =THIS_MODULE , }; - -static int __init nft_rt_module_init (void ) -{ -return nft_register_expr (&nft_rt_type); -} - -static void __exit nft_rt_module_exit(void) -{ -nft_unregister_expr (&nft_rt_type); -} - -module_init (nft_rt_module_init); -module_exit (nft_rt_module_exit); - -MODULE_LICENSE ("GPL" ); -MODULE_AUTHOR ("Anders K. Pedersen <[email protected]>" ); -MODULE_ALIAS_NFT_EXPR ("rt" );
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 41/51 netfilter: nf_tables: merge exthdr expression into nft core
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
before:
text data bss dec hex filename
5056 844 0 5900 170c net/netfilter/nft_exthdr.ko
102456 2316 401 105173 19ad5 net/netfilter/nf_tables.ko
after:
106410 2392 401 109203 1aa93 net/netfilter/nf_tables.ko
--- include/net/netfilter/nf_tables_core.h | 1 + net/netfilter/Kconfig | 6 ------ net/netfilter/Makefile | 3 +-- net/netfilter/nf_tables_core.c | 1 + net/netfilter/nft_exthdr.c | 23 ++--------------------- 5 files changed, 5 insertions(+), 29 deletions(-)
include/net/netfilter/nf_tables_core.h +1 -0
@@ -12,6 +12,7 @@ extern struct nft_expr_type nft_dynset_type;extern struct nft_expr_type nft_range_type;extern struct nft_expr_type nft_meta_type;extern struct nft_expr_type nft_rt_type; +extern struct nft_expr_type nft_exthdr_type;int nf_tables_core_module_init (void );void nf_tables_core_module_exit (void );
net/netfilter/Kconfig +0 -6
@@ -474,12 +474,6 @@ config NF_TABLES_NETDEV help This option enables support for the "netdev" table. -config NFT_EXTHDR - tristate "Netfilter nf_tables exthdr module" - help - This option adds the "exthdr" expression that you can use to match - IPv6 extension headers and tcp options. - config NFT_NUMGEN tristate "Netfilter nf_tables number generator module" help
net/netfilter/Makefile +1 -2
@@ -76,11 +76,10 @@ obj-$(CONFIG_NF_DUP_NETDEV) += nf_dup_netdev.o nf_tables-objs := nf_tables_core.o nf_tables_api.o nft_chain_filter.o \ nf_tables_trace.o nft_immediate.o nft_cmp.o nft_range.o \ nft_bitwise.o nft_byteorder.o nft_payload.o nft_lookup.o \ - nft_dynset.o nft_meta.o nft_rt.o + nft_dynset.o nft_meta.o nft_rt.o nft_exthdr.o obj-$(CONFIG_NF_TABLES) += nf_tables.o obj-$(CONFIG_NFT_COMPAT) += nft_compat.o -obj-$(CONFIG_NFT_EXTHDR) += nft_exthdr.o obj-$(CONFIG_NFT_NUMGEN) += nft_numgen.o obj-$(CONFIG_NFT_CT) += nft_ct.o obj-$(CONFIG_NFT_FLOW_OFFLOAD) += nft_flow_offload.o
net/netfilter/nf_tables_core.c +1 -0
@@ -253,6 +253,7 @@ static struct nft_expr_type *nft_basic_types[] = { &nft_range_type, &nft_meta_type, &nft_rt_type, + &nft_exthdr_type, };int __init nf_tables_core_module_init (void )
net/netfilter/nft_exthdr.c +2 -21
@@ -10,11 +10,10 @@#include <asm/unaligned.h> #include <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> #include <linux/netlink.h> #include <linux/netfilter.h> #include <linux/netfilter/nf_tables.h> +#include <net/netfilter/nf_tables_core.h> #include <net/netfilter/nf_tables.h> #include <net/tcp.h>
@@ -353,7 +352,6 @@ static int nft_exthdr_dump_set(struct sk_buff *skb, const struct nft_expr *expr)return nft_exthdr_dump_common (skb, priv); } -static struct nft_expr_type nft_exthdr_type;static const struct nft_expr_ops nft_exthdr_ipv6_ops = { .type = &nft_exthdr_type, .size =NFT_EXPR_SIZE (sizeof (struct nft_exthdr )),
@@ -407,27 +405,10 @@ nft_exthdr_select_ops(const struct nft_ctx *ctx,return ERR_PTR (-EOPNOTSUPP ); } -static struct nft_expr_type nft_exthdr_type__read_mostly = { +struct nft_expr_type nft_exthdr_type__read_mostly = { .name ="exthdr" , .select_ops = nft_exthdr_select_ops, .policy = nft_exthdr_policy, .maxattr =NFTA_EXTHDR_MAX , .owner =THIS_MODULE , }; - -static int __init nft_exthdr_module_init (void ) -{ -return nft_register_expr (&nft_exthdr_type); -} - -static void __exit nft_exthdr_module_exit(void) -{ -nft_unregister_expr (&nft_exthdr_type); -} - -module_init (nft_exthdr_module_init); -module_exit (nft_exthdr_module_exit); - -MODULE_LICENSE ("GPL" ); -MODULE_AUTHOR ("Patrick McHardy <[email protected]>" ); -MODULE_ALIAS_NFT_EXPR ("exthdr" );
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 42/51 ipvs: initialize tbl->entries after allocation
In reply to Pablo Neira AyusoFrom: Cong Wang <[email protected]>
tbl->entries is not initialized after kmalloc(), therefore causes an uninit-value warning in ip_vs_lblc_check_expire() as reported by syzbot.
--- net/netfilter/ipvs/ip_vs_lblcr.c | 1 + 1 file changed, 1 insertion(+)
net/netfilter/ipvs/ip_vs_lblcr.c +1 -0
@@ -535,6 +535,7 @@ static int ip_vs_lblcr_init_svc(struct ip_vs_service *svc) tbl->counter =1 ; tbl->dead = false; tbl->svc = svc; +atomic_set (&tbl->entries,0 );/* * Hook periodic timer for garbage collection
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 43/51 ipvs: initialize tbl->entries in ip_vs_lblc_init_svc()
In reply to Pablo Neira AyusoFrom: Cong Wang <[email protected]>
Similarly, tbl->entries is not initialized after kmalloc(), therefore causes an uninit-value warning in ip_vs_lblc_check_expire(), as reported by syzbot.
--- net/netfilter/ipvs/ip_vs_lblc.c | 1 + 1 file changed, 1 insertion(+)
net/netfilter/ipvs/ip_vs_lblc.c +1 -0
@@ -372,6 +372,7 @@ static int ip_vs_lblc_init_svc(struct ip_vs_service *svc) tbl->counter =1 ; tbl->dead = false; tbl->svc = svc; +atomic_set (&tbl->entries,0 );/* * Hook periodic timer for garbage collection
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 44/51 netfilter: nft_numgen: add map lookups for numgen statements
In reply to Pablo Neira AyusoFrom: Laura Garcia Liebana <[email protected]>
This patch includes a new attribute in the numgen structure to allow the lookup of an element based on the number generator as a key.
For this purpose, different ops have been included to extend the current numgen inc functions.
Currently, only supported for numgen incremental operations, but it will be supported for random in a follow-up patch.
--- include/uapi/linux/netfilter/nf_tables.h | 4 ++ net/netfilter/nft_numgen.c | 85 ++++++++++++++++++++++++++++++-- 2 files changed, 84 insertions(+), 5 deletions(-)
include/uapi/linux/netfilter/nf_tables.h +4 -0
@@ -1450,6 +1450,8 @@ enum nft_trace_types {* @NFTA_NG_MODULUS: maximum counter value (NLA_U32) * @NFTA_NG_TYPE: operation type (NLA_U32) * @NFTA_NG_OFFSET: offset to be added to the counter (NLA_U32) +* @NFTA_NG_SET_NAME: name of the map to lookup (NLA_STRING) +* @NFTA_NG_SET_ID: id of the map (NLA_U32) */ enum nft_ng_attributes {NFTA_NG_UNSPEC ,
@@ -1457,6 +1459,8 @@ enum nft_ng_attributes {NFTA_NG_MODULUS ,NFTA_NG_TYPE ,NFTA_NG_OFFSET , +NFTA_NG_SET_NAME , +NFTA_NG_SET_ID , __NFTA_NG_MAX };#define NFTA_NG_MAX (__NFTA_NG_MAX - 1)
net/netfilter/nft_numgen.c +80 -5
130 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 45/51 netfilter: nft_numgen: enable hashing of one element
In reply to Pablo Neira AyusoFrom: Laura Garcia Liebana <[email protected]>
The modulus in the hash function was limited to > 1 as initially there was no sense to create a hashing of just one element.
Nevertheless, there are certain cases specially for load balancing where this case needs to be addressed.
This patch fixes the following error.
Error: Could not process rule: Numerical result out of range add rule ip nftlb lb01 dnat to jhash ip saddr mod 1 map { 0: 192.168.0.10 } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The solution comes to force the hash to 0 when the modulus is 1.
--- net/netfilter/nft_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/nft_hash.c +1 -1
@@ -97,7 +97,7 @@ static int nft_jhash_init(const struct nft_ctx *ctx, priv->len = len; priv->modulus =ntohl (nla_get_be32 (tb[NFTA_HASH_MODULUS ])); -if (priv->modulus <=1 ) +if (priv->modulus <1 )return -ERANGE ;if (priv->offset + priv->modulus -1 < priv->offset)
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 46/51 netfilter: ip6t_srh: extend SRH matching for previous, next and last SID
In reply to Pablo Neira AyusoFrom: Ahmed Abdelsalam <[email protected]>
IPv6 Segment Routing Header (SRH) contains a list of SIDs to be crossed by SR encapsulated packet. Each SID is encoded as an IPv6 prefix.
When a Firewall receives an SR encapsulated packet, it should be able to identify which node previously processed the packet (previous SID), which node is going to process the packet next (next SID), and which node is the last to process the packet (last SID) which represent the final destination of the packet in case of inline SR mode.
An example use-case of using these features could be SID list that includes two firewalls. When the second firewall receives a packet, it can check whether the packet has been processed by the first firewall or not. Based on that check, it decides to apply all rules, apply just subset of the rules, or totally skip all rules and forward the packet to the next SID.
This patch extends SRH match to support matching previous SID, next SID, and last SID.
--- include/uapi/linux/netfilter_ipv6/ip6t_srh.h | 43 ++++++- net/ipv6/netfilter/ip6t_srh.c | 173 +++++++++++++++++++++++++-- 2 files changed, 205 insertions(+), 11 deletions(-)
include/uapi/linux/netfilter_ipv6/ip6t_srh.h +41 -2
@@ -17,7 +17,10 @@#define IP6T_SRH_LAST_GT 0x0100#define IP6T_SRH_LAST_LT 0x0200#define IP6T_SRH_TAG 0x0400 -#define IP6T_SRH_MASK 0x07FF +#define IP6T_SRH_PSID 0x0800 +#define IP6T_SRH_NSID 0x1000 +#define IP6T_SRH_LSID 0x2000 +#define IP6T_SRH_MASK 0x3FFF/* Values for "mt_invflags" field in struct ip6t_srh */ #define IP6T_SRH_INV_NEXTHDR 0x0001
@@ -31,7 +34,10 @@#define IP6T_SRH_INV_LAST_GT 0x0100#define IP6T_SRH_INV_LAST_LT 0x0200#define IP6T_SRH_INV_TAG 0x0400 -#define IP6T_SRH_INV_MASK 0x07FF +#define IP6T_SRH_INV_PSID 0x0800 +#define IP6T_SRH_INV_NSID 0x1000 +#define IP6T_SRH_INV_LSID 0x2000 +#define IP6T_SRH_INV_MASK 0x3FFF/** * struct ip6t_srh - SRH match options
@@ -54,4 +60,37 @@ struct ip6t_srh { __u16 mt_invflags; }; +/** +* struct ip6t_srh1 - SRH match options (revision 1) +* @ next_hdr: Next header field of SRH +* @ hdr_len: Extension header length field of SRH +* @ segs_left: Segments left field of SRH +* @ last_entry: Last entry field of SRH +* @ tag: Tag field of SRH +* @ psid_addr: Address of previous SID in SRH SID list +* @ nsid_addr: Address of NEXT SID in SRH SID list +* @ lsid_addr: Address of LAST SID in SRH SID list +* @ psid_msk: Mask of previous SID in SRH SID list +* @ nsid_msk: Mask of next SID in SRH SID list +* @ lsid_msk: MAsk of last SID in SRH SID list +* @ mt_flags: match options +* @ mt_invflags: Invert the sense of match options +*/ + +struct ip6t_srh1 { +__u8 next_hdr; +__u8 hdr_len; +__u8 segs_left; +__u8 last_entry; +__u16 tag; +struct in6_addr psid_addr; +struct in6_addr nsid_addr; +struct in6_addr lsid_addr; +struct in6_addr psid_msk; +struct in6_addr nsid_msk; +struct in6_addr lsid_msk; +__u16 mt_flags; +__u16 mt_invflags; +}; +#endif /*_IP6T_SRH_H*/
net/ipv6/netfilter/ip6t_srh.c +164 -9
193 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 47/51 netfilter: nf_nat: remove unused ct arg from lookup functions
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
--- include/net/netfilter/nf_nat_l3proto.h | 24 ++++++++---------------- net/ipv4/netfilter/iptable_nat.c | 3 +-- net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 14 +++++--------- net/ipv4/netfilter/nft_chain_nat_ipv4.c | 3 +-- net/ipv6/netfilter/ip6table_nat.c | 3 +-- net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 14 +++++--------- net/ipv6/netfilter/nft_chain_nat_ipv6.c | 3 +-- 7 files changed, 22 insertions(+), 42 deletions(-)
include/net/netfilter/nf_nat_l3proto.h +8 -16
@@ -48,30 +48,26 @@ unsigned int nf_nat_ipv4_in(void *priv, struct sk_buff *skb,const struct nf_hook_state *state, unsigned int (*do_chain)(void *priv,struct sk_buff *skb, -const struct nf_hook_state *state, - struct nf_conn *ct)); + const struct nf_hook_state *state));unsigned int nf_nat_ipv4_out (void *priv,struct sk_buff *skb,const struct nf_hook_state *state,unsigned int (*do_chain)(void *priv,struct sk_buff *skb, -const struct nf_hook_state *state, -struct nf_conn *ct)); +const struct nf_hook_state *state));unsigned int nf_nat_ipv4_local_fn (void *priv,struct sk_buff *skb,const struct nf_hook_state *state,unsigned int (*do_chain)(void *priv,struct sk_buff *skb, -const struct nf_hook_state *state, -struct nf_conn *ct)); +const struct nf_hook_state *state));unsigned int nf_nat_ipv4_fn (void *priv,struct sk_buff *skb,const struct nf_hook_state *state,unsigned int (*do_chain)(void *priv,struct sk_buff *skb, -const struct nf_hook_state *state, -struct nf_conn *ct)); +const struct nf_hook_state *state)); int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo,
@@ -81,29 +77,25 @@ unsigned int nf_nat_ipv6_in(void *priv, struct sk_buff *skb,const struct nf_hook_state *state, unsigned int (*do_chain)(void *priv,struct sk_buff *skb, -const struct nf_hook_state *state, - struct nf_conn *ct)); + const struct nf_hook_state *state));unsigned int nf_nat_ipv6_out (void *priv,struct sk_buff *skb,const struct nf_hook_state *state,unsigned int (*do_chain)(void *priv,struct sk_buff *skb, -const struct nf_hook_state *state, -struct nf_conn *ct)); +const struct nf_hook_state *state));unsigned int nf_nat_ipv6_local_fn (void *priv,struct sk_buff *skb,const struct nf_hook_state *state,unsigned int (*do_chain)(void *priv,struct sk_buff *skb, -const struct nf_hook_state *state, -struct nf_conn *ct)); +const struct nf_hook_state *state));unsigned int nf_nat_ipv6_fn (void *priv,struct sk_buff *skb,const struct nf_hook_state *state,unsigned int (*do_chain)(void *priv,struct sk_buff *skb, -const struct nf_hook_state *state, -struct nf_conn *ct)); +const struct nf_hook_state *state));#endif /* _NF_NAT_L3PROTO_H */
net/ipv4/netfilter/iptable_nat.c +1 -2
@@ -33,8 +33,7 @@ static const struct xt_table nf_nat_ipv4_table = {static unsigned int iptable_nat_do_chain (void *priv,struct sk_buff *skb, -const struct nf_hook_state *state, -struct nf_conn *ct) +const struct nf_hook_state *state) {return ipt_do_table (skb, state, state->net->ipv4.nat_table); }
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c +5 -9
@@ -246,8 +246,7 @@ nf_nat_ipv4_fn(void *priv, struct sk_buff *skb,const struct nf_hook_state *state, unsigned int (*do_chain)(void *priv, struct sk_buff *skb, - const struct nf_hook_state *state, - struct nf_conn *ct)) + const struct nf_hook_state *state)) { struct nf_conn *ct;enum ip_conntrack_info ctinfo;
@@ -285,7 +284,7 @@ nf_nat_ipv4_fn(void *priv, struct sk_buff *skb,if (!nf_nat_initialized (ct, maniptype)) {unsigned int ret; - ret =do_chain (priv, skb, state, ct); + ret =do_chain (priv, skb, state);if (ret !=NF_ACCEPT )return ret;
@@ -326,8 +325,7 @@ nf_nat_ipv4_in(void *priv, struct sk_buff *skb,const struct nf_hook_state *state, unsigned int (*do_chain)(void *priv,struct sk_buff *skb, -const struct nf_hook_state *state, - struct nf_conn *ct)) + const struct nf_hook_state *state)) { unsigned int ret; __be32 daddr = ip_hdr(skb)->daddr;
@@ -346,8 +344,7 @@ nf_nat_ipv4_out(void *priv, struct sk_buff *skb,const struct nf_hook_state *state, unsigned int (*do_chain)(void *priv, struct sk_buff *skb, - const struct nf_hook_state *state, - struct nf_conn *ct)) + const struct nf_hook_state *state)) { #ifdef CONFIG_XFRM const struct nf_conn *ct;
@@ -383,8 +380,7 @@ nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb,const struct nf_hook_state *state, unsigned int (*do_chain)(void *priv, struct sk_buff *skb, - const struct nf_hook_state *state, - struct nf_conn *ct)) + const struct nf_hook_state *state)) { const struct nf_conn *ct;enum ip_conntrack_info ctinfo;
net/ipv4/netfilter/nft_chain_nat_ipv4.c +1 -2
@@ -28,8 +28,7 @@static unsigned int nft_nat_do_chain (void *priv,struct sk_buff *skb, -const struct nf_hook_state *state, -struct nf_conn *ct) +const struct nf_hook_state *state) {struct nft_pktinfo pkt;
net/ipv6/netfilter/ip6table_nat.c +1 -2
@@ -35,8 +35,7 @@ static const struct xt_table nf_nat_ipv6_table = {static unsigned int ip6table_nat_do_chain (void *priv,struct sk_buff *skb, -const struct nf_hook_state *state, -struct nf_conn *ct) +const struct nf_hook_state *state) {return ip6t_do_table (skb, state, state->net->ipv6.ip6table_nat); }
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c +5 -9
@@ -257,8 +257,7 @@ nf_nat_ipv6_fn(void *priv, struct sk_buff *skb,const struct nf_hook_state *state, unsigned int (*do_chain)(void *priv, struct sk_buff *skb, - const struct nf_hook_state *state, - struct nf_conn *ct)) + const struct nf_hook_state *state)) { struct nf_conn *ct;enum ip_conntrack_info ctinfo;
@@ -303,7 +302,7 @@ nf_nat_ipv6_fn(void *priv, struct sk_buff *skb,if (!nf_nat_initialized (ct, maniptype)) {unsigned int ret; - ret =do_chain (priv, skb, state, ct); + ret =do_chain (priv, skb, state);if (ret !=NF_ACCEPT )return ret;
@@ -343,8 +342,7 @@ nf_nat_ipv6_in(void *priv, struct sk_buff *skb,const struct nf_hook_state *state, unsigned int (*do_chain)(void *priv,struct sk_buff *skb, -const struct nf_hook_state *state, - struct nf_conn *ct)) + const struct nf_hook_state *state)) { unsigned int ret; struct in6_addr daddr = ipv6_hdr(skb)->daddr;
@@ -363,8 +361,7 @@ nf_nat_ipv6_out(void *priv, struct sk_buff *skb,const struct nf_hook_state *state, unsigned int (*do_chain)(void *priv, struct sk_buff *skb, - const struct nf_hook_state *state, - struct nf_conn *ct)) + const struct nf_hook_state *state)) { #ifdef CONFIG_XFRM const struct nf_conn *ct;
@@ -400,8 +397,7 @@ nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb,const struct nf_hook_state *state, unsigned int (*do_chain)(void *priv, struct sk_buff *skb, - const struct nf_hook_state *state, - struct nf_conn *ct)) + const struct nf_hook_state *state)) { const struct nf_conn *ct;enum ip_conntrack_info ctinfo;
net/ipv6/netfilter/nft_chain_nat_ipv6.c +1 -2
@@ -26,8 +26,7 @@static unsigned int nft_nat_do_chain (void *priv,struct sk_buff *skb, -const struct nf_hook_state *state, -struct nf_conn *ct) +const struct nf_hook_state *state) {struct nft_pktinfo pkt;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 48/51 netfilter: nf_tables: Provide NFT_{RT,CT}_MAX for userspace
In reply to Pablo Neira AyusoFrom: Phil Sutter <[email protected]>
These macros allow conveniently declaring arrays which use NFT_{RT,CT}_* values as indexes.
--- include/uapi/linux/netfilter/nf_tables.h | 4 ++++ 1 file changed, 4 insertions(+)
include/uapi/linux/netfilter/nf_tables.h +4 -0
@@ -831,7 +831,9 @@ enum nft_rt_keys {NFT_RT_NEXTHOP4 ,NFT_RT_NEXTHOP6 ,NFT_RT_TCPMSS , + __NFT_RT_MAX }; +#define NFT_RT_MAX (__NFT_RT_MAX - 1)/** * enum nft_hash_types - nf_tables hash expression types
@@ -949,7 +951,9 @@ enum nft_ct_keys {NFT_CT_DST_IP ,NFT_CT_SRC_IP6 ,NFT_CT_DST_IP6 , + __NFT_CT_MAX }; +#define NFT_CT_MAX (__NFT_CT_MAX - 1)/** * enum nft_ct_attributes - nf_tables ct expression netlink attributes
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 49/51 netfilter: extract Passive OS fingerprint infrastructure from xt_osf
In reply to Pablo Neira AyusoFrom: Fernando Fernandez Mancera <[email protected]>
Add nf_osf_ttl() and nf_osf_match() into nf_osf.c to prepare for nf_tables support.
--- include/linux/netfilter/nf_osf.h | 27 +++++ include/uapi/linux/netfilter/nf_osf.h | 90 ++++++++++++++ include/uapi/linux/netfilter/xt_osf.h | 106 +++-------------- net/netfilter/Kconfig | 4 + net/netfilter/Makefile | 1 + net/netfilter/nf_osf.c | 218 ++++++++++++++++++++++++++++++++++ net/netfilter/xt_osf.c | 202 +------------------------------ 7 files changed, 359 insertions(+), 289 deletions(-) create mode 100644 include/linux/netfilter/nf_osf.h create mode 100644 include/uapi/linux/netfilter/nf_osf.h create mode 100644 net/netfilter/nf_osf.c
include/linux/netfilter/nf_osf.h new file +27 -0
@@ -0,0 +1,27 @@ +#include <uapi/linux/netfilter/nf_osf.h> + +/* Initial window size option state machine: multiple of mss, mtu or +* plain numeric value. Can also be made as plain numeric value which +* is not a multiple of specified value. +*/ +enum nf_osf_window_size_options { +OSF_WSS_PLAIN =0 , +OSF_WSS_MSS , +OSF_WSS_MTU , +OSF_WSS_MODULO , +OSF_WSS_MAX , +}; + +enum osf_fmatch_states { +/* Packet does not match the fingerprint */ +FMATCH_WRONG =0 , +/* Packet matches the fingerprint */ +FMATCH_OK , +/* Options do not match the fingerprint, but header does */ +FMATCH_OPT_WRONG , +}; + +bool nf_osf_match (const struct sk_buff *skb,u_int8_t family, +int hooknum,struct net_device *in,struct net_device *out, +const struct nf_osf_info *info,struct net *net, +const struct list_head *nf_osf_fingers);
include/uapi/linux/netfilter/nf_osf.h new file +90 -0
90 lines not on this page · raw message
include/uapi/linux/netfilter/xt_osf.h +17 -89
118 lines not on this page · raw message
net/netfilter/Kconfig +4 -0
@@ -444,6 +444,9 @@ config NETFILTER_SYNPROXY endif # NF_CONNTRACK +config NF_OSF + tristate 'Passive OS fingerprint infrastructure' + config NF_TABLES select NETFILTER_NETLINK tristate "Netfilter nf_tables support"
@@ -1358,6 +1361,7 @@ config NETFILTER_XT_MATCH_NFACCT config NETFILTER_XT_MATCH_OSF tristate '"osf" Passive OS fingerprint match' depends on NETFILTER_ADVANCED && NETFILTER_NETLINK + select NF_OSF help This option selects the Passive OS Fingerprinting match module that allows to passively match the remote operating system by
net/netfilter/Makefile +1 -0
@@ -101,6 +101,7 @@ obj-$(CONFIG_NFT_HASH) += nft_hash.o obj-$(CONFIG_NFT_FIB) += nft_fib.o obj-$(CONFIG_NFT_FIB_INET) += nft_fib_inet.o obj-$(CONFIG_NFT_FIB_NETDEV) += nft_fib_netdev.o +obj-$(CONFIG_NF_OSF) += nf_osf.o # nf_tables netdev obj-$(CONFIG_NFT_DUP_NETDEV) += nft_dup_netdev.o
net/netfilter/nf_osf.c new file +218 -0
218 lines not on this page · raw message
net/netfilter/xt_osf.c +2 -200
223 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 50/51 netfilter: ctnetlink: export nf_conntrack_max
In reply to Pablo Neira AyusoFrom: Florent Fourcot <[email protected]>
IPCTNL_MSG_CT_GET_STATS netlink command allow to monitor current number of conntrack entries. However, if one wants to compare it with the maximum (and detect exhaustion), the only solution is currently to read sysctl value.
This patch add nf_conntrack_max value in netlink message, and simplify monitoring for application built on netlink API.
--- include/uapi/linux/netfilter/nfnetlink_conntrack.h | 1 + net/netfilter/nf_conntrack_core.c | 1 + net/netfilter/nf_conntrack_netlink.c | 3 +++ 3 files changed, 5 insertions(+)
include/uapi/linux/netfilter/nfnetlink_conntrack.h +1 -0
@@ -262,6 +262,7 @@ enum ctattr_stats_cpu {enum ctattr_stats_global {CTA_STATS_GLOBAL_UNSPEC ,CTA_STATS_GLOBAL_ENTRIES , +CTA_STATS_GLOBAL_MAX_ENTRIES , __CTA_STATS_GLOBAL_MAX, };#define CTA_STATS_GLOBAL_MAX (__CTA_STATS_GLOBAL_MAX - 1)
net/netfilter/nf_conntrack_core.c +1 -0
@@ -186,6 +186,7 @@ unsigned int nf_conntrack_htable_size __read_mostly;EXPORT_SYMBOL_GPL (nf_conntrack_htable_size);unsigned int nf_conntrack_max__read_mostly ; +EXPORT_SYMBOL_GPL (nf_conntrack_max);seqcount_t nf_conntrack_generation__read_mostly ;static unsigned int nf_conntrack_hash_rnd__read_mostly ;
net/netfilter/nf_conntrack_netlink.c +3 -0
@@ -2205,6 +2205,9 @@ ctnetlink_stat_ct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,if (nla_put_be32 (skb,CTA_STATS_GLOBAL_ENTRIES ,htonl (nr_conntracks))) goto nla_put_failure; +if (nla_put_be32 (skb,CTA_STATS_GLOBAL_MAX_ENTRIES ,htonl (nf_conntrack_max))) + goto nla_put_failure; +nlmsg_end (skb, nlh);return skb->len;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 51/51 netfilter: nft_dynset: fix timeout updates on 32bit
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
This must now use a 64bit jiffies value, else we set a bogus timeout on 32bit.
--- net/netfilter/nft_dynset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/nft_dynset.c +1 -1
@@ -81,7 +81,7 @@ static void nft_dynset_eval(const struct nft_expr *expr,if (priv->op ==NFT_DYNSET_OP_UPDATE &&nft_set_ext_exists (ext,NFT_SET_EXT_EXPIRATION )) { timeout = priv->timeout ? : set->timeout; - *nft_set_ext_expiration (ext) = jiffies + timeout; + *nft_set_ext_expiration (ext) =get_jiffies_64 () + timeout; }if (sexpr !=NULL )
Signature · 1 line
2.11.0
David Miller
maintainerFrom: Pablo Neira Ayuso <[email protected]>
Date: Mon, 7 May 2018 00:46:18 +0200
Quoted 3 lines
The following patchset contains Netfilter/IPVS updates for your net-next tree, more relevant updates in this batch are:
...
Quoted 3 lines
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git
Pulled.