act_vlan.c (a30461080366214b690a367225a48c95d7a6a189) act_vlan.c (764e9a24480f6ffba5493fb21e6a7b030d6b8b67)
1/*
2 * Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 */

--- 95 unchanged lines hidden (view full) ---

104
105static int tcf_vlan_init(struct net *net, struct nlattr *nla,
106 struct nlattr *est, struct tc_action **a,
107 int ovr, int bind, bool rtnl_held,
108 struct netlink_ext_ack *extack)
109{
110 struct tc_action_net *tn = net_generic(net, vlan_net_id);
111 struct nlattr *tb[TCA_VLAN_MAX + 1];
1/*
2 * Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 */

--- 95 unchanged lines hidden (view full) ---

104
105static int tcf_vlan_init(struct net *net, struct nlattr *nla,
106 struct nlattr *est, struct tc_action **a,
107 int ovr, int bind, bool rtnl_held,
108 struct netlink_ext_ack *extack)
109{
110 struct tc_action_net *tn = net_generic(net, vlan_net_id);
111 struct nlattr *tb[TCA_VLAN_MAX + 1];
112 struct tcf_vlan_params *p, *p_old;
112 struct tcf_vlan_params *p;
113 struct tc_vlan *parm;
114 struct tcf_vlan *v;
115 int action;
116 u16 push_vid = 0;
117 __be16 push_proto = 0;
118 u8 push_prio = 0;
119 bool exists = false;
120 int ret = 0, err;

--- 76 unchanged lines hidden (view full) ---

197 ret = ACT_P_CREATED;
198 } else if (!ovr) {
199 tcf_idr_release(*a, bind);
200 return -EEXIST;
201 }
202
203 v = to_vlan(*a);
204
113 struct tc_vlan *parm;
114 struct tcf_vlan *v;
115 int action;
116 u16 push_vid = 0;
117 __be16 push_proto = 0;
118 u8 push_prio = 0;
119 bool exists = false;
120 int ret = 0, err;

--- 76 unchanged lines hidden (view full) ---

197 ret = ACT_P_CREATED;
198 } else if (!ovr) {
199 tcf_idr_release(*a, bind);
200 return -EEXIST;
201 }
202
203 v = to_vlan(*a);
204
205 ASSERT_RTNL();
206 p = kzalloc(sizeof(*p), GFP_KERNEL);
207 if (!p) {
208 tcf_idr_release(*a, bind);
209 return -ENOMEM;
210 }
211
205 p = kzalloc(sizeof(*p), GFP_KERNEL);
206 if (!p) {
207 tcf_idr_release(*a, bind);
208 return -ENOMEM;
209 }
210
212 v->tcf_action = parm->action;
213
214 p_old = rtnl_dereference(v->vlan_p);
215
216 p->tcfv_action = action;
217 p->tcfv_push_vid = push_vid;
218 p->tcfv_push_prio = push_prio;
219 p->tcfv_push_proto = push_proto;
220
211 p->tcfv_action = action;
212 p->tcfv_push_vid = push_vid;
213 p->tcfv_push_prio = push_prio;
214 p->tcfv_push_proto = push_proto;
215
221 rcu_assign_pointer(v->vlan_p, p);
216 spin_lock(&v->tcf_lock);
217 v->tcf_action = parm->action;
218 rcu_swap_protected(v->vlan_p, p, lockdep_is_held(&v->tcf_lock));
219 spin_unlock(&v->tcf_lock);
222
220
223 if (p_old)
224 kfree_rcu(p_old, rcu);
221 if (p)
222 kfree_rcu(p, rcu);
225
226 if (ret == ACT_P_CREATED)
227 tcf_idr_insert(tn, *a);
228 return ret;
229}
230
231static void tcf_vlan_cleanup(struct tc_action *a)
232{

--- 5 unchanged lines hidden (view full) ---

238 kfree_rcu(p, rcu);
239}
240
241static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a,
242 int bind, int ref)
243{
244 unsigned char *b = skb_tail_pointer(skb);
245 struct tcf_vlan *v = to_vlan(a);
223
224 if (ret == ACT_P_CREATED)
225 tcf_idr_insert(tn, *a);
226 return ret;
227}
228
229static void tcf_vlan_cleanup(struct tc_action *a)
230{

--- 5 unchanged lines hidden (view full) ---

236 kfree_rcu(p, rcu);
237}
238
239static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a,
240 int bind, int ref)
241{
242 unsigned char *b = skb_tail_pointer(skb);
243 struct tcf_vlan *v = to_vlan(a);
246 struct tcf_vlan_params *p = rtnl_dereference(v->vlan_p);
244 struct tcf_vlan_params *p;
247 struct tc_vlan opt = {
248 .index = v->tcf_index,
249 .refcnt = refcount_read(&v->tcf_refcnt) - ref,
250 .bindcnt = atomic_read(&v->tcf_bindcnt) - bind,
245 struct tc_vlan opt = {
246 .index = v->tcf_index,
247 .refcnt = refcount_read(&v->tcf_refcnt) - ref,
248 .bindcnt = atomic_read(&v->tcf_bindcnt) - bind,
251 .action = v->tcf_action,
252 .v_action = p->tcfv_action,
253 };
254 struct tcf_t t;
255
249 };
250 struct tcf_t t;
251
252 spin_lock(&v->tcf_lock);
253 opt.action = v->tcf_action;
254 p = rcu_dereference_protected(v->vlan_p, lockdep_is_held(&v->tcf_lock));
255 opt.v_action = p->tcfv_action;
256 if (nla_put(skb, TCA_VLAN_PARMS, sizeof(opt), &opt))
257 goto nla_put_failure;
258
259 if ((p->tcfv_action == TCA_VLAN_ACT_PUSH ||
260 p->tcfv_action == TCA_VLAN_ACT_MODIFY) &&
261 (nla_put_u16(skb, TCA_VLAN_PUSH_VLAN_ID, p->tcfv_push_vid) ||
262 nla_put_be16(skb, TCA_VLAN_PUSH_VLAN_PROTOCOL,
263 p->tcfv_push_proto) ||
264 (nla_put_u8(skb, TCA_VLAN_PUSH_VLAN_PRIORITY,
265 p->tcfv_push_prio))))
266 goto nla_put_failure;
267
268 tcf_tm_dump(&t, &v->tcf_tm);
269 if (nla_put_64bit(skb, TCA_VLAN_TM, sizeof(t), &t, TCA_VLAN_PAD))
270 goto nla_put_failure;
256 if (nla_put(skb, TCA_VLAN_PARMS, sizeof(opt), &opt))
257 goto nla_put_failure;
258
259 if ((p->tcfv_action == TCA_VLAN_ACT_PUSH ||
260 p->tcfv_action == TCA_VLAN_ACT_MODIFY) &&
261 (nla_put_u16(skb, TCA_VLAN_PUSH_VLAN_ID, p->tcfv_push_vid) ||
262 nla_put_be16(skb, TCA_VLAN_PUSH_VLAN_PROTOCOL,
263 p->tcfv_push_proto) ||
264 (nla_put_u8(skb, TCA_VLAN_PUSH_VLAN_PRIORITY,
265 p->tcfv_push_prio))))
266 goto nla_put_failure;
267
268 tcf_tm_dump(&t, &v->tcf_tm);
269 if (nla_put_64bit(skb, TCA_VLAN_TM, sizeof(t), &t, TCA_VLAN_PAD))
270 goto nla_put_failure;
271 spin_unlock(&v->tcf_lock);
272
271 return skb->len;
272
273nla_put_failure:
273 return skb->len;
274
275nla_put_failure:
276 spin_unlock(&v->tcf_lock);
274 nlmsg_trim(skb, b);
275 return -1;
276}
277
278static int tcf_vlan_walker(struct net *net, struct sk_buff *skb,
279 struct netlink_callback *cb, int type,
280 const struct tc_action_ops *ops,
281 struct netlink_ext_ack *extack)

--- 70 unchanged lines hidden ---
277 nlmsg_trim(skb, b);
278 return -1;
279}
280
281static int tcf_vlan_walker(struct net *net, struct sk_buff *skb,
282 struct netlink_callback *cb, int type,
283 const struct tc_action_ops *ops,
284 struct netlink_ext_ack *extack)

--- 70 unchanged lines hidden ---