static int tcf_simp_init(struct net *net, struct nlattr *nla, struct nlattr *est, struct tc_action **a, int ovr, int bind, struct netlink_ext_ack *extack) { struct tc_action_net *tn = net_generic(net, simp_net_id); struct nlattr *tb[TCA_DEF_MAX + 1]; struct tc_defact *parm; struct tcf_defact *d; bool exists = false; int ret = 0, err; if (nla == NULL) return -EINVAL; err = nla_parse_nested(tb, TCA_DEF_MAX, nla, simple_policy, NULL); if (err < 0) return err; if (tb[TCA_DEF_PARMS] == NULL) return -EINVAL; parm = nla_data(tb[TCA_DEF_PARMS]); exists = tcf_idr_check(tn, parm->index, a, bind); if (exists && bind) return 0; if (tb[TCA_DEF_DATA] == NULL) { if (exists) tcf_idr_release(*a, bind); return -EINVAL; } if (!exists) { ret = tcf_idr_create(tn, parm->index, est, a, &act_simp_ops, bind, false); if (ret) return ret; d = to_defact(*a); ret = alloc_defdata(d, tb[TCA_DEF_DATA]); if (ret < 0) { tcf_idr_release(*a, bind); return ret; } d->tcf_action = parm->action; ret = ACT_P_CREATED; } else { d = to_defact(*a); tcf_idr_release(*a, bind); if (!ovr) return -EEXIST; reset_policy(d, tb[TCA_DEF_DATA], parm); } if (ret == ACT_P_CREATED) tcf_idr_insert(tn, *a); return ret; }
static int tcf_simp_init(struct nlattr *nla, struct nlattr *est, struct tc_action *a, int ovr, int bind) { struct nlattr *tb[TCA_DEF_MAX + 1]; struct tc_defact *parm; struct tcf_defact *d; struct tcf_common *pc; char *defdata; int ret = 0, err; if (nla == NULL) return -EINVAL; err = nla_parse_nested(tb, TCA_DEF_MAX, nla, simple_policy); if (err < 0) return err; if (tb[TCA_DEF_PARMS] == NULL) return -EINVAL; if (tb[TCA_DEF_DATA] == NULL) return -EINVAL; parm = nla_data(tb[TCA_DEF_PARMS]); defdata = nla_data(tb[TCA_DEF_DATA]); pc = tcf_hash_check(parm->index, a, bind, &simp_hash_info); if (!pc) { pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind, &simp_idx_gen, &simp_hash_info); if (unlikely(!pc)) return -ENOMEM; d = to_defact(pc); ret = alloc_defdata(d, defdata); if (ret < 0) { kfree(pc); return ret; } d->tcf_action = parm->action; ret = ACT_P_CREATED; } else { d = to_defact(pc); if (!ovr) { tcf_simp_release(d, bind); return -EEXIST; } reset_policy(d, defdata, parm); } if (ret == ACT_P_CREATED) tcf_hash_insert(pc, &simp_hash_info); return ret; }