* [PATCH 00/25] nf-next pull request
From: Pablo Neira Ayuso @ 2014-09-10 15:10 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
Hi David,
The following patchset contains Netfilter/IPVS updates for your
net-next tree. Regarding nf_tables, most updates focus on consolidating
the NAT infrastructure and adding support for masquerading. More
specifically, they are:
1) use __u8 instead of u_int8_t in arptables header, from
Mike Frysinger.
2) Add support to match by skb->pkttype to the meta expression, from
Ana Rey.
3) Add support to match by cpu to the meta expression, also from
Ana Rey.
4) A smatch warning about IPSET_ATTR_MARKMASK validation, patch from
Vytas Dauksa.
5) Fix netnet and netportnet hash types the range support for IPv4,
from Sergey Popovich.
6) Fix missing-field-initializer warnings resolved, from Mark Rustad.
7) Dan Carperter reported possible integer overflows in ipset, from
Jozsef Kadlecsick.
8) Filter out accounting objects in nfacct by type, so you can
selectively reset quotas, from Alexey Perevalov.
9) Move specific NAT IPv4 functions to the core so x_tables and
nf_tables can share the same NAT IPv4 engine.
10) Use the new NAT IPv4 functions from nft_chain_nat_ipv4.
11) Move specific NAT IPv6 functions to the core so x_tables and
nf_tables can share the same NAT IPv4 engine.
12) Use the new NAT IPv6 functions from nft_chain_nat_ipv6.
13) Refactor code to add nft_delrule(), which can be reused in the
enhancement of the NFT_MSG_DELTABLE to remove a table and its
content, from Arturo Borrero.
14) Add a helper function to unregister chain hooks, from
Arturo Borrero.
15) A cleanup to rename to nft_delrule_by_chain for consistency with
the new nft_*() functions, also from Arturo.
16) Add support to match devgroup to the meta expression, from Ana Rey.
17) Reduce stack usage for IPVS socket option, from Julian Anastasov.
18) Remove unnecessary textsearch state initialization in xt_string,
from Bojan Prtvar.
19) Add several helper functions to nf_tables, more work to prepare
the enhancement of NFT_MSG_DELTABLE, again from Arturo Borrero.
20) Enhance NFT_MSG_DELTABLE to delete a table and its content, from
Arturo Borrero.
21) Support NAT flags in the nat expression to indicate the flavour,
eg. random fully, from Arturo.
22) Add missing audit code to ebtables when replacing tables, from
Nicolas Dichtel.
23) Generalize the IPv4 masquerading code to allow its re-use from
nf_tables, from Arturo.
24) Generalize the IPv6 masquerading code, also from Arturo.
25) Add the new masq expression to support IPv4/IPv6 masquerading
from nf_tables, also from Arturo.
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 c9d26423e56ce1ab4d786f92aebecf859d419293:
Merge tag 'pm+acpi-3.17-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm (2014-08-14 18:13:46 -0600)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git master
for you to fetch changes up to 9ba1f726bec090399eb9bb9157eb32dedc8e8c45:
netfilter: nf_tables: add new nft_masq expression (2014-09-09 16:31:30 +0200)
----------------------------------------------------------------
Alexey Perevalov (1):
netfilter: nfnetlink_acct: add filter support to nfacct counter list/reset
Ana Rey (3):
netfilter: nft_meta: add pkttype support
netfilter: nft_meta: Add cpu attribute support
netfilter: nf_tables: add devgroup support in meta expresion
Arturo Borrero (9):
netfilter: nf_tables: refactor rule deletion helper
netfilter: nf_tables: add helper to unregister chain hooks
netfilter: nf_tables: rename nf_table_delrule_by_chain()
netfilter: nf_tables: add helpers to schedule objects deletion
netfilter: nf_tables: extend NFT_MSG_DELTABLE to support flushing the ruleset
netfilter: nft_nat: include a flag attribute
netfilter: nf_nat: generalize IPv4 masquerading support for nf_tables
netfilter: nf_nat: generalize IPv6 masquerading support for nf_tables
netfilter: nf_tables: add new nft_masq expression
Bojan Prtvar (1):
netfilter: xt_string: Remove unnecessary initialization of struct ts_state
Jozsef Kadlecsik (1):
netfilter: ipset: Fix warn: integer overflows 'sizeof(*map) + size * set->dsize'
Julian Anastasov (1):
ipvs: reduce stack usage for sockopt data
Mark Rustad (1):
netfilter: ipset: Resolve missing-field-initializer warnings
Mike Frysinger (1):
uapi: netfilter_arp: use __u8 instead of u_int8_t
Nicolas Dichtel (1):
netfilter: ebtables: create audit records for replaces
Pablo Neira Ayuso (4):
netfilter: nat: move specific NAT IPv4 to core
netfilter: nft_chain_nat_ipv4: use generic IPv4 NAT code from core
netfilter: nat: move specific NAT IPv6 to core
netfilter: nft_chain_nat_ipv6: use generic IPv6 NAT code from core
Sergey Popovich (1):
netfilter: ipset: netnet,netportnet: Fix value range support for IPv4
Vytas Dauksa (1):
netfilter: ipset: Removed invalid IPSET_ATTR_MARKMASK validation
include/linux/netfilter/ipset/ip_set_list.h | 1 +
include/net/netfilter/ipv4/nf_nat_masquerade.h | 14 +
include/net/netfilter/ipv6/nf_nat_masquerade.h | 10 +
include/net/netfilter/nf_nat_l3proto.h | 75 ++++
include/net/netfilter/nft_masq.h | 16 +
include/uapi/linux/netfilter/nf_nat.h | 5 +
include/uapi/linux/netfilter/nf_tables.h | 21 ++
include/uapi/linux/netfilter/nfnetlink_acct.h | 8 +
include/uapi/linux/netfilter_arp/arpt_mangle.h | 2 +-
net/bridge/netfilter/ebtables.c | 15 +
net/ipv4/netfilter/Kconfig | 13 +
net/ipv4/netfilter/Makefile | 2 +
net/ipv4/netfilter/ipt_MASQUERADE.c | 108 +-----
net/ipv4/netfilter/iptable_nat.c | 233 ++----------
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 199 +++++++++++
net/ipv4/netfilter/nf_nat_masquerade_ipv4.c | 153 ++++++++
net/ipv4/netfilter/nft_chain_nat_ipv4.c | 157 ++------
net/ipv4/netfilter/nft_masq_ipv4.c | 89 +++++
net/ipv6/netfilter/Kconfig | 13 +
net/ipv6/netfilter/Makefile | 2 +
net/ipv6/netfilter/ip6t_MASQUERADE.c | 76 +---
net/ipv6/netfilter/ip6table_nat.c | 233 ++----------
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 199 +++++++++++
net/ipv6/netfilter/nf_nat_masquerade_ipv6.c | 120 +++++++
net/ipv6/netfilter/nft_chain_nat_ipv6.c | 165 ++-------
net/ipv6/netfilter/nft_masq_ipv6.c | 89 +++++
net/netfilter/Kconfig | 9 +
net/netfilter/Makefile | 1 +
net/netfilter/ipset/ip_set_bitmap_ip.c | 4 +-
net/netfilter/ipset/ip_set_bitmap_ipmac.c | 4 +-
net/netfilter/ipset/ip_set_bitmap_port.c | 4 +-
net/netfilter/ipset/ip_set_hash_gen.h | 2 +-
net/netfilter/ipset/ip_set_hash_ip.c | 8 +-
net/netfilter/ipset/ip_set_hash_ipport.c | 8 +-
net/netfilter/ipset/ip_set_hash_ipportip.c | 8 +-
net/netfilter/ipset/ip_set_hash_netnet.c | 13 +-
net/netfilter/ipset/ip_set_hash_netportnet.c | 6 +-
net/netfilter/ipset/ip_set_list_set.c | 4 +-
net/netfilter/ipvs/ip_vs_ctl.c | 111 +++---
net/netfilter/nf_tables_api.c | 454 +++++++++++++++---------
net/netfilter/nfnetlink_acct.c | 54 +++
net/netfilter/nft_masq.c | 59 +++
net/netfilter/nft_meta.c | 45 +++
net/netfilter/nft_nat.c | 16 +
net/netfilter/xt_string.c | 1 -
45 files changed, 1759 insertions(+), 1070 deletions(-)
create mode 100644 include/net/netfilter/ipv4/nf_nat_masquerade.h
create mode 100644 include/net/netfilter/ipv6/nf_nat_masquerade.h
create mode 100644 include/net/netfilter/nft_masq.h
create mode 100644 net/ipv4/netfilter/nf_nat_masquerade_ipv4.c
create mode 100644 net/ipv4/netfilter/nft_masq_ipv4.c
create mode 100644 net/ipv6/netfilter/nf_nat_masquerade_ipv6.c
create mode 100644 net/ipv6/netfilter/nft_masq_ipv6.c
create mode 100644 net/netfilter/nft_masq.c
^ permalink raw reply
* [PATCH 12/25] netfilter: nft_chain_nat_ipv6: use generic IPv6 NAT code from core
From: Pablo Neira Ayuso @ 2014-09-10 15:10 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1410361842-4656-1-git-send-email-pablo@netfilter.org>
Use the exported IPv6 NAT functions that are provided by the core. This
removes duplicated code so iptables and nft use the same NAT codebase.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/ipv6/netfilter/nft_chain_nat_ipv6.c | 163 +++++++------------------------
1 file changed, 36 insertions(+), 127 deletions(-)
diff --git a/net/ipv6/netfilter/nft_chain_nat_ipv6.c b/net/ipv6/netfilter/nft_chain_nat_ipv6.c
index c1c7449..1c4b75d 100644
--- a/net/ipv6/netfilter/nft_chain_nat_ipv6.c
+++ b/net/ipv6/netfilter/nft_chain_nat_ipv6.c
@@ -24,144 +24,53 @@
#include <net/netfilter/nf_nat_l3proto.h>
#include <net/ipv6.h>
-/*
- * IPv6 NAT chains
- */
-
-static unsigned int nft_nat_ipv6_fn(const struct nf_hook_ops *ops,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+static unsigned int nft_nat_do_chain(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ struct nf_conn *ct)
{
- enum ip_conntrack_info ctinfo;
- struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
- struct nf_conn_nat *nat;
- enum nf_nat_manip_type maniptype = HOOK2MANIP(ops->hooknum);
- __be16 frag_off;
- int hdrlen;
- u8 nexthdr;
struct nft_pktinfo pkt;
- unsigned int ret;
-
- if (ct == NULL || nf_ct_is_untracked(ct))
- return NF_ACCEPT;
-
- nat = nf_ct_nat_ext_add(ct);
- if (nat == NULL)
- return NF_ACCEPT;
-
- switch (ctinfo) {
- case IP_CT_RELATED:
- case IP_CT_RELATED + IP_CT_IS_REPLY:
- nexthdr = ipv6_hdr(skb)->nexthdr;
- hdrlen = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr),
- &nexthdr, &frag_off);
-
- if (hdrlen >= 0 && nexthdr == IPPROTO_ICMPV6) {
- if (!nf_nat_icmpv6_reply_translation(skb, ct, ctinfo,
- ops->hooknum,
- hdrlen))
- return NF_DROP;
- else
- return NF_ACCEPT;
- }
- /* Fall through */
- case IP_CT_NEW:
- if (nf_nat_initialized(ct, maniptype))
- break;
-
- nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out);
- ret = nft_do_chain(&pkt, ops);
- if (ret != NF_ACCEPT)
- return ret;
- if (!nf_nat_initialized(ct, maniptype)) {
- ret = nf_nat_alloc_null_binding(ct, ops->hooknum);
- if (ret != NF_ACCEPT)
- return ret;
- }
- default:
- break;
- }
+ nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out);
- return nf_nat_packet(ct, ctinfo, ops->hooknum, skb);
+ return nft_do_chain(&pkt, ops);
}
-static unsigned int nf_nat_ipv6_prerouting(const struct nf_hook_ops *ops,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+static unsigned int nft_nat_ipv6_fn(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
{
- struct in6_addr daddr = ipv6_hdr(skb)->daddr;
- unsigned int ret;
-
- ret = nft_nat_ipv6_fn(ops, skb, in, out, okfn);
- if (ret != NF_DROP && ret != NF_STOLEN &&
- ipv6_addr_cmp(&daddr, &ipv6_hdr(skb)->daddr))
- skb_dst_drop(skb);
-
- return ret;
+ return nf_nat_ipv6_fn(ops, skb, in, out, nft_nat_do_chain);
}
-static unsigned int nf_nat_ipv6_postrouting(const struct nf_hook_ops *ops,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+static unsigned int nft_nat_ipv6_in(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
{
- enum ip_conntrack_info ctinfo __maybe_unused;
- const struct nf_conn *ct __maybe_unused;
- unsigned int ret;
-
- ret = nft_nat_ipv6_fn(ops, skb, in, out, okfn);
-#ifdef CONFIG_XFRM
- if (ret != NF_DROP && ret != NF_STOLEN &&
- !(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
- (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
- enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
-
- if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
- &ct->tuplehash[!dir].tuple.dst.u3) ||
- (ct->tuplehash[dir].tuple.src.u.all !=
- ct->tuplehash[!dir].tuple.dst.u.all))
- if (nf_xfrm_me_harder(skb, AF_INET6) < 0)
- ret = NF_DROP;
- }
-#endif
- return ret;
+ return nf_nat_ipv6_in(ops, skb, in, out, nft_nat_do_chain);
}
-static unsigned int nf_nat_ipv6_output(const struct nf_hook_ops *ops,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+static unsigned int nft_nat_ipv6_out(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
{
- enum ip_conntrack_info ctinfo;
- const struct nf_conn *ct;
- unsigned int ret;
-
- ret = nft_nat_ipv6_fn(ops, skb, in, out, okfn);
- if (ret != NF_DROP && ret != NF_STOLEN &&
- (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
- enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+ return nf_nat_ipv6_out(ops, skb, in, out, nft_nat_do_chain);
+}
- if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3,
- &ct->tuplehash[!dir].tuple.src.u3)) {
- if (ip6_route_me_harder(skb))
- ret = NF_DROP;
- }
-#ifdef CONFIG_XFRM
- else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
- ct->tuplehash[dir].tuple.dst.u.all !=
- ct->tuplehash[!dir].tuple.src.u.all)
- if (nf_xfrm_me_harder(skb, AF_INET6))
- ret = NF_DROP;
-#endif
- }
- return ret;
+static unsigned int nft_nat_ipv6_local_fn(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ return nf_nat_ipv6_local_fn(ops, skb, in, out, nft_nat_do_chain);
}
static const struct nf_chain_type nft_chain_nat_ipv6 = {
@@ -174,9 +83,9 @@ static const struct nf_chain_type nft_chain_nat_ipv6 = {
(1 << NF_INET_LOCAL_OUT) |
(1 << NF_INET_LOCAL_IN),
.hooks = {
- [NF_INET_PRE_ROUTING] = nf_nat_ipv6_prerouting,
- [NF_INET_POST_ROUTING] = nf_nat_ipv6_postrouting,
- [NF_INET_LOCAL_OUT] = nf_nat_ipv6_output,
+ [NF_INET_PRE_ROUTING] = nft_nat_ipv6_in,
+ [NF_INET_POST_ROUTING] = nft_nat_ipv6_out,
+ [NF_INET_LOCAL_OUT] = nft_nat_ipv6_local_fn,
[NF_INET_LOCAL_IN] = nft_nat_ipv6_fn,
},
};
--
1.7.10.4
^ permalink raw reply related
* [PATCH 11/25] netfilter: nat: move specific NAT IPv6 to core
From: Pablo Neira Ayuso @ 2014-09-10 15:10 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1410361842-4656-1-git-send-email-pablo@netfilter.org>
Move the specific NAT IPv6 core functions that are called from the
hooks from ip6table_nat.c to nf_nat_l3proto_ipv6.c. This prepares the
ground to allow iptables and nft to use the same NAT engine code that
comes in a follow up patch.
This also renames nf_nat_ipv6_fn to nft_nat_ipv6_fn in
net/ipv6/netfilter/nft_chain_nat_ipv6.c to avoid a compilation breakage.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netfilter/nf_nat_l3proto.h | 37 +++++
net/ipv6/netfilter/ip6table_nat.c | 233 +++++-------------------------
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 199 +++++++++++++++++++++++++
net/ipv6/netfilter/nft_chain_nat_ipv6.c | 10 +-
4 files changed, 275 insertions(+), 204 deletions(-)
diff --git a/include/net/netfilter/nf_nat_l3proto.h b/include/net/netfilter/nf_nat_l3proto.h
index bc2d515..340c013 100644
--- a/include/net/netfilter/nf_nat_l3proto.h
+++ b/include/net/netfilter/nf_nat_l3proto.h
@@ -84,4 +84,41 @@ int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int hooknum, unsigned int hdrlen);
+unsigned int nf_nat_ipv6_in(const struct nf_hook_ops *ops, struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int (*do_chain)(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ struct nf_conn *ct));
+
+unsigned int nf_nat_ipv6_out(const struct nf_hook_ops *ops, struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int (*do_chain)(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ struct nf_conn *ct));
+
+unsigned int nf_nat_ipv6_local_fn(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int (*do_chain)(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ struct nf_conn *ct));
+
+unsigned int nf_nat_ipv6_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int (*do_chain)(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ struct nf_conn *ct));
+
#endif /* _NF_NAT_L3PROTO_H */
diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c
index 387d8b8..b0634ac 100644
--- a/net/ipv6/netfilter/ip6table_nat.c
+++ b/net/ipv6/netfilter/ip6table_nat.c
@@ -30,222 +30,57 @@ static const struct xt_table nf_nat_ipv6_table = {
.af = NFPROTO_IPV6,
};
-static unsigned int alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
-{
- /* Force range to this IP; let proto decide mapping for
- * per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
- */
- struct nf_nat_range range;
-
- range.flags = 0;
- pr_debug("Allocating NULL binding for %p (%pI6)\n", ct,
- HOOK2MANIP(hooknum) == NF_NAT_MANIP_SRC ?
- &ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip6 :
- &ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip6);
-
- return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum));
-}
-
-static unsigned int nf_nat_rule_find(struct sk_buff *skb, unsigned int hooknum,
- const struct net_device *in,
- const struct net_device *out,
- struct nf_conn *ct)
+static unsigned int ip6table_nat_do_chain(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ struct nf_conn *ct)
{
struct net *net = nf_ct_net(ct);
- unsigned int ret;
- ret = ip6t_do_table(skb, hooknum, in, out, net->ipv6.ip6table_nat);
- if (ret == NF_ACCEPT) {
- if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum)))
- ret = alloc_null_binding(ct, hooknum);
- }
- return ret;
+ return ip6t_do_table(skb, ops->hooknum, in, out, net->ipv6.ip6table_nat);
}
-static unsigned int
-nf_nat_ipv6_fn(const struct nf_hook_ops *ops,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+static unsigned int ip6table_nat_fn(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
{
- struct nf_conn *ct;
- enum ip_conntrack_info ctinfo;
- struct nf_conn_nat *nat;
- enum nf_nat_manip_type maniptype = HOOK2MANIP(ops->hooknum);
- __be16 frag_off;
- int hdrlen;
- u8 nexthdr;
-
- ct = nf_ct_get(skb, &ctinfo);
- /* Can't track? It's not due to stress, or conntrack would
- * have dropped it. Hence it's the user's responsibilty to
- * packet filter it out, or implement conntrack/NAT for that
- * protocol. 8) --RR
- */
- if (!ct)
- return NF_ACCEPT;
-
- /* Don't try to NAT if this packet is not conntracked */
- if (nf_ct_is_untracked(ct))
- return NF_ACCEPT;
-
- nat = nf_ct_nat_ext_add(ct);
- if (nat == NULL)
- return NF_ACCEPT;
-
- switch (ctinfo) {
- case IP_CT_RELATED:
- case IP_CT_RELATED_REPLY:
- nexthdr = ipv6_hdr(skb)->nexthdr;
- hdrlen = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr),
- &nexthdr, &frag_off);
-
- if (hdrlen >= 0 && nexthdr == IPPROTO_ICMPV6) {
- if (!nf_nat_icmpv6_reply_translation(skb, ct, ctinfo,
- ops->hooknum,
- hdrlen))
- return NF_DROP;
- else
- return NF_ACCEPT;
- }
- /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
- case IP_CT_NEW:
- /* Seen it before? This can happen for loopback, retrans,
- * or local packets.
- */
- if (!nf_nat_initialized(ct, maniptype)) {
- unsigned int ret;
-
- ret = nf_nat_rule_find(skb, ops->hooknum, in, out, ct);
- if (ret != NF_ACCEPT)
- return ret;
- } else {
- pr_debug("Already setup manip %s for ct %p\n",
- maniptype == NF_NAT_MANIP_SRC ? "SRC" : "DST",
- ct);
- if (nf_nat_oif_changed(ops->hooknum, ctinfo, nat, out))
- goto oif_changed;
- }
- break;
-
- default:
- /* ESTABLISHED */
- NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
- ctinfo == IP_CT_ESTABLISHED_REPLY);
- if (nf_nat_oif_changed(ops->hooknum, ctinfo, nat, out))
- goto oif_changed;
- }
-
- return nf_nat_packet(ct, ctinfo, ops->hooknum, skb);
-
-oif_changed:
- nf_ct_kill_acct(ct, ctinfo, skb);
- return NF_DROP;
+ return nf_nat_ipv6_fn(ops, skb, in, out, ip6table_nat_do_chain);
}
-static unsigned int
-nf_nat_ipv6_in(const struct nf_hook_ops *ops,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+static unsigned int ip6table_nat_in(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
{
- unsigned int ret;
- struct in6_addr daddr = ipv6_hdr(skb)->daddr;
-
- ret = nf_nat_ipv6_fn(ops, skb, in, out, okfn);
- if (ret != NF_DROP && ret != NF_STOLEN &&
- ipv6_addr_cmp(&daddr, &ipv6_hdr(skb)->daddr))
- skb_dst_drop(skb);
-
- return ret;
+ return nf_nat_ipv6_in(ops, skb, in, out, ip6table_nat_do_chain);
}
-static unsigned int
-nf_nat_ipv6_out(const struct nf_hook_ops *ops,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+static unsigned int ip6table_nat_out(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
{
-#ifdef CONFIG_XFRM
- const struct nf_conn *ct;
- enum ip_conntrack_info ctinfo;
- int err;
-#endif
- unsigned int ret;
-
- /* root is playing with raw sockets. */
- if (skb->len < sizeof(struct ipv6hdr))
- return NF_ACCEPT;
-
- ret = nf_nat_ipv6_fn(ops, skb, in, out, okfn);
-#ifdef CONFIG_XFRM
- if (ret != NF_DROP && ret != NF_STOLEN &&
- !(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
- (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
- enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
-
- if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
- &ct->tuplehash[!dir].tuple.dst.u3) ||
- (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
- ct->tuplehash[dir].tuple.src.u.all !=
- ct->tuplehash[!dir].tuple.dst.u.all)) {
- err = nf_xfrm_me_harder(skb, AF_INET6);
- if (err < 0)
- ret = NF_DROP_ERR(err);
- }
- }
-#endif
- return ret;
+ return nf_nat_ipv6_out(ops, skb, in, out, ip6table_nat_do_chain);
}
-static unsigned int
-nf_nat_ipv6_local_fn(const struct nf_hook_ops *ops,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+static unsigned int ip6table_nat_local_fn(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
{
- const struct nf_conn *ct;
- enum ip_conntrack_info ctinfo;
- unsigned int ret;
- int err;
-
- /* root is playing with raw sockets. */
- if (skb->len < sizeof(struct ipv6hdr))
- return NF_ACCEPT;
-
- ret = nf_nat_ipv6_fn(ops, skb, in, out, okfn);
- if (ret != NF_DROP && ret != NF_STOLEN &&
- (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
- enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
-
- if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3,
- &ct->tuplehash[!dir].tuple.src.u3)) {
- err = ip6_route_me_harder(skb);
- if (err < 0)
- ret = NF_DROP_ERR(err);
- }
-#ifdef CONFIG_XFRM
- else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
- ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
- ct->tuplehash[dir].tuple.dst.u.all !=
- ct->tuplehash[!dir].tuple.src.u.all) {
- err = nf_xfrm_me_harder(skb, AF_INET6);
- if (err < 0)
- ret = NF_DROP_ERR(err);
- }
-#endif
- }
- return ret;
+ return nf_nat_ipv6_local_fn(ops, skb, in, out, ip6table_nat_do_chain);
}
static struct nf_hook_ops nf_nat_ipv6_ops[] __read_mostly = {
/* Before packet filtering, change destination */
{
- .hook = nf_nat_ipv6_in,
+ .hook = ip6table_nat_in,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_PRE_ROUTING,
@@ -253,7 +88,7 @@ static struct nf_hook_ops nf_nat_ipv6_ops[] __read_mostly = {
},
/* After packet filtering, change source */
{
- .hook = nf_nat_ipv6_out,
+ .hook = ip6table_nat_out,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_POST_ROUTING,
@@ -261,7 +96,7 @@ static struct nf_hook_ops nf_nat_ipv6_ops[] __read_mostly = {
},
/* Before packet filtering, change destination */
{
- .hook = nf_nat_ipv6_local_fn,
+ .hook = ip6table_nat_local_fn,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_LOCAL_OUT,
@@ -269,7 +104,7 @@ static struct nf_hook_ops nf_nat_ipv6_ops[] __read_mostly = {
},
/* After packet filtering, change source */
{
- .hook = nf_nat_ipv6_fn,
+ .hook = ip6table_nat_fn,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_LOCAL_IN,
diff --git a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
index fc8e49b..c5812e1 100644
--- a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
@@ -261,6 +261,205 @@ int nf_nat_icmpv6_reply_translation(struct sk_buff *skb,
}
EXPORT_SYMBOL_GPL(nf_nat_icmpv6_reply_translation);
+unsigned int
+nf_nat_ipv6_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
+ const struct net_device *in, const struct net_device *out,
+ unsigned int (*do_chain)(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ struct nf_conn *ct))
+{
+ struct nf_conn *ct;
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn_nat *nat;
+ enum nf_nat_manip_type maniptype = HOOK2MANIP(ops->hooknum);
+ __be16 frag_off;
+ int hdrlen;
+ u8 nexthdr;
+
+ ct = nf_ct_get(skb, &ctinfo);
+ /* Can't track? It's not due to stress, or conntrack would
+ * have dropped it. Hence it's the user's responsibilty to
+ * packet filter it out, or implement conntrack/NAT for that
+ * protocol. 8) --RR
+ */
+ if (!ct)
+ return NF_ACCEPT;
+
+ /* Don't try to NAT if this packet is not conntracked */
+ if (nf_ct_is_untracked(ct))
+ return NF_ACCEPT;
+
+ nat = nf_ct_nat_ext_add(ct);
+ if (nat == NULL)
+ return NF_ACCEPT;
+
+ switch (ctinfo) {
+ case IP_CT_RELATED:
+ case IP_CT_RELATED_REPLY:
+ nexthdr = ipv6_hdr(skb)->nexthdr;
+ hdrlen = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr),
+ &nexthdr, &frag_off);
+
+ if (hdrlen >= 0 && nexthdr == IPPROTO_ICMPV6) {
+ if (!nf_nat_icmpv6_reply_translation(skb, ct, ctinfo,
+ ops->hooknum,
+ hdrlen))
+ return NF_DROP;
+ else
+ return NF_ACCEPT;
+ }
+ /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
+ case IP_CT_NEW:
+ /* Seen it before? This can happen for loopback, retrans,
+ * or local packets.
+ */
+ if (!nf_nat_initialized(ct, maniptype)) {
+ unsigned int ret;
+
+ ret = do_chain(ops, skb, in, out, ct);
+ if (ret != NF_ACCEPT)
+ return ret;
+
+ if (nf_nat_initialized(ct, HOOK2MANIP(ops->hooknum)))
+ break;
+
+ ret = nf_nat_alloc_null_binding(ct, ops->hooknum);
+ if (ret != NF_ACCEPT)
+ return ret;
+ } else {
+ pr_debug("Already setup manip %s for ct %p\n",
+ maniptype == NF_NAT_MANIP_SRC ? "SRC" : "DST",
+ ct);
+ if (nf_nat_oif_changed(ops->hooknum, ctinfo, nat, out))
+ goto oif_changed;
+ }
+ break;
+
+ default:
+ /* ESTABLISHED */
+ NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
+ ctinfo == IP_CT_ESTABLISHED_REPLY);
+ if (nf_nat_oif_changed(ops->hooknum, ctinfo, nat, out))
+ goto oif_changed;
+ }
+
+ return nf_nat_packet(ct, ctinfo, ops->hooknum, skb);
+
+oif_changed:
+ nf_ct_kill_acct(ct, ctinfo, skb);
+ return NF_DROP;
+}
+EXPORT_SYMBOL_GPL(nf_nat_ipv6_fn);
+
+unsigned int
+nf_nat_ipv6_in(const struct nf_hook_ops *ops, struct sk_buff *skb,
+ const struct net_device *in, const struct net_device *out,
+ unsigned int (*do_chain)(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ struct nf_conn *ct))
+{
+ unsigned int ret;
+ struct in6_addr daddr = ipv6_hdr(skb)->daddr;
+
+ ret = nf_nat_ipv6_fn(ops, skb, in, out, do_chain);
+ if (ret != NF_DROP && ret != NF_STOLEN &&
+ ipv6_addr_cmp(&daddr, &ipv6_hdr(skb)->daddr))
+ skb_dst_drop(skb);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nf_nat_ipv6_in);
+
+unsigned int
+nf_nat_ipv6_out(const struct nf_hook_ops *ops, struct sk_buff *skb,
+ const struct net_device *in, const struct net_device *out,
+ unsigned int (*do_chain)(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ struct nf_conn *ct))
+{
+#ifdef CONFIG_XFRM
+ const struct nf_conn *ct;
+ enum ip_conntrack_info ctinfo;
+ int err;
+#endif
+ unsigned int ret;
+
+ /* root is playing with raw sockets. */
+ if (skb->len < sizeof(struct ipv6hdr))
+ return NF_ACCEPT;
+
+ ret = nf_nat_ipv6_fn(ops, skb, in, out, do_chain);
+#ifdef CONFIG_XFRM
+ if (ret != NF_DROP && ret != NF_STOLEN &&
+ !(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
+ (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+
+ if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
+ &ct->tuplehash[!dir].tuple.dst.u3) ||
+ (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
+ ct->tuplehash[dir].tuple.src.u.all !=
+ ct->tuplehash[!dir].tuple.dst.u.all)) {
+ err = nf_xfrm_me_harder(skb, AF_INET6);
+ if (err < 0)
+ ret = NF_DROP_ERR(err);
+ }
+ }
+#endif
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nf_nat_ipv6_out);
+
+unsigned int
+nf_nat_ipv6_local_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
+ const struct net_device *in, const struct net_device *out,
+ unsigned int (*do_chain)(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ struct nf_conn *ct))
+{
+ const struct nf_conn *ct;
+ enum ip_conntrack_info ctinfo;
+ unsigned int ret;
+ int err;
+
+ /* root is playing with raw sockets. */
+ if (skb->len < sizeof(struct ipv6hdr))
+ return NF_ACCEPT;
+
+ ret = nf_nat_ipv6_fn(ops, skb, in, out, do_chain);
+ if (ret != NF_DROP && ret != NF_STOLEN &&
+ (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+
+ if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3,
+ &ct->tuplehash[!dir].tuple.src.u3)) {
+ err = ip6_route_me_harder(skb);
+ if (err < 0)
+ ret = NF_DROP_ERR(err);
+ }
+#ifdef CONFIG_XFRM
+ else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
+ ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
+ ct->tuplehash[dir].tuple.dst.u.all !=
+ ct->tuplehash[!dir].tuple.src.u.all) {
+ err = nf_xfrm_me_harder(skb, AF_INET6);
+ if (err < 0)
+ ret = NF_DROP_ERR(err);
+ }
+#endif
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nf_nat_ipv6_local_fn);
+
static int __init nf_nat_l3proto_ipv6_init(void)
{
int err;
diff --git a/net/ipv6/netfilter/nft_chain_nat_ipv6.c b/net/ipv6/netfilter/nft_chain_nat_ipv6.c
index d189fcb..c1c7449 100644
--- a/net/ipv6/netfilter/nft_chain_nat_ipv6.c
+++ b/net/ipv6/netfilter/nft_chain_nat_ipv6.c
@@ -28,7 +28,7 @@
* IPv6 NAT chains
*/
-static unsigned int nf_nat_ipv6_fn(const struct nf_hook_ops *ops,
+static unsigned int nft_nat_ipv6_fn(const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -97,7 +97,7 @@ static unsigned int nf_nat_ipv6_prerouting(const struct nf_hook_ops *ops,
struct in6_addr daddr = ipv6_hdr(skb)->daddr;
unsigned int ret;
- ret = nf_nat_ipv6_fn(ops, skb, in, out, okfn);
+ ret = nft_nat_ipv6_fn(ops, skb, in, out, okfn);
if (ret != NF_DROP && ret != NF_STOLEN &&
ipv6_addr_cmp(&daddr, &ipv6_hdr(skb)->daddr))
skb_dst_drop(skb);
@@ -115,7 +115,7 @@ static unsigned int nf_nat_ipv6_postrouting(const struct nf_hook_ops *ops,
const struct nf_conn *ct __maybe_unused;
unsigned int ret;
- ret = nf_nat_ipv6_fn(ops, skb, in, out, okfn);
+ ret = nft_nat_ipv6_fn(ops, skb, in, out, okfn);
#ifdef CONFIG_XFRM
if (ret != NF_DROP && ret != NF_STOLEN &&
!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
@@ -143,7 +143,7 @@ static unsigned int nf_nat_ipv6_output(const struct nf_hook_ops *ops,
const struct nf_conn *ct;
unsigned int ret;
- ret = nf_nat_ipv6_fn(ops, skb, in, out, okfn);
+ ret = nft_nat_ipv6_fn(ops, skb, in, out, okfn);
if (ret != NF_DROP && ret != NF_STOLEN &&
(ct = nf_ct_get(skb, &ctinfo)) != NULL) {
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
@@ -177,7 +177,7 @@ static const struct nf_chain_type nft_chain_nat_ipv6 = {
[NF_INET_PRE_ROUTING] = nf_nat_ipv6_prerouting,
[NF_INET_POST_ROUTING] = nf_nat_ipv6_postrouting,
[NF_INET_LOCAL_OUT] = nf_nat_ipv6_output,
- [NF_INET_LOCAL_IN] = nf_nat_ipv6_fn,
+ [NF_INET_LOCAL_IN] = nft_nat_ipv6_fn,
},
};
--
1.7.10.4
^ permalink raw reply related
* [PATCH 10/25] netfilter: nft_chain_nat_ipv4: use generic IPv4 NAT code from core
From: Pablo Neira Ayuso @ 2014-09-10 15:10 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1410361842-4656-1-git-send-email-pablo@netfilter.org>
Use the exported IPv4 NAT functions that are provided by the core. This
removes duplicated code so iptables and nft use the same NAT codebase.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/ipv4/netfilter/nft_chain_nat_ipv4.c | 157 ++++++++-----------------------
1 file changed, 37 insertions(+), 120 deletions(-)
diff --git a/net/ipv4/netfilter/nft_chain_nat_ipv4.c b/net/ipv4/netfilter/nft_chain_nat_ipv4.c
index 3964157..df547bf 100644
--- a/net/ipv4/netfilter/nft_chain_nat_ipv4.c
+++ b/net/ipv4/netfilter/nft_chain_nat_ipv4.c
@@ -26,136 +26,53 @@
#include <net/netfilter/nf_nat_l3proto.h>
#include <net/ip.h>
-/*
- * NAT chains
- */
-
-static unsigned int nf_nat_fn(const struct nf_hook_ops *ops,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+static unsigned int nft_nat_do_chain(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ struct nf_conn *ct)
{
- enum ip_conntrack_info ctinfo;
- struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
- struct nf_conn_nat *nat;
- enum nf_nat_manip_type maniptype = HOOK2MANIP(ops->hooknum);
struct nft_pktinfo pkt;
- unsigned int ret;
-
- if (ct == NULL || nf_ct_is_untracked(ct))
- return NF_ACCEPT;
-
- NF_CT_ASSERT(!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)));
-
- nat = nf_ct_nat_ext_add(ct);
- if (nat == NULL)
- return NF_ACCEPT;
-
- switch (ctinfo) {
- case IP_CT_RELATED:
- case IP_CT_RELATED + IP_CT_IS_REPLY:
- if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
- if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo,
- ops->hooknum))
- return NF_DROP;
- else
- return NF_ACCEPT;
- }
- /* Fall through */
- case IP_CT_NEW:
- if (nf_nat_initialized(ct, maniptype))
- break;
- nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
+ nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
- ret = nft_do_chain(&pkt, ops);
- if (ret != NF_ACCEPT)
- return ret;
- if (!nf_nat_initialized(ct, maniptype)) {
- ret = nf_nat_alloc_null_binding(ct, ops->hooknum);
- if (ret != NF_ACCEPT)
- return ret;
- }
- default:
- break;
- }
-
- return nf_nat_packet(ct, ctinfo, ops->hooknum, skb);
+ return nft_do_chain(&pkt, ops);
}
-static unsigned int nf_nat_prerouting(const struct nf_hook_ops *ops,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+static unsigned int nft_nat_ipv4_fn(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
{
- __be32 daddr = ip_hdr(skb)->daddr;
- unsigned int ret;
-
- ret = nf_nat_fn(ops, skb, in, out, okfn);
- if (ret != NF_DROP && ret != NF_STOLEN &&
- ip_hdr(skb)->daddr != daddr) {
- skb_dst_drop(skb);
- }
- return ret;
+ return nf_nat_ipv4_fn(ops, skb, in, out, nft_nat_do_chain);
}
-static unsigned int nf_nat_postrouting(const struct nf_hook_ops *ops,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+static unsigned int nft_nat_ipv4_in(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
{
- enum ip_conntrack_info ctinfo __maybe_unused;
- const struct nf_conn *ct __maybe_unused;
- unsigned int ret;
-
- ret = nf_nat_fn(ops, skb, in, out, okfn);
-#ifdef CONFIG_XFRM
- if (ret != NF_DROP && ret != NF_STOLEN &&
- (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
- enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
-
- if (ct->tuplehash[dir].tuple.src.u3.ip !=
- ct->tuplehash[!dir].tuple.dst.u3.ip ||
- ct->tuplehash[dir].tuple.src.u.all !=
- ct->tuplehash[!dir].tuple.dst.u.all)
- return nf_xfrm_me_harder(skb, AF_INET) == 0 ?
- ret : NF_DROP;
- }
-#endif
- return ret;
+ return nf_nat_ipv4_in(ops, skb, in, out, nft_nat_do_chain);
}
-static unsigned int nf_nat_output(const struct nf_hook_ops *ops,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+static unsigned int nft_nat_ipv4_out(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
{
- enum ip_conntrack_info ctinfo;
- const struct nf_conn *ct;
- unsigned int ret;
-
- ret = nf_nat_fn(ops, skb, in, out, okfn);
- if (ret != NF_DROP && ret != NF_STOLEN &&
- (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
- enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+ return nf_nat_ipv4_out(ops, skb, in, out, nft_nat_do_chain);
+}
- if (ct->tuplehash[dir].tuple.dst.u3.ip !=
- ct->tuplehash[!dir].tuple.src.u3.ip) {
- if (ip_route_me_harder(skb, RTN_UNSPEC))
- ret = NF_DROP;
- }
-#ifdef CONFIG_XFRM
- else if (ct->tuplehash[dir].tuple.dst.u.all !=
- ct->tuplehash[!dir].tuple.src.u.all)
- if (nf_xfrm_me_harder(skb, AF_INET))
- ret = NF_DROP;
-#endif
- }
- return ret;
+static unsigned int nft_nat_ipv4_local_fn(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ return nf_nat_ipv4_local_fn(ops, skb, in, out, nft_nat_do_chain);
}
static const struct nf_chain_type nft_chain_nat_ipv4 = {
@@ -168,10 +85,10 @@ static const struct nf_chain_type nft_chain_nat_ipv4 = {
(1 << NF_INET_LOCAL_OUT) |
(1 << NF_INET_LOCAL_IN),
.hooks = {
- [NF_INET_PRE_ROUTING] = nf_nat_prerouting,
- [NF_INET_POST_ROUTING] = nf_nat_postrouting,
- [NF_INET_LOCAL_OUT] = nf_nat_output,
- [NF_INET_LOCAL_IN] = nf_nat_fn,
+ [NF_INET_PRE_ROUTING] = nft_nat_ipv4_in,
+ [NF_INET_POST_ROUTING] = nft_nat_ipv4_out,
+ [NF_INET_LOCAL_OUT] = nft_nat_ipv4_local_fn,
+ [NF_INET_LOCAL_IN] = nft_nat_ipv4_fn,
},
};
--
1.7.10.4
^ permalink raw reply related
* [PATCH 08/25] netfilter: nfnetlink_acct: add filter support to nfacct counter list/reset
From: Pablo Neira Ayuso @ 2014-09-10 15:10 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1410361842-4656-1-git-send-email-pablo@netfilter.org>
From: Alexey Perevalov <a.perevalov@samsung.com>
You can use this to skip accounting objects when listing/resetting
via NFNL_MSG_ACCT_GET/NFNL_MSG_ACCT_GET_CTRZERO messages with the
NLM_F_DUMP netlink flag. The filtering covers the following cases:
1. No filter specified. In this case, the client will get old behaviour,
2. List/reset counter object only: In this case, you have to use
NFACCT_F_QUOTA as mask and value 0.
3. List/reset quota objects only: You have to use NFACCT_F_QUOTA_PKTS
as mask and value - the same, for byte based quota mask should be
NFACCT_F_QUOTA_BYTES and value - the same.
If you want to obtain the object with any quota type
(ie. NFACCT_F_QUOTA_PKTS|NFACCT_F_QUOTA_BYTES), you need to perform
two dump requests, one to obtain NFACCT_F_QUOTA_PKTS objects and
another for NFACCT_F_QUOTA_BYTES.
Signed-off-by: Alexey Perevalov <a.perevalov@samsung.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/uapi/linux/netfilter/nfnetlink_acct.h | 8 ++++
net/netfilter/nfnetlink_acct.c | 54 +++++++++++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/include/uapi/linux/netfilter/nfnetlink_acct.h b/include/uapi/linux/netfilter/nfnetlink_acct.h
index 51404ec..f3e34db 100644
--- a/include/uapi/linux/netfilter/nfnetlink_acct.h
+++ b/include/uapi/linux/netfilter/nfnetlink_acct.h
@@ -28,9 +28,17 @@ enum nfnl_acct_type {
NFACCT_USE,
NFACCT_FLAGS,
NFACCT_QUOTA,
+ NFACCT_FILTER,
__NFACCT_MAX
};
#define NFACCT_MAX (__NFACCT_MAX - 1)
+enum nfnl_attr_filter_type {
+ NFACCT_FILTER_UNSPEC,
+ NFACCT_FILTER_MASK,
+ NFACCT_FILTER_VALUE,
+ __NFACCT_FILTER_MAX
+};
+#define NFACCT_FILTER_MAX (__NFACCT_FILTER_MAX - 1)
#endif /* _UAPI_NFNL_ACCT_H_ */
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c
index 3ea0eac..c18af2f 100644
--- a/net/netfilter/nfnetlink_acct.c
+++ b/net/netfilter/nfnetlink_acct.c
@@ -40,6 +40,11 @@ struct nf_acct {
char data[0];
};
+struct nfacct_filter {
+ u32 value;
+ u32 mask;
+};
+
#define NFACCT_F_QUOTA (NFACCT_F_QUOTA_PKTS | NFACCT_F_QUOTA_BYTES)
#define NFACCT_OVERQUOTA_BIT 2 /* NFACCT_F_OVERQUOTA */
@@ -181,6 +186,7 @@ static int
nfnl_acct_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
struct nf_acct *cur, *last;
+ const struct nfacct_filter *filter = cb->data;
if (cb->args[2])
return 0;
@@ -197,6 +203,10 @@ nfnl_acct_dump(struct sk_buff *skb, struct netlink_callback *cb)
last = NULL;
}
+
+ if (filter && (cur->flags & filter->mask) != filter->value)
+ continue;
+
if (nfnl_acct_fill_info(skb, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq,
NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
@@ -211,6 +221,38 @@ nfnl_acct_dump(struct sk_buff *skb, struct netlink_callback *cb)
return skb->len;
}
+static int nfnl_acct_done(struct netlink_callback *cb)
+{
+ kfree(cb->data);
+ return 0;
+}
+
+static const struct nla_policy filter_policy[NFACCT_FILTER_MAX + 1] = {
+ [NFACCT_FILTER_MASK] = { .type = NLA_U32 },
+ [NFACCT_FILTER_VALUE] = { .type = NLA_U32 },
+};
+
+static struct nfacct_filter *
+nfacct_filter_alloc(const struct nlattr * const attr)
+{
+ struct nfacct_filter *filter;
+ struct nlattr *tb[NFACCT_FILTER_MAX + 1];
+ int err;
+
+ err = nla_parse_nested(tb, NFACCT_FILTER_MAX, attr, filter_policy);
+ if (err < 0)
+ return ERR_PTR(err);
+
+ filter = kzalloc(sizeof(struct nfacct_filter), GFP_KERNEL);
+ if (!filter)
+ return ERR_PTR(-ENOMEM);
+
+ filter->mask = ntohl(nla_get_be32(tb[NFACCT_FILTER_MASK]));
+ filter->value = ntohl(nla_get_be32(tb[NFACCT_FILTER_VALUE]));
+
+ return filter;
+}
+
static int
nfnl_acct_get(struct sock *nfnl, struct sk_buff *skb,
const struct nlmsghdr *nlh, const struct nlattr * const tb[])
@@ -222,7 +264,18 @@ nfnl_acct_get(struct sock *nfnl, struct sk_buff *skb,
if (nlh->nlmsg_flags & NLM_F_DUMP) {
struct netlink_dump_control c = {
.dump = nfnl_acct_dump,
+ .done = nfnl_acct_done,
};
+
+ if (tb[NFACCT_FILTER]) {
+ struct nfacct_filter *filter;
+
+ filter = nfacct_filter_alloc(tb[NFACCT_FILTER]);
+ if (IS_ERR(filter))
+ return PTR_ERR(filter);
+
+ c.data = filter;
+ }
return netlink_dump_start(nfnl, skb, nlh, &c);
}
@@ -314,6 +367,7 @@ static const struct nla_policy nfnl_acct_policy[NFACCT_MAX+1] = {
[NFACCT_PKTS] = { .type = NLA_U64 },
[NFACCT_FLAGS] = { .type = NLA_U32 },
[NFACCT_QUOTA] = { .type = NLA_U64 },
+ [NFACCT_FILTER] = {.type = NLA_NESTED },
};
static const struct nfnl_callback nfnl_acct_cb[NFNL_MSG_ACCT_MAX] = {
--
1.7.10.4
^ permalink raw reply related
* [PATCH 07/25] netfilter: ipset: Fix warn: integer overflows 'sizeof(*map) + size * set->dsize'
From: Pablo Neira Ayuso @ 2014-09-10 15:10 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1410361842-4656-1-git-send-email-pablo@netfilter.org>
From: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Dan Carpenter reported that the static checker emits the warning
net/netfilter/ipset/ip_set_list_set.c:600 init_list_set()
warn: integer overflows 'sizeof(*map) + size * set->dsize'
Limit the maximal number of elements in list type of sets.
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
---
include/linux/netfilter/ipset/ip_set_list.h | 1 +
net/netfilter/ipset/ip_set_list_set.c | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/include/linux/netfilter/ipset/ip_set_list.h b/include/linux/netfilter/ipset/ip_set_list.h
index 68c2aea..fe2622a 100644
--- a/include/linux/netfilter/ipset/ip_set_list.h
+++ b/include/linux/netfilter/ipset/ip_set_list.h
@@ -6,5 +6,6 @@
#define IP_SET_LIST_DEFAULT_SIZE 8
#define IP_SET_LIST_MIN_SIZE 4
+#define IP_SET_LIST_MAX_SIZE 65536
#endif /* __IP_SET_LIST_H */
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
index 3e2317f..f87adba 100644
--- a/net/netfilter/ipset/ip_set_list_set.c
+++ b/net/netfilter/ipset/ip_set_list_set.c
@@ -597,7 +597,9 @@ init_list_set(struct net *net, struct ip_set *set, u32 size)
struct set_elem *e;
u32 i;
- map = kzalloc(sizeof(*map) + size * set->dsize, GFP_KERNEL);
+ map = kzalloc(sizeof(*map) +
+ min_t(u32, size, IP_SET_LIST_MAX_SIZE) * set->dsize,
+ GFP_KERNEL);
if (!map)
return false;
--
1.7.10.4
^ permalink raw reply related
* [PATCH 05/25] netfilter: ipset: netnet,netportnet: Fix value range support for IPv4
From: Pablo Neira Ayuso @ 2014-09-10 15:10 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1410361842-4656-1-git-send-email-pablo@netfilter.org>
From: Sergey Popovich <popovich_sergei@mail.ru>
Ranges of values are broken with hash:net,net and hash:net,port,net.
hash:net,net
============
# ipset create test-nn hash:net,net
# ipset add test-nn 10.0.10.1-10.0.10.127,10.0.0.0/8
# ipset list test-nn
Name: test-nn
Type: hash:net,net
Revision: 0
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 16960
References: 0
Members:
10.0.10.1,10.0.0.0/8
# ipset test test-nn 10.0.10.65,10.0.0.1
10.0.10.65,10.0.0.1 is NOT in set test-nn.
# ipset test test-nn 10.0.10.1,10.0.0.1
10.0.10.1,10.0.0.1 is in set test-nn.
hash:net,port,net
=================
# ipset create test-npn hash:net,port,net
# ipset add test-npn 10.0.10.1-10.0.10.127,tcp:80,10.0.0.0/8
# ipset list test-npn
Name: test-npn
Type: hash:net,port,net
Revision: 0
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 17344
References: 0
Members:
10.0.10.8/29,tcp:80,10.0.0.0
10.0.10.16/28,tcp:80,10.0.0.0
10.0.10.2/31,tcp:80,10.0.0.0
10.0.10.64/26,tcp:80,10.0.0.0
10.0.10.32/27,tcp:80,10.0.0.0
10.0.10.4/30,tcp:80,10.0.0.0
10.0.10.1,tcp:80,10.0.0.0
# ipset list test-npn
# ipset test test-npn 10.0.10.126,tcp:80,10.0.0.2
10.0.10.126,tcp:80,10.0.0.2 is NOT in set test-npn.
# ipset test test-npn 10.0.10.126,tcp:80,10.0.0.0
10.0.10.126,tcp:80,10.0.0.0 is in set test-npn.
# ipset create test-npn hash:net,port,net
# ipset add test-npn 10.0.10.0/24,tcp:80-81,10.0.0.0/8
# ipset list test-npn
Name: test-npn
Type: hash:net,port,net
Revision: 0
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 17024
References: 0
Members:
10.0.10.0,tcp:80,10.0.0.0
10.0.10.0,tcp:81,10.0.0.0
# ipset test test-npn 10.0.10.126,tcp:80,10.0.0.0
10.0.10.126,tcp:80,10.0.0.0 is NOT in set test-npn.
# ipset test test-npn 10.0.10.0,tcp:80,10.0.0.0
10.0.10.0,tcp:80,10.0.0.0 is in set test-npn.
Correctly setup from..to variables where no IPSET_ATTR_IP_TO{,2}
attribute is given, so in range processing loop we construct proper
cidr value. Check whenever we have no ranges and can short cut in
hash:net,net properly. Use unlikely() where appropriate, to comply
with other modules.
Signed-off-by: Sergey Popovich <popovich_sergei@mail.ru>
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
---
net/netfilter/ipset/ip_set_hash_netnet.c | 13 +++++++------
net/netfilter/ipset/ip_set_hash_netportnet.c | 6 ++++--
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/net/netfilter/ipset/ip_set_hash_netnet.c b/net/netfilter/ipset/ip_set_hash_netnet.c
index 3e99987..96b1313 100644
--- a/net/netfilter/ipset/ip_set_hash_netnet.c
+++ b/net/netfilter/ipset/ip_set_hash_netnet.c
@@ -203,7 +203,7 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
flags |= (IPSET_FLAG_NOMATCH << 16);
}
- if (adt == IPSET_TEST || !(tb[IPSET_ATTR_IP_TO] &&
+ if (adt == IPSET_TEST || !(tb[IPSET_ATTR_IP_TO] ||
tb[IPSET_ATTR_IP2_TO])) {
e.ip[0] = htonl(ip & ip_set_hostmask(e.cidr[0]));
e.ip[1] = htonl(ip2_from & ip_set_hostmask(e.cidr[1]));
@@ -219,9 +219,10 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
return ret;
if (ip_to < ip)
swap(ip, ip_to);
- if (ip + UINT_MAX == ip_to)
+ if (unlikely(ip + UINT_MAX == ip_to))
return -IPSET_ERR_HASH_RANGE;
- }
+ } else
+ ip_set_mask_from_to(ip, ip_to, e.cidr[0]);
ip2_to = ip2_from;
if (tb[IPSET_ATTR_IP2_TO]) {
@@ -230,10 +231,10 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
return ret;
if (ip2_to < ip2_from)
swap(ip2_from, ip2_to);
- if (ip2_from + UINT_MAX == ip2_to)
+ if (unlikely(ip2_from + UINT_MAX == ip2_to))
return -IPSET_ERR_HASH_RANGE;
-
- }
+ } else
+ ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]);
if (retried)
ip = ntohl(h->next.ip[0]);
diff --git a/net/netfilter/ipset/ip_set_hash_netportnet.c b/net/netfilter/ipset/ip_set_hash_netportnet.c
index c0d2ba7..2f00343 100644
--- a/net/netfilter/ipset/ip_set_hash_netportnet.c
+++ b/net/netfilter/ipset/ip_set_hash_netportnet.c
@@ -257,7 +257,8 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
swap(ip, ip_to);
if (unlikely(ip + UINT_MAX == ip_to))
return -IPSET_ERR_HASH_RANGE;
- }
+ } else
+ ip_set_mask_from_to(ip, ip_to, e.cidr[0]);
port_to = port = ntohs(e.port);
if (tb[IPSET_ATTR_PORT_TO]) {
@@ -275,7 +276,8 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
swap(ip2_from, ip2_to);
if (unlikely(ip2_from + UINT_MAX == ip2_to))
return -IPSET_ERR_HASH_RANGE;
- }
+ } else
+ ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]);
if (retried)
ip = ntohl(h->next.ip[0]);
--
1.7.10.4
^ permalink raw reply related
* [PATCH 01/25] uapi: netfilter_arp: use __u8 instead of u_int8_t
From: Pablo Neira Ayuso @ 2014-09-10 15:10 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1410361842-4656-1-git-send-email-pablo@netfilter.org>
From: Mike Frysinger <vapier@gentoo.org>
Similarly, the u_int8_t type is non-standard and not defined. Change
it to use __u8 like the rest of the netfilter headers.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/uapi/linux/netfilter_arp/arpt_mangle.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/uapi/linux/netfilter_arp/arpt_mangle.h b/include/uapi/linux/netfilter_arp/arpt_mangle.h
index 250f502..8c2b16a 100644
--- a/include/uapi/linux/netfilter_arp/arpt_mangle.h
+++ b/include/uapi/linux/netfilter_arp/arpt_mangle.h
@@ -13,7 +13,7 @@ struct arpt_mangle
union {
struct in_addr tgt_ip;
} u_t;
- u_int8_t flags;
+ __u8 flags;
int target;
};
--
1.7.10.4
^ permalink raw reply related
* Re: gcc 4.8.3 miscompiles drivers/net/ethernet/freescale/fec_main.c ?!
From: David Jander @ 2014-09-10 14:49 UTC (permalink / raw)
To: Mikael Pettersson
Cc: Russell King, David S. Miller, netdev, linux-arm-kernel,
m.olbrich
In-Reply-To: <21520.17620.519242.597681@gargle.gargle.HOWL>
(included Michael Olbrich in CC)...
On Wed, 10 Sep 2014 14:32:20 +0200
Mikael Pettersson <mikpelinux@gmail.com> wrote:
> David Jander writes:
> >
> > Hi,
> >
> > I am seeing a strange problem when building a recent kernel with
> > gcc-4.8.3 for armv7-a that contains the following patch:
> >
> > https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit?id=bfd4ecdd87d350e19457fe0d02fa1e046774c44e
> >
> > Unfortunately I am not good enough at reading ARM assembly output from
> > GCC to understand whats going wrong, so I am asking for help.
> >
> > I started noticing ethernet packet loss on a i.MX6 board after upgrading
> > the kernel from 3.16-rc-something to latest mainline. The problem is very
> > easy to reproduce so I started git-bisecting. Git bisect gave me the
> > above patch as the culprit, and indeed: Without the patch a flood-ping
> > goes fine (just one dot on screen, no lost packets). I apply the patch
> > and the dots start filling the screen instantly.
> >
> > I am compiling the kernel using Pengutronix's OSELAS toolchain version
> > 2013.12.1, which is based on linaro gcc-4.8.3 without any relevant patches
> > AFAIK.
>
> Linaro's toolchain is itself heavily modified compared to FSF gcc-4.8.3,
> so first please try a pure vanilla FSF gcc-4.8.3, and then a likewise
> vanilla gcc-4.9.1. If those also cause the malfunction, then you have
> proof for a bug in upstream gcc (or possibly undefined code in the kernel),
> otherwise the bug is likely Linaro's.
Thanks. I will try to build gcc-4.8.3 from vanilla FSF sources and try to
reproduce the problem there. Do you think there is a chance this is still a
kernel bug?
I have assembly output of both working and broken cases (inlined and
non-inlined function). I can post them here or send to anyone who wants to
try to make sense of it....
> > Compiling with -O2 breaks the code, while -Os seems to produce a correctly
> > working kernel.
> >
> > I decided to make changes to the code and see if I could find other ways
> > to "fix" the problem, and I got the following result:
> >
> > The above mentioned patch introduces the static function
> > fec_enet_hwtstamp() near line 1068 of fec_main.c. If I make an exact copy
> > of this function, where I only change the name (e.g. fec_enet_hwtstamp2),
> > and change one of the two places this function is called to instead use
> > the other name, GCC inlines both copies and the problem disappears!
> >
> > Since I am not very good at GCC internals nor do I know this piece of
> > code in fec_main.c very well, I am asking here for help in hunting down
> > the real bug, which I suspect is in GCC... but I want to know for sure.
> >
> > Best regards,
> >
> > --
> > David Jander
> > Protonic Holland.
Best regards,
--
David Jander
Protonic Holland.
^ permalink raw reply
* Re: [PATCH net-next 2/5] ceph: Convert pr_warning to pr_warn
From: Ilya Dryomov @ 2014-09-10 14:41 UTC (permalink / raw)
To: Joe Perches
Cc: netdev, Sage Weil, David S. Miller, Ceph Development,
Linux Kernel Mailing List
In-Reply-To: <CALFYKtBsETt-PPmENUtKZuypqMH0rF2+ZOm0Dv0jWn1_yutFhA@mail.gmail.com>
On Wed, Sep 10, 2014 at 4:30 PM, Ilya Dryomov <ilya.dryomov@inktank.com> wrote:
> On Wed, Sep 10, 2014 at 8:17 AM, Joe Perches <joe@perches.com> wrote:
>> Use the more common pr_warn.
>>
>> Other miscellanea:
>>
>> o Coalesce formats
>> o Realign arguments
>>
>> Signed-off-by: Joe Perches <joe@perches.com>
>> ---
>> net/ceph/ceph_common.c | 15 +++++++++------
>> net/ceph/messenger.c | 19 ++++++++++---------
>> net/ceph/osd_client.c | 15 +++++++--------
>> net/ceph/osdmap.c | 20 ++++++++++----------
>> 4 files changed, 36 insertions(+), 33 deletions(-)
>>
>> diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
>> index 1675021..58fbfe1 100644
>> --- a/net/ceph/ceph_common.c
>> +++ b/net/ceph/ceph_common.c
>> @@ -293,17 +293,20 @@ static int get_secret(struct ceph_crypto_key *dst, const char *name) {
>> key_err = PTR_ERR(ukey);
>> switch (key_err) {
>> case -ENOKEY:
>> - pr_warning("ceph: Mount failed due to key not found: %s\n", name);
>> + pr_warn("ceph: Mount failed due to key not found: %s\n",
>> + name);
>> break;
>> case -EKEYEXPIRED:
>> - pr_warning("ceph: Mount failed due to expired key: %s\n", name);
>> + pr_warn("ceph: Mount failed due to expired key: %s\n",
>> + name);
>> break;
>> case -EKEYREVOKED:
>> - pr_warning("ceph: Mount failed due to revoked key: %s\n", name);
>> + pr_warn("ceph: Mount failed due to revoked key: %s\n",
>> + name);
>> break;
>> default:
>> - pr_warning("ceph: Mount failed due to unknown key error"
>> - " %d: %s\n", key_err, name);
>> + pr_warn("ceph: Mount failed due to unknown key error %d: %s\n",
>> + key_err, name);
>> }
>> err = -EPERM;
>> goto out;
>> @@ -433,7 +436,7 @@ ceph_parse_options(char *options, const char *dev_name,
>>
>> /* misc */
>> case Opt_osdtimeout:
>> - pr_warning("ignoring deprecated osdtimeout option\n");
>> + pr_warn("ignoring deprecated osdtimeout option\n");
>> break;
>> case Opt_osdkeepalivetimeout:
>> opt->osd_keepalive_timeout = intval;
>> diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
>> index b2f571d..a7203be 100644
>> --- a/net/ceph/messenger.c
>> +++ b/net/ceph/messenger.c
>> @@ -1937,11 +1937,11 @@ static int process_banner(struct ceph_connection *con)
>> sizeof(con->peer_addr)) != 0 &&
>> !(addr_is_blank(&con->actual_peer_addr.in_addr) &&
>> con->actual_peer_addr.nonce == con->peer_addr.nonce)) {
>> - pr_warning("wrong peer, want %s/%d, got %s/%d\n",
>> - ceph_pr_addr(&con->peer_addr.in_addr),
>> - (int)le32_to_cpu(con->peer_addr.nonce),
>> - ceph_pr_addr(&con->actual_peer_addr.in_addr),
>> - (int)le32_to_cpu(con->actual_peer_addr.nonce));
>> + pr_warn("wrong peer, want %s/%d, got %s/%d\n",
>> + ceph_pr_addr(&con->peer_addr.in_addr),
>> + (int)le32_to_cpu(con->peer_addr.nonce),
>> + ceph_pr_addr(&con->actual_peer_addr.in_addr),
>> + (int)le32_to_cpu(con->actual_peer_addr.nonce));
>> con->error_msg = "wrong peer at address";
>> return -1;
>> }
>> @@ -2302,7 +2302,7 @@ static int read_partial_message(struct ceph_connection *con)
>>
>> BUG_ON(!con->in_msg ^ skip);
>> if (con->in_msg && data_len > con->in_msg->data_length) {
>> - pr_warning("%s skipping long message (%u > %zd)\n",
>> + pr_warn("%s skipping long message (%u > %zd)\n",
>> __func__, data_len, con->in_msg->data_length);
>> ceph_msg_put(con->in_msg);
>> con->in_msg = NULL;
>> @@ -2712,7 +2712,7 @@ static bool con_sock_closed(struct ceph_connection *con)
>> CASE(OPEN);
>> CASE(STANDBY);
>> default:
>> - pr_warning("%s con %p unrecognized state %lu\n",
>> + pr_warn("%s con %p unrecognized state %lu\n",
>> __func__, con, con->state);
>> con->error_msg = "unrecognized con state";
>> BUG();
>> @@ -2828,8 +2828,9 @@ static void con_work(struct work_struct *work)
>> */
>> static void con_fault(struct ceph_connection *con)
>> {
>> - pr_warning("%s%lld %s %s\n", ENTITY_NAME(con->peer_name),
>> - ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg);
>> + pr_warn("%s%lld %s %s\n",
>> + ENTITY_NAME(con->peer_name),
>> + ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg);
>> dout("fault %p state %lu to peer %s\n",
>> con, con->state, ceph_pr_addr(&con->peer_addr.in_addr));
>>
>> diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
>> index 30f6faf..8ebb748 100644
>> --- a/net/ceph/osd_client.c
>> +++ b/net/ceph/osd_client.c
>> @@ -1774,8 +1774,8 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
>> }
>> bytes = le32_to_cpu(msg->hdr.data_len);
>> if (payload_len != bytes) {
>> - pr_warning("sum of op payload lens %d != data_len %d",
>> - payload_len, bytes);
>> + pr_warn("sum of op payload lens %d != data_len %d\n",
>> + payload_len, bytes);
>> goto bad_put;
>> }
>>
>> @@ -2797,10 +2797,10 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
>> ceph_msg_revoke_incoming(req->r_reply);
>>
>> if (front_len > req->r_reply->front_alloc_len) {
>> - pr_warning("get_reply front %d > preallocated %d (%u#%llu)\n",
>> - front_len, req->r_reply->front_alloc_len,
>> - (unsigned int)con->peer_name.type,
>> - le64_to_cpu(con->peer_name.num));
>> + pr_warn("get_reply front %d > preallocated %d (%u#%llu)\n",
>> + front_len, req->r_reply->front_alloc_len,
>> + (unsigned int)con->peer_name.type,
>> + le64_to_cpu(con->peer_name.num));
>> m = ceph_msg_new(CEPH_MSG_OSD_OPREPLY, front_len, GFP_NOFS,
>> false);
>> if (!m)
>> @@ -2823,8 +2823,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
>> if (osd_data->pages &&
>> unlikely(osd_data->length < data_len)) {
>>
>> - pr_warning("tid %lld reply has %d bytes "
>> - "we had only %llu bytes ready\n",
>> + pr_warn("tid %lld reply has %d bytes we had only %llu bytes ready\n",
>> tid, data_len, osd_data->length);
>> *skip = 1;
>> ceph_msg_put(m);
>> diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c
>> index c547e46..ae5a507 100644
>> --- a/net/ceph/osdmap.c
>> +++ b/net/ceph/osdmap.c
>> @@ -521,11 +521,11 @@ static int decode_pool(void **p, void *end, struct ceph_pg_pool_info *pi)
>> ev = ceph_decode_8(p); /* encoding version */
>> cv = ceph_decode_8(p); /* compat version */
>> if (ev < 5) {
>> - pr_warning("got v %d < 5 cv %d of ceph_pg_pool\n", ev, cv);
>> + pr_warn("got v %d < 5 cv %d of ceph_pg_pool\n", ev, cv);
>> return -EINVAL;
>> }
>> if (cv > 9) {
>> - pr_warning("got v %d cv %d > 9 of ceph_pg_pool\n", ev, cv);
>> + pr_warn("got v %d cv %d > 9 of ceph_pg_pool\n", ev, cv);
>> return -EINVAL;
>> }
>> len = ceph_decode_32(p);
>> @@ -729,9 +729,9 @@ static int get_osdmap_client_data_v(void **p, void *end,
>>
>> ceph_decode_8_safe(p, end, struct_compat, e_inval);
>> if (struct_compat > OSDMAP_WRAPPER_COMPAT_VER) {
>> - pr_warning("got v %d cv %d > %d of %s ceph_osdmap\n",
>> - struct_v, struct_compat,
>> - OSDMAP_WRAPPER_COMPAT_VER, prefix);
>> + pr_warn("got v %d cv %d > %d of %s ceph_osdmap\n",
>> + struct_v, struct_compat,
>> + OSDMAP_WRAPPER_COMPAT_VER, prefix);
>> return -EINVAL;
>> }
>> *p += 4; /* ignore wrapper struct_len */
>> @@ -739,9 +739,9 @@ static int get_osdmap_client_data_v(void **p, void *end,
>> ceph_decode_8_safe(p, end, struct_v, e_inval);
>> ceph_decode_8_safe(p, end, struct_compat, e_inval);
>> if (struct_compat > OSDMAP_CLIENT_DATA_COMPAT_VER) {
>> - pr_warning("got v %d cv %d > %d of %s ceph_osdmap client data\n",
>> - struct_v, struct_compat,
>> - OSDMAP_CLIENT_DATA_COMPAT_VER, prefix);
>> + pr_warn("got v %d cv %d > %d of %s ceph_osdmap client data\n",
>> + struct_v, struct_compat,
>> + OSDMAP_CLIENT_DATA_COMPAT_VER, prefix);
>> return -EINVAL;
>> }
>> *p += 4; /* ignore client data struct_len */
>> @@ -751,8 +751,8 @@ static int get_osdmap_client_data_v(void **p, void *end,
>> *p -= 1;
>> ceph_decode_16_safe(p, end, version, e_inval);
>> if (version < 6) {
>> - pr_warning("got v %d < 6 of %s ceph_osdmap\n", version,
>> - prefix);
>> + pr_warn("got v %d < 6 of %s ceph_osdmap\n",
>> + version, prefix);
>> return -EINVAL;
>> }
>>
>> --
>> 1.8.1.2.459.gbcd45b4.dirty
>
> Looks good. I'll take it though ceph tree to avoid possible conflicts?
Applied.
Thanks,
Ilya
^ permalink raw reply
* Re: 3.17-rc1 oops during network interface configuration
From: Eric Dumazet @ 2014-09-10 14:24 UTC (permalink / raw)
To: Or Gerlitz
Cc: Chuck Lever, Govindarajulu Varadarajan, David S. Miller, netdev,
LKML Kernel, linux-rdma, Bart Van Assche, Saeed Mahameed,
Tal Alon, Yevgeny Petrilin, Roland Dreier
In-Reply-To: <541000F1.5000805@mellanox.com>
On Wed, 2014-09-10 at 10:42 +0300, Or Gerlitz wrote:
> Hi Chuck, thanks for bisecting this out. Indeed, as of this kernel 3.2
> commit 936d7de "IPoIB: Stop lying about hard_header_len and use skb->cb
> to stash LL addresses" we are using the skb->cb field to enable proper
> work under GRO and avoid another historical quirk we had there... so I
> think we can definetly consider commit e0f31d849 to introduce a severe
> regression... Govindarajulu, Dave - what's your thinking here? any quick
> idea on how to fix?
I mentioned the IB stuff when patch was posted, and David replied :
"I think this is fine, IPOIB's control block will need still just 44
bytes after these changes, so there will still be 4 bytes to spare."
http://patchwork.ozlabs.org/patch/357584/
My suggestion was to reduce sch_choke usage and not store the whole
flow_keys.
^ permalink raw reply
* Re: [PATCH net-next 2/5] ceph: Convert pr_warning to pr_warn
From: Joe Perches @ 2014-09-10 14:20 UTC (permalink / raw)
To: Ilya Dryomov
Cc: netdev, Sage Weil, David S. Miller, Ceph Development,
Linux Kernel Mailing List
In-Reply-To: <CALFYKtCiGXhMZ-f0B=TGSNGZCng8NVYWCV-wwOHq3xPdKO+-Kw@mail.gmail.com>
On Wed, 2014-09-10 at 16:38 +0400, Ilya Dryomov wrote:
> On Wed, Sep 10, 2014 at 8:17 AM, Joe Perches <joe@perches.com> wrote:
> > Use the more common pr_warn.
> >
> > Other miscellanea:
> >
> > o Coalesce formats
> > o Realign arguments
[]
> > diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
[]
> > @@ -2828,8 +2828,9 @@ static void con_work(struct work_struct *work)
> > */
> > static void con_fault(struct ceph_connection *con)
> > {
> > - pr_warning("%s%lld %s %s\n", ENTITY_NAME(con->peer_name),
> > - ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg);
> > + pr_warn("%s%lld %s %s\n",
> > + ENTITY_NAME(con->peer_name),
> > + ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg);
>
> Just wondering, why did you move ENITITY_NAME argument to the next
> line? I see you are doing this pretty consistently. Is this a style
> guideline or something?
Hello Ilya.
It's just a personal preference to have the
formats on one line and its arguments on
another when the format and its arguments
don't fit 80 columns.
Maximal 80 column fill isn't always easy for me
to read.
I find it easier to match formats and arguments
when scanning because my eye doesn't have to
scan to the end of the format line.
If you don't like it, it's your code. Change it.
cheers, Joe
^ permalink raw reply
* [PATCH net] mlx4: Fix wrong endianess access with QP context flags
From: Or Gerlitz @ 2014-09-10 14:15 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Matan Barak, Amir Vadai, Or Gerlitz
We wrongly tested QP context bits without BE conversion
as was spotted by sparse...
drivers/infiniband/hw/mlx4/qp.c:1685:38: sparse: restricted __be32 degrades to integer
Fix that!
Fixes: d2fce8a ('mlx4: Set user-space raw Ethernet QPs to properly handle VXLAN traffic')
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
---
drivers/infiniband/hw/mlx4/qp.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index efb9eff..8365039 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -1682,7 +1682,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
MLX4_IB_LINK_TYPE_ETH;
if (dev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) {
/* set QP to receive both tunneled & non-tunneled packets */
- if (!(context->flags & (1 << MLX4_RSS_QPC_FLAG_OFFSET)))
+ if (!(context->flags & cpu_to_be32(1 << MLX4_RSS_QPC_FLAG_OFFSET)))
context->srqn = cpu_to_be32(7 << 28);
}
}
--
1.7.1
^ permalink raw reply related
* Re: [PATCH net-next v2 0/2] sunvnet: Reduce LDC message overhead.
From: Sowmini Varadhan @ 2014-09-10 14:04 UTC (permalink / raw)
To: David Miller; +Cc: raghuram.kothakota, netdev
In-Reply-To: <20140908143802.GF31377@oracle.com>
Excuse me if I am missing something obvious, but what was the
verdict on this? Is there any additional clarification/information
I can provide, if this is being mulled over?
--Sowmini
On (09/08/14 10:38), Sowmini Varadhan wrote:
>
> On (09/04/14 22:37), David Miller wrote:
> >
> > From: Sowmini Varadhan <sowmini.varadhan@oracle.com>
> >
> > > This patchset has an updated version of the v1 changes to reduce the
> > > overhead from LDC messages.
> >
> > Let's hold on these changes until the memory barrier issues brought up
> > by David is resolved.
>
> On (09/07/14 16:19), David Miller wrote (in the patch 2/2 thread for this set):
> >
> > > So what (if any) is the outstanding question about wmb() at this
> > > point?
> >
> > I don't think there is any, thanks.
>
> I'm not sure where we stand with this- do I need to resubmit any/all of
> those two patches?
>
> --Sowmini
^ permalink raw reply
* [PATCH] Documentation: filter: Add MIPS to architectures with BPF JIT
From: Markos Chandras @ 2014-09-10 13:51 UTC (permalink / raw)
To: netdev
Cc: Markos Chandras, Randy Dunlap, David S. Miller, Daniel Borkmann,
Alexei Starovoitov, linux-doc, linux-kernel
In-Reply-To: <1409322218-3689-1-git-send-email-markos.chandras@imgtec.com>
MIPS supports BPF JIT since v3.16-rc1
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Daniel Borkmann <dborkman@redhat.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: linux-doc@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Acked-by: Daniel Borkmann <dborkman@redhat.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
Documentation/networking/filter.txt | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Documentation/networking/filter.txt b/Documentation/networking/filter.txt
index c48a9704bda8..d16f424c5e8d 100644
--- a/Documentation/networking/filter.txt
+++ b/Documentation/networking/filter.txt
@@ -462,9 +462,9 @@ JIT compiler
------------
The Linux kernel has a built-in BPF JIT compiler for x86_64, SPARC, PowerPC,
-ARM and s390 and can be enabled through CONFIG_BPF_JIT. The JIT compiler is
-transparently invoked for each attached filter from user space or for internal
-kernel users if it has been previously enabled by root:
+ARM, MIPS and s390 and can be enabled through CONFIG_BPF_JIT. The JIT compiler
+is transparently invoked for each attached filter from user space or for
+internal kernel users if it has been previously enabled by root:
echo 1 > /proc/sys/net/core/bpf_jit_enable
--
2.1.0
^ permalink raw reply related
* Re: [PATCH net-next] ipv6: implement rt_genid_bump_ipv6 with fn_sernum and remove rt6i_genid
From: Hannes Frederic Sowa @ 2014-09-10 13:42 UTC (permalink / raw)
To: Vlad Yasevich; +Cc: netdev, Eric Dumazet, Nicolas Dichtel
In-Reply-To: <54105185.7010206@gmail.com>
Hi Vlad,
On Mi, 2014-09-10 at 09:26 -0400, Vlad Yasevich wrote:
> On 09/10/2014 05:31 AM, Hannes Frederic Sowa wrote:
> > Some special routes will never be cloned in IPv6. Those are mainly
> > DST_HOST routes without RTF_NONEXTHOP or RTF_GATEWAY flags, thus mostly
> > routes handling the input path.
> >
> > rt_genid depends on rt6_info clones being removed from the trie and
> > recreated with current rt6i_genid, thus bumping the genid would invalidate
> > all routes cached in the sockets and relookup will recreate them. But in
> > case a non-cloned route ends up in the per-socket cache, it will never
> > be recreated, thus will never get a current rt_genid.
> >
> > After the rt_genid is incremented for the first time all those routes
> > will always get invalidated by ip6_dst_check on the next check, thus
> > making early socket demultiplexing absolutely pointless for IPv6. It is
> > not possible to solve this with rt6i_genid, thus remove it.
> >
> > In case we need to force the sockets to relookup the routes we now
> > increase the fn_sernum on all fibnodes in the routing tree. This is a
> > costly operation but should only happen if we have major routing/policy
> > changes in the kernel (e.g. manual route adding/removal, xfrm policy
> > changes). Also this patch optimized the walk over the trie a bit, we
> > don't touch every rt6_info but only touch the fib6_nodes.
> >
> > Thanks to Eric Dumazet who noticed this problem.
>
> I also noticed the ipv6_ifa_notify() is called a lot with even being
> 0. This will only trigger rtnl notification, but would not trigger any
> routing table changes, but would trigger a call to bump the gen_id
> which now would perform a rather expensive clean-table operation.
>
> In particular the loop in manage_tempaddrs() is very scary as it can
> bump the rev multiples times.
>
> I think it the genid bump in __ipv6_ifa_notify() should only happen
> if there was an actual address change.
Yes, maybe we don't even need to bump id in ipv6_ifa_notify at all, I am
still investigating. :)
Thanks,
Hannes
^ permalink raw reply
* [PATCH net 2/4] net/mlx4: Use the correct VSD mask in UPDATE_QP
From: Or Gerlitz @ 2014-09-10 13:41 UTC (permalink / raw)
To: David S. Miller
Cc: netdev, Jack Morgenstein, Amir Vadai, Matan Barak, Or Gerlitz
In-Reply-To: <1410356516-23594-1-git-send-email-ogerlitz@mellanox.com>
From: Matan Barak <matanb@mellanox.com>
When doing VGT->VST->VGT state changes, we used an incorrect mask
for the vlan-stripping-disable (VSD) flag, hence the vlan related policy
for user-space Raw Ethernet QPs open by VFs wasn't really applied.
Fix that, by using the correct mask.
Fixes: f0f829b ('net/mlx4_core: Add immediate activate for VGT->VST->VGT')
Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
---
.../net/ethernet/mellanox/mlx4/resource_tracker.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index 1089367..f87a4a3 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -4818,7 +4818,7 @@ void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work)
MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED;
upd_context = mailbox->buf;
- upd_context->qp_mask = cpu_to_be64(MLX4_UPD_QP_MASK_VSD);
+ upd_context->qp_mask = cpu_to_be64(1ULL << MLX4_UPD_QP_MASK_VSD);
spin_lock_irq(mlx4_tlock(dev));
list_for_each_entry_safe(qp, tmp, qp_list, com.list) {
--
1.7.1
^ permalink raw reply related
* [PATCH net 3/4] net/mlx4: Avoid dealing with MAC index in UPDATE_QP wrapper if not needed
From: Or Gerlitz @ 2014-09-10 13:41 UTC (permalink / raw)
To: David S. Miller
Cc: netdev, Jack Morgenstein, Amir Vadai, Matan Barak, Or Gerlitz
In-Reply-To: <1410356516-23594-1-git-send-email-ogerlitz@mellanox.com>
From: Matan Barak <matanb@mellanox.com>
The current wrapper implementation of the UPDATE_QP command tries to get
the MAC index, even if MAC wasn't set by the VF. Fix it up to only handle
the MAC field if it's valid.
Fixes: ce8d9e0 ('net/mlx4_core: Add UPDATE_QP SRIOV wrapper support')
Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
---
.../net/ethernet/mellanox/mlx4/resource_tracker.c | 18 +++++++++++-------
1 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index f87a4a3..2fe61b6 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -3998,13 +3998,17 @@ int mlx4_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave,
}
port = (rqp->sched_queue >> 6 & 1) + 1;
- smac_index = cmd->qp_context.pri_path.grh_mylmc;
- err = mac_find_smac_ix_in_slave(dev, slave, port,
- smac_index, &mac);
- if (err) {
- mlx4_err(dev, "Failed to update qpn 0x%x, MAC is invalid. smac_ix: %d\n",
- qpn, smac_index);
- goto err_mac;
+
+ if (pri_addr_path_mask & (1ULL << MLX4_UPD_QP_PATH_MASK_MAC_INDEX)) {
+ smac_index = cmd->qp_context.pri_path.grh_mylmc;
+ err = mac_find_smac_ix_in_slave(dev, slave, port,
+ smac_index, &mac);
+
+ if (err) {
+ mlx4_err(dev, "Failed to update qpn 0x%x, MAC is invalid. smac_ix: %d\n",
+ qpn, smac_index);
+ goto err_mac;
+ }
}
err = mlx4_cmd(dev, inbox->dma,
--
1.7.1
^ permalink raw reply related
* [PATCH net 4/4] net/mlx4: Set vlan stripping policy by the right command
From: Or Gerlitz @ 2014-09-10 13:41 UTC (permalink / raw)
To: David S. Miller
Cc: netdev, Jack Morgenstein, Amir Vadai, Matan Barak, Or Gerlitz
In-Reply-To: <1410356516-23594-1-git-send-email-ogerlitz@mellanox.com>
From: Matan Barak <matanb@mellanox.com>
Changing the vlan stripping policy of the QP isn't supported by older
firmware versions for the INIT2RTR command. Nevertheless, we've used it.
Fix that by doing this policy change using INIT2RTR only if the firmware
supports it, otherwise, we call UPDATE_QP command to do the task.
Fixes: 7677fc9 ('net/mlx4: Strengthen VLAN tags/priorities enforcement in VST mode')
Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
---
drivers/infiniband/hw/mlx4/main.c | 2 +-
drivers/net/ethernet/mellanox/mlx4/qp.c | 12 ++++++++++--
.../net/ethernet/mellanox/mlx4/resource_tracker.c | 18 ++++++++++++++++--
include/linux/mlx4/device.h | 1 +
include/linux/mlx4/qp.h | 12 ++++++++++--
5 files changed, 38 insertions(+), 7 deletions(-)
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index af82563..162b82c 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -1680,7 +1680,7 @@ static void mlx4_ib_update_qps(struct mlx4_ib_dev *ibdev,
goto unlock;
update_params.smac_index = new_smac_index;
- if (mlx4_update_qp(ibdev->dev, &qp->mqp, MLX4_UPDATE_QP_SMAC,
+ if (mlx4_update_qp(ibdev->dev, qp->mqp.qpn, MLX4_UPDATE_QP_SMAC,
&update_params)) {
release_mac = new_smac;
goto unlock;
diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c
index 0dc31d8..2301365 100644
--- a/drivers/net/ethernet/mellanox/mlx4/qp.c
+++ b/drivers/net/ethernet/mellanox/mlx4/qp.c
@@ -390,13 +390,14 @@ err_icm:
EXPORT_SYMBOL_GPL(mlx4_qp_alloc);
#define MLX4_UPDATE_QP_SUPPORTED_ATTRS MLX4_UPDATE_QP_SMAC
-int mlx4_update_qp(struct mlx4_dev *dev, struct mlx4_qp *qp,
+int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn,
enum mlx4_update_qp_attr attr,
struct mlx4_update_qp_params *params)
{
struct mlx4_cmd_mailbox *mailbox;
struct mlx4_update_qp_context *cmd;
u64 pri_addr_path_mask = 0;
+ u64 qp_mask = 0;
int err = 0;
mailbox = mlx4_alloc_cmd_mailbox(dev);
@@ -413,9 +414,16 @@ int mlx4_update_qp(struct mlx4_dev *dev, struct mlx4_qp *qp,
cmd->qp_context.pri_path.grh_mylmc = params->smac_index;
}
+ if (attr & MLX4_UPDATE_QP_VSD) {
+ qp_mask |= 1ULL << MLX4_UPD_QP_MASK_VSD;
+ if (params->flags & MLX4_UPDATE_QP_PARAMS_FLAGS_VSD_ENABLE)
+ cmd->qp_context.param3 |= cpu_to_be32(MLX4_STRIP_VLAN);
+ }
+
cmd->primary_addr_path_mask = cpu_to_be64(pri_addr_path_mask);
+ cmd->qp_mask = cpu_to_be64(qp_mask);
- err = mlx4_cmd(dev, mailbox->dma, qp->qpn & 0xffffff, 0,
+ err = mlx4_cmd(dev, mailbox->dma, qpn & 0xffffff, 0,
MLX4_CMD_UPDATE_QP, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_NATIVE);
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index 2fe61b6..5d2498d 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -702,11 +702,13 @@ static int update_vport_qp_param(struct mlx4_dev *dev,
struct mlx4_qp_context *qpc = inbox->buf + 8;
struct mlx4_vport_oper_state *vp_oper;
struct mlx4_priv *priv;
+ u32 qp_type;
int port;
port = (qpc->pri_path.sched_queue & 0x40) ? 2 : 1;
priv = mlx4_priv(dev);
vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
+ qp_type = (be32_to_cpu(qpc->flags) >> 16) & 0xff;
if (MLX4_VGT != vp_oper->state.default_vlan) {
/* the reserved QPs (special, proxy, tunnel)
@@ -715,8 +717,20 @@ static int update_vport_qp_param(struct mlx4_dev *dev,
if (mlx4_is_qp_reserved(dev, qpn))
return 0;
- /* force strip vlan by clear vsd */
- qpc->param3 &= ~cpu_to_be32(MLX4_STRIP_VLAN);
+ /* force strip vlan by clear vsd, MLX QP refers to Raw Ethernet */
+ if (qp_type == MLX4_QP_ST_UD ||
+ (qp_type == MLX4_QP_ST_MLX && mlx4_is_eth(dev, port))) {
+ if (dev->caps.bmme_flags & MLX4_BMME_FLAG_VSD_INIT2RTR) {
+ *(__be32 *)inbox->buf =
+ cpu_to_be32(be32_to_cpu(*(__be32 *)inbox->buf) |
+ MLX4_QP_OPTPAR_VLAN_STRIPPING);
+ qpc->param3 &= ~cpu_to_be32(MLX4_STRIP_VLAN);
+ } else {
+ struct mlx4_update_qp_params params = {.flags = 0};
+
+ mlx4_update_qp(dev, qpn, MLX4_UPDATE_QP_VSD, ¶ms);
+ }
+ }
if (vp_oper->state.link_state == IFLA_VF_LINK_STATE_DISABLE &&
dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP) {
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 511c6e0..a5b7d7c 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -209,6 +209,7 @@ enum {
MLX4_BMME_FLAG_TYPE_2_WIN = 1 << 9,
MLX4_BMME_FLAG_RESERVED_LKEY = 1 << 10,
MLX4_BMME_FLAG_FAST_REG_WR = 1 << 11,
+ MLX4_BMME_FLAG_VSD_INIT2RTR = 1 << 28,
};
enum mlx4_event {
diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h
index 7040dc9..5f4e36c 100644
--- a/include/linux/mlx4/qp.h
+++ b/include/linux/mlx4/qp.h
@@ -56,7 +56,8 @@ enum mlx4_qp_optpar {
MLX4_QP_OPTPAR_RNR_RETRY = 1 << 13,
MLX4_QP_OPTPAR_ACK_TIMEOUT = 1 << 14,
MLX4_QP_OPTPAR_SCHED_QUEUE = 1 << 16,
- MLX4_QP_OPTPAR_COUNTER_INDEX = 1 << 20
+ MLX4_QP_OPTPAR_COUNTER_INDEX = 1 << 20,
+ MLX4_QP_OPTPAR_VLAN_STRIPPING = 1 << 21,
};
enum mlx4_qp_state {
@@ -423,13 +424,20 @@ struct mlx4_wqe_inline_seg {
enum mlx4_update_qp_attr {
MLX4_UPDATE_QP_SMAC = 1 << 0,
+ MLX4_UPDATE_QP_VSD = 1 << 2,
+ MLX4_UPDATE_QP_SUPPORTED_ATTRS = (1 << 2) - 1
+};
+
+enum mlx4_update_qp_params_flags {
+ MLX4_UPDATE_QP_PARAMS_FLAGS_VSD_ENABLE = 1 << 0,
};
struct mlx4_update_qp_params {
u8 smac_index;
+ u32 flags;
};
-int mlx4_update_qp(struct mlx4_dev *dev, struct mlx4_qp *qp,
+int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn,
enum mlx4_update_qp_attr attr,
struct mlx4_update_qp_params *params);
int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
--
1.7.1
^ permalink raw reply related
* [PATCH net 1/4] net/mlx4: Correctly configure single ported VFs from the host
From: Or Gerlitz @ 2014-09-10 13:41 UTC (permalink / raw)
To: David S. Miller
Cc: netdev, Jack Morgenstein, Amir Vadai, Matan Barak, Or Gerlitz
In-Reply-To: <1410356516-23594-1-git-send-email-ogerlitz@mellanox.com>
From: Matan Barak <matanb@mellanox.com>
Single port VFs are seen PCI wise on both ports of the PF (we don't have
single port PFs with ConnectX). With this in mind, it's possible for
virtualization tools to try and configure a single ported VF through
the "wrong" PF port.
To handle that, we use the PF driver mapping of single port VFs to NIC
ports and adjust the port value before calling into the low level
code that does the actual VF configuration
Fixes: 449fc48 ('net/mlx4: Adapt code for N-Port VF')
Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx4/cmd.c | 21 +++++++++++++++++++++
1 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index 65a4a0f..02a2e90 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -2389,6 +2389,22 @@ struct mlx4_slaves_pport mlx4_phys_to_slaves_pport_actv(
}
EXPORT_SYMBOL_GPL(mlx4_phys_to_slaves_pport_actv);
+static int mlx4_slaves_closest_port(struct mlx4_dev *dev, int slave, int port)
+{
+ struct mlx4_active_ports actv_ports = mlx4_get_active_ports(dev, slave);
+ int min_port = find_first_bit(actv_ports.ports, dev->caps.num_ports)
+ + 1;
+ int max_port = min_port +
+ bitmap_weight(actv_ports.ports, dev->caps.num_ports);
+
+ if (port < min_port)
+ port = min_port;
+ else if (port >= max_port)
+ port = max_port - 1;
+
+ return port;
+}
+
int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac)
{
struct mlx4_priv *priv = mlx4_priv(dev);
@@ -2402,6 +2418,7 @@ int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac)
if (slave < 0)
return -EINVAL;
+ port = mlx4_slaves_closest_port(dev, slave, port);
s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
s_info->mac = mac;
mlx4_info(dev, "default mac on vf %d port %d to %llX will take afect only after vf restart\n",
@@ -2428,6 +2445,7 @@ int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos)
if (slave < 0)
return -EINVAL;
+ port = mlx4_slaves_closest_port(dev, slave, port);
vf_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
if ((0 == vlan) && (0 == qos))
@@ -2455,6 +2473,7 @@ bool mlx4_get_slave_default_vlan(struct mlx4_dev *dev, int port, int slave,
struct mlx4_priv *priv;
priv = mlx4_priv(dev);
+ port = mlx4_slaves_closest_port(dev, slave, port);
vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
if (MLX4_VGT != vp_oper->state.default_vlan) {
@@ -2482,6 +2501,7 @@ int mlx4_set_vf_spoofchk(struct mlx4_dev *dev, int port, int vf, bool setting)
if (slave < 0)
return -EINVAL;
+ port = mlx4_slaves_closest_port(dev, slave, port);
s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
s_info->spoofchk = setting;
@@ -2535,6 +2555,7 @@ int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_stat
if (slave < 0)
return -EINVAL;
+ port = mlx4_slaves_closest_port(dev, slave, port);
switch (link_state) {
case IFLA_VF_LINK_STATE_AUTO:
/* get current link state */
--
1.7.1
^ permalink raw reply related
* [PATCH net 0/4] mlx4 SRIOV fixes
From: Or Gerlitz @ 2014-09-10 13:41 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Jack Morgenstein, Amir Vadai, Or Gerlitz
Hi Dave,
This series contains few SRIOV related fixes from Matan, please apply to net.
Or.
Matan Barak (4):
net/mlx4: Correctly configure single ported VFs from the host
net/mlx4: Use the correct VSD mask in UPDATE_QP
net/mlx4: Avoid dealing with MAC index in UPDATE_QP wrapper if not needed
net/mlx4: Set vlan stripping policy by the right command
drivers/infiniband/hw/mlx4/main.c | 2 +-
drivers/net/ethernet/mellanox/mlx4/cmd.c | 21 +++++++++++
drivers/net/ethernet/mellanox/mlx4/qp.c | 12 +++++-
.../net/ethernet/mellanox/mlx4/resource_tracker.c | 38 ++++++++++++++-----
include/linux/mlx4/device.h | 1 +
include/linux/mlx4/qp.h | 12 +++++-
6 files changed, 71 insertions(+), 15 deletions(-)
^ permalink raw reply
* Re: Multicast packets being lost (3.10 stable)
From: Linus Lüssing @ 2014-09-10 13:33 UTC (permalink / raw)
To: netdev
Cc: openwrt-devel, Greg Kroah-Hartman, bridge, David Miller,
Stephen Hemminger
In-Reply-To: <20140325125231.GW6008@Linus-Debian>
I just got a complaint about bridges, multicast and a
3.10 kernel again. Seems like nobody had any objections about
queueing these two patches for stable ( 2)+3) )?
Also I'm still missing some more fixes in the stable branches.
Especially 5), 6) and 7) are of high priority (next to 2) and 3) )
in my opinion as otherwise IPv6 in general could be broken for people
using 3.12 or 3.13 (as 3.12 contains a patch which activates
multicast snooping for link-local addresses, too: 3c3769e63).
Here is a more ordered list of patches I'd suggest to be queued for
stable:
1) bridge: fix switched interval for MLD Query types
-> 32de868cb (present since 3.10)
2) bridge: disable snooping if there is no querier
-> b00589af3 (present since 3.11)
3) bridge: don't try to update timers in case of broken MLD queries
-> 248ba8ec0 (present since 3.11)
4) Revert "bridge: only expire the mdb entry when query is received"
-> 454594f3b (present since 3.12)
5) bridge: multicast: add sanity check for query source addresses
-> 6565b9eee (present since 3.14)
6) bridge: multicast: add sanity check for general query destination
-> 9ed973cc4 (present since 3.14)
7) bridge: multicast: enable snooping on general queries only
-> 20a599bec (present since 3.14)
Let me know what you'd think about that or if there's any trouble
applying them to older kernels.
Cheers, Linus
On Tue, Mar 25, 2014 at 02:06:07PM +0100, Linus Lüssing wrote:
> That commit is supposed to be a fix and seems to be a easily
> cherry-pickable on top of 3.10. So I think it's suitable for
> stable
>
> There are two follow-up commit for this particular patch that I'm aware
> of: "bridge: separate querier and query timer into IGMP/IPv4
> and MLD/IPv6 ones" (cc0fdd80). That's just an optimization
> and can be ignored for stable.
>
> The second one is "bridge: don't try to update timers in case of
> broken MLD queries" (248ba8ec0). Which is a direct fix for
> b00589af3 and should therefore go into stable, too, if b00589af3
> goes into stable.
>
> Cheers, Linus
>
>
> On Mon, Mar 24, 2014 at 09:41:07AM -0700, Stephen Hemminger wrote:
> > We are seeing multicast snooping related issues.
> > Is there some reason this commit never went into stable (3.10)
> >
> > commit b00589af3b04736376f24625ab0b394642e89e29
> > Author: Linus Lüssing <linus.luessing@web.de>
> > Date: Thu Aug 1 01:06:20 2013 +0200
> >
> > bridge: disable snooping if there is no querier
> >
> > If there is no querier on a link then we won't get periodic reports and
> > therefore won't be able to learn about multicast listeners behind ports,
> > potentially leading to lost multicast packets, especially for multicast
> > listeners that joined before the creation of the bridge.
> >
> > These lost multicast packets can appear since c5c23260594
> > ("bridge: Add multicast_querier toggle and disable queries by default")
> > in particular.
> >
> > With this patch we are flooding multicast packets if our querier is
> > disabled and if we didn't detect any other querier.
> >
> > A grace period of the Maximum Response Delay of the querier is added to
> > give multicast responses enough time to arrive and to be learned from
> > before disabling the flooding behaviour again.
> >
> > Signed-off-by: Linus Lüssing <linus.luessing@web.de>
> > Signed-off-by: David S. Miller <davem@davemloft.net>
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
^ permalink raw reply
* Re: [systemd-devel] [RFC v2 3/6] kthread: warn on kill signal if not OOM
From: James Bottomley @ 2014-09-10 13:31 UTC (permalink / raw)
To: Ceriel Jacobs
Cc: Tom Gundersen, Luis R. Rodriguez, One Thousand Gnomes,
Takashi Iwai, Kay Sievers, Oleg Nesterov, Praveen Krishnamoorthy,
hare, Nagalakshmi Nandigama, Wu Zhangjin, Tetsuo Handa,
mpt-fusionlinux.pdl, Tim Gardner, Benjamin Poirier,
Santosh Rastapur, Casey Leedom, Hariprasad S, Pierre Fersing,
Sreekanth Reddy, Arjan van de Ven, Abhijit Mahajan
In-Reply-To: <541022F4.4020501@crashplan.pro>
On Wed, 2014-09-10 at 12:07 +0200, Ceriel Jacobs wrote:
> Tom Gundersen schreef op 10-09-14 om 08:46:
> >> >Indeed. What I proposed with a multiplier for the timeout for the
> >> >different types of built in commands was deemed complex but saw no
> >> >alternatives proposed despite my interest to work on one and
> >> >clarifications noted that this was a design regression. Not quite sure
> >> >what else I could have done here. I'm interested in learning what the
> >> >better approach is for the future as if we want to marry init + kernel
> >> >we need a smooth way for us to discuss design without getting worked
> >> >up about it, or taking it personal. I really want this to work as I
> >> >personally like systemd so far.
> > How about this: keep the timeout global, but also introduce a
> > (relatively short, say 10 or 15 seconds) timeout after which a warning
> > is printed. Even if nothing is actually killed, having workers (be it
> > insmod or something else) take longer than a couple of seconds is
> > likely a sign that something is seriously off somewhere.
> I don't agree with the statement that something is seriously off when it
> takes more then 10 to 15 seconds.
>
> When probing only one hard disk drive, then I do agree that something is
> seriously off after 10 to 15 seconds.
Really? We keep explaining that arbitrary times are wrong. A while ago
the Adaptec driver used to use 15s as its bus settle time after the
initial reset (it's now a Kconfig variable set at 5s) and a Parallel bus
takes a minimum of 4s to scan and has to be done sequentially. If any
probed device is having difficulty, that can escalate way beyond this
into the tens to hundreds of seconds. If your root disk is on it,
you're waiting or not booting.
> When probing a SAS bus with one hundred hard disk drives in standby
> mode, then I do expect that to take longer then 10 to 15 seconds.
Good luck with that even on SAS if you have a lot of expanders.
For an installed system, you know what you need (usually root and
possibly one other disc like /home), so you spawn all the insertions
asynchronously and then wait for just the devices you need them but,
since the alternative is panic when init isn't found, this wait better
be quite long (if not forever, given the consequence is guaranteed
failure). Everything else can be async, but, as I've pointed out
before, it can be async in user space (fire and forget) instead of the
kernel.
James
^ permalink raw reply
* Re: [Patch v2 net-next 09/12] net: fec: change FEC alignment according to i.mx6 sx requirement
From: Fabio Estevam @ 2014-09-10 13:27 UTC (permalink / raw)
To: Zhi Li
Cc: Frank Li, Duan Fugang-B38611, David S. Miller,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Shawn Guo,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <CAHrpEqSf8j7NUZDAORYwN4cbd2MBA9bcKa9mzNGg4JJiKsJKvA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Wed, Sep 10, 2014 at 10:22 AM, Zhi Li <lznuaa-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On Wed, Sep 10, 2014 at 7:51 AM, Fabio Estevam <festevam-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> On Tue, Sep 9, 2014 at 5:15 PM, Frank Li <Frank.Li-KZfg59tc24xl57MIdRCFDg@public.gmane.org> wrote:
>>
>>> + fep->rx_align = 0x3;
>>> + fep->tx_align = 0x3;
>>
>> Why do you unconditionally set it as 0x3? It was 0xf for ARM and 0x3
>> for non-ARM.
>
> Will fix it at next version.
Also, please make sure to add Russell King on Cc in the next version.
He has recently done a lot of work in this driver.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH net-next] ipv6: implement rt_genid_bump_ipv6 with fn_sernum and remove rt6i_genid
From: Vlad Yasevich @ 2014-09-10 13:26 UTC (permalink / raw)
To: Hannes Frederic Sowa, netdev; +Cc: Eric Dumazet, Nicolas Dichtel
In-Reply-To: <130f98f49b1b90a30908bfda8f01109c91edfe1c.1410341451.git.hannes@stressinduktion.org>
On 09/10/2014 05:31 AM, Hannes Frederic Sowa wrote:
> Some special routes will never be cloned in IPv6. Those are mainly
> DST_HOST routes without RTF_NONEXTHOP or RTF_GATEWAY flags, thus mostly
> routes handling the input path.
>
> rt_genid depends on rt6_info clones being removed from the trie and
> recreated with current rt6i_genid, thus bumping the genid would invalidate
> all routes cached in the sockets and relookup will recreate them. But in
> case a non-cloned route ends up in the per-socket cache, it will never
> be recreated, thus will never get a current rt_genid.
>
> After the rt_genid is incremented for the first time all those routes
> will always get invalidated by ip6_dst_check on the next check, thus
> making early socket demultiplexing absolutely pointless for IPv6. It is
> not possible to solve this with rt6i_genid, thus remove it.
>
> In case we need to force the sockets to relookup the routes we now
> increase the fn_sernum on all fibnodes in the routing tree. This is a
> costly operation but should only happen if we have major routing/policy
> changes in the kernel (e.g. manual route adding/removal, xfrm policy
> changes). Also this patch optimized the walk over the trie a bit, we
> don't touch every rt6_info but only touch the fib6_nodes.
>
> Thanks to Eric Dumazet who noticed this problem.
Hi Hannes
I also noticed the ipv6_ifa_notify() is called a lot with even being
0. This will only trigger rtnl notification, but would not trigger any
routing table changes, but would trigger a call to bump the gen_id
which now would perform a rather expensive clean-table operation.
In particular the loop in manage_tempaddrs() is very scary as it can
bump the rev multiples times.
I think it the genid bump in __ipv6_ifa_notify() should only happen
if there was an actual address change.
-vlad
>
> Fixes: 6f3118b571b8 ("ipv6: use net->rt_genid to check dst validity")
> Cc: Eric Dumazet <eric.dumazet@gmail.com>
> Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
> ---
>
> Notes:
> I based this patch on net-next, because it "only" fixes a performance
> problem so far and want it to be a bit more exposed to testing before
> a possible submission to stable.
>
> include/net/ip6_fib.h | 5 ++--
> include/net/net_namespace.h | 4 +++-
> net/core/dst.c | 8 +++++++
> net/ipv6/ip6_fib.c | 57 ++++++++++++++++++++++++++++++++++++---------
> net/ipv6/route.c | 4 ----
> 5 files changed, 59 insertions(+), 19 deletions(-)
>
> diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
> index 9bcb220..a5e09b8 100644
> --- a/include/net/ip6_fib.h
> +++ b/include/net/ip6_fib.h
> @@ -119,8 +119,6 @@ struct rt6_info {
> struct inet6_dev *rt6i_idev;
> unsigned long _rt6i_peer;
>
> - u32 rt6i_genid;
> -
> /* more non-fragment space at head required */
> unsigned short rt6i_nfheader_len;
>
> @@ -281,7 +279,8 @@ struct fib6_node *fib6_locate(struct fib6_node *root,
> const struct in6_addr *daddr, int dst_len,
> const struct in6_addr *saddr, int src_len);
>
> -void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg),
> +void fib6_clean_all(struct net *net,
> + int (*rt_visit)(struct rt6_info *, void *arg),
> void *arg);
>
> int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info,
> diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
> index 361d260..e0b0476 100644
> --- a/include/net/net_namespace.h
> +++ b/include/net/net_namespace.h
> @@ -358,9 +358,11 @@ static inline int rt_genid_ipv6(struct net *net)
> return atomic_read(&net->ipv6.rt_genid);
> }
>
> +extern void (*__rt_genid_bump_ipv6)(struct net *net);
> static inline void rt_genid_bump_ipv6(struct net *net)
> {
> - atomic_inc(&net->ipv6.rt_genid);
> + if (__rt_genid_bump_ipv6)
> + __rt_genid_bump_ipv6(net);
> }
> #else
> static inline int rt_genid_ipv6(struct net *net)
> diff --git a/net/core/dst.c b/net/core/dst.c
> index a028409..995183b 100644
> --- a/net/core/dst.c
> +++ b/net/core/dst.c
> @@ -23,6 +23,14 @@
>
> #include <net/dst.h>
>
> +/* as soon as the ipv6 module registers, this function is used to
> + * force all cached routing lookups to relookup
> + */
> +#if IS_ENABLED(CONFIG_IPV6)
> +void (*__rt_genid_bump_ipv6)(struct net *net);
> +EXPORT_SYMBOL(__rt_genid_bump_ipv6);
> +#endif
> +
> /*
> * Theory of operations:
> * 1) We use a list, protected by a spinlock, to add
> diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
> index 76b7f5e..d23b76f 100644
> --- a/net/ipv6/ip6_fib.c
> +++ b/net/ipv6/ip6_fib.c
> @@ -106,10 +106,15 @@ static inline void fib6_walker_unlink(struct fib6_walker_t *w)
> }
> static __inline__ u32 fib6_new_sernum(void)
> {
> - u32 n = ++rt_sernum;
> - if ((__s32)n <= 0)
> - rt_sernum = n = 1;
> - return n;
> + u32 new, old;
> +
> + do {
> + old = ACCESS_ONCE(rt_sernum);
> + new = old + 1;
> + if ((s32)new <= 0)
> + new = 1;
> + } while (cmpxchg(&rt_sernum, old, new) != old);
> + return new;
> }
>
> /*
> @@ -1553,25 +1558,28 @@ static int fib6_clean_node(struct fib6_walker_t *w)
> */
>
> static void fib6_clean_tree(struct net *net, struct fib6_node *root,
> - int (*func)(struct rt6_info *, void *arg),
> + int (*node_visit)(struct fib6_walker_t *),
> + int (*rt_visit)(struct rt6_info *, void *arg),
> int prune, void *arg)
> {
> struct fib6_cleaner_t c;
>
> c.w.root = root;
> - c.w.func = fib6_clean_node;
> + c.w.func = node_visit;
> c.w.prune = prune;
> c.w.count = 0;
> c.w.skip = 0;
> - c.func = func;
> + c.func = rt_visit;
> c.arg = arg;
> c.net = net;
>
> fib6_walk(&c.w);
> }
>
> -void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg),
> - void *arg)
> +static void __fib6_clean_all(struct net *net,
> + int (*node_visit)(struct fib6_walker_t *),
> + int (*rt_visit)(struct rt6_info *, void *arg),
> + void *arg)
> {
> struct fib6_table *table;
> struct hlist_head *head;
> @@ -1583,13 +1591,20 @@ void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg),
> hlist_for_each_entry_rcu(table, head, tb6_hlist) {
> write_lock_bh(&table->tb6_lock);
> fib6_clean_tree(net, &table->tb6_root,
> - func, 0, arg);
> + node_visit, rt_visit, 0, arg);
> write_unlock_bh(&table->tb6_lock);
> }
> }
> rcu_read_unlock();
> }
>
> +void fib6_clean_all(struct net *net,
> + int (*rt_visit)(struct rt6_info *, void *arg),
> + void *arg)
> +{
> + __fib6_clean_all(net, fib6_clean_node, rt_visit, arg);
> +}
> +
> static int fib6_prune_clone(struct rt6_info *rt, void *arg)
> {
> if (rt->rt6i_flags & RTF_CACHE) {
> @@ -1602,7 +1617,25 @@ static int fib6_prune_clone(struct rt6_info *rt, void *arg)
>
> static void fib6_prune_clones(struct net *net, struct fib6_node *fn)
> {
> - fib6_clean_tree(net, fn, fib6_prune_clone, 1, NULL);
> + fib6_clean_tree(net, fn, fib6_clean_node, fib6_prune_clone, 1, NULL);
> +}
> +
> +static int fib6_upd_sernum(struct fib6_walker_t *w)
> +{
> + struct fib6_cleaner_t *c = container_of(w, struct fib6_cleaner_t, w);
> + int *sernum = c->arg;
> +
> + w->node->fn_sernum = *sernum;
> + w->leaf = NULL;
> + return 0;
> +}
> +
> +static void fib6_genid_bump(struct net *net)
> +{
> + int sernum;
> +
> + sernum = fib6_new_sernum();
> + __fib6_clean_all(net, fib6_upd_sernum, NULL, &sernum);
> }
>
> /*
> @@ -1788,6 +1821,8 @@ int __init fib6_init(void)
> NULL);
> if (ret)
> goto out_unregister_subsys;
> +
> + __rt_genid_bump_ipv6 = fib6_genid_bump;
> out:
> return ret;
>
> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> index f74b041..a318dd89 100644
> --- a/net/ipv6/route.c
> +++ b/net/ipv6/route.c
> @@ -314,7 +314,6 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net,
>
> memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
> rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers);
> - rt->rt6i_genid = rt_genid_ipv6(net);
> INIT_LIST_HEAD(&rt->rt6i_siblings);
> }
> return rt;
> @@ -1096,9 +1095,6 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
> * DST_OBSOLETE_FORCE_CHK which forces validation calls down
> * into this function always.
> */
> - if (rt->rt6i_genid != rt_genid_ipv6(dev_net(rt->dst.dev)))
> - return NULL;
> -
> if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie))
> return NULL;
>
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox