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 --- |