On Mon, Jan 23, 2017 at 2:07 AM, Jiri Pirko <[email protected]> wrote:
> +
> +static int tcf_sample_init(struct net *net, struct nlattr *nla,
> + struct nlattr *est, struct tc_action **a, int ovr,
> + int bind)
> +{
> + struct tc_action_net *tn = net_generic(net, sample_net_id);
> + struct nlattr *tb[TCA_SAMPLE_MAX + 1];
> + struct psample_group *psample_group;
> + struct tc_sample *parm;
> + struct tcf_sample *s;
> + bool exists = false;
> + int ret;
> +
> + if (!nla)
> + return -EINVAL;
> + ret = nla_parse_nested(tb, TCA_SAMPLE_MAX, nla, sample_policy);
> + if (ret < 0)
> + return ret;
> + if (!tb[TCA_SAMPLE_PARMS] || !tb[TCA_SAMPLE_RATE] ||
> + !tb[TCA_SAMPLE_PSAMPLE_GROUP])
> + return -EINVAL;
> +
> + parm = nla_data(tb[TCA_SAMPLE_PARMS]);
> +
> + exists = tcf_hash_check(tn, parm->index, a, bind);
> + if (exists && bind)
> + return 0;
> +
> + if (!exists) {
> + ret = tcf_hash_create(tn, parm->index, est, a,
> + &act_sample_ops, bind, false);
> + if (ret)
> + return ret;
> + ret = ACT_P_CREATED;
> + } else {
> + tcf_hash_release(*a, bind);
> + if (!ovr)
> + return -EEXIST;
> + }
> + s = to_sample(*a);
> +
> + ASSERT_RTNL();
Copy-n-paste from mirred aciton? This is not needed for you, mirred
needs it because of target netdevice.
> + s->tcf_action = parm->action;
> + s->rate = nla_get_u32(tb[TCA_SAMPLE_RATE]);
> + s->psample_group_num = nla_get_u32(tb[TCA_SAMPLE_PSAMPLE_GROUP]);
> + psample_group = psample_group_get(net, s->psample_group_num);
> + if (!psample_group)
> + return -ENOMEM;
I don't think you can just return here, needs tcf_hash_cleanup() for create
case, right?
> + RCU_INIT_POINTER(s->psample_group, psample_group);
> +
> + if (tb[TCA_SAMPLE_TRUNC_SIZE]) {
> + s->truncate = true;
> + s->trunc_size = nla_get_u32(tb[TCA_SAMPLE_TRUNC_SIZE]);
> + }
Do you need tcf_lock here if RCU only protects ->psample_group??
> +
> + if (ret == ACT_P_CREATED)
> + tcf_hash_insert(tn, *a);
> + return ret;
> +}
> +
Thanks.