* [patch net-next v2 10/20] net: sched: cls_fw: rename fw_change_attrs function
From: Jiri Pirko @ 2017-08-04 12:29 UTC (permalink / raw)
To: netdev; +Cc: davem, jhs, xiyou.wangcong, daniel, mlxsw
In-Reply-To: <20170804122915.15177-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@mellanox.com>
Since the function name is misleading since it is not changing
anything, name it similarly to other cls.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_fw.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index a53fa75..358bf34 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -190,10 +190,9 @@ static const struct nla_policy fw_policy[TCA_FW_MAX + 1] = {
[TCA_FW_MASK] = { .type = NLA_U32 },
};
-static int
-fw_change_attrs(struct net *net, struct tcf_proto *tp, struct fw_filter *f,
- struct nlattr **tb, struct nlattr **tca, unsigned long base,
- bool ovr)
+static int fw_set_parms(struct net *net, struct tcf_proto *tp,
+ struct fw_filter *f, struct nlattr **tb,
+ struct nlattr **tca, unsigned long base, bool ovr)
{
struct fw_head *head = rtnl_dereference(tp->root);
struct tcf_exts e;
@@ -282,7 +281,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
return err;
}
- err = fw_change_attrs(net, tp, fnew, tb, tca, base, ovr);
+ err = fw_set_parms(net, tp, fnew, tb, tca, base, ovr);
if (err < 0) {
tcf_exts_destroy(&fnew->exts);
kfree(fnew);
@@ -330,7 +329,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
f->id = handle;
f->tp = tp;
- err = fw_change_attrs(net, tp, f, tb, tca, base, ovr);
+ err = fw_set_parms(net, tp, f, tb, tca, base, ovr);
if (err < 0)
goto errout;
--
2.9.3
^ permalink raw reply related
* [patch net-next v2 11/20] net: sched: cls_flower: no need to call tcf_exts_change for newly allocated struct
From: Jiri Pirko @ 2017-08-04 12:29 UTC (permalink / raw)
To: netdev; +Cc: davem, jhs, xiyou.wangcong, daniel, mlxsw
In-Reply-To: <20170804122915.15177-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@mellanox.com>
As the f struct was allocated right before fl_set_parms call, no need
to use tcf_exts_change to do atomic change, and we can just fill-up
the unused exts struct directly by tcf_exts_validate.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_flower.c | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 7832eb9..7ab524f 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -852,15 +852,11 @@ static int fl_set_parms(struct net *net, struct tcf_proto *tp,
unsigned long base, struct nlattr **tb,
struct nlattr *est, bool ovr)
{
- struct tcf_exts e;
int err;
- err = tcf_exts_init(&e, TCA_FLOWER_ACT, 0);
+ err = tcf_exts_validate(net, tp, tb, est, &f->exts, ovr);
if (err < 0)
return err;
- err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
- if (err < 0)
- goto errout;
if (tb[TCA_FLOWER_CLASSID]) {
f->res.classid = nla_get_u32(tb[TCA_FLOWER_CLASSID]);
@@ -869,17 +865,12 @@ static int fl_set_parms(struct net *net, struct tcf_proto *tp,
err = fl_set_key(net, tb, &f->key, &mask->key);
if (err)
- goto errout;
+ return err;
fl_mask_update_range(mask);
fl_set_masked_key(&f->mkey, &f->key, mask);
- tcf_exts_change(tp, &f->exts, &e);
-
return 0;
-errout:
- tcf_exts_destroy(&e);
- return err;
}
static u32 fl_grab_new_handle(struct tcf_proto *tp,
--
2.9.3
^ permalink raw reply related
* [patch net-next v2 12/20] net: sched: cls_fw: no need to call tcf_exts_change for newly allocated struct
From: Jiri Pirko @ 2017-08-04 12:29 UTC (permalink / raw)
To: netdev; +Cc: davem, jhs, xiyou.wangcong, daniel, mlxsw
In-Reply-To: <20170804122915.15177-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@mellanox.com>
As the f struct was allocated right before fw_set_parms call, no need
to use tcf_exts_change to do atomic change, and we can just fill-up
the unused exts struct directly by tcf_exts_validate.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_fw.c | 21 +++++----------------
1 file changed, 5 insertions(+), 16 deletions(-)
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index 358bf34..11f178f 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -195,16 +195,12 @@ static int fw_set_parms(struct net *net, struct tcf_proto *tp,
struct nlattr **tca, unsigned long base, bool ovr)
{
struct fw_head *head = rtnl_dereference(tp->root);
- struct tcf_exts e;
u32 mask;
int err;
- err = tcf_exts_init(&e, TCA_FW_ACT, TCA_FW_POLICE);
+ err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &f->exts, ovr);
if (err < 0)
return err;
- err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
- if (err < 0)
- goto errout;
if (tb[TCA_FW_CLASSID]) {
f->res.classid = nla_get_u32(tb[TCA_FW_CLASSID]);
@@ -215,10 +211,8 @@ static int fw_set_parms(struct net *net, struct tcf_proto *tp,
if (tb[TCA_FW_INDEV]) {
int ret;
ret = tcf_change_indev(net, tb[TCA_FW_INDEV]);
- if (ret < 0) {
- err = ret;
- goto errout;
- }
+ if (ret < 0)
+ return ret;
f->ifindex = ret;
}
#endif /* CONFIG_NET_CLS_IND */
@@ -227,16 +221,11 @@ static int fw_set_parms(struct net *net, struct tcf_proto *tp,
if (tb[TCA_FW_MASK]) {
mask = nla_get_u32(tb[TCA_FW_MASK]);
if (mask != head->mask)
- goto errout;
+ return err;
} else if (head->mask != 0xFFFFFFFF)
- goto errout;
-
- tcf_exts_change(tp, &f->exts, &e);
+ return err;
return 0;
-errout:
- tcf_exts_destroy(&e);
- return err;
}
static int fw_change(struct net *net, struct sk_buff *in_skb,
--
2.9.3
^ permalink raw reply related
* [patch net-next v2 13/20] net: sched: cls_matchall: no need to call tcf_exts_change for newly allocated struct
From: Jiri Pirko @ 2017-08-04 12:29 UTC (permalink / raw)
To: netdev; +Cc: davem, jhs, xiyou.wangcong, daniel, mlxsw
In-Reply-To: <20170804122915.15177-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@mellanox.com>
As the head struct was allocated right before mall_set_parms call,
no need to use tcf_exts_change to do atomic change, and we can just
fill-up the unused exts struct directly by tcf_exts_validate.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_matchall.c | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c
index 9dc26c3..f35177b 100644
--- a/net/sched/cls_matchall.c
+++ b/net/sched/cls_matchall.c
@@ -120,27 +120,17 @@ static int mall_set_parms(struct net *net, struct tcf_proto *tp,
unsigned long base, struct nlattr **tb,
struct nlattr *est, bool ovr)
{
- struct tcf_exts e;
int err;
- err = tcf_exts_init(&e, TCA_MATCHALL_ACT, 0);
- if (err)
- return err;
- err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
+ err = tcf_exts_validate(net, tp, tb, est, &head->exts, ovr);
if (err < 0)
- goto errout;
+ return err;
if (tb[TCA_MATCHALL_CLASSID]) {
head->res.classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]);
tcf_bind_filter(tp, &head->res, base);
}
-
- tcf_exts_change(tp, &head->exts, &e);
-
return 0;
-errout:
- tcf_exts_destroy(&e);
- return err;
}
static int mall_change(struct net *net, struct sk_buff *in_skb,
--
2.9.3
^ permalink raw reply related
* [patch net-next v2 14/20] net: sched: cls_basic: no need to call tcf_exts_change for newly allocated struct
From: Jiri Pirko @ 2017-08-04 12:29 UTC (permalink / raw)
To: netdev; +Cc: davem, jhs, xiyou.wangcong, daniel, mlxsw
In-Reply-To: <20170804122915.15177-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@mellanox.com>
As the f struct was allocated right before basic_set_parms call, no need
to use tcf_exts_change to do atomic change, and we can just fill-up
the unused exts struct directly by tcf_exts_validate.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_basic.c | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 979cd26..7c7a821 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -129,31 +129,22 @@ static int basic_set_parms(struct net *net, struct tcf_proto *tp,
struct nlattr *est, bool ovr)
{
int err;
- struct tcf_exts e;
- err = tcf_exts_init(&e, TCA_BASIC_ACT, TCA_BASIC_POLICE);
+ err = tcf_exts_validate(net, tp, tb, est, &f->exts, ovr);
if (err < 0)
return err;
- err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
- if (err < 0)
- goto errout;
err = tcf_em_tree_validate(tp, tb[TCA_BASIC_EMATCHES], &f->ematches);
if (err < 0)
- goto errout;
+ return err;
if (tb[TCA_BASIC_CLASSID]) {
f->res.classid = nla_get_u32(tb[TCA_BASIC_CLASSID]);
tcf_bind_filter(tp, &f->res, base);
}
- tcf_exts_change(tp, &f->exts, &e);
f->tp = tp;
-
return 0;
-errout:
- tcf_exts_destroy(&e);
- return err;
}
static int basic_change(struct net *net, struct sk_buff *in_skb,
--
2.9.3
^ permalink raw reply related
* [patch net-next v2 15/20] net: sched: cls_bpf: no need to call tcf_exts_change for newly allocated struct
From: Jiri Pirko @ 2017-08-04 12:29 UTC (permalink / raw)
To: netdev; +Cc: davem, jhs, xiyou.wangcong, daniel, mlxsw
In-Reply-To: <20170804122915.15177-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@mellanox.com>
As the prog struct was allocated right before cls_bpf_set_parms call,
no need to use tcf_exts_change to do atomic change, and we can just
fill-up the unused exts struct directly by tcf_exts_validate.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_bpf.c | 25 ++++++-------------------
1 file changed, 6 insertions(+), 19 deletions(-)
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index e9ab837..cf248c3 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -387,7 +387,6 @@ static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp,
struct nlattr **tb, struct nlattr *est, bool ovr)
{
bool is_bpf, is_ebpf, have_exts = false;
- struct tcf_exts exts;
u32 gen_flags = 0;
int ret;
@@ -396,30 +395,23 @@ static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp,
if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf))
return -EINVAL;
- ret = tcf_exts_init(&exts, TCA_BPF_ACT, TCA_BPF_POLICE);
+ ret = tcf_exts_validate(net, tp, tb, est, &prog->exts, ovr);
if (ret < 0)
return ret;
- ret = tcf_exts_validate(net, tp, tb, est, &exts, ovr);
- if (ret < 0)
- goto errout;
if (tb[TCA_BPF_FLAGS]) {
u32 bpf_flags = nla_get_u32(tb[TCA_BPF_FLAGS]);
- if (bpf_flags & ~TCA_BPF_FLAG_ACT_DIRECT) {
- ret = -EINVAL;
- goto errout;
- }
+ if (bpf_flags & ~TCA_BPF_FLAG_ACT_DIRECT)
+ return -EINVAL;
have_exts = bpf_flags & TCA_BPF_FLAG_ACT_DIRECT;
}
if (tb[TCA_BPF_FLAGS_GEN]) {
gen_flags = nla_get_u32(tb[TCA_BPF_FLAGS_GEN]);
if (gen_flags & ~CLS_BPF_SUPPORTED_GEN_FLAGS ||
- !tc_flags_valid(gen_flags)) {
- ret = -EINVAL;
- goto errout;
- }
+ !tc_flags_valid(gen_flags))
+ return -EINVAL;
}
prog->exts_integrated = have_exts;
@@ -428,19 +420,14 @@ static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp,
ret = is_bpf ? cls_bpf_prog_from_ops(tb, prog) :
cls_bpf_prog_from_efd(tb, prog, tp);
if (ret < 0)
- goto errout;
+ return ret;
if (tb[TCA_BPF_CLASSID]) {
prog->res.classid = nla_get_u32(tb[TCA_BPF_CLASSID]);
tcf_bind_filter(tp, &prog->res, base);
}
- tcf_exts_change(tp, &prog->exts, &exts);
return 0;
-
-errout:
- tcf_exts_destroy(&exts);
- return ret;
}
static u32 cls_bpf_grab_new_handle(struct tcf_proto *tp,
--
2.9.3
^ permalink raw reply related
* [patch net-next v2 16/20] net: sched: cls_cgroup: no need to call tcf_exts_change for newly allocated struct
From: Jiri Pirko @ 2017-08-04 12:29 UTC (permalink / raw)
To: netdev; +Cc: davem, jhs, xiyou.wangcong, daniel, mlxsw
In-Reply-To: <20170804122915.15177-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@mellanox.com>
As the new struct just was allocated, so no need to use tcf_exts_change
to do atomic change, and we can just fill-up the unused exts struct
directly by tcf_exts_validate.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_cgroup.c | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index ce7d38b..df7a582 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -76,7 +76,6 @@ static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
struct nlattr *tb[TCA_CGROUP_MAX + 1];
struct cls_cgroup_head *head = rtnl_dereference(tp->root);
struct cls_cgroup_head *new;
- struct tcf_exts e;
int err;
if (!tca[TCA_OPTIONS])
@@ -102,22 +101,13 @@ static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
if (err < 0)
goto errout;
- err = tcf_exts_init(&e, TCA_CGROUP_ACT, TCA_CGROUP_POLICE);
+ err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &new->exts, ovr);
if (err < 0)
goto errout;
- err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
- if (err < 0) {
- tcf_exts_destroy(&e);
- goto errout;
- }
err = tcf_em_tree_validate(tp, tb[TCA_CGROUP_EMATCHES], &new->ematches);
- if (err < 0) {
- tcf_exts_destroy(&e);
+ if (err < 0)
goto errout;
- }
-
- tcf_exts_change(tp, &new->exts, &e);
rcu_assign_pointer(tp->root, new);
if (head)
--
2.9.3
^ permalink raw reply related
* [patch net-next v2 17/20] net: sched: cls_flow: no need to call tcf_exts_change for newly allocated struct
From: Jiri Pirko @ 2017-08-04 12:29 UTC (permalink / raw)
To: netdev; +Cc: davem, jhs, xiyou.wangcong, daniel, mlxsw
In-Reply-To: <20170804122915.15177-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@mellanox.com>
As the fnew struct just was allocated, so no need to use tcf_exts_change
to do atomic change, and we can just fill-up the unused exts struct
directly by tcf_exts_validate.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_flow.c | 41 ++++++++++++++++-------------------------
1 file changed, 16 insertions(+), 25 deletions(-)
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 71fd1af..55e281b2 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -388,7 +388,6 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
struct flow_filter *fold, *fnew;
struct nlattr *opt = tca[TCA_OPTIONS];
struct nlattr *tb[TCA_FLOW_MAX + 1];
- struct tcf_exts e;
unsigned int nkeys = 0;
unsigned int perturb_period = 0;
u32 baseclass = 0;
@@ -424,31 +423,27 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
return -EOPNOTSUPP;
}
- err = tcf_exts_init(&e, TCA_FLOW_ACT, TCA_FLOW_POLICE);
- if (err < 0)
- goto err1;
- err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
- if (err < 0)
- goto err1;
-
- err = -ENOBUFS;
fnew = kzalloc(sizeof(*fnew), GFP_KERNEL);
if (!fnew)
- goto err1;
+ return -ENOBUFS;
err = tcf_em_tree_validate(tp, tb[TCA_FLOW_EMATCHES], &fnew->ematches);
if (err < 0)
- goto err2;
+ goto err1;
err = tcf_exts_init(&fnew->exts, TCA_FLOW_ACT, TCA_FLOW_POLICE);
if (err < 0)
- goto err3;
+ goto err2;
+
+ err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &fnew->exts, ovr);
+ if (err < 0)
+ goto err2;
fold = (struct flow_filter *)*arg;
if (fold) {
err = -EINVAL;
if (fold->handle != handle && handle)
- goto err3;
+ goto err2;
/* Copy fold into fnew */
fnew->tp = fold->tp;
@@ -468,31 +463,31 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
if (tb[TCA_FLOW_MODE])
mode = nla_get_u32(tb[TCA_FLOW_MODE]);
if (mode != FLOW_MODE_HASH && nkeys > 1)
- goto err3;
+ goto err2;
if (mode == FLOW_MODE_HASH)
perturb_period = fold->perturb_period;
if (tb[TCA_FLOW_PERTURB]) {
if (mode != FLOW_MODE_HASH)
- goto err3;
+ goto err2;
perturb_period = nla_get_u32(tb[TCA_FLOW_PERTURB]) * HZ;
}
} else {
err = -EINVAL;
if (!handle)
- goto err3;
+ goto err2;
if (!tb[TCA_FLOW_KEYS])
- goto err3;
+ goto err2;
mode = FLOW_MODE_MAP;
if (tb[TCA_FLOW_MODE])
mode = nla_get_u32(tb[TCA_FLOW_MODE]);
if (mode != FLOW_MODE_HASH && nkeys > 1)
- goto err3;
+ goto err2;
if (tb[TCA_FLOW_PERTURB]) {
if (mode != FLOW_MODE_HASH)
- goto err3;
+ goto err2;
perturb_period = nla_get_u32(tb[TCA_FLOW_PERTURB]) * HZ;
}
@@ -510,8 +505,6 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
setup_deferrable_timer(&fnew->perturb_timer, flow_perturbation,
(unsigned long)fnew);
- tcf_exts_change(tp, &fnew->exts, &e);
-
netif_keep_dst(qdisc_dev(tp->q));
if (tb[TCA_FLOW_KEYS]) {
@@ -550,13 +543,11 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
call_rcu(&fold->rcu, flow_destroy_filter);
return 0;
-err3:
+err2:
tcf_exts_destroy(&fnew->exts);
tcf_em_tree_destroy(&fnew->ematches);
-err2:
- kfree(fnew);
err1:
- tcf_exts_destroy(&e);
+ kfree(fnew);
return err;
}
--
2.9.3
^ permalink raw reply related
* [patch net-next v2 18/20] net: sched: cls_route: no need to call tcf_exts_change for newly allocated struct
From: Jiri Pirko @ 2017-08-04 12:29 UTC (permalink / raw)
To: netdev; +Cc: davem, jhs, xiyou.wangcong, daniel, mlxsw
In-Reply-To: <20170804122915.15177-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@mellanox.com>
As the f struct was allocated right before route4_set_parms call,
no need to use tcf_exts_change to do atomic change, and we can just
fill-up the unused exts struct directly by tcf_exts_validate.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_route.c | 30 +++++++++---------------------
1 file changed, 9 insertions(+), 21 deletions(-)
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index 26f8636..f1e7d78 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -372,37 +372,32 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp,
struct route4_filter *fp;
unsigned int h1;
struct route4_bucket *b;
- struct tcf_exts e;
int err;
- err = tcf_exts_init(&e, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE);
+ err = tcf_exts_validate(net, tp, tb, est, &f->exts, ovr);
if (err < 0)
return err;
- err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
- if (err < 0)
- goto errout;
- err = -EINVAL;
if (tb[TCA_ROUTE4_TO]) {
if (new && handle & 0x8000)
- goto errout;
+ return -EINVAL;
to = nla_get_u32(tb[TCA_ROUTE4_TO]);
if (to > 0xFF)
- goto errout;
+ return -EINVAL;
nhandle = to;
}
if (tb[TCA_ROUTE4_FROM]) {
if (tb[TCA_ROUTE4_IIF])
- goto errout;
+ return -EINVAL;
id = nla_get_u32(tb[TCA_ROUTE4_FROM]);
if (id > 0xFF)
- goto errout;
+ return -EINVAL;
nhandle |= id << 16;
} else if (tb[TCA_ROUTE4_IIF]) {
id = nla_get_u32(tb[TCA_ROUTE4_IIF]);
if (id > 0x7FFF)
- goto errout;
+ return -EINVAL;
nhandle |= (id | 0x8000) << 16;
} else
nhandle |= 0xFFFF << 16;
@@ -410,27 +405,25 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp,
if (handle && new) {
nhandle |= handle & 0x7F00;
if (nhandle != handle)
- goto errout;
+ return -EINVAL;
}
h1 = to_hash(nhandle);
b = rtnl_dereference(head->table[h1]);
if (!b) {
- err = -ENOBUFS;
b = kzalloc(sizeof(struct route4_bucket), GFP_KERNEL);
if (b == NULL)
- goto errout;
+ return -ENOBUFS;
rcu_assign_pointer(head->table[h1], b);
} else {
unsigned int h2 = from_hash(nhandle >> 16);
- err = -EEXIST;
for (fp = rtnl_dereference(b->ht[h2]);
fp;
fp = rtnl_dereference(fp->next))
if (fp->handle == f->handle)
- goto errout;
+ return -EEXIST;
}
if (tb[TCA_ROUTE4_TO])
@@ -450,12 +443,7 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp,
tcf_bind_filter(tp, &f->res, base);
}
- tcf_exts_change(tp, &f->exts, &e);
-
return 0;
-errout:
- tcf_exts_destroy(&e);
- return err;
}
static int route4_change(struct net *net, struct sk_buff *in_skb,
--
2.9.3
^ permalink raw reply related
* [patch net-next v2 19/20] net: sched: cls_u32: no need to call tcf_exts_change for newly allocated struct
From: Jiri Pirko @ 2017-08-04 12:29 UTC (permalink / raw)
To: netdev; +Cc: davem, jhs, xiyou.wangcong, daniel, mlxsw
In-Reply-To: <20170804122915.15177-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@mellanox.com>
As the n struct was allocated right before u32_set_parms call,
no need to use tcf_exts_change to do atomic change, and we can just
fill-up the unused exts struct directly by tcf_exts_validate.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_u32.c | 18 ++++--------------
1 file changed, 4 insertions(+), 14 deletions(-)
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 2d01195..9fd2437 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -723,29 +723,24 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp,
struct tc_u_knode *n, struct nlattr **tb,
struct nlattr *est, bool ovr)
{
- struct tcf_exts e;
int err;
- err = tcf_exts_init(&e, TCA_U32_ACT, TCA_U32_POLICE);
+ err = tcf_exts_validate(net, tp, tb, est, &n->exts, ovr);
if (err < 0)
return err;
- err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
- if (err < 0)
- goto errout;
- err = -EINVAL;
if (tb[TCA_U32_LINK]) {
u32 handle = nla_get_u32(tb[TCA_U32_LINK]);
struct tc_u_hnode *ht_down = NULL, *ht_old;
if (TC_U32_KEY(handle))
- goto errout;
+ return -EINVAL;
if (handle) {
ht_down = u32_lookup_ht(ht->tp_c, handle);
if (ht_down == NULL)
- goto errout;
+ return -EINVAL;
ht_down->refcnt++;
}
@@ -765,16 +760,11 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp,
int ret;
ret = tcf_change_indev(net, tb[TCA_U32_INDEV]);
if (ret < 0)
- goto errout;
+ return -EINVAL;
n->ifindex = ret;
}
#endif
- tcf_exts_change(tp, &n->exts, &e);
-
return 0;
-errout:
- tcf_exts_destroy(&e);
- return err;
}
static void u32_replace_knode(struct tcf_proto *tp, struct tc_u_common *tp_c,
--
2.9.3
^ permalink raw reply related
* [patch net-next v2 20/20] net: sched: avoid atomic swap in tcf_exts_change
From: Jiri Pirko @ 2017-08-04 12:29 UTC (permalink / raw)
To: netdev; +Cc: davem, jhs, xiyou.wangcong, daniel, mlxsw
In-Reply-To: <20170804122915.15177-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@mellanox.com>
tcf_exts_change is always called on newly created exts, which are not used
on fastpath. Therefore, simple struct copy is enough.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/pkt_cls.h | 3 +--
net/sched/cls_api.c | 10 ++--------
net/sched/cls_rsvp.h | 4 ++--
net/sched/cls_tcindex.c | 6 +++---
4 files changed, 8 insertions(+), 15 deletions(-)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index b8959c9..e0c54f1 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -201,8 +201,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp,
struct nlattr **tb, struct nlattr *rate_tlv,
struct tcf_exts *exts, bool ovr);
void tcf_exts_destroy(struct tcf_exts *exts);
-void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
- struct tcf_exts *src);
+void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src);
int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts);
int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts);
int tcf_exts_get_dev(struct net_device *dev, struct tcf_exts *exts,
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 735d556..e655221 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -883,18 +883,12 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
}
EXPORT_SYMBOL(tcf_exts_validate);
-void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
- struct tcf_exts *src)
+void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src)
{
#ifdef CONFIG_NET_CLS_ACT
struct tcf_exts old = *dst;
- tcf_tree_lock(tp);
- dst->nr_actions = src->nr_actions;
- dst->actions = src->actions;
- dst->type = src->type;
- tcf_tree_unlock(tp);
-
+ *dst = *src;
tcf_exts_destroy(&old);
#endif
}
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 0d9d077..4adb67a 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -518,7 +518,7 @@ static int rsvp_change(struct net *net, struct sk_buff *in_skb,
tcf_bind_filter(tp, &n->res, base);
}
- tcf_exts_change(tp, &n->exts, &e);
+ tcf_exts_change(&n->exts, &e);
rsvp_replace(tp, n, handle);
return 0;
}
@@ -591,7 +591,7 @@ static int rsvp_change(struct net *net, struct sk_buff *in_skb,
if (f->tunnelhdr == 0)
tcf_bind_filter(tp, &f->res, base);
- tcf_exts_change(tp, &f->exts, &e);
+ tcf_exts_change(&f->exts, &e);
fp = &s->ht[h2];
for (nfp = rtnl_dereference(*fp); nfp;
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index 66924d1..d69f828 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -419,9 +419,9 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
}
if (old_r)
- tcf_exts_change(tp, &r->exts, &e);
+ tcf_exts_change(&r->exts, &e);
else
- tcf_exts_change(tp, &cr.exts, &e);
+ tcf_exts_change(&cr.exts, &e);
if (old_r && old_r != r) {
err = tcindex_filter_result_init(old_r);
@@ -439,7 +439,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
struct tcindex_filter *nfp;
struct tcindex_filter __rcu **fp;
- tcf_exts_change(tp, &f->result.exts, &r->exts);
+ tcf_exts_change(&f->result.exts, &r->exts);
fp = cp->h + (handle % cp->hash);
for (nfp = rtnl_dereference(*fp);
--
2.9.3
^ permalink raw reply related
* Re: [PATCH] MIPS: Add missing file for eBPF JIT.
From: Daniel Borkmann @ 2017-08-04 13:05 UTC (permalink / raw)
To: David S. Miller
Cc: David Daney, Alexei Starovoitov, netdev, linux-kernel, linux-mips,
ralf, James.Cowgill, markos.chandras
In-Reply-To: <20170804001012.24901-1-david.daney@cavium.com>
On 08/04/2017 02:10 AM, David Daney wrote:
> Inexplicably, commit f381bf6d82f0 ("MIPS: Add support for eBPF JIT.")
> lost a file somewhere on its path to Linus' tree. Add back the
> missing ebpf_jit.c so that we can build with CONFIG_BPF_JIT selected.
>
> This version of ebpf_jit.c is identical to the original except for two
> minor change need to resolve conflicts with changes merged from the
> BPF branch:
>
> A) Set prog->jited_len = image_size;
> B) Use BPF_TAIL_CALL instead of BPF_CALL | BPF_X
>
> Fixes: f381bf6d82f0 ("MIPS: Add support for eBPF JIT.")
> Signed-off-by: David Daney <david.daney@cavium.com>
> ---
>
> It might be best to merge this along the path of BPF fixes rather than
> MIPS, as the MIPS maintainer (Ralf) seems to be inactive recently.
Looks like situation is that multiple people including myself tried
to contact Ralf due to 'half/mis-applied' MIPS BPF JIT in [1,2] that
sits currently in Linus tree, but never got a reply back since mid June.
Given the work was accepted long ago but incorrectly merged, would be
great if this could still be fixed up with this patch. Given Ralf seems
unfortunately unresponsive, is there a chance, if people are fine with
it, that we could try route this fix e.g. via -net instead before a
final v4.13?
Anyway, the generic pieces interacting with core BPF look good to me:
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Thanks,
Daniel
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f381bf6d82f032b7410185b35d000ea370ac706b
[2] https://patchwork.linux-mips.org/patch/16369/
^ permalink raw reply
* [PATCH] net: Reduce skb_warn_bad_offload() noise.
From: Tonghao Zhang @ 2017-08-04 13:11 UTC (permalink / raw)
To: netdev; +Cc: Tonghao Zhang, Eric Dumazet, Willem de Bruijn, Pravin B Shelar
This patch will revert the b2504a5dbe "net: reduce
skb_warn_bad_offload() noise". The ovs will call the
__skb_gso_segment() with tx false. When segmenting UDP with UFO,
the __skb_gso_segment raises a warning as below [1], because the
ip_summed is CHECKSUM_NONE. While the net-next has removed the
UFO support, but the 4.11 and 4.12 kernel don't address that problem.
In the kernel, only qdisc_pkt_len_init() (__dev_queue_xmit call it.)
uses the SKB_GSO_DODGY to do something. Other places just set it.
The warn described in b2504a5dbe is shown [2]. We may know that:
1. the net_device don’t have qdisc.
2. the skb->ip_summed was changed to CHECKSUM_NONE. it maybe
changed in skb_checksum_help() when calling validate_xmit_skb().
or other place.
And we should not revert the 6e7bc478c9 "net: skb_needs_check() accepts
CHECKSUM_NONE for tx". The check is necessary.
[1]
[321428.168903] WARNING: CPU: 0 PID: 2279 at net/core/dev.c:2562
skb_warn_bad_offload+0xc4/0x110
[321428.168906] san0: caps=(0x000004009fbb58e9, 0x0000000000000000) len=6769
data_len=6727 gso_size=1480 gso_type=2 ip_summed=0
[321428.168955] CPU: 0 PID: 2279 Comm: ruby-mri 4.11.12-200.fc25.x86_64 #1
[321428.168956] Hardware name: Supermicro SYS-1028U-TNRTP+/X10DRU-i+, BIOS 1.1 07/22/2015
[321428.168957] Call Trace:
[321428.168962] dump_stack+0x63/0x86
[321428.168965] __warn+0xcb/0xf0
[321428.168966] warn_slowpath_fmt+0x5a/0x80
[321428.168968] skb_warn_bad_offload+0xc4/0x110
[321428.168970] __skb_gso_segment+0x190/0x1a0
[321428.168977] queue_gso_packets+0x62/0x160 [openvswitch]
[321428.168992] ovs_dp_upcall+0x31/0x60 [openvswitch]
[321428.168994] ovs_dp_process_packet+0x10d/0x130 [openvswitch]
[321428.168997] ovs_vport_receive+0x76/0xd0 [openvswitch]
[321428.169013] internal_dev_xmit+0x28/0x60 [openvswitch]
[321428.169014] dev_hard_start_xmit+0xa3/0x1f0
[321428.169016] __dev_queue_xmit+0x592/0x650
[321428.169026] dev_queue_xmit+0x10/0x20
[2]
WARNING: CPU: 1 PID: 6768 at net/core/dev.c:2439 skb_warn_bad_offload+0x2af/0x390 net/core/dev.c:2434
lo: caps=(0x000000a2803b7c69, 0x0000000000000000) len=138 data_len=0 gso_size=15883 gso_type=4 ip_summed=0
Kernel panic - not syncing: panic_on_warn set ...
CPU: 1 PID: 6768 Comm: syz-executor1 Not tainted 4.9.0 #5
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
ffff8801c063ecd8 ffffffff82346bdf ffffffff00000001 1ffff100380c7d2e
ffffed00380c7d26 0000000041b58ab3 ffffffff84b37e38 ffffffff823468f1
ffffffff84820740 ffffffff84f289c0 dffffc0000000000 ffff8801c063ee20
Call Trace:
[<ffffffff82346bdf>] __dump_stack lib/dump_stack.c:15 [inline]
[<ffffffff82346bdf>] dump_stack+0x2ee/0x3ef lib/dump_stack.c:51
[<ffffffff81827e34>] panic+0x1fb/0x412 kernel/panic.c:179
[<ffffffff8141f704>] __warn+0x1c4/0x1e0 kernel/panic.c:542
[<ffffffff8141f7e5>] warn_slowpath_fmt+0xc5/0x100 kernel/panic.c:565
[<ffffffff8356cbaf>] skb_warn_bad_offload+0x2af/0x390 net/core/dev.c:2434
[<ffffffff83585cd2>] __skb_gso_segment+0x482/0x780 net/core/dev.c:2706
[<ffffffff83586f19>] skb_gso_segment include/linux/netdevice.h:3985 [inline]
[<ffffffff83586f19>] validate_xmit_skb+0x5c9/0xc20 net/core/dev.c:2969
[<ffffffff835892bb>] __dev_queue_xmit+0xe6b/0x1e70 net/core/dev.c:3383
[<ffffffff8358a2d7>] dev_queue_xmit+0x17/0x20 net/core/dev.c:3424
Cc: Eric Dumazet <edumazet@google.com>
Cc: Willem de Bruijn <willemb@google.com>
Cc: Pravin B Shelar <pshelar@ovn.org>
Signed-off-by: Tonghao Zhang <xiangxia.m.yue@gmail.com>
---
net/core/dev.c | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 1d75499..97e6989 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2753,11 +2753,11 @@ static inline bool skb_needs_check(struct sk_buff *skb, bool tx_path)
struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
netdev_features_t features, bool tx_path)
{
- struct sk_buff *segs;
-
if (unlikely(skb_needs_check(skb, tx_path))) {
int err;
+ skb_warn_bad_offload(skb);
+
/* We're going to init ->check field in TCP or UDP header */
err = skb_cow_head(skb, 0);
if (err < 0)
@@ -2786,12 +2786,7 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
skb_reset_mac_header(skb);
skb_reset_mac_len(skb);
- segs = skb_mac_gso_segment(skb, features);
-
- if (unlikely(skb_needs_check(skb, tx_path)))
- skb_warn_bad_offload(skb);
-
- return segs;
+ return skb_mac_gso_segment(skb, features);
}
EXPORT_SYMBOL(__skb_gso_segment);
--
1.8.3.1
^ permalink raw reply related
* Re: [net-next PATCH] net: comment fixes against BPF devmap helper calls
From: Daniel Borkmann @ 2017-08-04 13:21 UTC (permalink / raw)
To: John Fastabend, davem; +Cc: netdev, ast
In-Reply-To: <20170804045822.1032.43840.stgit@john-Precision-Tower-5810>
On 08/04/2017 06:58 AM, John Fastabend wrote:
> Update BPF comments to accurately reflect XDP usage.
>
> Fixes: 97f91a7cf04ff ("bpf: add bpf_redirect_map helper routine")
> Reported-by: Alexei Starovoitov <ast@kernel.org>
> Signed-off-by: John Fastabend <john.fastabend@gmail.com>
> ---
> include/uapi/linux/bpf.h | 16 +++++++++++-----
> 1 file changed, 11 insertions(+), 5 deletions(-)
>
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index 1106a8c..1ae061e 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -345,14 +345,20 @@ enum bpf_attach_type {
> * int bpf_redirect(ifindex, flags)
> * redirect to another netdev
> * @ifindex: ifindex of the net device
> - * @flags: bit 0 - if set, redirect to ingress instead of egress
> - * other bits - reserved
> - * Return: TC_ACT_REDIRECT
> - * int bpf_redirect_map(key, map, flags)
> + * @flags:
> + * cls_bpf:
> + * bit 0 - if set, redirect to ingress instead of egress
> + * other bits - reserved
> + * xdp_bpf:
> + * all bits - reserved
> + * Return: cls_bpf: TC_ACT_REDIRECT
> + * xdp_bfp: XDP_REDIRECT
We should probably also mention the XDP_ABORTED / TC_ACT_SHOT
on error(/misuse) similarly as below.
> + * int bpf_redirect_map(map, key, flags)
> * redirect to endpoint in map
> + * @map: pointer to dev map
> * @key: index in map to lookup
> - * @map: fd of map to do lookup in
> * @flags: --
> + * Return: XDP_REDIRECT on success or XDP_ABORT on error
> *
> * u32 bpf_get_route_realm(skb)
> * retrieve a dst's tclassid
>
^ permalink raw reply
* [PATCH net-next 2/5] ipv6: sr: export SRH insertion functions
From: David Lebrun @ 2017-08-04 13:24 UTC (permalink / raw)
To: netdev; +Cc: David Lebrun
In-Reply-To: <20170804132415.9701-1-david.lebrun@uclouvain.be>
This patch exports the seg6_do_srh_encap() and seg6_do_srh_inline()
functions. It also removes the CONFIG_IPV6_SEG6_INLINE knob
that enabled the compilation of seg6_do_srh_inline(). This function
is now built-in.
Signed-off-by: David Lebrun <david.lebrun@uclouvain.be>
---
include/net/seg6.h | 2 ++
net/ipv6/Kconfig | 12 ------------
net/ipv6/seg6_iptunnel.c | 12 ++++--------
3 files changed, 6 insertions(+), 20 deletions(-)
diff --git a/include/net/seg6.h b/include/net/seg6.h
index 4e03575..a32abb0 100644
--- a/include/net/seg6.h
+++ b/include/net/seg6.h
@@ -58,5 +58,7 @@ extern int seg6_iptunnel_init(void);
extern void seg6_iptunnel_exit(void);
extern bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len);
+extern int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh);
+extern int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh);
#endif
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 48c4529..50181a9 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -315,18 +315,6 @@ config IPV6_SEG6_LWTUNNEL
If unsure, say N.
-config IPV6_SEG6_INLINE
- bool "IPv6: direct Segment Routing Header insertion "
- depends on IPV6_SEG6_LWTUNNEL
- ---help---
- Support for direct insertion of the Segment Routing Header,
- also known as inline mode. Be aware that direct insertion of
- extension headers (as opposed to encapsulation) may break
- multiple mechanisms such as PMTUD or IPSec AH. Use this feature
- only if you know exactly what you are doing.
-
- If unsure, say N.
-
config IPV6_SEG6_HMAC
bool "IPv6: Segment Routing HMAC support"
depends on IPV6
diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
index 264d772..20b1ba8 100644
--- a/net/ipv6/seg6_iptunnel.c
+++ b/net/ipv6/seg6_iptunnel.c
@@ -91,7 +91,7 @@ static void set_tun_src(struct net *net, struct net_device *dev,
}
/* encapsulate an IPv6 packet within an outer IPv6 header with a given SRH */
-static int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
+int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
{
struct net *net = dev_net(skb_dst(skb)->dev);
struct ipv6hdr *hdr, *inner_hdr;
@@ -141,10 +141,10 @@ static int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
return 0;
}
+EXPORT_SYMBOL(seg6_do_srh_encap);
/* insert an SRH within an IPv6 packet, just after the IPv6 header */
-#ifdef CONFIG_IPV6_SEG6_INLINE
-static int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
+int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
{
struct ipv6hdr *hdr, *oldhdr;
struct ipv6_sr_hdr *isrh;
@@ -193,7 +193,7 @@ static int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
return 0;
}
-#endif
+EXPORT_SYMBOL(seg6_do_srh_inline);
static int seg6_do_srh(struct sk_buff *skb)
{
@@ -209,12 +209,10 @@ static int seg6_do_srh(struct sk_buff *skb)
}
switch (tinfo->mode) {
-#ifdef CONFIG_IPV6_SEG6_INLINE
case SEG6_IPTUN_MODE_INLINE:
err = seg6_do_srh_inline(skb, tinfo->srh);
skb_reset_inner_headers(skb);
break;
-#endif
case SEG6_IPTUN_MODE_ENCAP:
err = seg6_do_srh_encap(skb, tinfo->srh);
break;
@@ -357,10 +355,8 @@ static int seg6_build_state(struct nlattr *nla,
return -EINVAL;
switch (tuninfo->mode) {
-#ifdef CONFIG_IPV6_SEG6_INLINE
case SEG6_IPTUN_MODE_INLINE:
break;
-#endif
case SEG6_IPTUN_MODE_ENCAP:
break;
default:
--
2.10.2
^ permalink raw reply related
* [PATCH net-next 1/5] ipv6: sr: allow SRH insertion with arbitrary segments_left value
From: David Lebrun @ 2017-08-04 13:24 UTC (permalink / raw)
To: netdev; +Cc: David Lebrun
In-Reply-To: <20170804132415.9701-1-david.lebrun@uclouvain.be>
The seg6_validate_srh() function only allows SRHs whose active segment is
the first segment of the path. However, an application may insert an SRH
whose active segment is not the first one. Such an application might be
for example an SR-aware Virtual Network Function.
This patch enables to insert SRHs with an arbitrary active segment.
Signed-off-by: David Lebrun <david.lebrun@uclouvain.be>
---
net/ipv6/exthdrs.c | 4 ++--
net/ipv6/seg6.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 3cec529..9551613 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -882,7 +882,7 @@ static void ipv6_push_rthdr4(struct sk_buff *skb, u8 *proto,
(hops - 1) * sizeof(struct in6_addr));
sr_phdr->segments[0] = **addr_p;
- *addr_p = &sr_ihdr->segments[hops - 1];
+ *addr_p = &sr_ihdr->segments[sr_ihdr->segments_left];
#ifdef CONFIG_IPV6_SEG6_HMAC
if (sr_has_hmac(sr_phdr)) {
@@ -1174,7 +1174,7 @@ struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
{
struct ipv6_sr_hdr *srh = (struct ipv6_sr_hdr *)opt->srcrt;
- fl6->daddr = srh->segments[srh->first_segment];
+ fl6->daddr = srh->segments[srh->segments_left];
break;
}
default:
diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c
index 15fba55..81c2339 100644
--- a/net/ipv6/seg6.c
+++ b/net/ipv6/seg6.c
@@ -40,7 +40,7 @@ bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len)
if (((srh->hdrlen + 1) << 3) != len)
return false;
- if (srh->segments_left != srh->first_segment)
+ if (srh->segments_left > srh->first_segment)
return false;
tlv_offset = sizeof(*srh) + ((srh->first_segment + 1) << 4);
--
2.10.2
^ permalink raw reply related
* [PATCH net-next 0/5] ipv6: sr: add support for advanced local segment processing
From: David Lebrun @ 2017-08-04 13:24 UTC (permalink / raw)
To: netdev; +Cc: David Lebrun
The current implementation of IPv6 SR supports SRH insertion/encapsulation
and basic segment endpoint behavior (i.e., processing of an SRH contained in
a packet whose active segment (IPv6 DA) is routed to the local node). This
behavior simply consists of updating the DA to the next segment and forwarding
the packet accordingly. This processing is realised for all such packets,
regardless of the active segment.
The most recent specifications of IPv6 SR [1] [2] extend the SRH processing
features as follows. Each segment endpoint defines a MyLocalSID table.
This table maps segments to operations to perform. For each ingress IPv6
packet whose DA is part of a given prefix, the segment endpoint looks
up the active segment (i.e., the IPv6 DA) in the MyLocalSID table and
applies the corresponding operation. Such specifications enable to specify
arbitrary operations besides the basic SRH processing and allow for a more
fine-grained classification.
This patch series implements those extended specifications by leveraging
a new type of lightweight tunnel, seg6local. The MyLocalSID table is
simply an arbitrary routing table (using CONFIG_IPV6_MULTIPLE_TABLES). The
following commands would assign the prefix fc00::/64 to the MyLocalSID
table, map the segment fc00::42 to the regular SRH processing function
(named "End"), and drop all packets received with an undefined active
segment:
ip -6 rule add fc00::/64 lookup 100
ip -6 route add fc00::42 encap seg6local action End dev eth0 table 100
ip -6 route add blackhole default table 100
As another example, the following command would assign the segment
fc00::1234 to the regular SRH processing function, except that the
processed packet must be forwarded to the next-hop fc42::1 (this operation
is named "End.X"):
ip -6 route add fc00::1234 encap seg6local action End.X nh6 fc42::1 dev eth0 table 100
Those two basic operations (End and End.X) are defined in [1]. A more
extensive list of advanced operations is defined in [2].
The first two patches of the series are preliminary work that remove an
assumption about initial SRH format, and export the two functions used to
insert and encapsulate an SRH onto packets. The third patch defines the
new seg6local lightweight tunnel and implement the core functions. The
fourth patch implements the operations needed to handle the newly defined
rtnetlink attributes. The fifth patch implements a few SRH processing
operations, including End and End.X.
[1] https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-07
[2] https://tools.ietf.org/html/draft-filsfils-spring-srv6-network-programming-01
David Lebrun (5):
ipv6: sr: allow SRH insertion with arbitrary segments_left value
ipv6: sr: export SRH insertion functions
ipv6: sr: define core operations for seg6local lightweight tunnel
ipv6: sr: add rtnetlink functions for seg6local action parameters
ipv6: sr: implement several seg6local actions
include/linux/seg6_local.h | 6 +
include/net/seg6.h | 4 +
include/uapi/linux/lwtunnel.h | 1 +
include/uapi/linux/seg6_local.h | 68 ++++
net/core/lwtunnel.c | 2 +
net/ipv6/Kconfig | 15 +-
net/ipv6/Makefile | 2 +-
net/ipv6/exthdrs.c | 4 +-
net/ipv6/seg6.c | 7 +-
net/ipv6/seg6_iptunnel.c | 12 +-
net/ipv6/seg6_local.c | 766 ++++++++++++++++++++++++++++++++++++++++
11 files changed, 862 insertions(+), 25 deletions(-)
create mode 100644 include/linux/seg6_local.h
create mode 100644 include/uapi/linux/seg6_local.h
create mode 100644 net/ipv6/seg6_local.c
--
2.10.2
^ permalink raw reply
* [PATCH net-next 4/5] ipv6: sr: add rtnetlink functions for seg6local action parameters
From: David Lebrun @ 2017-08-04 13:24 UTC (permalink / raw)
To: netdev; +Cc: David Lebrun
In-Reply-To: <20170804132415.9701-1-david.lebrun@uclouvain.be>
This patch adds the necessary functions to parse, fill, and compare
seg6local rtnetlink attributes, for all defined action parameters.
- The SRH parameter defines an SRH to be inserted or encapsulated.
- The TABLE parameter defines the table to use for the route lookup of
the next segment or the inner decapsulated packet.
- The NH4 parameter defines the IPv4 next-hop for an inner decapsulated
IPv4 packet.
- The NH6 parameter defines the IPv6 next-hop for the next segment or
for an inner decapsulated IPv6 packet
- The IIF parameter defines an ingress interface index.
- The OIF parameter defines an egress interface index.
Signed-off-by: David Lebrun <david.lebrun@uclouvain.be>
---
net/ipv6/seg6_local.c | 211 +++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 193 insertions(+), 18 deletions(-)
diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
index 53615d7..ab1fc1b 100644
--- a/net/ipv6/seg6_local.c
+++ b/net/ipv6/seg6_local.c
@@ -104,6 +104,181 @@ static const struct nla_policy seg6_local_policy[SEG6_LOCAL_MAX + 1] = {
[SEG6_LOCAL_OIF] = { .type = NLA_U32 },
};
+static int parse_nla_srh(struct nlattr **attrs, struct seg6_local_lwt *slwt)
+{
+ struct ipv6_sr_hdr *srh;
+ int len;
+
+ srh = nla_data(attrs[SEG6_LOCAL_SRH]);
+ len = nla_len(attrs[SEG6_LOCAL_SRH]);
+
+ /* SRH must contain at least one segment */
+ if (len < sizeof(*srh) + sizeof(struct in6_addr))
+ return -EINVAL;
+
+ if (!seg6_validate_srh(srh, len))
+ return -EINVAL;
+
+ slwt->srh = kmalloc(len, GFP_KERNEL);
+ if (!slwt->srh)
+ return -ENOMEM;
+
+ memcpy(slwt->srh, srh, len);
+
+ slwt->headroom += len;
+
+ return 0;
+}
+
+static int put_nla_srh(struct sk_buff *skb, struct seg6_local_lwt *slwt)
+{
+ struct ipv6_sr_hdr *srh;
+ struct nlattr *nla;
+ int len;
+
+ srh = slwt->srh;
+ len = (srh->hdrlen + 1) << 3;
+
+ nla = nla_reserve(skb, SEG6_LOCAL_SRH, len);
+ if (!nla)
+ return -EMSGSIZE;
+
+ memcpy(nla_data(nla), srh, len);
+
+ return 0;
+}
+
+static int cmp_nla_srh(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
+{
+ int len = (a->srh->hdrlen + 1) << 3;
+
+ if (len != ((b->srh->hdrlen + 1) << 3))
+ return 1;
+
+ return memcmp(a->srh, b->srh, len);
+}
+
+static int parse_nla_table(struct nlattr **attrs, struct seg6_local_lwt *slwt)
+{
+ slwt->table = nla_get_u32(attrs[SEG6_LOCAL_TABLE]);
+
+ return 0;
+}
+
+static int put_nla_table(struct sk_buff *skb, struct seg6_local_lwt *slwt)
+{
+ if (nla_put_u32(skb, SEG6_LOCAL_TABLE, slwt->table))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int cmp_nla_table(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
+{
+ if (a->table != b->table)
+ return 1;
+
+ return 0;
+}
+
+static int parse_nla_nh4(struct nlattr **attrs, struct seg6_local_lwt *slwt)
+{
+ memcpy(&slwt->nh4, nla_data(attrs[SEG6_LOCAL_NH4]),
+ sizeof(struct in_addr));
+
+ return 0;
+}
+
+static int put_nla_nh4(struct sk_buff *skb, struct seg6_local_lwt *slwt)
+{
+ struct nlattr *nla;
+
+ nla = nla_reserve(skb, SEG6_LOCAL_NH4, sizeof(struct in_addr));
+ if (!nla)
+ return -EMSGSIZE;
+
+ memcpy(nla_data(nla), &slwt->nh4, sizeof(struct in_addr));
+
+ return 0;
+}
+
+static int cmp_nla_nh4(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
+{
+ return memcmp(&a->nh4, &b->nh4, sizeof(struct in_addr));
+}
+
+static int parse_nla_nh6(struct nlattr **attrs, struct seg6_local_lwt *slwt)
+{
+ memcpy(&slwt->nh6, nla_data(attrs[SEG6_LOCAL_NH6]),
+ sizeof(struct in6_addr));
+
+ return 0;
+}
+
+static int put_nla_nh6(struct sk_buff *skb, struct seg6_local_lwt *slwt)
+{
+ struct nlattr *nla;
+
+ nla = nla_reserve(skb, SEG6_LOCAL_NH6, sizeof(struct in6_addr));
+ if (!nla)
+ return -EMSGSIZE;
+
+ memcpy(nla_data(nla), &slwt->nh6, sizeof(struct in6_addr));
+
+ return 0;
+}
+
+static int cmp_nla_nh6(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
+{
+ return memcmp(&a->nh6, &b->nh6, sizeof(struct in6_addr));
+}
+
+static int parse_nla_iif(struct nlattr **attrs, struct seg6_local_lwt *slwt)
+{
+ slwt->iif = nla_get_u32(attrs[SEG6_LOCAL_IIF]);
+
+ return 0;
+}
+
+static int put_nla_iif(struct sk_buff *skb, struct seg6_local_lwt *slwt)
+{
+ if (nla_put_u32(skb, SEG6_LOCAL_IIF, slwt->iif))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int cmp_nla_iif(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
+{
+ if (a->iif != b->iif)
+ return 1;
+
+ return 0;
+}
+
+static int parse_nla_oif(struct nlattr **attrs, struct seg6_local_lwt *slwt)
+{
+ slwt->oif = nla_get_u32(attrs[SEG6_LOCAL_OIF]);
+
+ return 0;
+}
+
+static int put_nla_oif(struct sk_buff *skb, struct seg6_local_lwt *slwt)
+{
+ if (nla_put_u32(skb, SEG6_LOCAL_OIF, slwt->oif))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int cmp_nla_oif(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
+{
+ if (a->oif != b->oif)
+ return 1;
+
+ return 0;
+}
+
struct seg6_action_param {
int (*parse)(struct nlattr **attrs, struct seg6_local_lwt *slwt);
int (*put)(struct sk_buff *skb, struct seg6_local_lwt *slwt);
@@ -111,29 +286,29 @@ struct seg6_action_param {
};
static struct seg6_action_param seg6_action_params[SEG6_LOCAL_MAX + 1] = {
- [SEG6_LOCAL_SRH] = { .parse = NULL,
- .put = NULL,
- .cmp = NULL },
+ [SEG6_LOCAL_SRH] = { .parse = parse_nla_srh,
+ .put = put_nla_srh,
+ .cmp = cmp_nla_srh },
- [SEG6_LOCAL_TABLE] = { .parse = NULL,
- .put = NULL,
- .cmp = NULL },
+ [SEG6_LOCAL_TABLE] = { .parse = parse_nla_table,
+ .put = put_nla_table,
+ .cmp = cmp_nla_table },
- [SEG6_LOCAL_NH4] = { .parse = NULL,
- .put = NULL,
- .cmp = NULL },
+ [SEG6_LOCAL_NH4] = { .parse = parse_nla_nh4,
+ .put = put_nla_nh4,
+ .cmp = cmp_nla_nh4 },
- [SEG6_LOCAL_NH6] = { .parse = NULL,
- .put = NULL,
- .cmp = NULL },
+ [SEG6_LOCAL_NH6] = { .parse = parse_nla_nh6,
+ .put = put_nla_nh6,
+ .cmp = cmp_nla_nh6 },
- [SEG6_LOCAL_IIF] = { .parse = NULL,
- .put = NULL,
- .cmp = NULL },
+ [SEG6_LOCAL_IIF] = { .parse = parse_nla_iif,
+ .put = put_nla_iif,
+ .cmp = cmp_nla_iif },
- [SEG6_LOCAL_OIF] = { .parse = NULL,
- .put = NULL,
- .cmp = NULL },
+ [SEG6_LOCAL_OIF] = { .parse = parse_nla_oif,
+ .put = put_nla_oif,
+ .cmp = cmp_nla_oif },
};
static int parse_nla_action(struct nlattr **attrs, struct seg6_local_lwt *slwt)
--
2.10.2
^ permalink raw reply related
* [PATCH net-next 3/5] ipv6: sr: define core operations for seg6local lightweight tunnel
From: David Lebrun @ 2017-08-04 13:24 UTC (permalink / raw)
To: netdev; +Cc: David Lebrun
In-Reply-To: <20170804132415.9701-1-david.lebrun@uclouvain.be>
This patch implements a new type of lightweight tunnel named seg6local.
A seg6local lwt is defined by a type of action and a set of parameters.
The action represents the operation to perform on the packets matching the
lwt's route, and is not necessarily an encapsulation. The set of parameters
are arguments for the processing function.
Each action is defined in a struct seg6_action_desc within
seg6_action_table[]. This structure contains the action, mandatory
attributes, the processing function, and a static headroom size required by
the action. The mandatory attributes are encoded as a bitmask field. The
static headroom is set to a non-zero value when the processing function
always add a constant number of bytes to the skb (e.g. the header size for
encapsulations).
To facilitate rtnetlink-related operations such as parsing, fill_encap,
and cmp_encap, each type of action parameter is associated to three
function pointers, in seg6_action_params[].
All actions defined in seg6_local.h are detailed in [1].
[1] https://tools.ietf.org/html/draft-filsfils-spring-srv6-network-programming-01
Signed-off-by: David Lebrun <david.lebrun@uclouvain.be>
---
include/linux/seg6_local.h | 6 +
include/net/seg6.h | 2 +
include/uapi/linux/lwtunnel.h | 1 +
include/uapi/linux/seg6_local.h | 68 +++++++++
net/core/lwtunnel.c | 2 +
net/ipv6/Kconfig | 3 +-
net/ipv6/Makefile | 2 +-
net/ipv6/seg6.c | 5 +
net/ipv6/seg6_local.c | 320 ++++++++++++++++++++++++++++++++++++++++
9 files changed, 407 insertions(+), 2 deletions(-)
create mode 100644 include/linux/seg6_local.h
create mode 100644 include/uapi/linux/seg6_local.h
create mode 100644 net/ipv6/seg6_local.c
diff --git a/include/linux/seg6_local.h b/include/linux/seg6_local.h
new file mode 100644
index 0000000..ee63e76
--- /dev/null
+++ b/include/linux/seg6_local.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_SEG6_LOCAL_H
+#define _LINUX_SEG6_LOCAL_H
+
+#include <uapi/linux/seg6_local.h>
+
+#endif
diff --git a/include/net/seg6.h b/include/net/seg6.h
index a32abb0..5379f55 100644
--- a/include/net/seg6.h
+++ b/include/net/seg6.h
@@ -56,6 +56,8 @@ extern int seg6_init(void);
extern void seg6_exit(void);
extern int seg6_iptunnel_init(void);
extern void seg6_iptunnel_exit(void);
+extern int seg6_local_init(void);
+extern void seg6_local_exit(void);
extern bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len);
extern int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh);
diff --git a/include/uapi/linux/lwtunnel.h b/include/uapi/linux/lwtunnel.h
index 92724cba..7fdd19c 100644
--- a/include/uapi/linux/lwtunnel.h
+++ b/include/uapi/linux/lwtunnel.h
@@ -11,6 +11,7 @@ enum lwtunnel_encap_types {
LWTUNNEL_ENCAP_IP6,
LWTUNNEL_ENCAP_SEG6,
LWTUNNEL_ENCAP_BPF,
+ LWTUNNEL_ENCAP_SEG6_LOCAL,
__LWTUNNEL_ENCAP_MAX,
};
diff --git a/include/uapi/linux/seg6_local.h b/include/uapi/linux/seg6_local.h
new file mode 100644
index 0000000..ef2d8c3
--- /dev/null
+++ b/include/uapi/linux/seg6_local.h
@@ -0,0 +1,68 @@
+/*
+ * SR-IPv6 implementation
+ *
+ * Author:
+ * David Lebrun <david.lebrun@uclouvain.be>
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _UAPI_LINUX_SEG6_LOCAL_H
+#define _UAPI_LINUX_SEG6_LOCAL_H
+
+#include <linux/seg6.h>
+
+enum {
+ SEG6_LOCAL_UNSPEC,
+ SEG6_LOCAL_ACTION,
+ SEG6_LOCAL_SRH,
+ SEG6_LOCAL_TABLE,
+ SEG6_LOCAL_NH4,
+ SEG6_LOCAL_NH6,
+ SEG6_LOCAL_IIF,
+ SEG6_LOCAL_OIF,
+ __SEG6_LOCAL_MAX,
+};
+#define SEG6_LOCAL_MAX (__SEG6_LOCAL_MAX - 1)
+
+enum {
+ SEG6_LOCAL_ACTION_UNSPEC = 0,
+ /* node segment */
+ SEG6_LOCAL_ACTION_END = 1,
+ /* adjacency segment (IPv6 cross-connect) */
+ SEG6_LOCAL_ACTION_END_X = 2,
+ /* lookup of next seg NH in table */
+ SEG6_LOCAL_ACTION_END_T = 3,
+ /* decap and L2 cross-connect */
+ SEG6_LOCAL_ACTION_END_DX2 = 4,
+ /* decap and IPv6 cross-connect */
+ SEG6_LOCAL_ACTION_END_DX6 = 5,
+ /* decap and IPv4 cross-connect */
+ SEG6_LOCAL_ACTION_END_DX4 = 6,
+ /* decap and lookup of DA in v6 table */
+ SEG6_LOCAL_ACTION_END_DT6 = 7,
+ /* decap and lookup of DA in v4 table */
+ SEG6_LOCAL_ACTION_END_DT4 = 8,
+ /* binding segment with insertion */
+ SEG6_LOCAL_ACTION_END_B6 = 9,
+ /* binding segment with encapsulation */
+ SEG6_LOCAL_ACTION_END_B6_ENCAP = 10,
+ /* binding segment with MPLS encap */
+ SEG6_LOCAL_ACTION_END_BM = 11,
+ /* lookup last seg in table */
+ SEG6_LOCAL_ACTION_END_S = 12,
+ /* forward to SR-unaware VNF with static proxy */
+ SEG6_LOCAL_ACTION_END_AS = 13,
+ /* forward to SR-unaware VNF with masquerading */
+ SEG6_LOCAL_ACTION_END_AM = 14,
+
+ __SEG6_LOCAL_ACTION_MAX,
+};
+
+#define SEG6_LOCAL_ACTION_MAX (__SEG6_LOCAL_ACTION_MAX - 1)
+
+#endif
diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c
index d9cb353..3091001 100644
--- a/net/core/lwtunnel.c
+++ b/net/core/lwtunnel.c
@@ -44,6 +44,8 @@ static const char *lwtunnel_encap_str(enum lwtunnel_encap_types encap_type)
return "SEG6";
case LWTUNNEL_ENCAP_BPF:
return "BPF";
+ case LWTUNNEL_ENCAP_SEG6_LOCAL:
+ return "SEG6LOCAL";
case LWTUNNEL_ENCAP_IP6:
case LWTUNNEL_ENCAP_IP:
case LWTUNNEL_ENCAP_NONE:
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 50181a9..0d72239 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -311,7 +311,8 @@ config IPV6_SEG6_LWTUNNEL
---help---
Support for encapsulation of packets within an outer IPv6
header and a Segment Routing Header using the lightweight
- tunnels mechanism.
+ tunnels mechanism. Also enable support for advanced local
+ processing of SRv6 packets based on their active segment.
If unsure, say N.
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index f8b24c2..10e3423 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -23,7 +23,7 @@ ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o
ipv6-$(CONFIG_PROC_FS) += proc.o
ipv6-$(CONFIG_SYN_COOKIES) += syncookies.o
ipv6-$(CONFIG_NETLABEL) += calipso.o
-ipv6-$(CONFIG_IPV6_SEG6_LWTUNNEL) += seg6_iptunnel.o
+ipv6-$(CONFIG_IPV6_SEG6_LWTUNNEL) += seg6_iptunnel.o seg6_local.o
ipv6-$(CONFIG_IPV6_SEG6_HMAC) += seg6_hmac.o
ipv6-objs += $(ipv6-y)
diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c
index 81c2339..c814077 100644
--- a/net/ipv6/seg6.c
+++ b/net/ipv6/seg6.c
@@ -456,6 +456,10 @@ int __init seg6_init(void)
err = seg6_iptunnel_init();
if (err)
goto out_unregister_pernet;
+
+ err = seg6_local_init();
+ if (err)
+ goto out_unregister_pernet;
#endif
#ifdef CONFIG_IPV6_SEG6_HMAC
@@ -471,6 +475,7 @@ int __init seg6_init(void)
#ifdef CONFIG_IPV6_SEG6_HMAC
out_unregister_iptun:
#ifdef CONFIG_IPV6_SEG6_LWTUNNEL
+ seg6_local_exit();
seg6_iptunnel_exit();
#endif
#endif
diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
new file mode 100644
index 0000000..53615d7
--- /dev/null
+++ b/net/ipv6/seg6_local.c
@@ -0,0 +1,320 @@
+/*
+ * SR-IPv6 implementation
+ *
+ * Author:
+ * David Lebrun <david.lebrun@uclouvain.be>
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/net.h>
+#include <linux/module.h>
+#include <net/ip.h>
+#include <net/lwtunnel.h>
+#include <net/netevent.h>
+#include <net/netns/generic.h>
+#include <net/ip6_fib.h>
+#include <net/route.h>
+#include <net/seg6.h>
+#include <linux/seg6.h>
+#include <linux/seg6_local.h>
+#include <net/addrconf.h>
+#include <net/ip6_route.h>
+#include <net/dst_cache.h>
+#ifdef CONFIG_IPV6_SEG6_HMAC
+#include <net/seg6_hmac.h>
+#endif
+
+struct seg6_local_lwt;
+
+struct seg6_action_desc {
+ int action;
+ unsigned long attrs;
+ int (*input)(struct sk_buff *skb, struct seg6_local_lwt *slwt);
+ int static_headroom;
+};
+
+struct seg6_local_lwt {
+ int action;
+ struct ipv6_sr_hdr *srh;
+ int table;
+ struct in_addr nh4;
+ struct in6_addr nh6;
+ int iif;
+ int oif;
+
+ int headroom;
+ struct seg6_action_desc *desc;
+};
+
+static struct seg6_local_lwt *seg6_local_lwtunnel(struct lwtunnel_state *lwt)
+{
+ return (struct seg6_local_lwt *)lwt->data;
+}
+
+static struct seg6_action_desc seg6_action_table[] = {
+ {
+ .action = SEG6_LOCAL_ACTION_END,
+ .attrs = 0,
+ },
+};
+
+static struct seg6_action_desc *__get_action_desc(int action)
+{
+ struct seg6_action_desc *desc;
+ int i, count;
+
+ count = sizeof(seg6_action_table) / sizeof(struct seg6_action_desc);
+ for (i = 0; i < count; i++) {
+ desc = &seg6_action_table[i];
+ if (desc->action == action)
+ return desc;
+ }
+
+ return NULL;
+}
+
+static int seg6_local_input(struct sk_buff *skb)
+{
+ struct dst_entry *orig_dst = skb_dst(skb);
+ struct seg6_action_desc *desc;
+ struct seg6_local_lwt *slwt;
+
+ slwt = seg6_local_lwtunnel(orig_dst->lwtstate);
+ desc = slwt->desc;
+
+ return desc->input(skb, slwt);
+}
+
+static const struct nla_policy seg6_local_policy[SEG6_LOCAL_MAX + 1] = {
+ [SEG6_LOCAL_ACTION] = { .type = NLA_U32 },
+ [SEG6_LOCAL_SRH] = { .type = NLA_BINARY },
+ [SEG6_LOCAL_TABLE] = { .type = NLA_U32 },
+ [SEG6_LOCAL_NH4] = { .type = NLA_BINARY,
+ .len = sizeof(struct in_addr) },
+ [SEG6_LOCAL_NH6] = { .type = NLA_BINARY,
+ .len = sizeof(struct in6_addr) },
+ [SEG6_LOCAL_IIF] = { .type = NLA_U32 },
+ [SEG6_LOCAL_OIF] = { .type = NLA_U32 },
+};
+
+struct seg6_action_param {
+ int (*parse)(struct nlattr **attrs, struct seg6_local_lwt *slwt);
+ int (*put)(struct sk_buff *skb, struct seg6_local_lwt *slwt);
+ int (*cmp)(struct seg6_local_lwt *a, struct seg6_local_lwt *b);
+};
+
+static struct seg6_action_param seg6_action_params[SEG6_LOCAL_MAX + 1] = {
+ [SEG6_LOCAL_SRH] = { .parse = NULL,
+ .put = NULL,
+ .cmp = NULL },
+
+ [SEG6_LOCAL_TABLE] = { .parse = NULL,
+ .put = NULL,
+ .cmp = NULL },
+
+ [SEG6_LOCAL_NH4] = { .parse = NULL,
+ .put = NULL,
+ .cmp = NULL },
+
+ [SEG6_LOCAL_NH6] = { .parse = NULL,
+ .put = NULL,
+ .cmp = NULL },
+
+ [SEG6_LOCAL_IIF] = { .parse = NULL,
+ .put = NULL,
+ .cmp = NULL },
+
+ [SEG6_LOCAL_OIF] = { .parse = NULL,
+ .put = NULL,
+ .cmp = NULL },
+};
+
+static int parse_nla_action(struct nlattr **attrs, struct seg6_local_lwt *slwt)
+{
+ struct seg6_action_param *param;
+ struct seg6_action_desc *desc;
+ int i, err;
+
+ desc = __get_action_desc(slwt->action);
+ if (!desc)
+ return -EINVAL;
+
+ if (!desc->input)
+ return -EOPNOTSUPP;
+
+ slwt->desc = desc;
+ slwt->headroom += desc->static_headroom;
+
+ for (i = 0; i < SEG6_LOCAL_MAX + 1; i++) {
+ if (desc->attrs & (1 << i)) {
+ if (!attrs[i])
+ return -EINVAL;
+
+ param = &seg6_action_params[i];
+
+ err = param->parse(attrs, slwt);
+ if (err < 0)
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int seg6_local_build_state(struct nlattr *nla, unsigned int family,
+ const void *cfg, struct lwtunnel_state **ts,
+ struct netlink_ext_ack *extack)
+{
+ struct nlattr *tb[SEG6_LOCAL_MAX + 1];
+ struct lwtunnel_state *newts;
+ struct seg6_local_lwt *slwt;
+ int err;
+
+ err = nla_parse_nested(tb, SEG6_LOCAL_MAX, nla, seg6_local_policy,
+ extack);
+
+ if (err < 0)
+ return err;
+
+ if (!tb[SEG6_LOCAL_ACTION])
+ return -EINVAL;
+
+ newts = lwtunnel_state_alloc(sizeof(*slwt));
+ if (!newts)
+ return -ENOMEM;
+
+ slwt = seg6_local_lwtunnel(newts);
+ slwt->action = nla_get_u32(tb[SEG6_LOCAL_ACTION]);
+
+ err = parse_nla_action(tb, slwt);
+ if (err < 0)
+ goto out_free;
+
+ newts->type = LWTUNNEL_ENCAP_SEG6_LOCAL;
+ newts->flags = LWTUNNEL_STATE_INPUT_REDIRECT;
+ newts->headroom = slwt->headroom;
+
+ *ts = newts;
+
+ return 0;
+
+out_free:
+ kfree(slwt->srh);
+ kfree(newts);
+ return err;
+}
+
+static void seg6_local_destroy_state(struct lwtunnel_state *lwt)
+{
+ struct seg6_local_lwt *slwt = seg6_local_lwtunnel(lwt);
+
+ kfree(slwt->srh);
+}
+
+static int seg6_local_fill_encap(struct sk_buff *skb,
+ struct lwtunnel_state *lwt)
+{
+ struct seg6_local_lwt *slwt = seg6_local_lwtunnel(lwt);
+ struct seg6_action_param *param;
+ int i, err;
+
+ if (nla_put_u32(skb, SEG6_LOCAL_ACTION, slwt->action))
+ return -EMSGSIZE;
+
+ for (i = 0; i < SEG6_LOCAL_MAX + 1; i++) {
+ if (slwt->desc->attrs & (1 << i)) {
+ param = &seg6_action_params[i];
+ err = param->put(skb, slwt);
+ if (err < 0)
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int seg6_local_get_encap_size(struct lwtunnel_state *lwt)
+{
+ struct seg6_local_lwt *slwt = seg6_local_lwtunnel(lwt);
+ unsigned long attrs;
+ int nlsize;
+
+ nlsize = nla_total_size(4); /* action */
+
+ attrs = slwt->desc->attrs;
+
+ if (attrs & (1 << SEG6_LOCAL_SRH))
+ nlsize += nla_total_size((slwt->srh->hdrlen + 1) << 3);
+
+ if (attrs & (1 << SEG6_LOCAL_TABLE))
+ nlsize += nla_total_size(4);
+
+ if (attrs & (1 << SEG6_LOCAL_NH4))
+ nlsize += nla_total_size(4);
+
+ if (attrs & (1 << SEG6_LOCAL_NH6))
+ nlsize += nla_total_size(16);
+
+ if (attrs & (1 << SEG6_LOCAL_IIF))
+ nlsize += nla_total_size(4);
+
+ if (attrs & (1 << SEG6_LOCAL_OIF))
+ nlsize += nla_total_size(4);
+
+ return nlsize;
+}
+
+static int seg6_local_cmp_encap(struct lwtunnel_state *a,
+ struct lwtunnel_state *b)
+{
+ struct seg6_local_lwt *slwt_a, *slwt_b;
+ struct seg6_action_param *param;
+ int i;
+
+ slwt_a = seg6_local_lwtunnel(a);
+ slwt_b = seg6_local_lwtunnel(b);
+
+ if (slwt_a->action != slwt_b->action)
+ return 1;
+
+ if (slwt_a->desc->attrs != slwt_b->desc->attrs)
+ return 1;
+
+ for (i = 0; i < SEG6_LOCAL_MAX + 1; i++) {
+ if (slwt_a->desc->attrs & (1 << i)) {
+ param = &seg6_action_params[i];
+ if (param->cmp(slwt_a, slwt_b))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static const struct lwtunnel_encap_ops seg6_local_ops = {
+ .build_state = seg6_local_build_state,
+ .destroy_state = seg6_local_destroy_state,
+ .input = seg6_local_input,
+ .fill_encap = seg6_local_fill_encap,
+ .get_encap_size = seg6_local_get_encap_size,
+ .cmp_encap = seg6_local_cmp_encap,
+ .owner = THIS_MODULE,
+};
+
+int __init seg6_local_init(void)
+{
+ return lwtunnel_encap_add_ops(&seg6_local_ops,
+ LWTUNNEL_ENCAP_SEG6_LOCAL);
+}
+
+void seg6_local_exit(void)
+{
+ lwtunnel_encap_del_ops(&seg6_local_ops, LWTUNNEL_ENCAP_SEG6_LOCAL);
+}
--
2.10.2
^ permalink raw reply related
* [PATCH net-next 5/5] ipv6: sr: implement several seg6local actions
From: David Lebrun @ 2017-08-04 13:25 UTC (permalink / raw)
To: netdev; +Cc: David Lebrun
In-Reply-To: <20170804132415.9701-1-david.lebrun@uclouvain.be>
This patch implements the following seg6local actions.
- SEG6_LOCAL_ACTION_END: regular SRH processing. The DA of the packet
is updated to the next segment and forwarded accordingly.
- SEG6_LOCAL_ACTION_END_X: same as above, except that the packet is
forwarded to the specified IPv6 next-hop.
- SEG6_LOCAL_ACTION_END_DX6: decapsulate the packet and forward to
inner IPv6 packet to the specified IPv6 next-hop.
- SEG6_LOCAL_ACTION_END_B6: insert the specified SRH directly after
the IPv6 header of the packet.
- SEG6_LOCAL_ACTION_END_B6_ENCAP: encapsulate the packet within
an outer IPv6 header, containing the specified SRH.
Signed-off-by: David Lebrun <david.lebrun@uclouvain.be>
---
net/ipv6/seg6_local.c | 271 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 271 insertions(+)
diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
index ab1fc1b..147680e 100644
--- a/net/ipv6/seg6_local.c
+++ b/net/ipv6/seg6_local.c
@@ -58,11 +58,282 @@ static struct seg6_local_lwt *seg6_local_lwtunnel(struct lwtunnel_state *lwt)
return (struct seg6_local_lwt *)lwt->data;
}
+static struct ipv6_sr_hdr *get_srh(struct sk_buff *skb)
+{
+ struct ipv6_sr_hdr *srh;
+ struct ipv6hdr *hdr;
+ int len;
+
+ hdr = ipv6_hdr(skb);
+ if (hdr->nexthdr != IPPROTO_ROUTING)
+ return NULL;
+
+ srh = (struct ipv6_sr_hdr *)(hdr + 1);
+ len = (srh->hdrlen + 1) << 3;
+
+ if (!pskb_may_pull(skb, sizeof(*hdr) + len))
+ return NULL;
+
+ if (!seg6_validate_srh(srh, len))
+ return NULL;
+
+ return srh;
+}
+
+static struct ipv6_sr_hdr *get_and_validate_srh(struct sk_buff *skb)
+{
+ struct ipv6_sr_hdr *srh;
+
+ srh = get_srh(skb);
+ if (!srh)
+ return NULL;
+
+ if (srh->segments_left == 0)
+ return NULL;
+
+#ifdef CONFIG_IPV6_SEG6_HMAC
+ if (!seg6_hmac_validate_skb(skb))
+ return NULL;
+#endif
+
+ return srh;
+}
+
+/* regular endpoint function */
+static int input_action_end(struct sk_buff *skb, struct seg6_local_lwt *slwt)
+{
+ struct ipv6_sr_hdr *srh;
+ struct in6_addr *addr;
+
+ srh = get_and_validate_srh(skb);
+ if (!srh)
+ goto drop;
+
+ srh->segments_left--;
+ addr = srh->segments + srh->segments_left;
+
+ ipv6_hdr(skb)->daddr = *addr;
+
+ skb_dst_drop(skb);
+ ip6_route_input(skb);
+
+ return dst_input(skb);
+
+drop:
+ kfree_skb(skb);
+ return -EINVAL;
+}
+
+/* regular endpoint, and forward to specified nexthop */
+static int input_action_end_x(struct sk_buff *skb, struct seg6_local_lwt *slwt)
+{
+ struct net *net = dev_net(skb->dev);
+ struct ipv6_sr_hdr *srh;
+ struct dst_entry *dst;
+ struct in6_addr *addr;
+ struct ipv6hdr *hdr;
+ struct flowi6 fl6;
+ int flags;
+
+ srh = get_and_validate_srh(skb);
+ if (!srh)
+ goto drop;
+
+ srh->segments_left--;
+ addr = srh->segments + srh->segments_left;
+
+ hdr = ipv6_hdr(skb);
+ hdr->daddr = *addr;
+
+ skb_dst_drop(skb);
+
+ fl6.flowi6_iif = skb->dev->ifindex;
+ fl6.daddr = slwt->nh6;
+ fl6.saddr = hdr->saddr;
+ fl6.flowlabel = ip6_flowinfo(hdr);
+ fl6.flowi6_mark = skb->mark;
+ fl6.flowi6_proto = hdr->nexthdr;
+
+ flags = RT6_LOOKUP_F_HAS_SADDR | RT6_LOOKUP_F_IFACE |
+ RT6_LOOKUP_F_REACHABLE;
+
+ dst = ip6_route_input_lookup(net, skb->dev, &fl6, flags);
+ if (dst->dev->flags & IFF_LOOPBACK)
+ goto drop;
+
+ skb_dst_set(skb, dst);
+
+ return dst_input(skb);
+
+drop:
+ kfree_skb(skb);
+ return -EINVAL;
+}
+
+/* decapsulate and forward to specified nexthop */
+static int input_action_end_dx6(struct sk_buff *skb,
+ struct seg6_local_lwt *slwt)
+{
+ struct net *net = dev_net(skb->dev);
+ struct ipv6hdr *inner_hdr;
+ struct ipv6_sr_hdr *srh;
+ struct dst_entry *dst;
+ unsigned int off = 0;
+ struct flowi6 fl6;
+ bool use_nh;
+ int flags;
+
+ /* this function accepts IPv6 encapsulated packets, with either
+ * an SRH with SL=0, or no SRH.
+ */
+
+ srh = get_srh(skb);
+ if (srh && srh->segments_left > 0)
+ goto drop;
+
+#ifdef CONFIG_IPV6_SEG6_HMAC
+ if (srh && !seg6_hmac_validate_skb(skb))
+ goto drop;
+#endif
+
+ if (ipv6_find_hdr(skb, &off, IPPROTO_IPV6, NULL, NULL) < 0)
+ goto drop;
+
+ if (!pskb_pull(skb, off))
+ goto drop;
+
+ skb_postpull_rcsum(skb, skb_network_header(skb), off);
+
+ skb_reset_network_header(skb);
+ skb_reset_transport_header(skb);
+ skb->encapsulation = 0;
+
+ inner_hdr = ipv6_hdr(skb);
+
+ /* The inner packet is not associated to any local interface,
+ * so we do not call netif_rx().
+ *
+ * If slwt->nh6 is set to ::, then lookup the nexthop for the
+ * inner packet's DA. Otherwise, use the specified nexthop.
+ */
+
+ use_nh = !ipv6_addr_any(&slwt->nh6);
+
+ skb_dst_drop(skb);
+
+ fl6.flowi6_iif = skb->dev->ifindex;
+ fl6.daddr = use_nh ? slwt->nh6 : inner_hdr->daddr;
+ fl6.saddr = inner_hdr->saddr;
+ fl6.flowlabel = ip6_flowinfo(inner_hdr);
+ fl6.flowi6_mark = skb->mark;
+ fl6.flowi6_proto = inner_hdr->nexthdr;
+
+ flags = RT6_LOOKUP_F_HAS_SADDR | RT6_LOOKUP_F_REACHABLE;
+ if (use_nh)
+ flags |= RT6_LOOKUP_F_IFACE;
+
+ dst = ip6_route_input_lookup(net, skb->dev, &fl6, flags);
+ if (dst->dev->flags & IFF_LOOPBACK)
+ goto drop;
+
+ skb_dst_set(skb, dst);
+
+ return dst_input(skb);
+drop:
+ kfree_skb(skb);
+ return -EINVAL;
+}
+
+/* push an SRH on top of the current one */
+static int input_action_end_b6(struct sk_buff *skb, struct seg6_local_lwt *slwt)
+{
+ struct ipv6_sr_hdr *srh;
+ int err = -EINVAL;
+
+ srh = get_and_validate_srh(skb);
+ if (!srh)
+ goto drop;
+
+ err = seg6_do_srh_inline(skb, slwt->srh);
+ if (err)
+ goto drop;
+
+ ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+ skb_set_transport_header(skb, sizeof(struct ipv6hdr));
+
+ skb_dst_drop(skb);
+ ip6_route_input(skb);
+
+ return dst_input(skb);
+
+drop:
+ kfree_skb(skb);
+ return err;
+}
+
+/* encapsulate within an outer IPv6 header and a specified SRH */
+static int input_action_end_b6_encap(struct sk_buff *skb,
+ struct seg6_local_lwt *slwt)
+{
+ struct ipv6_sr_hdr *srh;
+ struct in6_addr *addr;
+ int err = -EINVAL;
+
+ srh = get_and_validate_srh(skb);
+ if (!srh)
+ goto drop;
+
+ srh->segments_left--;
+ addr = srh->segments + srh->segments_left;
+ ipv6_hdr(skb)->daddr = *addr;
+
+ skb_reset_inner_headers(skb);
+ skb->encapsulation = 1;
+
+ err = seg6_do_srh_encap(skb, slwt->srh);
+ if (err)
+ goto drop;
+
+ ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+ skb_set_transport_header(skb, sizeof(struct ipv6hdr));
+
+ skb_dst_drop(skb);
+ ip6_route_input(skb);
+
+ return dst_input(skb);
+
+drop:
+ kfree_skb(skb);
+ return err;
+}
+
static struct seg6_action_desc seg6_action_table[] = {
{
.action = SEG6_LOCAL_ACTION_END,
.attrs = 0,
+ .input = input_action_end,
+ },
+ {
+ .action = SEG6_LOCAL_ACTION_END_X,
+ .attrs = (1 << SEG6_LOCAL_NH6),
+ .input = input_action_end_x,
},
+ {
+ .action = SEG6_LOCAL_ACTION_END_DX6,
+ .attrs = (1 << SEG6_LOCAL_NH6),
+ .input = input_action_end_dx6,
+ },
+ {
+ .action = SEG6_LOCAL_ACTION_END_B6,
+ .attrs = (1 << SEG6_LOCAL_SRH),
+ .input = input_action_end_b6,
+ },
+ {
+ .action = SEG6_LOCAL_ACTION_END_B6_ENCAP,
+ .attrs = (1 << SEG6_LOCAL_SRH),
+ .input = input_action_end_b6_encap,
+ .static_headroom = sizeof(struct ipv6hdr),
+ }
};
static struct seg6_action_desc *__get_action_desc(int action)
--
2.10.2
^ permalink raw reply related
* RE: [PATCH] PCI: Update ACS quirk for more Intel 10G NICs
From: David Laight @ 2017-08-04 13:28 UTC (permalink / raw)
To: 'Bjorn Helgaas', Roland Dreier
Cc: Bjorn Helgaas, linux-pci@vger.kernel.org, netdev@vger.kernel.org,
Emil Tantilov
In-Reply-To: <20170803214911.GG20308@bhelgaas-glaptop.roam.corp.google.com>
From: Bjorn Helgaas
> Sent: 03 August 2017 22:49
> On Thu, Jul 20, 2017 at 02:41:01PM -0700, Roland Dreier wrote:
> > From: Roland Dreier <roland@purestorage.com>
> >
> > Add one more variant of the 82599 plus the device IDs for X540 and X550
> > variants. Intel has confirmed that none of these devices does peer-to-peer
> > between functions. The X540 and X550 have added ACS capabilities in their
> > PCI config space, but the ACS control register is hard-wired to 0 for both
> > devices, so we still need the quirk for IOMMU grouping to allow assignment
> > of individual SR-IOV functions.
...
> > --- a/drivers/pci/quirks.c
> > +++ b/drivers/pci/quirks.c
> > @@ -4335,12 +4335,33 @@ static const struct pci_dev_acs_enabled {
> > { PCI_VENDOR_ID_INTEL, 0x1507, pci_quirk_mf_endpoint_acs },
> > { PCI_VENDOR_ID_INTEL, 0x1514, pci_quirk_mf_endpoint_acs },
> > { PCI_VENDOR_ID_INTEL, 0x151C, pci_quirk_mf_endpoint_acs },
> > + { PCI_VENDOR_ID_INTEL, 0x1528, pci_quirk_mf_endpoint_acs },
> > { PCI_VENDOR_ID_INTEL, 0x1529, pci_quirk_mf_endpoint_acs },
> > + { PCI_VENDOR_ID_INTEL, 0x154A, pci_quirk_mf_endpoint_acs },
...
That list is looking a bit long.
Is it possible to run-time determine that the ACS control register is hard wired
to zero, and apply the quirk to all such devices.
Or even changing to a (device & mask) == value test??
David
^ permalink raw reply
* Re: [PATCH] net: Reduce skb_warn_bad_offload() noise.
From: Eric Dumazet @ 2017-08-04 13:29 UTC (permalink / raw)
To: Tonghao Zhang; +Cc: netdev, Eric Dumazet, Willem de Bruijn, Pravin B Shelar
In-Reply-To: <1501852317-11684-1-git-send-email-xiangxia.m.yue@gmail.com>
On Fri, 2017-08-04 at 06:11 -0700, Tonghao Zhang wrote:
> This patch will revert the b2504a5dbe "net: reduce
> skb_warn_bad_offload() noise". The ovs will call the
> __skb_gso_segment() with tx false. When segmenting UDP with UFO,
> the __skb_gso_segment raises a warning as below [1], because the
> ip_summed is CHECKSUM_NONE. While the net-next has removed the
> UFO support, but the 4.11 and 4.12 kernel don't address that problem.
>
> In the kernel, only qdisc_pkt_len_init() (__dev_queue_xmit call it.)
> uses the SKB_GSO_DODGY to do something. Other places just set it.
> The warn described in b2504a5dbe is shown [2]. We may know that:
> 1. the net_device don’t have qdisc.
> 2. the skb->ip_summed was changed to CHECKSUM_NONE. it maybe
> changed in skb_checksum_help() when calling validate_xmit_skb().
> or other place.
>
> And we should not revert the 6e7bc478c9 "net: skb_needs_check() accepts
> CHECKSUM_NONE for tx". The check is necessary.
Why is it necessary ?
If you revert b2504a5dbe, then we also need to revert 6e7bc478c9,
unless you provide hard facts.
>
> [1]
> [321428.168903] WARNING: CPU: 0 PID: 2279 at net/core/dev.c:2562
> skb_warn_bad_offload+0xc4/0x110
> [321428.168906] san0: caps=(0x000004009fbb58e9, 0x0000000000000000) len=6769
> data_len=6727 gso_size=1480 gso_type=2 ip_summed=0
>
> [321428.168955] CPU: 0 PID: 2279 Comm: ruby-mri 4.11.12-200.fc25.x86_64 #1
> [321428.168956] Hardware name: Supermicro SYS-1028U-TNRTP+/X10DRU-i+, BIOS 1.1 07/22/2015
> [321428.168957] Call Trace:
> [321428.168962] dump_stack+0x63/0x86
> [321428.168965] __warn+0xcb/0xf0
> [321428.168966] warn_slowpath_fmt+0x5a/0x80
> [321428.168968] skb_warn_bad_offload+0xc4/0x110
> [321428.168970] __skb_gso_segment+0x190/0x1a0
> [321428.168977] queue_gso_packets+0x62/0x160 [openvswitch]
> [321428.168992] ovs_dp_upcall+0x31/0x60 [openvswitch]
> [321428.168994] ovs_dp_process_packet+0x10d/0x130 [openvswitch]
> [321428.168997] ovs_vport_receive+0x76/0xd0 [openvswitch]
> [321428.169013] internal_dev_xmit+0x28/0x60 [openvswitch]
> [321428.169014] dev_hard_start_xmit+0xa3/0x1f0
> [321428.169016] __dev_queue_xmit+0x592/0x650
> [321428.169026] dev_queue_xmit+0x10/0x20
>
> [2]
> WARNING: CPU: 1 PID: 6768 at net/core/dev.c:2439 skb_warn_bad_offload+0x2af/0x390 net/core/dev.c:2434
> lo: caps=(0x000000a2803b7c69, 0x0000000000000000) len=138 data_len=0 gso_size=15883 gso_type=4 ip_summed=0
> Kernel panic - not syncing: panic_on_warn set ...
>
> CPU: 1 PID: 6768 Comm: syz-executor1 Not tainted 4.9.0 #5
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
> ffff8801c063ecd8 ffffffff82346bdf ffffffff00000001 1ffff100380c7d2e
> ffffed00380c7d26 0000000041b58ab3 ffffffff84b37e38 ffffffff823468f1
> ffffffff84820740 ffffffff84f289c0 dffffc0000000000 ffff8801c063ee20
> Call Trace:
Why are you adding this trace that was part of the b2504a5dbef3
changelog ?
> [<ffffffff82346bdf>] __dump_stack lib/dump_stack.c:15 [inline]
> [<ffffffff82346bdf>] dump_stack+0x2ee/0x3ef lib/dump_stack.c:51
> [<ffffffff81827e34>] panic+0x1fb/0x412 kernel/panic.c:179
> [<ffffffff8141f704>] __warn+0x1c4/0x1e0 kernel/panic.c:542
> [<ffffffff8141f7e5>] warn_slowpath_fmt+0xc5/0x100 kernel/panic.c:565
> [<ffffffff8356cbaf>] skb_warn_bad_offload+0x2af/0x390 net/core/dev.c:2434
> [<ffffffff83585cd2>] __skb_gso_segment+0x482/0x780 net/core/dev.c:2706
> [<ffffffff83586f19>] skb_gso_segment include/linux/netdevice.h:3985 [inline]
> [<ffffffff83586f19>] validate_xmit_skb+0x5c9/0xc20 net/core/dev.c:2969
> [<ffffffff835892bb>] __dev_queue_xmit+0xe6b/0x1e70 net/core/dev.c:3383
> [<ffffffff8358a2d7>] dev_queue_xmit+0x17/0x20 net/core/dev.c:3424
>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Willem de Bruijn <willemb@google.com>
> Cc: Pravin B Shelar <pshelar@ovn.org>
> Signed-off-by: Tonghao Zhang <xiangxia.m.yue@gmail.com>
> ---
IMO, this description is too confusing, I do not understand this patch.
^ permalink raw reply
* Re: [PATCH net 1/2] bpf, s390: fix jit branch offset related to ldimm64
From: Michael Holzheu @ 2017-08-04 13:44 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: davem, ast, netdev
In-Reply-To: <a63b808ceaa481dfae896bcf611fc489fdc59080.1501848914.git.daniel@iogearbox.net>
Am Fri, 4 Aug 2017 14:20:54 +0200
schrieb Daniel Borkmann <daniel@iogearbox.net>:
> While testing some other work that required JIT modifications, I
> run into test_bpf causing a hang when JIT enabled on s390. The
> problematic test case was the one from ddc665a4bb4b (bpf, arm64:
> fix jit branch offset related to ldimm64), and turns out that we
> do have a similar issue on s390 as well. In bpf_jit_prog() we
> update next instruction address after returning from bpf_jit_insn()
> with an insn_count. bpf_jit_insn() returns either -1 in case of
> error (e.g. unsupported insn), 1 or 2. The latter is only the
> case for ldimm64 due to spanning 2 insns, however, next address
> is only set to i + 1 not taking actual insn_count into account,
> thus fix is to use insn_count instead of 1. bpf_jit_enable in
> mode 2 provides also disasm on s390:
>
> Before fix:
>
> 000003ff800349b6: a7f40003 brc 15,3ff800349bc ; target
> 000003ff800349ba: 0000 unknown
> 000003ff800349bc: e3b0f0700024 stg %r11,112(%r15)
> 000003ff800349c2: e3e0f0880024 stg %r14,136(%r15)
> 000003ff800349c8: 0db0 basr %r11,%r0
> 000003ff800349ca: c0ef00000000 llilf %r14,0
> 000003ff800349d0: e320b0360004 lg %r2,54(%r11)
> 000003ff800349d6: e330b03e0004 lg %r3,62(%r11)
> 000003ff800349dc: ec23ffeda065 clgrj %r2,%r3,10,3ff800349b6 ; jmp
> 000003ff800349e2: e3e0b0460004 lg %r14,70(%r11)
> 000003ff800349e8: e3e0b04e0004 lg %r14,78(%r11)
> 000003ff800349ee: b904002e lgr %r2,%r14
> 000003ff800349f2: e3b0f0700004 lg %r11,112(%r15)
> 000003ff800349f8: e3e0f0880004 lg %r14,136(%r15)
> 000003ff800349fe: 07fe bcr 15,%r14
>
> After fix:
>
> 000003ff80ef3db4: a7f40003 brc 15,3ff80ef3dba
> 000003ff80ef3db8: 0000 unknown
> 000003ff80ef3dba: e3b0f0700024 stg %r11,112(%r15)
> 000003ff80ef3dc0: e3e0f0880024 stg %r14,136(%r15)
> 000003ff80ef3dc6: 0db0 basr %r11,%r0
> 000003ff80ef3dc8: c0ef00000000 llilf %r14,0
> 000003ff80ef3dce: e320b0360004 lg %r2,54(%r11)
> 000003ff80ef3dd4: e330b03e0004 lg %r3,62(%r11)
> 000003ff80ef3dda: ec230006a065 clgrj %r2,%r3,10,3ff80ef3de6 ; jmp
> 000003ff80ef3de0: e3e0b0460004 lg %r14,70(%r11)
> 000003ff80ef3de6: e3e0b04e0004 lg %r14,78(%r11) ; target
> 000003ff80ef3dec: b904002e lgr %r2,%r14
> 000003ff80ef3df0: e3b0f0700004 lg %r11,112(%r15)
> 000003ff80ef3df6: e3e0f0880004 lg %r14,136(%r15)
> 000003ff80ef3dfc: 07fe bcr 15,%r14
>
> test_bpf.ko suite runs fine after the fix.
>
> Fixes: 054623105728 ("s390/bpf: Add s390x eBPF JIT compiler backend")
> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
> Tested-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
What about "Cc: stable@vger.kernel.org"?
Michael
^ permalink raw reply
* Re: [PATCH iproute2] netns: make /var/run/netns bind-mount recursive
From: Eric W. Biederman @ 2017-08-04 13:41 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: Casey Callendrello, netdev
In-Reply-To: <20170803160421.58eb0a4a@xeon-e3>
Stephen Hemminger <stephen@networkplumber.org> writes:
> On Tue, 1 Aug 2017 17:46:09 +0200
> Casey Callendrello <casey.callendrello@coreos.com> wrote:
>
>> When ip netns {add|delete} is first run, it bind-mounts /var/run/netns
>> on top of itself, then marks it as shared. However, if there are already
>> bind-mounts in the directory from other tools, these would not be
>> propagated. Fix this by recursively bind-mounting.
>>
>> Signed-off-by: Casey Callendrello <casey.callendrello@coreos.com>
>> ---
>> ip/ipnetns.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>
> Looks good, but I want a review by Eric to make sure this doesn't
> break other things.
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
I don't see any possible problems with this. This will just keep all of
the mounts showing up.
It would be really nice if we could at some point detect that a parent
directory is shared (which happens with a common init system) and skip
the steps of the bind mount and making them shared as they are
redundant. However while that might also solve this issue that is
something for another day.
Eric
^ permalink raw reply
* Re: [PATCH net 1/2] bpf, s390: fix jit branch offset related to ldimm64
From: Daniel Borkmann @ 2017-08-04 13:52 UTC (permalink / raw)
To: Michael Holzheu; +Cc: davem, ast, netdev
In-Reply-To: <20170804154420.6faae20a@TP-holzheu>
On 08/04/2017 03:44 PM, Michael Holzheu wrote:
> Am Fri, 4 Aug 2017 14:20:54 +0200
> schrieb Daniel Borkmann <daniel@iogearbox.net>:
[...]
>
> What about "Cc: stable@vger.kernel.org"?
Handled by Dave, see also: Documentation/networking/netdev-FAQ.txt +117
Cheers,
Daniel
^ 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