| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * net/sched/act_simple.c Simple example of an action |
|---|
| 3 | 4 | * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or |
|---|
| 5 | | - * modify it under the terms of the GNU General Public License |
|---|
| 6 | | - * as published by the Free Software Foundation; either version |
|---|
| 7 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 8 | | - * |
|---|
| 9 | 5 | * Authors: Jamal Hadi Salim (2005-8) |
|---|
| 10 | | - * |
|---|
| 11 | 6 | */ |
|---|
| 12 | 7 | |
|---|
| 13 | 8 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 18 | 13 | #include <linux/rtnetlink.h> |
|---|
| 19 | 14 | #include <net/netlink.h> |
|---|
| 20 | 15 | #include <net/pkt_sched.h> |
|---|
| 21 | | - |
|---|
| 22 | | -#define TCA_ACT_SIMP 22 |
|---|
| 16 | +#include <net/pkt_cls.h> |
|---|
| 23 | 17 | |
|---|
| 24 | 18 | #include <linux/tc_act/tc_defact.h> |
|---|
| 25 | 19 | #include <net/tc_act/tc_defact.h> |
|---|
| .. | .. |
|---|
| 41 | 35 | * Example if this was the 3rd packet and the string was "hello" |
|---|
| 42 | 36 | * then it would look like "hello_3" (without quotes) |
|---|
| 43 | 37 | */ |
|---|
| 44 | | - pr_info("simple: %s_%d\n", |
|---|
| 38 | + pr_info("simple: %s_%llu\n", |
|---|
| 45 | 39 | (char *)d->tcfd_defdata, d->tcf_bstats.packets); |
|---|
| 46 | 40 | spin_unlock(&d->tcf_lock); |
|---|
| 47 | 41 | return d->tcf_action; |
|---|
| .. | .. |
|---|
| 62 | 56 | return 0; |
|---|
| 63 | 57 | } |
|---|
| 64 | 58 | |
|---|
| 65 | | -static void reset_policy(struct tcf_defact *d, const struct nlattr *defdata, |
|---|
| 66 | | - struct tc_defact *p) |
|---|
| 59 | +static int reset_policy(struct tc_action *a, const struct nlattr *defdata, |
|---|
| 60 | + struct tc_defact *p, struct tcf_proto *tp, |
|---|
| 61 | + struct netlink_ext_ack *extack) |
|---|
| 67 | 62 | { |
|---|
| 63 | + struct tcf_chain *goto_ch = NULL; |
|---|
| 64 | + struct tcf_defact *d; |
|---|
| 65 | + int err; |
|---|
| 66 | + |
|---|
| 67 | + err = tcf_action_check_ctrlact(p->action, tp, &goto_ch, extack); |
|---|
| 68 | + if (err < 0) |
|---|
| 69 | + return err; |
|---|
| 70 | + d = to_defact(a); |
|---|
| 68 | 71 | spin_lock_bh(&d->tcf_lock); |
|---|
| 69 | | - d->tcf_action = p->action; |
|---|
| 72 | + goto_ch = tcf_action_set_ctrlact(a, p->action, goto_ch); |
|---|
| 70 | 73 | memset(d->tcfd_defdata, 0, SIMP_MAX_DATA); |
|---|
| 71 | 74 | nla_strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA); |
|---|
| 72 | 75 | spin_unlock_bh(&d->tcf_lock); |
|---|
| 76 | + if (goto_ch) |
|---|
| 77 | + tcf_chain_put_by_act(goto_ch); |
|---|
| 78 | + return 0; |
|---|
| 73 | 79 | } |
|---|
| 74 | 80 | |
|---|
| 75 | 81 | static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = { |
|---|
| .. | .. |
|---|
| 80 | 86 | static int tcf_simp_init(struct net *net, struct nlattr *nla, |
|---|
| 81 | 87 | struct nlattr *est, struct tc_action **a, |
|---|
| 82 | 88 | int ovr, int bind, bool rtnl_held, |
|---|
| 89 | + struct tcf_proto *tp, u32 flags, |
|---|
| 83 | 90 | struct netlink_ext_ack *extack) |
|---|
| 84 | 91 | { |
|---|
| 85 | 92 | struct tc_action_net *tn = net_generic(net, simp_net_id); |
|---|
| 86 | 93 | struct nlattr *tb[TCA_DEF_MAX + 1]; |
|---|
| 94 | + struct tcf_chain *goto_ch = NULL; |
|---|
| 87 | 95 | struct tc_defact *parm; |
|---|
| 88 | 96 | struct tcf_defact *d; |
|---|
| 89 | 97 | bool exists = false; |
|---|
| .. | .. |
|---|
| 93 | 101 | if (nla == NULL) |
|---|
| 94 | 102 | return -EINVAL; |
|---|
| 95 | 103 | |
|---|
| 96 | | - err = nla_parse_nested(tb, TCA_DEF_MAX, nla, simple_policy, NULL); |
|---|
| 104 | + err = nla_parse_nested_deprecated(tb, TCA_DEF_MAX, nla, simple_policy, |
|---|
| 105 | + NULL); |
|---|
| 97 | 106 | if (err < 0) |
|---|
| 98 | 107 | return err; |
|---|
| 99 | 108 | |
|---|
| .. | .. |
|---|
| 119 | 128 | |
|---|
| 120 | 129 | if (!exists) { |
|---|
| 121 | 130 | ret = tcf_idr_create(tn, index, est, a, |
|---|
| 122 | | - &act_simp_ops, bind, false); |
|---|
| 131 | + &act_simp_ops, bind, false, flags); |
|---|
| 123 | 132 | if (ret) { |
|---|
| 124 | 133 | tcf_idr_cleanup(tn, index); |
|---|
| 125 | 134 | return ret; |
|---|
| 126 | 135 | } |
|---|
| 127 | 136 | |
|---|
| 128 | 137 | d = to_defact(*a); |
|---|
| 129 | | - ret = alloc_defdata(d, tb[TCA_DEF_DATA]); |
|---|
| 130 | | - if (ret < 0) { |
|---|
| 131 | | - tcf_idr_release(*a, bind); |
|---|
| 132 | | - return ret; |
|---|
| 133 | | - } |
|---|
| 134 | | - d->tcf_action = parm->action; |
|---|
| 138 | + err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, |
|---|
| 139 | + extack); |
|---|
| 140 | + if (err < 0) |
|---|
| 141 | + goto release_idr; |
|---|
| 142 | + |
|---|
| 143 | + err = alloc_defdata(d, tb[TCA_DEF_DATA]); |
|---|
| 144 | + if (err < 0) |
|---|
| 145 | + goto put_chain; |
|---|
| 146 | + |
|---|
| 147 | + tcf_action_set_ctrlact(*a, parm->action, goto_ch); |
|---|
| 135 | 148 | ret = ACT_P_CREATED; |
|---|
| 136 | 149 | } else { |
|---|
| 137 | | - d = to_defact(*a); |
|---|
| 138 | | - |
|---|
| 139 | 150 | if (!ovr) { |
|---|
| 140 | | - tcf_idr_release(*a, bind); |
|---|
| 141 | | - return -EEXIST; |
|---|
| 151 | + err = -EEXIST; |
|---|
| 152 | + goto release_idr; |
|---|
| 142 | 153 | } |
|---|
| 143 | 154 | |
|---|
| 144 | | - reset_policy(d, tb[TCA_DEF_DATA], parm); |
|---|
| 155 | + err = reset_policy(*a, tb[TCA_DEF_DATA], parm, tp, extack); |
|---|
| 156 | + if (err) |
|---|
| 157 | + goto release_idr; |
|---|
| 145 | 158 | } |
|---|
| 146 | 159 | |
|---|
| 147 | | - if (ret == ACT_P_CREATED) |
|---|
| 148 | | - tcf_idr_insert(tn, *a); |
|---|
| 149 | 160 | return ret; |
|---|
| 161 | +put_chain: |
|---|
| 162 | + if (goto_ch) |
|---|
| 163 | + tcf_chain_put_by_act(goto_ch); |
|---|
| 164 | +release_idr: |
|---|
| 165 | + tcf_idr_release(*a, bind); |
|---|
| 166 | + return err; |
|---|
| 150 | 167 | } |
|---|
| 151 | 168 | |
|---|
| 152 | 169 | static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, |
|---|
| .. | .. |
|---|
| 190 | 207 | return tcf_generic_walker(tn, skb, cb, type, ops, extack); |
|---|
| 191 | 208 | } |
|---|
| 192 | 209 | |
|---|
| 193 | | -static int tcf_simp_search(struct net *net, struct tc_action **a, u32 index, |
|---|
| 194 | | - struct netlink_ext_ack *extack) |
|---|
| 210 | +static int tcf_simp_search(struct net *net, struct tc_action **a, u32 index) |
|---|
| 195 | 211 | { |
|---|
| 196 | 212 | struct tc_action_net *tn = net_generic(net, simp_net_id); |
|---|
| 197 | 213 | |
|---|
| .. | .. |
|---|
| 200 | 216 | |
|---|
| 201 | 217 | static struct tc_action_ops act_simp_ops = { |
|---|
| 202 | 218 | .kind = "simple", |
|---|
| 203 | | - .type = TCA_ACT_SIMP, |
|---|
| 219 | + .id = TCA_ID_SIMP, |
|---|
| 204 | 220 | .owner = THIS_MODULE, |
|---|
| 205 | 221 | .act = tcf_simp_act, |
|---|
| 206 | 222 | .dump = tcf_simp_dump, |
|---|