* [PATCH 00/14] Netfilter fixes for net
From: Pablo Neira Ayuso @ 2017-01-26 16:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
Hi David,
The following patchset contains a large batch with Netfilter fixes for
your net tree, they are:
1) Two patches to solve conntrack garbage collector cpu hogging, one to
remove GC_MAX_EVICTS and another to look at the ratio (scanned entries
vs. evicted entries) to make a decision on whether to reduce or not
the scanning interval. From Florian Westphal.
2) Two patches to fix incorrect set element counting if NLM_F_EXCL is
is not set. Moreover, don't decrenent set->nelems from abort patch
if -ENFILE which leaks a spare slot in the set. This includes a
patch to deconstify the set walk callback to update set->ndeact.
3) Two fixes for the fwmark_reflect sysctl feature: Propagate mark to
reply packets both from nf_reject and local stack, from Pau Espin Pedrol.
4) Fix incorrect handling of loopback traffic in rpfilter and nf_tables
fib expression, from Liping Zhang.
5) Fix oops on stateful objects netlink dump, when no filter is specified.
Also from Liping Zhang.
6) Fix a build error if proc is not available in ipt_CLUSTERIP, related
to fix that was applied in the previous batch for net. From Arnd Bergmann.
7) Fix lack of string validation in table, chain, set and stateful
object names in nf_tables, from Liping Zhang. Moreover, restrict
maximum log prefix length to 127 bytes, otherwise explicitly bail
out.
8) Two patches to fix spelling and typos in nf_tables uapi header file
and Kconfig, patches from Alexander Alemayhu and William Breathitt Gray.
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git
Thanks a lot!
----------------------------------------------------------------
The following changes since commit 03430fa10b99e95e3a15eb7c00978fb1652f3b24:
Merge branch 'bcm_sf2-fixes' (2017-01-08 22:01:22 -0500)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git HEAD
for you to fetch changes up to b2c11e4b9536ebab6b39929e1fe15f57039ab445:
netfilter: nf_tables: bump set->ndeact on set flush (2017-01-24 21:46:59 +0100)
----------------------------------------------------------------
Alexander Alemayhu (1):
netfilter: nf_tables: fix spelling mistakes
Arnd Bergmann (1):
netfilter: ipt_CLUSTERIP: fix build error without procfs
Florian Westphal (2):
netfilter: conntrack: remove GC_MAX_EVICTS break
netfilter: conntrack: refine gc worker heuristics, redux
Liping Zhang (4):
netfilter: rpfilter: fix incorrect loopback packet judgment
netfilter: nf_tables: fix possible oops when dumping stateful objects
netfilter: nf_tables: validate the name size when possible
netfilter: nft_log: restrict the log prefix length to 127
Pablo Neira Ayuso (3):
netfilter: nf_tables: fix set->nelems counting with no NLM_F_EXCL
netfilter: nf_tables: deconstify walk callback function
netfilter: nf_tables: bump set->ndeact on set flush
Pau Espin Pedrol (2):
netfilter: use fwmark_reflect in nf_send_reset
tcp: fix mark propagation with fwmark_reflect enabled
William Breathitt Gray (1):
netfilter: Fix typo in NF_CONNTRACK Kconfig option description
include/net/netfilter/nf_tables.h | 6 +--
include/net/netfilter/nft_fib.h | 6 +++
include/uapi/linux/netfilter/nf_log.h | 2 +
include/uapi/linux/netfilter/nf_tables.h | 4 +-
net/ipv4/ip_output.c | 1 +
net/ipv4/netfilter/ipt_CLUSTERIP.c | 7 +++-
net/ipv4/netfilter/ipt_rpfilter.c | 8 ++--
net/ipv4/netfilter/nf_reject_ipv4.c | 2 +
net/ipv4/netfilter/nft_fib_ipv4.c | 15 +++----
net/ipv6/netfilter/ip6t_rpfilter.c | 8 ++--
net/ipv6/netfilter/nf_reject_ipv6.c | 3 ++
net/ipv6/netfilter/nft_fib_ipv6.c | 13 ++-----
net/ipv6/tcp_ipv6.c | 1 +
net/netfilter/Kconfig | 2 +-
net/netfilter/nf_conntrack_core.c | 44 ++++++++++-----------
net/netfilter/nf_log.c | 1 -
net/netfilter/nf_tables_api.c | 67 +++++++++++++++++++-------------
net/netfilter/nft_dynset.c | 3 +-
net/netfilter/nft_log.c | 3 +-
net/netfilter/nft_lookup.c | 3 +-
net/netfilter/nft_objref.c | 6 ++-
net/netfilter/nft_set_hash.c | 2 +-
net/netfilter/nft_set_rbtree.c | 2 +-
23 files changed, 116 insertions(+), 93 deletions(-)
^ permalink raw reply
* [PATCH 13/14] netfilter: nf_tables: deconstify walk callback function
From: Pablo Neira Ayuso @ 2017-01-26 16:38 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1485448687-6072-1-git-send-email-pablo@netfilter.org>
The flush operation needs to modify set and element objects, so let's
deconstify this.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netfilter/nf_tables.h | 6 +++---
net/netfilter/nf_tables_api.c | 24 ++++++++++++------------
net/netfilter/nft_set_hash.c | 2 +-
net/netfilter/nft_set_rbtree.c | 2 +-
4 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 924325c46aab..7dfdb517f0be 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -207,9 +207,9 @@ struct nft_set_iter {
unsigned int skip;
int err;
int (*fn)(const struct nft_ctx *ctx,
- const struct nft_set *set,
+ struct nft_set *set,
const struct nft_set_iter *iter,
- const struct nft_set_elem *elem);
+ struct nft_set_elem *elem);
};
/**
@@ -301,7 +301,7 @@ struct nft_set_ops {
void (*remove)(const struct nft_set *set,
const struct nft_set_elem *elem);
void (*walk)(const struct nft_ctx *ctx,
- const struct nft_set *set,
+ struct nft_set *set,
struct nft_set_iter *iter);
unsigned int (*privsize)(const struct nlattr * const nla[]);
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 831a9a16f563..5bd0068320fb 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -3087,9 +3087,9 @@ static int nf_tables_delset(struct net *net, struct sock *nlsk,
}
static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
- const struct nft_set *set,
+ struct nft_set *set,
const struct nft_set_iter *iter,
- const struct nft_set_elem *elem)
+ struct nft_set_elem *elem)
{
const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
enum nft_registers dreg;
@@ -3308,9 +3308,9 @@ struct nft_set_dump_args {
};
static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
- const struct nft_set *set,
+ struct nft_set *set,
const struct nft_set_iter *iter,
- const struct nft_set_elem *elem)
+ struct nft_set_elem *elem)
{
struct nft_set_dump_args *args;
@@ -3322,7 +3322,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
{
struct net *net = sock_net(skb->sk);
u8 genmask = nft_genmask_cur(net);
- const struct nft_set *set;
+ struct nft_set *set;
struct nft_set_dump_args args;
struct nft_ctx ctx;
struct nlattr *nla[NFTA_SET_ELEM_LIST_MAX + 1];
@@ -3890,9 +3890,9 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
}
static int nft_flush_set(const struct nft_ctx *ctx,
- const struct nft_set *set,
+ struct nft_set *set,
const struct nft_set_iter *iter,
- const struct nft_set_elem *elem)
+ struct nft_set_elem *elem)
{
struct nft_trans *trans;
int err;
@@ -3907,8 +3907,8 @@ static int nft_flush_set(const struct nft_ctx *ctx,
goto err1;
}
- nft_trans_elem_set(trans) = (struct nft_set *)set;
- nft_trans_elem(trans) = *((struct nft_set_elem *)elem);
+ nft_trans_elem_set(trans) = set;
+ nft_trans_elem(trans) = *elem;
list_add_tail(&trans->list, &ctx->net->nft.commit_list);
return 0;
@@ -5019,9 +5019,9 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx,
const struct nft_chain *chain);
static int nf_tables_loop_check_setelem(const struct nft_ctx *ctx,
- const struct nft_set *set,
+ struct nft_set *set,
const struct nft_set_iter *iter,
- const struct nft_set_elem *elem)
+ struct nft_set_elem *elem)
{
const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
const struct nft_data *data;
@@ -5045,7 +5045,7 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx,
{
const struct nft_rule *rule;
const struct nft_expr *expr, *last;
- const struct nft_set *set;
+ struct nft_set *set;
struct nft_set_binding *binding;
struct nft_set_iter iter;
diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
index 1e20e2bbb6d9..e36069fb76ae 100644
--- a/net/netfilter/nft_set_hash.c
+++ b/net/netfilter/nft_set_hash.c
@@ -212,7 +212,7 @@ static void nft_hash_remove(const struct nft_set *set,
rhashtable_remove_fast(&priv->ht, &he->node, nft_hash_params);
}
-static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set,
+static void nft_hash_walk(const struct nft_ctx *ctx, struct nft_set *set,
struct nft_set_iter *iter)
{
struct nft_hash *priv = nft_set_priv(set);
diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
index 08376e50f6cd..f06f55ee516d 100644
--- a/net/netfilter/nft_set_rbtree.c
+++ b/net/netfilter/nft_set_rbtree.c
@@ -221,7 +221,7 @@ static void *nft_rbtree_deactivate(const struct net *net,
}
static void nft_rbtree_walk(const struct nft_ctx *ctx,
- const struct nft_set *set,
+ struct nft_set *set,
struct nft_set_iter *iter)
{
const struct nft_rbtree *priv = nft_set_priv(set);
--
2.1.4
^ permalink raw reply related
* [PATCH 11/14] netfilter: nft_log: restrict the log prefix length to 127
From: Pablo Neira Ayuso @ 2017-01-26 16:38 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1485448687-6072-1-git-send-email-pablo@netfilter.org>
From: Liping Zhang <zlpnobody@gmail.com>
First, log prefix will be truncated to NF_LOG_PREFIXLEN-1, i.e. 127,
at nf_log_packet(), so the extra part is useless.
Second, after adding a log rule with a very very long prefix, we will
fail to dump the nft rules after this _special_ one, but acctually,
they do exist. For example:
# name_65000=$(printf "%0.sQ" {1..65000})
# nft add rule filter output log prefix "$name_65000"
# nft add rule filter output counter
# nft add rule filter output counter
# nft list chain filter output
table ip filter {
chain output {
type filter hook output priority 0; policy accept;
}
}
So now, restrict the log prefix length to NF_LOG_PREFIXLEN-1.
Fixes: 96518518cc41 ("netfilter: add nftables")
Signed-off-by: Liping Zhang <zlpnobody@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/uapi/linux/netfilter/nf_log.h | 2 ++
net/netfilter/nf_log.c | 1 -
net/netfilter/nft_log.c | 3 ++-
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/netfilter/nf_log.h b/include/uapi/linux/netfilter/nf_log.h
index 8be21e02387d..d0b5fa91ff54 100644
--- a/include/uapi/linux/netfilter/nf_log.h
+++ b/include/uapi/linux/netfilter/nf_log.h
@@ -9,4 +9,6 @@
#define NF_LOG_MACDECODE 0x20 /* Decode MAC header */
#define NF_LOG_MASK 0x2f
+#define NF_LOG_PREFIXLEN 128
+
#endif /* _NETFILTER_NF_LOG_H */
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index 3dca90dc24ad..ffb9e8ada899 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -13,7 +13,6 @@
/* Internal logging interface, which relies on the real
LOG target modules */
-#define NF_LOG_PREFIXLEN 128
#define NFLOGGER_NAME_LEN 64
static struct nf_logger __rcu *loggers[NFPROTO_NUMPROTO][NF_LOG_TYPE_MAX] __read_mostly;
diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c
index 6271e40a3dd6..6f6e64423643 100644
--- a/net/netfilter/nft_log.c
+++ b/net/netfilter/nft_log.c
@@ -39,7 +39,8 @@ static void nft_log_eval(const struct nft_expr *expr,
static const struct nla_policy nft_log_policy[NFTA_LOG_MAX + 1] = {
[NFTA_LOG_GROUP] = { .type = NLA_U16 },
- [NFTA_LOG_PREFIX] = { .type = NLA_STRING },
+ [NFTA_LOG_PREFIX] = { .type = NLA_STRING,
+ .len = NF_LOG_PREFIXLEN - 1 },
[NFTA_LOG_SNAPLEN] = { .type = NLA_U32 },
[NFTA_LOG_QTHRESHOLD] = { .type = NLA_U16 },
[NFTA_LOG_LEVEL] = { .type = NLA_U32 },
--
2.1.4
^ permalink raw reply related
* [PATCH 10/14] netfilter: nf_tables: validate the name size when possible
From: Pablo Neira Ayuso @ 2017-01-26 16:38 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1485448687-6072-1-git-send-email-pablo@netfilter.org>
From: Liping Zhang <zlpnobody@gmail.com>
Currently, if the user add a stateful object with the name size exceed
NFT_OBJ_MAXNAMELEN - 1 (i.e. 31), we truncate it down to 31 silently.
This is not friendly, furthermore, this will cause duplicated stateful
objects when the first 31 characters of the name is same. So limit the
stateful object's name size to NFT_OBJ_MAXNAMELEN - 1.
After apply this patch, error message will be printed out like this:
# name_32=$(printf "%0.sQ" {1..32})
# nft add counter filter $name_32
<cmdline>:1:1-52: Error: Could not process rule: Numerical result out
of range
add counter filter QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Also this patch cleans up the codes which missing the name size limit
validation in nftables.
Fixes: e50092404c1b ("netfilter: nf_tables: add stateful objects")
Signed-off-by: Liping Zhang <zlpnobody@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_tables_api.c | 21 ++++++++++++++-------
net/netfilter/nft_dynset.c | 3 ++-
net/netfilter/nft_lookup.c | 3 ++-
net/netfilter/nft_objref.c | 6 ++++--
4 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 091d2dcc63b2..b84c7b25219b 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -928,7 +928,8 @@ static struct nft_chain *nf_tables_chain_lookup(const struct nft_table *table,
}
static const struct nla_policy nft_chain_policy[NFTA_CHAIN_MAX + 1] = {
- [NFTA_CHAIN_TABLE] = { .type = NLA_STRING },
+ [NFTA_CHAIN_TABLE] = { .type = NLA_STRING,
+ .len = NFT_TABLE_MAXNAMELEN - 1 },
[NFTA_CHAIN_HANDLE] = { .type = NLA_U64 },
[NFTA_CHAIN_NAME] = { .type = NLA_STRING,
.len = NFT_CHAIN_MAXNAMELEN - 1 },
@@ -1854,7 +1855,8 @@ static struct nft_rule *nf_tables_rule_lookup(const struct nft_chain *chain,
}
static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = {
- [NFTA_RULE_TABLE] = { .type = NLA_STRING },
+ [NFTA_RULE_TABLE] = { .type = NLA_STRING,
+ .len = NFT_TABLE_MAXNAMELEN - 1 },
[NFTA_RULE_CHAIN] = { .type = NLA_STRING,
.len = NFT_CHAIN_MAXNAMELEN - 1 },
[NFTA_RULE_HANDLE] = { .type = NLA_U64 },
@@ -2443,7 +2445,8 @@ nft_select_set_ops(const struct nlattr * const nla[],
}
static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
- [NFTA_SET_TABLE] = { .type = NLA_STRING },
+ [NFTA_SET_TABLE] = { .type = NLA_STRING,
+ .len = NFT_TABLE_MAXNAMELEN - 1 },
[NFTA_SET_NAME] = { .type = NLA_STRING,
.len = NFT_SET_MAXNAMELEN - 1 },
[NFTA_SET_FLAGS] = { .type = NLA_U32 },
@@ -3192,8 +3195,10 @@ static const struct nla_policy nft_set_elem_policy[NFTA_SET_ELEM_MAX + 1] = {
};
static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX + 1] = {
- [NFTA_SET_ELEM_LIST_TABLE] = { .type = NLA_STRING },
- [NFTA_SET_ELEM_LIST_SET] = { .type = NLA_STRING },
+ [NFTA_SET_ELEM_LIST_TABLE] = { .type = NLA_STRING,
+ .len = NFT_TABLE_MAXNAMELEN - 1 },
+ [NFTA_SET_ELEM_LIST_SET] = { .type = NLA_STRING,
+ .len = NFT_SET_MAXNAMELEN - 1 },
[NFTA_SET_ELEM_LIST_ELEMENTS] = { .type = NLA_NESTED },
[NFTA_SET_ELEM_LIST_SET_ID] = { .type = NLA_U32 },
};
@@ -4032,8 +4037,10 @@ struct nft_object *nf_tables_obj_lookup(const struct nft_table *table,
EXPORT_SYMBOL_GPL(nf_tables_obj_lookup);
static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = {
- [NFTA_OBJ_TABLE] = { .type = NLA_STRING },
- [NFTA_OBJ_NAME] = { .type = NLA_STRING },
+ [NFTA_OBJ_TABLE] = { .type = NLA_STRING,
+ .len = NFT_TABLE_MAXNAMELEN - 1 },
+ [NFTA_OBJ_NAME] = { .type = NLA_STRING,
+ .len = NFT_OBJ_MAXNAMELEN - 1 },
[NFTA_OBJ_TYPE] = { .type = NLA_U32 },
[NFTA_OBJ_DATA] = { .type = NLA_NESTED },
};
diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c
index 7de2f46734a4..049ad2d9ee66 100644
--- a/net/netfilter/nft_dynset.c
+++ b/net/netfilter/nft_dynset.c
@@ -98,7 +98,8 @@ static void nft_dynset_eval(const struct nft_expr *expr,
}
static const struct nla_policy nft_dynset_policy[NFTA_DYNSET_MAX + 1] = {
- [NFTA_DYNSET_SET_NAME] = { .type = NLA_STRING },
+ [NFTA_DYNSET_SET_NAME] = { .type = NLA_STRING,
+ .len = NFT_SET_MAXNAMELEN - 1 },
[NFTA_DYNSET_SET_ID] = { .type = NLA_U32 },
[NFTA_DYNSET_OP] = { .type = NLA_U32 },
[NFTA_DYNSET_SREG_KEY] = { .type = NLA_U32 },
diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c
index d4f97fa7e21d..e21aea7e5ec8 100644
--- a/net/netfilter/nft_lookup.c
+++ b/net/netfilter/nft_lookup.c
@@ -49,7 +49,8 @@ static void nft_lookup_eval(const struct nft_expr *expr,
}
static const struct nla_policy nft_lookup_policy[NFTA_LOOKUP_MAX + 1] = {
- [NFTA_LOOKUP_SET] = { .type = NLA_STRING },
+ [NFTA_LOOKUP_SET] = { .type = NLA_STRING,
+ .len = NFT_SET_MAXNAMELEN - 1 },
[NFTA_LOOKUP_SET_ID] = { .type = NLA_U32 },
[NFTA_LOOKUP_SREG] = { .type = NLA_U32 },
[NFTA_LOOKUP_DREG] = { .type = NLA_U32 },
diff --git a/net/netfilter/nft_objref.c b/net/netfilter/nft_objref.c
index 415a65ba2b85..1ae8c49ca4a1 100644
--- a/net/netfilter/nft_objref.c
+++ b/net/netfilter/nft_objref.c
@@ -193,10 +193,12 @@ nft_objref_select_ops(const struct nft_ctx *ctx,
}
static const struct nla_policy nft_objref_policy[NFTA_OBJREF_MAX + 1] = {
- [NFTA_OBJREF_IMM_NAME] = { .type = NLA_STRING },
+ [NFTA_OBJREF_IMM_NAME] = { .type = NLA_STRING,
+ .len = NFT_OBJ_MAXNAMELEN - 1 },
[NFTA_OBJREF_IMM_TYPE] = { .type = NLA_U32 },
[NFTA_OBJREF_SET_SREG] = { .type = NLA_U32 },
- [NFTA_OBJREF_SET_NAME] = { .type = NLA_STRING },
+ [NFTA_OBJREF_SET_NAME] = { .type = NLA_STRING,
+ .len = NFT_SET_MAXNAMELEN - 1 },
[NFTA_OBJREF_SET_ID] = { .type = NLA_U32 },
};
--
2.1.4
^ permalink raw reply related
* [PATCH 03/14] netfilter: nf_tables: fix spelling mistakes
From: Pablo Neira Ayuso @ 2017-01-26 16:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1485448687-6072-1-git-send-email-pablo@netfilter.org>
From: Alexander Alemayhu <alexander@alemayhu.com>
o s/numerice/numeric
o s/opertaor/operator
Signed-off-by: Alexander Alemayhu <alexander@alemayhu.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/uapi/linux/netfilter/nf_tables.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 881d49e94569..e3f27e09eb2b 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -235,7 +235,7 @@ enum nft_rule_compat_flags {
/**
* enum nft_rule_compat_attributes - nf_tables rule compat attributes
*
- * @NFTA_RULE_COMPAT_PROTO: numerice value of handled protocol (NLA_U32)
+ * @NFTA_RULE_COMPAT_PROTO: numeric value of handled protocol (NLA_U32)
* @NFTA_RULE_COMPAT_FLAGS: bitmask of enum nft_rule_compat_flags (NLA_U32)
*/
enum nft_rule_compat_attributes {
@@ -499,7 +499,7 @@ enum nft_bitwise_attributes {
* enum nft_byteorder_ops - nf_tables byteorder operators
*
* @NFT_BYTEORDER_NTOH: network to host operator
- * @NFT_BYTEORDER_HTON: host to network opertaor
+ * @NFT_BYTEORDER_HTON: host to network operator
*/
enum nft_byteorder_ops {
NFT_BYTEORDER_NTOH,
--
2.1.4
^ permalink raw reply related
* [PATCH 02/14] tcp: fix mark propagation with fwmark_reflect enabled
From: Pablo Neira Ayuso @ 2017-01-26 16:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1485448687-6072-1-git-send-email-pablo@netfilter.org>
From: Pau Espin Pedrol <pespin.shar@gmail.com>
Otherwise, RST packets generated by the TCP stack for non-existing
sockets always have mark 0.
The mark from the original packet is assigned to the netns_ipv4/6
socket used to send the response so that it can get copied into the
response skb when the socket sends it.
Fixes: e110861f8609 ("net: add a sysctl to reflect the fwmark on replies")
Cc: Lorenzo Colitti <lorenzo@google.com>
Signed-off-by: Pau Espin Pedrol <pau.espin@tessares.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/ipv4/ip_output.c | 1 +
net/ipv6/tcp_ipv6.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index fac275c48108..b67719f45953 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1629,6 +1629,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
sk->sk_protocol = ip_hdr(skb)->protocol;
sk->sk_bound_dev_if = arg->bound_dev_if;
sk->sk_sndbuf = sysctl_wmem_default;
+ sk->sk_mark = fl4.flowi4_mark;
err = ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base,
len, 0, &ipc, &rt, MSG_DONTWAIT);
if (unlikely(err)) {
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 73bc8fc68acd..2b20622a5824 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -840,6 +840,7 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL);
if (!IS_ERR(dst)) {
skb_dst_set(buff, dst);
+ ctl_sk->sk_mark = fl6.flowi6_mark;
ip6_xmit(ctl_sk, buff, &fl6, NULL, tclass);
TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
if (rst)
--
2.1.4
^ permalink raw reply related
* [PATCH 01/14] netfilter: use fwmark_reflect in nf_send_reset
From: Pablo Neira Ayuso @ 2017-01-26 16:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1485448687-6072-1-git-send-email-pablo@netfilter.org>
From: Pau Espin Pedrol <pau.espin@tessares.net>
Otherwise, RST packets generated by ipt_REJECT always have mark 0 when
the routing is checked later in the same code path.
Fixes: e110861f8609 ("net: add a sysctl to reflect the fwmark on replies")
Cc: Lorenzo Colitti <lorenzo@google.com>
Signed-off-by: Pau Espin Pedrol <pau.espin@tessares.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/ipv4/netfilter/nf_reject_ipv4.c | 2 ++
net/ipv6/netfilter/nf_reject_ipv6.c | 3 +++
2 files changed, 5 insertions(+)
diff --git a/net/ipv4/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c
index fd8220213afc..146d86105183 100644
--- a/net/ipv4/netfilter/nf_reject_ipv4.c
+++ b/net/ipv4/netfilter/nf_reject_ipv4.c
@@ -126,6 +126,8 @@ void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
/* ip_route_me_harder expects skb->dst to be set */
skb_dst_set_noref(nskb, skb_dst(oldskb));
+ nskb->mark = IP4_REPLY_MARK(net, oldskb->mark);
+
skb_reserve(nskb, LL_MAX_HEADER);
niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP,
ip4_dst_hoplimit(skb_dst(nskb)));
diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c
index 10090400c72f..eedee5d108d9 100644
--- a/net/ipv6/netfilter/nf_reject_ipv6.c
+++ b/net/ipv6/netfilter/nf_reject_ipv6.c
@@ -157,6 +157,7 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
fl6.fl6_sport = otcph->dest;
fl6.fl6_dport = otcph->source;
fl6.flowi6_oif = l3mdev_master_ifindex(skb_dst(oldskb)->dev);
+ fl6.flowi6_mark = IP6_REPLY_MARK(net, oldskb->mark);
security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));
dst = ip6_route_output(net, NULL, &fl6);
if (dst->error) {
@@ -180,6 +181,8 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
skb_dst_set(nskb, dst);
+ nskb->mark = fl6.flowi6_mark;
+
skb_reserve(nskb, hh_len + dst->header_len);
ip6h = nf_reject_ip6hdr_put(nskb, oldskb, IPPROTO_TCP,
ip6_dst_hoplimit(dst));
--
2.1.4
^ permalink raw reply related
* Re: iproute2: using .maxattr = IFLA_VLAN_MAX??
From: Murali Karicheri @ 2017-01-26 16:27 UTC (permalink / raw)
To: Rosen, Rami, open list:TI NETCP ETHERNET DRIVER
In-Reply-To: <9B0331B6EBBD0E4684FBFAEDA55776F93D496CA4@HASMSX110.ger.corp.intel.com>
On 01/23/2017 03:45 PM, Rosen, Rami wrote:
> Hi, Murali,
>
>> This appears to be a cut-n-paste bug as the source is based on ip/iplink_vlan.c and should be fixed to IFLA_HSR_MAX.
>
> You are right.
> The "HSR section" indeed defines IFLA_HSR_MAX in include/linux/if_link.h of iproute2 as the max attributes number.
>
> And in the top of ip/iplink_hsr.c you will find this comment, which enhances your assumption about the origin of this mistake:
>
> /*
> ...
> Based on iplink_vlan.c by Patrick McHardy <kaber@trash.net
> ...
> */
>
> Regards,
> Rami Rosen
>
Hi, Rami,
Thanks for confirming. I will send out a patch for fixing this when I get a chance to
test hsr for my work in the next few days.
--
Murali Karicheri
Linux Kernel, Keystone
^ permalink raw reply
* Re: ip_rcv_finish() NULL pointer kernel panic
From: Florian Westphal @ 2017-01-26 16:24 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Roy Keene, netdev, netfilter-devel
In-Reply-To: <1485446279.5145.141.camel@edumazet-glaptop3.roam.corp.google.com>
Eric Dumazet <eric.dumazet@gmail.com> wrote:
> > Though possibly with different things not setting the "input" function
> > pointer in the "struct dst_entry".
> >
> > include/net/dst.h:
> > 496 static inline int dst_input(struct sk_buff *skb) {
> > 498 return skb_dst(skb)->input(skb);
> > 499 }
> >
> > Is there any reason not to check to see if this pointer is NULL before
> > blindly calling it ?
>
> Sure. It can not be NULL at this point.
>
> Just look at the code in ip_rcv_finish() :
>
> It first make sure to get a valid dst.
>
> Something is broken, probably in bridge netfilter code.
>
> I suspect the dst here points to &br->fake_rtable, and this is not
> expected.
>
> br_drop_fake_rtable() should have been called somewhere ...
I think it makes sense to set dst->incoming
to a stub in br_netfilter_rtable_init() to just kfree_skb()+
WARN_ON_ONCE(), no need to add code to ip stack or crash kernel
due to brnf bug.
^ permalink raw reply
* [PATCH] net: macb: Fix 64 bit addressing support for GEM
From: Rafal Ozieblo @ 2017-01-26 16:24 UTC (permalink / raw)
To: Nicolas Ferre, netdev, linux-kernel, harinikatakamlinux; +Cc: Rafal Ozieblo
This patch adds support for 32 bit GEM in
64 bit system. It checks capability at runtime
and uses appropriate buffer descriptor.
Signed-off-by: Rafal Ozieblo <rafalo@cadence.com>
---
drivers/net/ethernet/cadence/macb.c | 182 +++++++++++++++++++++++++-----------
drivers/net/ethernet/cadence/macb.h | 20 +++-
2 files changed, 144 insertions(+), 58 deletions(-)
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index c0fb80a..6afff3d 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -43,13 +43,13 @@
#define DEFAULT_RX_RING_SIZE 512 /* must be power of 2 */
#define MIN_RX_RING_SIZE 64
#define MAX_RX_RING_SIZE 8192
-#define RX_RING_BYTES(bp) (sizeof(struct macb_dma_desc) \
+#define RX_RING_BYTES(bp) (macb_dma_desc_get_size(bp) \
* (bp)->rx_ring_size)
#define DEFAULT_TX_RING_SIZE 512 /* must be power of 2 */
#define MIN_TX_RING_SIZE 64
#define MAX_TX_RING_SIZE 4096
-#define TX_RING_BYTES(bp) (sizeof(struct macb_dma_desc) \
+#define TX_RING_BYTES(bp) (macb_dma_desc_get_size(bp) \
* (bp)->tx_ring_size)
/* level of occupied TX descriptors under which we wake up TX process */
@@ -78,6 +78,37 @@
*/
#define MACB_HALT_TIMEOUT 1230
+/* DMA buffer descriptor might be different size
+ * depends on hardware configuration.
+ */
+static unsigned int macb_dma_desc_get_size(struct macb *bp)
+{
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+ if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+ return sizeof(struct macb_dma_desc) + sizeof(struct macb_dma_desc_64);
+#endif
+ return sizeof(struct macb_dma_desc);
+}
+
+static unsigned int macb_adj_dma_desc_idx(struct macb *bp, unsigned int idx)
+{
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+ /* Dma buffer descriptor is 4 words length (instead of 2 words)
+ * for 64b GEM.
+ */
+ if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+ idx <<= 1;
+#endif
+ return idx;
+}
+
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+static struct macb_dma_desc_64 *macb_64b_desc(struct macb *bp, struct macb_dma_desc *desc)
+{
+ return (struct macb_dma_desc_64 *)((void *)desc + sizeof(struct macb_dma_desc));
+}
+#endif
+
/* Ring buffer accessors */
static unsigned int macb_tx_ring_wrap(struct macb *bp, unsigned int index)
{
@@ -87,7 +118,9 @@ static unsigned int macb_tx_ring_wrap(struct macb *bp, unsigned int index)
static struct macb_dma_desc *macb_tx_desc(struct macb_queue *queue,
unsigned int index)
{
- return &queue->tx_ring[macb_tx_ring_wrap(queue->bp, index)];
+ index = macb_tx_ring_wrap(queue->bp, index);
+ index = macb_adj_dma_desc_idx(queue->bp, index);
+ return &queue->tx_ring[index];
}
static struct macb_tx_skb *macb_tx_skb(struct macb_queue *queue,
@@ -101,7 +134,7 @@ static dma_addr_t macb_tx_dma(struct macb_queue *queue, unsigned int index)
dma_addr_t offset;
offset = macb_tx_ring_wrap(queue->bp, index) *
- sizeof(struct macb_dma_desc);
+ macb_dma_desc_get_size(queue->bp);
return queue->tx_ring_dma + offset;
}
@@ -113,7 +146,9 @@ static unsigned int macb_rx_ring_wrap(struct macb *bp, unsigned int index)
static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index)
{
- return &bp->rx_ring[macb_rx_ring_wrap(bp, index)];
+ index = macb_rx_ring_wrap(bp, index);
+ index = macb_adj_dma_desc_idx(bp, index);
+ return &bp->rx_ring[index];
}
static void *macb_rx_buffer(struct macb *bp, unsigned int index)
@@ -560,12 +595,32 @@ static void macb_tx_unmap(struct macb *bp, struct macb_tx_skb *tx_skb)
}
}
-static inline void macb_set_addr(struct macb_dma_desc *desc, dma_addr_t addr)
+static void macb_set_addr(struct macb *bp, struct macb_dma_desc *desc, dma_addr_t addr)
{
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+ struct macb_dma_desc_64 *desc_64;
+
+ if (bp->hw_dma_cap == HW_DMA_CAP_64B) {
+ desc_64 = macb_64b_desc(bp, desc);
+ desc_64->addrh = (u32)(addr >> 32);
+ }
+#endif
desc->addr = (u32)addr;
+}
+
+static dma_addr_t macb_get_addr(struct macb *bp, struct macb_dma_desc *desc)
+{
+ dma_addr_t addr = 0;
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
- desc->addrh = (u32)(addr >> 32);
+ struct macb_dma_desc_64 *desc_64;
+
+ if (bp->hw_dma_cap == HW_DMA_CAP_64B) {
+ desc_64 = macb_64b_desc(bp, desc);
+ addr = ((u64)(desc_64->addrh) << 32);
+ }
#endif
+ addr |= MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
+ return addr;
}
static void macb_tx_error_task(struct work_struct *work)
@@ -574,7 +629,7 @@ static void macb_tx_error_task(struct work_struct *work)
tx_error_task);
struct macb *bp = queue->bp;
struct macb_tx_skb *tx_skb;
- struct macb_dma_desc *desc;
+ struct macb_dma_desc *desc;
struct sk_buff *skb;
unsigned int tail;
unsigned long flags;
@@ -649,7 +704,7 @@ static void macb_tx_error_task(struct work_struct *work)
/* Set end of TX queue */
desc = macb_tx_desc(queue, 0);
- macb_set_addr(desc, 0);
+ macb_set_addr(bp, desc, 0);
desc->ctrl = MACB_BIT(TX_USED);
/* Make descriptor updates visible to hardware */
@@ -658,7 +713,8 @@ static void macb_tx_error_task(struct work_struct *work)
/* Reinitialize the TX desc queue */
queue_writel(queue, TBQP, (u32)(queue->tx_ring_dma));
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
- queue_writel(queue, TBQPH, (u32)(queue->tx_ring_dma >> 32));
+ if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+ queue_writel(queue, TBQPH, (u32)(queue->tx_ring_dma >> 32));
#endif
/* Make TX ring reflect state of hardware */
queue->tx_head = 0;
@@ -750,6 +806,7 @@ static void gem_rx_refill(struct macb *bp)
unsigned int entry;
struct sk_buff *skb;
dma_addr_t paddr;
+ struct macb_dma_desc *desc;
while (CIRC_SPACE(bp->rx_prepared_head, bp->rx_tail,
bp->rx_ring_size) > 0) {
@@ -759,6 +816,7 @@ static void gem_rx_refill(struct macb *bp)
rmb();
bp->rx_prepared_head++;
+ desc = macb_rx_desc(bp, entry);
if (!bp->rx_skbuff[entry]) {
/* allocate sk_buff for this free entry in ring */
@@ -782,14 +840,14 @@ static void gem_rx_refill(struct macb *bp)
if (entry == bp->rx_ring_size - 1)
paddr |= MACB_BIT(RX_WRAP);
- macb_set_addr(&(bp->rx_ring[entry]), paddr);
- bp->rx_ring[entry].ctrl = 0;
+ macb_set_addr(bp, desc, paddr);
+ desc->ctrl = 0;
/* properly align Ethernet header */
skb_reserve(skb, NET_IP_ALIGN);
} else {
- bp->rx_ring[entry].addr &= ~MACB_BIT(RX_USED);
- bp->rx_ring[entry].ctrl = 0;
+ desc->addr &= ~MACB_BIT(RX_USED);
+ desc->ctrl = 0;
}
}
@@ -835,16 +893,13 @@ static int gem_rx(struct macb *bp, int budget)
bool rxused;
entry = macb_rx_ring_wrap(bp, bp->rx_tail);
- desc = &bp->rx_ring[entry];
+ desc = macb_rx_desc(bp, entry);
/* Make hw descriptor updates visible to CPU */
rmb();
rxused = (desc->addr & MACB_BIT(RX_USED)) ? true : false;
- addr = MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
- addr |= ((u64)(desc->addrh) << 32);
-#endif
+ addr = macb_get_addr(bp, desc);
ctrl = desc->ctrl;
if (!rxused)
@@ -987,15 +1042,17 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
static inline void macb_init_rx_ring(struct macb *bp)
{
dma_addr_t addr;
+ struct macb_dma_desc *desc = NULL;
int i;
addr = bp->rx_buffers_dma;
for (i = 0; i < bp->rx_ring_size; i++) {
- bp->rx_ring[i].addr = addr;
- bp->rx_ring[i].ctrl = 0;
+ desc = macb_rx_desc(bp, i);
+ macb_set_addr(bp, desc, addr);
+ desc->ctrl = 0;
addr += bp->rx_buffer_size;
}
- bp->rx_ring[bp->rx_ring_size - 1].addr |= MACB_BIT(RX_WRAP);
+ desc->addr |= MACB_BIT(RX_WRAP);
bp->rx_tail = 0;
}
@@ -1008,15 +1065,14 @@ static int macb_rx(struct macb *bp, int budget)
for (tail = bp->rx_tail; budget > 0; tail++) {
struct macb_dma_desc *desc = macb_rx_desc(bp, tail);
- u32 addr, ctrl;
+ u32 ctrl;
/* Make hw descriptor updates visible to CPU */
rmb();
- addr = desc->addr;
ctrl = desc->ctrl;
- if (!(addr & MACB_BIT(RX_USED)))
+ if (!(desc->addr & MACB_BIT(RX_USED)))
break;
if (ctrl & MACB_BIT(RX_SOF)) {
@@ -1336,7 +1392,7 @@ static unsigned int macb_tx_map(struct macb *bp,
i = tx_head;
entry = macb_tx_ring_wrap(bp, i);
ctrl = MACB_BIT(TX_USED);
- desc = &queue->tx_ring[entry];
+ desc = macb_tx_desc(queue, entry);
desc->ctrl = ctrl;
if (lso_ctrl) {
@@ -1358,7 +1414,7 @@ static unsigned int macb_tx_map(struct macb *bp,
i--;
entry = macb_tx_ring_wrap(bp, i);
tx_skb = &queue->tx_skb[entry];
- desc = &queue->tx_ring[entry];
+ desc = macb_tx_desc(queue, entry);
ctrl = (u32)tx_skb->size;
if (eof) {
@@ -1379,7 +1435,7 @@ static unsigned int macb_tx_map(struct macb *bp,
ctrl |= MACB_BF(MSS_MFS, mss_mfs);
/* Set TX buffer descriptor */
- macb_set_addr(desc, tx_skb->mapping);
+ macb_set_addr(bp, desc, tx_skb->mapping);
/* desc->addr must be visible to hardware before clearing
* 'TX_USED' bit in desc->ctrl.
*/
@@ -1586,11 +1642,9 @@ static void gem_free_rx_buffers(struct macb *bp)
if (!skb)
continue;
- desc = &bp->rx_ring[i];
- addr = MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
- addr |= ((u64)(desc->addrh) << 32);
-#endif
+ desc = macb_rx_desc(bp, i);
+ addr = macb_get_addr(bp, desc);
+
dma_unmap_single(&bp->pdev->dev, addr, bp->rx_buffer_size,
DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
@@ -1711,15 +1765,17 @@ static int macb_alloc_consistent(struct macb *bp)
static void gem_init_rings(struct macb *bp)
{
struct macb_queue *queue;
+ struct macb_dma_desc *desc = NULL;
unsigned int q;
int i;
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
for (i = 0; i < bp->tx_ring_size; i++) {
- queue->tx_ring[i].addr = 0;
- queue->tx_ring[i].ctrl = MACB_BIT(TX_USED);
+ desc = macb_tx_desc(queue, i);
+ macb_set_addr(bp, desc, 0);
+ desc->ctrl = MACB_BIT(TX_USED);
}
- queue->tx_ring[bp->tx_ring_size - 1].ctrl |= MACB_BIT(TX_WRAP);
+ desc->ctrl |= MACB_BIT(TX_WRAP);
queue->tx_head = 0;
queue->tx_tail = 0;
}
@@ -1733,16 +1789,18 @@ static void gem_init_rings(struct macb *bp)
static void macb_init_rings(struct macb *bp)
{
int i;
+ struct macb_dma_desc *desc = NULL;
macb_init_rx_ring(bp);
for (i = 0; i < bp->tx_ring_size; i++) {
- bp->queues[0].tx_ring[i].addr = 0;
- bp->queues[0].tx_ring[i].ctrl = MACB_BIT(TX_USED);
+ desc = macb_tx_desc(&bp->queues[0], i);
+ macb_set_addr(bp, desc, 0);
+ desc->ctrl = MACB_BIT(TX_USED);
}
bp->queues[0].tx_head = 0;
bp->queues[0].tx_tail = 0;
- bp->queues[0].tx_ring[bp->tx_ring_size - 1].ctrl |= MACB_BIT(TX_WRAP);
+ desc->ctrl |= MACB_BIT(TX_WRAP);
}
static void macb_reset_hw(struct macb *bp)
@@ -1863,7 +1921,8 @@ static void macb_configure_dma(struct macb *bp)
dmacfg &= ~GEM_BIT(TXCOEN);
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
- dmacfg |= GEM_BIT(ADDR64);
+ if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+ dmacfg |= GEM_BIT(ADDR64);
#endif
netdev_dbg(bp->dev, "Cadence configure DMA with 0x%08x\n",
dmacfg);
@@ -1912,12 +1971,14 @@ static void macb_init_hw(struct macb *bp)
/* Initialize TX and RX buffers */
macb_writel(bp, RBQP, (u32)(bp->rx_ring_dma));
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
- macb_writel(bp, RBQPH, (u32)(bp->rx_ring_dma >> 32));
+ if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+ macb_writel(bp, RBQPH, (u32)(bp->rx_ring_dma >> 32));
#endif
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
queue_writel(queue, TBQP, (u32)(queue->tx_ring_dma));
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
- queue_writel(queue, TBQPH, (u32)(queue->tx_ring_dma >> 32));
+ if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+ queue_writel(queue, TBQPH, (u32)(queue->tx_ring_dma >> 32));
#endif
/* Enable interrupts */
@@ -2627,7 +2688,8 @@ static int macb_init(struct platform_device *pdev)
queue->IMR = GEM_IMR(hw_q - 1);
queue->TBQP = GEM_TBQP(hw_q - 1);
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
- queue->TBQPH = GEM_TBQPH(hw_q -1);
+ if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+ queue->TBQPH = GEM_TBQPH(hw_q - 1);
#endif
} else {
/* queue0 uses legacy registers */
@@ -2637,7 +2699,8 @@ static int macb_init(struct platform_device *pdev)
queue->IMR = MACB_IMR;
queue->TBQP = MACB_TBQP;
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
- queue->TBQPH = MACB_TBQPH;
+ if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+ queue->TBQPH = MACB_TBQPH;
#endif
}
@@ -2730,13 +2793,14 @@ static int macb_init(struct platform_device *pdev)
static int at91ether_start(struct net_device *dev)
{
struct macb *lp = netdev_priv(dev);
+ struct macb_dma_desc *desc;
dma_addr_t addr;
u32 ctl;
int i;
lp->rx_ring = dma_alloc_coherent(&lp->pdev->dev,
(AT91ETHER_MAX_RX_DESCR *
- sizeof(struct macb_dma_desc)),
+ macb_dma_desc_get_size(lp)),
&lp->rx_ring_dma, GFP_KERNEL);
if (!lp->rx_ring)
return -ENOMEM;
@@ -2748,7 +2812,7 @@ static int at91ether_start(struct net_device *dev)
if (!lp->rx_buffers) {
dma_free_coherent(&lp->pdev->dev,
AT91ETHER_MAX_RX_DESCR *
- sizeof(struct macb_dma_desc),
+ macb_dma_desc_get_size(lp),
lp->rx_ring, lp->rx_ring_dma);
lp->rx_ring = NULL;
return -ENOMEM;
@@ -2756,13 +2820,14 @@ static int at91ether_start(struct net_device *dev)
addr = lp->rx_buffers_dma;
for (i = 0; i < AT91ETHER_MAX_RX_DESCR; i++) {
- lp->rx_ring[i].addr = addr;
- lp->rx_ring[i].ctrl = 0;
+ desc = macb_rx_desc(lp, i);
+ macb_set_addr(lp, desc, addr);
+ desc->ctrl = 0;
addr += AT91ETHER_MAX_RBUFF_SZ;
}
/* Set the Wrap bit on the last descriptor */
- lp->rx_ring[AT91ETHER_MAX_RX_DESCR - 1].addr |= MACB_BIT(RX_WRAP);
+ desc->addr |= MACB_BIT(RX_WRAP);
/* Reset buffer index */
lp->rx_tail = 0;
@@ -2834,7 +2899,7 @@ static int at91ether_close(struct net_device *dev)
dma_free_coherent(&lp->pdev->dev,
AT91ETHER_MAX_RX_DESCR *
- sizeof(struct macb_dma_desc),
+ macb_dma_desc_get_size(lp),
lp->rx_ring, lp->rx_ring_dma);
lp->rx_ring = NULL;
@@ -2885,13 +2950,15 @@ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
static void at91ether_rx(struct net_device *dev)
{
struct macb *lp = netdev_priv(dev);
+ struct macb_dma_desc *desc;
unsigned char *p_recv;
struct sk_buff *skb;
unsigned int pktlen;
- while (lp->rx_ring[lp->rx_tail].addr & MACB_BIT(RX_USED)) {
+ desc = macb_rx_desc(lp, lp->rx_tail);
+ while (desc->addr & MACB_BIT(RX_USED)) {
p_recv = lp->rx_buffers + lp->rx_tail * AT91ETHER_MAX_RBUFF_SZ;
- pktlen = MACB_BF(RX_FRMLEN, lp->rx_ring[lp->rx_tail].ctrl);
+ pktlen = MACB_BF(RX_FRMLEN, desc->ctrl);
skb = netdev_alloc_skb(dev, pktlen + 2);
if (skb) {
skb_reserve(skb, 2);
@@ -2905,17 +2972,19 @@ static void at91ether_rx(struct net_device *dev)
lp->stats.rx_dropped++;
}
- if (lp->rx_ring[lp->rx_tail].ctrl & MACB_BIT(RX_MHASH_MATCH))
+ if (desc->ctrl & MACB_BIT(RX_MHASH_MATCH))
lp->stats.multicast++;
/* reset ownership bit */
- lp->rx_ring[lp->rx_tail].addr &= ~MACB_BIT(RX_USED);
+ desc->addr &= ~MACB_BIT(RX_USED);
/* wrap after last buffer */
if (lp->rx_tail == AT91ETHER_MAX_RX_DESCR - 1)
lp->rx_tail = 0;
else
lp->rx_tail++;
+
+ desc = macb_rx_desc(lp, lp->rx_tail);
}
}
@@ -3211,8 +3280,11 @@ static int macb_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET);
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
- if (GEM_BFEXT(DBWDEF, gem_readl(bp, DCFG1)) > GEM_DBW32)
+ if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) {
dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
+ bp->hw_dma_cap = HW_DMA_CAP_64B;
+ } else
+ bp->hw_dma_cap = HW_DMA_CAP_32B;
#endif
spin_lock_init(&bp->lock);
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index d67adad..fc8550a 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -385,6 +385,8 @@
/* Bitfields in DCFG6. */
#define GEM_PBUF_LSO_OFFSET 27
#define GEM_PBUF_LSO_SIZE 1
+#define GEM_DAW64_OFFSET 23
+#define GEM_DAW64_SIZE 1
/* Constants for CLK */
#define MACB_CLK_DIV8 0
@@ -487,12 +489,20 @@
struct macb_dma_desc {
u32 addr;
u32 ctrl;
+};
+
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
- u32 addrh;
- u32 resvd;
-#endif
+enum macb_hw_dma_cap {
+ HW_DMA_CAP_32B,
+ HW_DMA_CAP_64B,
};
+struct macb_dma_desc_64 {
+ u32 addrh;
+ u32 resvd;
+};
+#endif
+
/* DMA descriptor bitfields */
#define MACB_RX_USED_OFFSET 0
#define MACB_RX_USED_SIZE 1
@@ -874,6 +884,10 @@ struct macb {
unsigned int jumbo_max_len;
u32 wol;
+
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+ enum macb_hw_dma_cap hw_dma_cap;
+#endif
};
static inline bool macb_is_gem(struct macb *bp)
--
2.4.5
^ permalink raw reply related
* RE: [PATCH] Fix 64 bit addressing support for GEM
From: Rafal Ozieblo @ 2017-01-26 16:16 UTC (permalink / raw)
To: Rafal Ozieblo, Nicolas Ferre, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, harinikatakamlinux@gmail.com
In-Reply-To: <1485442837-26598-1-git-send-email-rafalo@cadence.com>
-----Original Message-----
> From: Rafal Ozieblo [mailto:rafalo@cadence.com]
> Sent: 26 stycznia 2017 16:01
> Subject: [PATCH] Fix 64 bit addressing support for GEM
>
> This patch adds support for 32 bit GEM in
> 64 bit system. It checks capability at runtime
> and uses appropriate buffer descriptor.
>
> Signed-off-by: Rafal Ozieblo <rafalo@cadence.com>
> ---
> #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
> - if (GEM_BFEXT(DBWDEF, gem_readl(bp, DCFG1)) > GEM_DBW32)
> + if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) {
> + pr_emerg("rozieblo: 64B!\n");
I forgot to remove that log message.
^ permalink raw reply
* Re: ip_rcv_finish() NULL pointer kernel panic
From: Roy Keene @ 2017-01-26 16:02 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev, netfilter-devel
In-Reply-To: <1485446279.5145.141.camel@edumazet-glaptop3.roam.corp.google.com>
> On Thu, 2017-01-26 at 09:32 -0600, Roy Keene wrote:
>> This bug appears to have existed for a long time:
>>
>> https://www.spinics.net/lists/netdev/msg222459.html
>>
>> http://www.kernelhub.org/?p=2&msg=823752
>>
>> Though possibly with different things not setting the "input" function
>> pointer in the "struct dst_entry".
>>
>> include/net/dst.h:
>> 496 static inline int dst_input(struct sk_buff *skb) {
>> 498 return skb_dst(skb)->input(skb);
>> 499 }
>>
>> Is there any reason not to check to see if this pointer is NULL before
>> blindly calling it ?
>
> Sure. It can not be NULL at this point.
>
It clearly can be NULL at this point, since there are kernel panics for
15 years of this -- going all the way back to 2.2.20 !
https://lists.gt.net/linux/kernel/250077
It seems like it might actually be a good idea to do as Alex Bligh
suggested all those years ago and I re-suggested now.
> Just look at the code in ip_rcv_finish() :
>
> It first make sure to get a valid dst.
>
> Something is broken, probably in bridge netfilter code.
>
I'll try poking around there.
> I suspect the dst here points to &br->fake_rtable, and this is not
> expected.
>
> br_drop_fake_rtable() should have been called somewhere ...
>
Thanks,
Roy Keene
^ permalink raw reply
* Re: ip_rcv_finish() NULL pointer kernel panic
From: Eric Dumazet @ 2017-01-26 15:57 UTC (permalink / raw)
To: Roy Keene; +Cc: netdev, netfilter-devel
In-Reply-To: <alpine.LNX.2.02.1701260927040.24491@maul.oc9.org>
On Thu, 2017-01-26 at 09:32 -0600, Roy Keene wrote:
> This bug appears to have existed for a long time:
>
> https://www.spinics.net/lists/netdev/msg222459.html
>
> http://www.kernelhub.org/?p=2&msg=823752
>
> Though possibly with different things not setting the "input" function
> pointer in the "struct dst_entry".
>
> include/net/dst.h:
> 496 static inline int dst_input(struct sk_buff *skb) {
> 498 return skb_dst(skb)->input(skb);
> 499 }
>
> Is there any reason not to check to see if this pointer is NULL before
> blindly calling it ?
Sure. It can not be NULL at this point.
Just look at the code in ip_rcv_finish() :
It first make sure to get a valid dst.
Something is broken, probably in bridge netfilter code.
I suspect the dst here points to &br->fake_rtable, and this is not
expected.
br_drop_fake_rtable() should have been called somewhere ...
^ permalink raw reply
* Re: IPv6-UDP 0x0000 checksum
From: Johannes Berg @ 2017-01-26 15:36 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev-u79uwXL29TY76Z2rM5mHXA, linux-wireless
In-Reply-To: <1485444476.5145.136.camel-XN9IlZ5yJG9HTL0Zs8A6p+yfmBU6pStAUsxypvmhUTTZJqsBc5GL+g@public.gmane.org>
On Thu, 2017-01-26 at 07:27 -0800, Eric Dumazet wrote:
>
> if (!uh->check && !udp_sk(sk)->no_check6_rx) {
> udp6_csum_zero_error(skb);
> goto csum_error;
> }
Yeah, I'd found no_check6_rx already, was still trying to figure out this one :)
Looks like we actually check uh->check regardless of anything the
driver said (CHECKSUM_UNNECESSARY, or whatever), so we should be fine
even with the hardware tagging it as good in this case.
johannes
^ permalink raw reply
* Re: [PATCH v2 0/4] USB support for Broadcom NSP SoC
From: Kishon Vijay Abraham I @ 2017-01-26 15:34 UTC (permalink / raw)
To: Yendapally Reddy Dhananjaya Reddy, Rob Herring, Mark Rutland,
Russell King, Ray Jui, Scott Branden, Jon Mason, Florian Fainelli
Cc: bcm-kernel-feedback-list, devicetree, linux-kernel,
linux-arm-kernel, netdev
In-Reply-To: <1484669670-4201-1-git-send-email-yendapally.reddy@broadcom.com>
On Tuesday 17 January 2017 09:44 PM, Yendapally Reddy Dhananjaya Reddy wrote:
> This patch set contains the usb support for Broadcom NSP SoC. The
> usb3 phy is internal to the SoC and is accessed through mdio interface.
> The mdio interface can be used to access either internal usb3 phy or
> external ethernet phy using a multiplexer.
>
> The first patch provides the documentation details for usb3 phy. The
> second patch provides the changes to the mdio bus driver. The third
> patch provides the phy driver and fourth patch provides the enable
> method for usb.
merged the 1st and 4th patch to linux-phy.
Thanks
Kishon
>
> This patch series has been tested on NSP bcm958625HR board.
> This patch series is based on v4.10.0-rc3 and is available from
> github-repo: https://github.com/Broadcom/cygnus-linux.git
> branch:nsp-usb-v2
>
> Changes in v2:
> * Remove separate nsp mux driver as suggested by Andrew Lunn
> * Addressed comments from Scott and Rob
>
> Yendapally Reddy Dhananjaya Reddy (4):
> dt-bindings: phy: Add documentation for NSP USB3 PHY
> net: phy: Initialize mdio clock at probe function
> phy: Add USB3 PHY support for Broadcom NSP SoC
> arm: dts: nsp: Add USB nodes to device tree
>
> .../devicetree/bindings/phy/brcm,nsp-usb3-phy.txt | 39 +++++
> arch/arm/boot/dts/bcm-nsp.dtsi | 56 +++++++
> arch/arm/boot/dts/bcm958625k.dts | 16 ++
> drivers/net/phy/mdio-bcm-iproc.c | 6 +-
> drivers/phy/Kconfig | 8 +
> drivers/phy/Makefile | 1 +
> drivers/phy/phy-bcm-nsp-usb3.c | 176 +++++++++++++++++++++
> 7 files changed, 298 insertions(+), 4 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/phy/brcm,nsp-usb3-phy.txt
> create mode 100644 drivers/phy/phy-bcm-nsp-usb3.c
>
^ permalink raw reply
* Re: [PATCH net v2 3/3] gtp: fix cross netns recv on gtp socket
From: Pablo Neira Ayuso @ 2017-01-26 15:34 UTC (permalink / raw)
To: Andreas Schultz; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte
In-Reply-To: <20170126151134.2892-4-aschultz@tpip.net>
On Thu, Jan 26, 2017 at 04:11:34PM +0100, Andreas Schultz wrote:
> The use of the passed through netlink src_net to check for a
> cross netns operation was wrong. Using the GTP socket and the
> GTP netdevice is always correct (even if the netdev has been
> moved to new netns after link creation).
>
> Remove the now obsolete net field from gtp_dev.
>
> Signed-off-by: Andreas Schultz <aschultz@tpip.net>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
^ permalink raw reply
* Re: [PATCH net v2 2/3] gtp: clear DF bit on GTP packet txç
From: Pablo Neira Ayuso @ 2017-01-26 15:34 UTC (permalink / raw)
To: Andreas Schultz; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte
In-Reply-To: <20170126151134.2892-3-aschultz@tpip.net>
On Thu, Jan 26, 2017 at 04:11:33PM +0100, Andreas Schultz wrote:
> 3GPP TS 29.281 and 3GPP TS 29.060 imply that GTP-U packets should be
> sent with the DF bit cleared. For example 3GPP TS 29.060, Release 8,
> Section 13.2.2:
>
> > Backbone router: Any router in the backbone may fragment the GTP
> > packet if needed, according to IPv4.
>
> Acked-by: Harald Welte <laforge@netfilter.org>
> Signed-off-by: Andreas Schultz <aschultz@tpip.net>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
^ permalink raw reply
* Re: [PATCH net v2 1/3] gtp: add genl family modules alias
From: Pablo Neira Ayuso @ 2017-01-26 15:34 UTC (permalink / raw)
To: Andreas Schultz; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte
In-Reply-To: <20170126151134.2892-2-aschultz@tpip.net>
On Thu, Jan 26, 2017 at 04:11:32PM +0100, Andreas Schultz wrote:
> Auto-load the module when userspace asks for the gtp netlink
> family.
>
> Acked-by: Harald Welte <laforge@netfilter.org>
> Signed-off-by: Andreas Schultz <aschultz@tpip.net>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
^ permalink raw reply
* Re: ip_rcv_finish() NULL pointer kernel panic
From: Roy Keene @ 2017-01-26 15:32 UTC (permalink / raw)
To: netdev, linux-kernel
In-Reply-To: <alpine.LNX.2.02.1701260627510.24491@maul.oc9.org>
This bug appears to have existed for a long time:
https://www.spinics.net/lists/netdev/msg222459.html
http://www.kernelhub.org/?p=2&msg=823752
Though possibly with different things not setting the "input" function
pointer in the "struct dst_entry".
include/net/dst.h:
496 static inline int dst_input(struct sk_buff *skb) {
498 return skb_dst(skb)->input(skb);
499 }
Is there any reason not to check to see if this pointer is NULL before
blindly calling it ?
On Thu, 26 Jan 2017, Roy Keene wrote:
> [Resending to netdev from LKML]
>
> All,
>
> I am experiencing a kernel panic on different (but identical)
> hardware in ip_rcv_finish on Linux 4.4.39 (but I can see no changes that
> would improve the situation on 4.4.44, or master).
>
> Looking at the disassembly at the last stack frame it looks like we are
> calling a NULL function pointer in net/ipv4/ip_input.c:365
>
> Panic:
>
>
> [ 214.518262] BUG: unable to handle kernel NULL pointer dereference at (null)
> [ 214.612199] IP: [< (null)>] (null)
> [ 214.672744] PGD 0 [ 214.696887] Oops: 0010 [#1] SMP [ 214.735697] Modules
> linked in: br_netfilter(+) tun 8021q bridge stp llc bonding iTCO_wdt
> iTCO_vendor_support tpm_tis tpm kvm_intel kvm irqbypass sb_edac edac_core
> ixgbe mdio ipmi_si ipmi_msghandler lpc_ich mfd_core mousedev evdev igb dca
> procmemro(O) nokeyctl(O) noptrace(O)
> [ 215.029240] CPU: 34 PID: 0 Comm: swapper/34 Tainted: G O 4.4.39 #1
> [ 215.116720] Hardware name: Cisco Systems Inc UCSC-C220-M3L/UCSC-C220-M3L,
> BIOS C220M3.2.0.13a.0.0713160937 07/13/16
> [ 215.241644] task: ffff882038fb4380 ti: ffff8810392b0000 task.ti:
> ffff8810392b0000
> [ 215.331207] RIP: 0010:[<0000000000000000>] [< (null)>] (null)
> [ 215.420877] RSP: 0018:ffff88103fec3880 EFLAGS: 00010286
> [ 215.484436] RAX: ffff881011631000 RBX: ffff881011067100 RCX:
> 0000000000000000
> [ 215.569836] RDX: 0000000000000000 RSI: 0000000000000000 RDI:
> ffff881011067100
> [ 215.655234] RBP: ffff88103fec38a8 R08: 0000000000000008 R09:
> ffff8810116300a0
> [ 215.740629] R10: 0000000000000000 R11: 0000000000000000 R12:
> ffff881018917dce
> [ 215.826030] R13: ffffffff81c9be00 R14: ffffffff81c9be00 R15:
> ffff881011630078
> [ 215.911432] FS: 0000000000000000(0000) GS:ffff88103fec0000(0000)
> knlGS:0000000000000000
> [ 216.008274] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [ 216.077032] CR2: 0000000000000000 CR3: 0000001011b9d000 CR4:
> 00000000001406e0
> [ 216.162430] Stack:
> [ 216.186461] ffffffff8157d7f9 ffff881011067100 ffff881018917dce
> ffff881011630000
> [ 216.275407] ffffffff81c9be00 ffff88103fec3918 ffffffff8157e0db
> 0000000000000000
> [ 216.364352] 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 216.453301] Call Trace:
> [ 216.482536] <IRQ> [ 216.505533] [<ffffffff8157d7f9>] ?
> ip_rcv_finish+0x99/0x320
> [ 216.575442] [<ffffffff8157e0db>] ip_rcv+0x25b/0x370
> [ 216.634842] [<ffffffff81540e0b>] __netif_receive_skb_core+0x2cb/0xa20
> [ 216.712965] [<ffffffff81541578>] __netif_receive_skb+0x18/0x60
> [ 216.783801] [<ffffffff815415e3>] netif_receive_skb_internal+0x23/0x80
> [ 216.861921] [<ffffffff8154165c>] netif_receive_skb+0x1c/0x70
> [ 216.930686] [<ffffffffa02f6439>] br_handle_frame_finish+0x1b9/0x5b0
> [bridge]
> [ 217.016091] [<ffffffff81187a00>] ? ___slab_alloc+0x1d0/0x440
> [ 217.084849] [<ffffffffa0584074>] br_nf_pre_routing_finish+0x174/0x3d0
> [br_netfilter]
> [ 217.178568] [<ffffffffa0584c07>] ? br_nf_pre_routing+0x97/0x470
> [br_netfilter]
> [ 217.266052] [<ffffffffa02f6280>] ? br_handle_local_finish+0x80/0x80
> [bridge]
> [ 217.351450] [<ffffffffa0584d17>] br_nf_pre_routing+0x1a7/0x470
> [br_netfilter]
> [ 217.437891] [<ffffffff81572f6d>] nf_iterate+0x5d/0x70
> [ 217.499367] [<ffffffff81572fe4>] nf_hook_slow+0x64/0xc0
> [ 217.562928] [<ffffffffa02f69e9>] br_handle_frame+0x1b9/0x290 [bridge]
> [ 217.641048] [<ffffffffa02f6280>] ? br_handle_local_finish+0x80/0x80
> [bridge]
> [ 217.726446] [<ffffffff81540e82>] __netif_receive_skb_core+0x342/0xa20
> [ 217.804566] [<ffffffff815a7916>] ? tcp4_gro_receive+0x126/0x1d0
> [ 217.876445] [<ffffffff815b7446>] ? inet_gro_receive+0x1c6/0x250
> [ 217.948322] [<ffffffff81541578>] __netif_receive_skb+0x18/0x60
> [ 218.019161] [<ffffffff815415e3>] netif_receive_skb_internal+0x23/0x80
> [ 218.097281] [<ffffffff81542213>] napi_gro_receive+0xc3/0x110
> [ 218.166051] [<ffffffffa00a801f>] ixgbe_clean_rx_irq+0x52f/0xa70 [ixgbe]
> [ 218.246255] [<ffffffffa00a9248>] ixgbe_poll+0x438/0x790 [ixgbe]
> [ 218.318131] [<ffffffff81541a6e>] net_rx_action+0x1ee/0x320
> [ 218.384813] [<ffffffff8109c837>] ? handle_irq_event_percpu+0x167/0x1d0
> [ 218.463973] [<ffffffff8105c3c1>] __do_softirq+0x101/0x280
> [ 218.529608] [<ffffffff8105c69e>] irq_exit+0x8e/0x90
> [ 218.589007] [<ffffffff816dd504>] do_IRQ+0x54/0xd0
> [ 218.646323] [<ffffffff816dba02>] common_interrupt+0x82/0x82
> [ 218.714039] <EOI> [ 218.737040] [<ffffffff814fb4f3>] ?
> cpuidle_enter_state+0x133/0x2a0
> [ 218.814226] [<ffffffff814fb4cf>] ? cpuidle_enter_state+0x10f/0x2a0
> [ 218.889224] [<ffffffff814fb697>] cpuidle_enter+0x17/0x20
> [ 218.953825] [<ffffffff81093cf1>] cpu_startup_entry+0x2a1/0x300
> [ 219.024663] [<ffffffff8103838d>] start_secondary+0xed/0xf0
> [ 219.091337] Code: Bad RIP value.
> [ 219.131186] RIP [< (null)>] (null)
> [ 219.192770] RSP <ffff88103fec3880>
> [ 219.234483] CR2: 0000000000000000
> [ 219.274121] ---[ end trace 9ce5d4620e3bcbdf ]---
> [ 219.274125] BUG: unable to handle kernel NULL pointer dereference at (null)
> [ 219.274126] IP: [< (null)>] (null)
> [ 219.274126] PGD 0 [ 219.274128] Oops: 0010 [#2] SMP [ 219.274137] Modules
> linked in: br_netfilter(+) tun 8021q bridge stp llc bonding iTCO_wdt
> iTCO_vendor_support tpm_tis tpm kvm_intel kvm irqbypass sb_edac edac_core
> ixgbe mdio ipmi_si ipmi_msghandler lpc_ich mfd_core mousedev evdev igb dca
> procmemro(O) nokeyctl(O) noptrace(O)
> [ 219.274139] CPU: 7 PID: 0 Comm: swapper/7 Tainted: G D O 4.4.39 #1
> [ 219.274140] Hardware name: Cisco Systems Inc UCSC-C220-M3L/UCSC-C220-M3L,
> BIOS C220M3.2.0.13a.0.0713160937 07/13/16
> [ 219.274141] task: ffff882038f84380 ti: ffff881039044000 task.ti:
> ffff881039044000
> [ 219.274142] RIP: 0010:[<0000000000000000>] [< (null)>] (null)
> [ 219.274143] RSP: 0018:ffff88103fce3880 EFLAGS: 00010286
> [ 219.274143] RAX: ffff881
>
>
> Notes:
> ----
> include/linux/skbuff.h:
>
> 734 #define SKB_DST_NOREF 1UL
> 735 #define SKB_DST_PTRMASK ~(SKB_DST_NOREF)
> ...
> 743 static inline struct dst_entry *skb_dst(const struct sk_buff *skb) {
> 745 /* If refdst was not refcounted, check we still are in a
> 746 * rcu_read_lock section
> 747 */
> 748 WARN_ON((skb->_skb_refdst & SKB_DST_NOREF) &&
> 749 !rcu_read_lock_held() &&
> 750 !rcu_read_lock_bh_held());
> 751 return (struct dst_entry *)(skb->_skb_refdst &
> SKB_DST_PTRMASK);
> 752 }
> ---
> include/net/dst.h:
> 496 static inline int dst_input(struct sk_buff *skb) {
> 498 return skb_dst(skb)->input(skb);
> 499 }
> ---
> net/ipv4/ip_input.c:
>
> 359 rt = skb_rtable(skb);
> 360 if (rt->rt_type == RTN_MULTICAST) {
> 361 IP_UPD_PO_STATS_BH(net, IPSTATS_MIB_INMCAST, skb->len);
> 362 } else if (rt->rt_type == RTN_BROADCAST)
> 363 IP_UPD_PO_STATS_BH(net, IPSTATS_MIB_INBCAST, skb->len);
> 364
> 365 return dst_input(skb);
> ----
> Expand net/ipv4/ip_input.c:365:
> return dst_input(skb);
>
> Into:
> return skb_dst(skb)->input(skb);
>
> Into:
> return ((struct dst_entry *)(skb->_skb_refdst &
> SKB_DST_PTRMASK))->input(skb);
>
> Into:
> return ((struct dst_entry *)(skb->_skb_refdst & (~(1UL))))->input(skb);
>
> Into:
> return ((struct dst_entry *)(skb->_skb_refdst &
> 0xfffffffffffffffe))->input(skb);
> ----
> Disassembly with C code next to it
> 0xffffffff8157d7d4 <ip_rcv_finish+116> movzwl 0xa0(%rdx),%edx
> | rt = skb_rtable(skb);
> 0xffffffff8157d7db <ip_rcv_finish+123> cmp $0x5,%dx
> | if (rt->rt_type == RTN_MULTICAST) {
> 0xffffffff8157d7df <ip_rcv_finish+127> je 0xffffffff8157d908
> <ip_rcv_finish+424> ....
> 0xffffffff8157d7e5 <ip_rcv_finish+133> cmp $0x3,%dx
> | } else if (rt->rt_type == RTN_BROADCAST)
> 0xffffffff8157d7e9 <ip_rcv_finish+137> je 0xffffffff8157d87e
> <ip_rcv_finish+286> ...
> 0xffffffff8157d7ef <ip_rcv_finish+143> and $0xfffffffffffffffe,%rax
> | skb->_skb_refdst & SKB_DST_PTRMASK
> 0xffffffff8157d7f3 <ip_rcv_finish+147> mov %rbx,%rdi
> --> 0xffffffff8157d7f6 <ip_rcv_finish+150> callq *0x50(%rax)
> | ((struct dst_entry *)(skb->_skb_refdst & SKB_DST_PTRMASK))->input(skb)
> 0xffffffff8157d7f9 <ip_rcv_finish+153> pop %rbx
> 0xffffffff8157d7fa <ip_rcv_finish+154> pop %r12
> 0xffffffff8157d7fc <ip_rcv_finish+156> pop %r13
> 0xffffffff8157d7fe <ip_rcv_finish+158> pop %r14
> 0xffffffff8157d800 <ip_rcv_finish+160> pop %rbp
> 0xffffffff8157d801 <ip_rcv_finish+161> retq
> ----
>
> This leads me to believe that ((struct dst_entry *)(skb->_skb_refdst &
> SKB_DST_PTRMASK))->input is NULL and we are jumping there (callq).
>
>
> Under what conditions would ((struct dst_entry *)(skb->_skb_refdst &
> SKB_DST_PTRMASK))->input be NULL at this point ?
>
> Thanks,
> Roy Keene
>
^ permalink raw reply
* Re: IPv6-UDP 0x0000 checksum
From: Johannes Berg @ 2017-01-26 15:32 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev, linux-wireless
In-Reply-To: <1485444276.5145.133.camel@edumazet-glaptop3.roam.corp.google.com>
On Thu, 2017-01-26 at 07:24 -0800, Eric Dumazet wrote:
> On Thu, 2017-01-26 at 15:49 +0100, Johannes Berg wrote:
>
> > Unfortunately, I haven't been able to actually test this yet. I
> > also
> > didn't find the code that would drop frames with CSUM 0 either, so
> > I'm
> > thinking - for now - that if all the csum handling is skipped,
> > dropping
> > 0 csum frames would also be, and then we'd accept a frame we should
> > actually have dropped.
> >
> > I'll go test this I guess :)
> >
> > Any pointers to where 0 csum frames are dropped?
>
> Probably in udp6_csum_init()
Well, now that I see that, I see that they're actually valid in some
circumstances. Oops. :)
Will need to revisit, and check how we set no_check6_rx, etc.
johannes
^ permalink raw reply
* Re: IPv6-UDP 0x0000 checksum
From: Eric Dumazet @ 2017-01-26 15:27 UTC (permalink / raw)
To: Johannes Berg; +Cc: netdev-u79uwXL29TY76Z2rM5mHXA, linux-wireless
In-Reply-To: <1485444276.5145.133.camel-XN9IlZ5yJG9HTL0Zs8A6p+yfmBU6pStAUsxypvmhUTTZJqsBc5GL+g@public.gmane.org>
On Thu, 2017-01-26 at 07:24 -0800, Eric Dumazet wrote:
> On Thu, 2017-01-26 at 15:49 +0100, Johannes Berg wrote:
>
> > Unfortunately, I haven't been able to actually test this yet. I also
> > didn't find the code that would drop frames with CSUM 0 either, so I'm
> > thinking - for now - that if all the csum handling is skipped, dropping
> > 0 csum frames would also be, and then we'd accept a frame we should
> > actually have dropped.
> >
> > I'll go test this I guess :)
> >
> > Any pointers to where 0 csum frames are dropped?
>
> Probably in udp6_csum_init()
vi +804 net/ipv6/udp.c
if (!uh->check && !udp_sk(sk)->no_check6_rx) {
udp6_csum_zero_error(skb);
goto csum_error;
}
^ permalink raw reply
* Re: IPv6-UDP 0x0000 checksum
From: Eric Dumazet @ 2017-01-26 15:24 UTC (permalink / raw)
To: Johannes Berg; +Cc: netdev-u79uwXL29TY76Z2rM5mHXA, linux-wireless
In-Reply-To: <1485442164.14760.11.camel-cdvu00un1VgdHxzADdlk8Q@public.gmane.org>
On Thu, 2017-01-26 at 15:49 +0100, Johannes Berg wrote:
> Unfortunately, I haven't been able to actually test this yet. I also
> didn't find the code that would drop frames with CSUM 0 either, so I'm
> thinking - for now - that if all the csum handling is skipped, dropping
> 0 csum frames would also be, and then we'd accept a frame we should
> actually have dropped.
>
> I'll go test this I guess :)
>
> Any pointers to where 0 csum frames are dropped?
Probably in udp6_csum_init()
^ permalink raw reply
* [PATCH net-next v2 0/2] gtp: simple gtp improvements
From: Andreas Schultz @ 2017-01-26 15:21 UTC (permalink / raw)
To: Pablo Neira
Cc: netdev, Lionel Gauthier, openbsc, Harald Welte, SF Markus Elfring
This is the part of the previous "simple gtp improvements" series
that Pablo indicated should go into net-next.
The rcu_lock removal is small correctness changes. Passing invalid
to user space allows for more standards compliant handling of invalid
tunnels.
^ permalink raw reply
* [PATCH net-next v2 1/2] gtp: remove unnecessary rcu_read_lock
From: Andreas Schultz @ 2017-01-26 15:21 UTC (permalink / raw)
To: Pablo Neira
Cc: netdev, Lionel Gauthier, openbsc, Harald Welte, SF Markus Elfring
In-Reply-To: <20170126152149.3284-1-aschultz@tpip.net>
The rcu read lock is hold by default in the ip input path. There
is no need to hold it twice in the socket recv decapsulate code path.
Signed-off-by: Andreas Schultz <aschultz@tpip.net>
---
drivers/net/gtp.c | 24 ++++--------------------
1 file changed, 4 insertions(+), 20 deletions(-)
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 8b6810b..5c63a37 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -184,7 +184,6 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
sizeof(struct gtp0_header);
struct gtp0_header *gtp0;
struct pdp_ctx *pctx;
- int ret = 0;
if (!pskb_may_pull(skb, hdrlen))
return -1;
@@ -197,26 +196,19 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
if (gtp0->type != GTP_TPDU)
return 1;
- rcu_read_lock();
pctx = gtp0_pdp_find(gtp, be64_to_cpu(gtp0->tid));
if (!pctx) {
netdev_dbg(gtp->dev, "No PDP ctx to decap skb=%p\n", skb);
- ret = -1;
- goto out_rcu;
+ return -1;
}
if (!gtp_check_src_ms(skb, pctx, hdrlen)) {
netdev_dbg(gtp->dev, "No PDP ctx for this MS\n");
- ret = -1;
- goto out_rcu;
+ return -1;
}
- rcu_read_unlock();
/* Get rid of the GTP + UDP headers. */
return iptunnel_pull_header(skb, hdrlen, skb->protocol, xnet);
-out_rcu:
- rcu_read_unlock();
- return ret;
}
static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
@@ -226,7 +218,6 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
sizeof(struct gtp1_header);
struct gtp1_header *gtp1;
struct pdp_ctx *pctx;
- int ret = 0;
if (!pskb_may_pull(skb, hdrlen))
return -1;
@@ -254,26 +245,19 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr));
- rcu_read_lock();
pctx = gtp1_pdp_find(gtp, ntohl(gtp1->tid));
if (!pctx) {
netdev_dbg(gtp->dev, "No PDP ctx to decap skb=%p\n", skb);
- ret = -1;
- goto out_rcu;
+ return -1;
}
if (!gtp_check_src_ms(skb, pctx, hdrlen)) {
netdev_dbg(gtp->dev, "No PDP ctx for this MS\n");
- ret = -1;
- goto out_rcu;
+ return -1;
}
- rcu_read_unlock();
/* Get rid of the GTP + UDP headers. */
return iptunnel_pull_header(skb, hdrlen, skb->protocol, xnet);
-out_rcu:
- rcu_read_unlock();
- return ret;
}
static void gtp_encap_disable(struct gtp_dev *gtp)
--
2.10.2
^ permalink raw reply related
* [PATCH net-next v2 2/2] gtp: let userspace handle packets for invalid tunnels
From: Andreas Schultz @ 2017-01-26 15:21 UTC (permalink / raw)
To: Pablo Neira
Cc: netdev, Lionel Gauthier, openbsc, Harald Welte, SF Markus Elfring
In-Reply-To: <20170126152149.3284-1-aschultz@tpip.net>
enable userspace to send error replies for invalid tunnels
Acked-by: Harald Welte <laforge@netfilter.org>
Signed-off-by: Andreas Schultz <aschultz@tpip.net>
---
drivers/net/gtp.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 5c63a37..5dd7de6 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -199,12 +199,12 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
pctx = gtp0_pdp_find(gtp, be64_to_cpu(gtp0->tid));
if (!pctx) {
netdev_dbg(gtp->dev, "No PDP ctx to decap skb=%p\n", skb);
- return -1;
+ return 1;
}
if (!gtp_check_src_ms(skb, pctx, hdrlen)) {
netdev_dbg(gtp->dev, "No PDP ctx for this MS\n");
- return -1;
+ return 1;
}
/* Get rid of the GTP + UDP headers. */
@@ -248,12 +248,12 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
pctx = gtp1_pdp_find(gtp, ntohl(gtp1->tid));
if (!pctx) {
netdev_dbg(gtp->dev, "No PDP ctx to decap skb=%p\n", skb);
- return -1;
+ return 1;
}
if (!gtp_check_src_ms(skb, pctx, hdrlen)) {
netdev_dbg(gtp->dev, "No PDP ctx for this MS\n");
- return -1;
+ return 1;
}
/* Get rid of the GTP + UDP headers. */
--
2.10.2
^ permalink raw reply related
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