aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-05-10 23:50:16 -0400
committerDavid S. Miller <davem@davemloft.net>2016-05-10 23:50:16 -0400
commit6e14313f01f02f324d5dd68a49d34ec1e4bb569e (patch)
tree9df50855210ff3adbf60291dfba1ea284370d9e0 /net
parent84a527a41f38a80353f185d05e41b021e1ff672b (diff)
parent4e8c861550105f7aaa85a19b2571151cb8eceaa2 (diff)
Merge branch 'net-sched-fixes'
Jamal Hadi Salim says: ==================== Some actions were broken in allowing for late binding of actions. Late binding workflow is as follows: a) create an action and provide all necessary parameters for it Optionally provide an index or let the kernel give you one. Example: sudo tc actions add action police rate 1kbit burst 90k drop index 1 b) later on bind to the pre-created action from a filter definition by merely specifying the index. Example: sudo tc filter add dev lo parent ffff: protocol ip prio 8 \ u32 match ip src 127.0.0.8/32 flowid 1:8 action police index 1 ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/sched/act_ife.c14
-rw-r--r--net/sched/act_ipt.c19
-rw-r--r--net/sched/act_mirred.c19
-rw-r--r--net/sched/act_simple.c18
-rw-r--r--net/sched/act_skbedit.c18
-rw-r--r--net/sched/act_vlan.c22
6 files changed, 74 insertions, 36 deletions
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index c589a9ba506a..343d011aa818 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -423,7 +423,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
423 u16 ife_type = 0; 423 u16 ife_type = 0;
424 u8 *daddr = NULL; 424 u8 *daddr = NULL;
425 u8 *saddr = NULL; 425 u8 *saddr = NULL;
426 int ret = 0; 426 int ret = 0, exists = 0;
427 int err; 427 int err;
428 428
429 err = nla_parse_nested(tb, TCA_IFE_MAX, nla, ife_policy); 429 err = nla_parse_nested(tb, TCA_IFE_MAX, nla, ife_policy);
@@ -435,25 +435,29 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
435 435
436 parm = nla_data(tb[TCA_IFE_PARMS]); 436 parm = nla_data(tb[TCA_IFE_PARMS]);
437 437
438 exists = tcf_hash_check(tn, parm->index, a, bind);
439 if (exists && bind)
440 return 0;
441
438 if (parm->flags & IFE_ENCODE) { 442 if (parm->flags & IFE_ENCODE) {
439 /* Until we get issued the ethertype, we cant have 443 /* Until we get issued the ethertype, we cant have
440 * a default.. 444 * a default..
441 **/ 445 **/
442 if (!tb[TCA_IFE_TYPE]) { 446 if (!tb[TCA_IFE_TYPE]) {
447 if (exists)
448 tcf_hash_release(a, bind);
443 pr_info("You MUST pass etherype for encoding\n"); 449 pr_info("You MUST pass etherype for encoding\n");
444 return -EINVAL; 450 return -EINVAL;
445 } 451 }
446 } 452 }
447 453
448 if (!tcf_hash_check(tn, parm->index, a, bind)) { 454 if (!exists) {
449 ret = tcf_hash_create(tn, parm->index, est, a, sizeof(*ife), 455 ret = tcf_hash_create(tn, parm->index, est, a, sizeof(*ife),
450 bind, false); 456 bind, false);
451 if (ret) 457 if (ret)
452 return ret; 458 return ret;
453 ret = ACT_P_CREATED; 459 ret = ACT_P_CREATED;
454 } else { 460 } else {
455 if (bind) /* dont override defaults */
456 return 0;
457 tcf_hash_release(a, bind); 461 tcf_hash_release(a, bind);
458 if (!ovr) 462 if (!ovr)
459 return -EEXIST; 463 return -EEXIST;
@@ -495,6 +499,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
495 NULL); 499 NULL);
496 if (err) { 500 if (err) {
497metadata_parse_err: 501metadata_parse_err:
502 if (exists)
503 tcf_hash_release(a, bind);
498 if (ret == ACT_P_CREATED) 504 if (ret == ACT_P_CREATED)
499 _tcf_ife_cleanup(a, bind); 505 _tcf_ife_cleanup(a, bind);
500 506
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 350e134cffb3..8b5270008a6e 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -96,7 +96,7 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
96 struct tcf_ipt *ipt; 96 struct tcf_ipt *ipt;
97 struct xt_entry_target *td, *t; 97 struct xt_entry_target *td, *t;
98 char *tname; 98 char *tname;
99 int ret = 0, err; 99 int ret = 0, err, exists = 0;
100 u32 hook = 0; 100 u32 hook = 0;
101 u32 index = 0; 101 u32 index = 0;
102 102
@@ -107,18 +107,23 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
107 if (err < 0) 107 if (err < 0)
108 return err; 108 return err;
109 109
110 if (tb[TCA_IPT_HOOK] == NULL) 110 if (tb[TCA_IPT_INDEX] != NULL)
111 return -EINVAL; 111 index = nla_get_u32(tb[TCA_IPT_INDEX]);
112 if (tb[TCA_IPT_TARG] == NULL) 112
113 exists = tcf_hash_check(tn, index, a, bind);
114 if (exists && bind)
115 return 0;
116
117 if (tb[TCA_IPT_HOOK] == NULL || tb[TCA_IPT_TARG] == NULL) {
118 if (exists)
119 tcf_hash_release(a, bind);
113 return -EINVAL; 120 return -EINVAL;
121 }
114 122
115 td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]); 123 td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]);
116 if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size) 124 if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size)
117 return -EINVAL; 125 return -EINVAL;
118 126
119 if (tb[TCA_IPT_INDEX] != NULL)
120 index = nla_get_u32(tb[TCA_IPT_INDEX]);
121
122 if (!tcf_hash_check(tn, index, a, bind)) { 127 if (!tcf_hash_check(tn, index, a, bind)) {
123 ret = tcf_hash_create(tn, index, est, a, sizeof(*ipt), bind, 128 ret = tcf_hash_create(tn, index, est, a, sizeof(*ipt), bind,
124 false); 129 false);
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index e8a760cf7775..8f3948dd38b8 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -61,7 +61,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
61 struct tc_mirred *parm; 61 struct tc_mirred *parm;
62 struct tcf_mirred *m; 62 struct tcf_mirred *m;
63 struct net_device *dev; 63 struct net_device *dev;
64 int ret, ok_push = 0; 64 int ret, ok_push = 0, exists = 0;
65 65
66 if (nla == NULL) 66 if (nla == NULL)
67 return -EINVAL; 67 return -EINVAL;
@@ -71,17 +71,27 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
71 if (tb[TCA_MIRRED_PARMS] == NULL) 71 if (tb[TCA_MIRRED_PARMS] == NULL)
72 return -EINVAL; 72 return -EINVAL;
73 parm = nla_data(tb[TCA_MIRRED_PARMS]); 73 parm = nla_data(tb[TCA_MIRRED_PARMS]);
74
75 exists = tcf_hash_check(tn, parm->index, a, bind);
76 if (exists && bind)
77 return 0;
78
74 switch (parm->eaction) { 79 switch (parm->eaction) {
75 case TCA_EGRESS_MIRROR: 80 case TCA_EGRESS_MIRROR:
76 case TCA_EGRESS_REDIR: 81 case TCA_EGRESS_REDIR:
77 break; 82 break;
78 default: 83 default:
84 if (exists)
85 tcf_hash_release(a, bind);
79 return -EINVAL; 86 return -EINVAL;
80 } 87 }
81 if (parm->ifindex) { 88 if (parm->ifindex) {
82 dev = __dev_get_by_index(net, parm->ifindex); 89 dev = __dev_get_by_index(net, parm->ifindex);
83 if (dev == NULL) 90 if (dev == NULL) {
91 if (exists)
92 tcf_hash_release(a, bind);
84 return -ENODEV; 93 return -ENODEV;
94 }
85 switch (dev->type) { 95 switch (dev->type) {
86 case ARPHRD_TUNNEL: 96 case ARPHRD_TUNNEL:
87 case ARPHRD_TUNNEL6: 97 case ARPHRD_TUNNEL6:
@@ -99,7 +109,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
99 dev = NULL; 109 dev = NULL;
100 } 110 }
101 111
102 if (!tcf_hash_check(tn, parm->index, a, bind)) { 112 if (!exists) {
103 if (dev == NULL) 113 if (dev == NULL)
104 return -EINVAL; 114 return -EINVAL;
105 ret = tcf_hash_create(tn, parm->index, est, a, 115 ret = tcf_hash_create(tn, parm->index, est, a,
@@ -108,9 +118,6 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
108 return ret; 118 return ret;
109 ret = ACT_P_CREATED; 119 ret = ACT_P_CREATED;
110 } else { 120 } else {
111 if (bind)
112 return 0;
113
114 tcf_hash_release(a, bind); 121 tcf_hash_release(a, bind);
115 if (!ovr) 122 if (!ovr)
116 return -EEXIST; 123 return -EEXIST;
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index 75b2be13fbcc..3a33fb648a6d 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -87,7 +87,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
87 struct tc_defact *parm; 87 struct tc_defact *parm;
88 struct tcf_defact *d; 88 struct tcf_defact *d;
89 char *defdata; 89 char *defdata;
90 int ret = 0, err; 90 int ret = 0, err, exists = 0;
91 91
92 if (nla == NULL) 92 if (nla == NULL)
93 return -EINVAL; 93 return -EINVAL;
@@ -99,13 +99,21 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
99 if (tb[TCA_DEF_PARMS] == NULL) 99 if (tb[TCA_DEF_PARMS] == NULL)
100 return -EINVAL; 100 return -EINVAL;
101 101
102 if (tb[TCA_DEF_DATA] == NULL)
103 return -EINVAL;
104 102
105 parm = nla_data(tb[TCA_DEF_PARMS]); 103 parm = nla_data(tb[TCA_DEF_PARMS]);
104 exists = tcf_hash_check(tn, parm->index, a, bind);
105 if (exists && bind)
106 return 0;
107
108 if (tb[TCA_DEF_DATA] == NULL) {
109 if (exists)
110 tcf_hash_release(a, bind);
111 return -EINVAL;
112 }
113
106 defdata = nla_data(tb[TCA_DEF_DATA]); 114 defdata = nla_data(tb[TCA_DEF_DATA]);
107 115
108 if (!tcf_hash_check(tn, parm->index, a, bind)) { 116 if (!exists) {
109 ret = tcf_hash_create(tn, parm->index, est, a, 117 ret = tcf_hash_create(tn, parm->index, est, a,
110 sizeof(*d), bind, false); 118 sizeof(*d), bind, false);
111 if (ret) 119 if (ret)
@@ -122,8 +130,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
122 } else { 130 } else {
123 d = to_defact(a); 131 d = to_defact(a);
124 132
125 if (bind)
126 return 0;
127 tcf_hash_release(a, bind); 133 tcf_hash_release(a, bind);
128 if (!ovr) 134 if (!ovr)
129 return -EEXIST; 135 return -EEXIST;
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index cfcdbdc00c9b..69da5a8f0034 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -69,7 +69,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
69 struct tcf_skbedit *d; 69 struct tcf_skbedit *d;
70 u32 flags = 0, *priority = NULL, *mark = NULL; 70 u32 flags = 0, *priority = NULL, *mark = NULL;
71 u16 *queue_mapping = NULL; 71 u16 *queue_mapping = NULL;
72 int ret = 0, err; 72 int ret = 0, err, exists = 0;
73 73
74 if (nla == NULL) 74 if (nla == NULL)
75 return -EINVAL; 75 return -EINVAL;
@@ -96,12 +96,18 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
96 mark = nla_data(tb[TCA_SKBEDIT_MARK]); 96 mark = nla_data(tb[TCA_SKBEDIT_MARK]);
97 } 97 }
98 98
99 if (!flags)
100 return -EINVAL;
101
102 parm = nla_data(tb[TCA_SKBEDIT_PARMS]); 99 parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
103 100
104 if (!tcf_hash_check(tn, parm->index, a, bind)) { 101 exists = tcf_hash_check(tn, parm->index, a, bind);
102 if (exists && bind)
103 return 0;
104
105 if (!flags) {
106 tcf_hash_release(a, bind);
107 return -EINVAL;
108 }
109
110 if (!exists) {
105 ret = tcf_hash_create(tn, parm->index, est, a, 111 ret = tcf_hash_create(tn, parm->index, est, a,
106 sizeof(*d), bind, false); 112 sizeof(*d), bind, false);
107 if (ret) 113 if (ret)
@@ -111,8 +117,6 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
111 ret = ACT_P_CREATED; 117 ret = ACT_P_CREATED;
112 } else { 118 } else {
113 d = to_skbedit(a); 119 d = to_skbedit(a);
114 if (bind)
115 return 0;
116 tcf_hash_release(a, bind); 120 tcf_hash_release(a, bind);
117 if (!ovr) 121 if (!ovr)
118 return -EEXIST; 122 return -EEXIST;
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
index bab8ae0cefc0..c45f926dafb9 100644
--- a/net/sched/act_vlan.c
+++ b/net/sched/act_vlan.c
@@ -77,7 +77,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
77 int action; 77 int action;
78 __be16 push_vid = 0; 78 __be16 push_vid = 0;
79 __be16 push_proto = 0; 79 __be16 push_proto = 0;
80 int ret = 0; 80 int ret = 0, exists = 0;
81 int err; 81 int err;
82 82
83 if (!nla) 83 if (!nla)
@@ -90,15 +90,25 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
90 if (!tb[TCA_VLAN_PARMS]) 90 if (!tb[TCA_VLAN_PARMS])
91 return -EINVAL; 91 return -EINVAL;
92 parm = nla_data(tb[TCA_VLAN_PARMS]); 92 parm = nla_data(tb[TCA_VLAN_PARMS]);
93 exists = tcf_hash_check(tn, parm->index, a, bind);
94 if (exists && bind)
95 return 0;
96
93 switch (parm->v_action) { 97 switch (parm->v_action) {
94 case TCA_VLAN_ACT_POP: 98 case TCA_VLAN_ACT_POP:
95 break; 99 break;
96 case TCA_VLAN_ACT_PUSH: 100 case TCA_VLAN_ACT_PUSH:
97 if (!tb[TCA_VLAN_PUSH_VLAN_ID]) 101 if (!tb[TCA_VLAN_PUSH_VLAN_ID]) {
102 if (exists)
103 tcf_hash_release(a, bind);
98 return -EINVAL; 104 return -EINVAL;
105 }
99 push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]); 106 push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
100 if (push_vid >= VLAN_VID_MASK) 107 if (push_vid >= VLAN_VID_MASK) {
108 if (exists)
109 tcf_hash_release(a, bind);
101 return -ERANGE; 110 return -ERANGE;
111 }
102 112
103 if (tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]) { 113 if (tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]) {
104 push_proto = nla_get_be16(tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]); 114 push_proto = nla_get_be16(tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]);
@@ -114,11 +124,13 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
114 } 124 }
115 break; 125 break;
116 default: 126 default:
127 if (exists)
128 tcf_hash_release(a, bind);
117 return -EINVAL; 129 return -EINVAL;
118 } 130 }
119 action = parm->v_action; 131 action = parm->v_action;
120 132
121 if (!tcf_hash_check(tn, parm->index, a, bind)) { 133 if (!exists) {
122 ret = tcf_hash_create(tn, parm->index, est, a, 134 ret = tcf_hash_create(tn, parm->index, est, a,
123 sizeof(*v), bind, false); 135 sizeof(*v), bind, false);
124 if (ret) 136 if (ret)
@@ -126,8 +138,6 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
126 138
127 ret = ACT_P_CREATED; 139 ret = ACT_P_CREATED;
128 } else { 140 } else {
129 if (bind)
130 return 0;
131 tcf_hash_release(a, bind); 141 tcf_hash_release(a, bind);
132 if (!ovr) 142 if (!ovr)
133 return -EEXIST; 143 return -EEXIST;