0001
0002
0003
0004
0005
0006
0007 #include <linux/types.h>
0008 #include <linux/kernel.h>
0009 #include <linux/string.h>
0010 #include <linux/errno.h>
0011 #include <linux/skbuff.h>
0012 #include <linux/rtnetlink.h>
0013 #include <linux/module.h>
0014 #include <linux/init.h>
0015 #include <linux/gfp.h>
0016 #include <net/net_namespace.h>
0017 #include <net/netlink.h>
0018 #include <net/pkt_sched.h>
0019 #include <linux/tc_act/tc_sample.h>
0020 #include <net/tc_act/tc_sample.h>
0021 #include <net/psample.h>
0022 #include <net/pkt_cls.h>
0023
0024 #include <linux/if_arp.h>
0025
0026 static unsigned int sample_net_id;
0027 static struct tc_action_ops act_sample_ops;
0028
0029 static const struct nla_policy sample_policy[TCA_SAMPLE_MAX + 1] = {
0030 [TCA_SAMPLE_PARMS] = { .len = sizeof(struct tc_sample) },
0031 [TCA_SAMPLE_RATE] = { .type = NLA_U32 },
0032 [TCA_SAMPLE_TRUNC_SIZE] = { .type = NLA_U32 },
0033 [TCA_SAMPLE_PSAMPLE_GROUP] = { .type = NLA_U32 },
0034 };
0035
0036 static int tcf_sample_init(struct net *net, struct nlattr *nla,
0037 struct nlattr *est, struct tc_action **a,
0038 struct tcf_proto *tp,
0039 u32 flags, struct netlink_ext_ack *extack)
0040 {
0041 struct tc_action_net *tn = net_generic(net, sample_net_id);
0042 bool bind = flags & TCA_ACT_FLAGS_BIND;
0043 struct nlattr *tb[TCA_SAMPLE_MAX + 1];
0044 struct psample_group *psample_group;
0045 u32 psample_group_num, rate, index;
0046 struct tcf_chain *goto_ch = NULL;
0047 struct tc_sample *parm;
0048 struct tcf_sample *s;
0049 bool exists = false;
0050 int ret, err;
0051
0052 if (!nla)
0053 return -EINVAL;
0054 ret = nla_parse_nested_deprecated(tb, TCA_SAMPLE_MAX, nla,
0055 sample_policy, NULL);
0056 if (ret < 0)
0057 return ret;
0058 if (!tb[TCA_SAMPLE_PARMS] || !tb[TCA_SAMPLE_RATE] ||
0059 !tb[TCA_SAMPLE_PSAMPLE_GROUP])
0060 return -EINVAL;
0061
0062 parm = nla_data(tb[TCA_SAMPLE_PARMS]);
0063 index = parm->index;
0064 err = tcf_idr_check_alloc(tn, &index, a, bind);
0065 if (err < 0)
0066 return err;
0067 exists = err;
0068 if (exists && bind)
0069 return 0;
0070
0071 if (!exists) {
0072 ret = tcf_idr_create(tn, index, est, a,
0073 &act_sample_ops, bind, true, flags);
0074 if (ret) {
0075 tcf_idr_cleanup(tn, index);
0076 return ret;
0077 }
0078 ret = ACT_P_CREATED;
0079 } else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
0080 tcf_idr_release(*a, bind);
0081 return -EEXIST;
0082 }
0083 err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
0084 if (err < 0)
0085 goto release_idr;
0086
0087 rate = nla_get_u32(tb[TCA_SAMPLE_RATE]);
0088 if (!rate) {
0089 NL_SET_ERR_MSG(extack, "invalid sample rate");
0090 err = -EINVAL;
0091 goto put_chain;
0092 }
0093 psample_group_num = nla_get_u32(tb[TCA_SAMPLE_PSAMPLE_GROUP]);
0094 psample_group = psample_group_get(net, psample_group_num);
0095 if (!psample_group) {
0096 err = -ENOMEM;
0097 goto put_chain;
0098 }
0099
0100 s = to_sample(*a);
0101
0102 spin_lock_bh(&s->tcf_lock);
0103 goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
0104 s->rate = rate;
0105 s->psample_group_num = psample_group_num;
0106 psample_group = rcu_replace_pointer(s->psample_group, psample_group,
0107 lockdep_is_held(&s->tcf_lock));
0108
0109 if (tb[TCA_SAMPLE_TRUNC_SIZE]) {
0110 s->truncate = true;
0111 s->trunc_size = nla_get_u32(tb[TCA_SAMPLE_TRUNC_SIZE]);
0112 }
0113 spin_unlock_bh(&s->tcf_lock);
0114
0115 if (psample_group)
0116 psample_group_put(psample_group);
0117 if (goto_ch)
0118 tcf_chain_put_by_act(goto_ch);
0119
0120 return ret;
0121 put_chain:
0122 if (goto_ch)
0123 tcf_chain_put_by_act(goto_ch);
0124 release_idr:
0125 tcf_idr_release(*a, bind);
0126 return err;
0127 }
0128
0129 static void tcf_sample_cleanup(struct tc_action *a)
0130 {
0131 struct tcf_sample *s = to_sample(a);
0132 struct psample_group *psample_group;
0133
0134
0135 psample_group = rcu_dereference_protected(s->psample_group, 1);
0136 RCU_INIT_POINTER(s->psample_group, NULL);
0137 if (psample_group)
0138 psample_group_put(psample_group);
0139 }
0140
0141 static bool tcf_sample_dev_ok_push(struct net_device *dev)
0142 {
0143 switch (dev->type) {
0144 case ARPHRD_TUNNEL:
0145 case ARPHRD_TUNNEL6:
0146 case ARPHRD_SIT:
0147 case ARPHRD_IPGRE:
0148 case ARPHRD_IP6GRE:
0149 case ARPHRD_VOID:
0150 case ARPHRD_NONE:
0151 return false;
0152 default:
0153 return true;
0154 }
0155 }
0156
0157 static int tcf_sample_act(struct sk_buff *skb, const struct tc_action *a,
0158 struct tcf_result *res)
0159 {
0160 struct tcf_sample *s = to_sample(a);
0161 struct psample_group *psample_group;
0162 struct psample_metadata md = {};
0163 int retval;
0164
0165 tcf_lastuse_update(&s->tcf_tm);
0166 bstats_update(this_cpu_ptr(s->common.cpu_bstats), skb);
0167 retval = READ_ONCE(s->tcf_action);
0168
0169 psample_group = rcu_dereference_bh(s->psample_group);
0170
0171
0172 if (psample_group && (prandom_u32() % s->rate == 0)) {
0173 if (!skb_at_tc_ingress(skb)) {
0174 md.in_ifindex = skb->skb_iif;
0175 md.out_ifindex = skb->dev->ifindex;
0176 } else {
0177 md.in_ifindex = skb->dev->ifindex;
0178 }
0179
0180
0181 if (skb_at_tc_ingress(skb) && tcf_sample_dev_ok_push(skb->dev))
0182 skb_push(skb, skb->mac_len);
0183
0184 md.trunc_size = s->truncate ? s->trunc_size : skb->len;
0185 psample_sample_packet(psample_group, skb, s->rate, &md);
0186
0187 if (skb_at_tc_ingress(skb) && tcf_sample_dev_ok_push(skb->dev))
0188 skb_pull(skb, skb->mac_len);
0189 }
0190
0191 return retval;
0192 }
0193
0194 static void tcf_sample_stats_update(struct tc_action *a, u64 bytes, u64 packets,
0195 u64 drops, u64 lastuse, bool hw)
0196 {
0197 struct tcf_sample *s = to_sample(a);
0198 struct tcf_t *tm = &s->tcf_tm;
0199
0200 tcf_action_update_stats(a, bytes, packets, drops, hw);
0201 tm->lastuse = max_t(u64, tm->lastuse, lastuse);
0202 }
0203
0204 static int tcf_sample_dump(struct sk_buff *skb, struct tc_action *a,
0205 int bind, int ref)
0206 {
0207 unsigned char *b = skb_tail_pointer(skb);
0208 struct tcf_sample *s = to_sample(a);
0209 struct tc_sample opt = {
0210 .index = s->tcf_index,
0211 .refcnt = refcount_read(&s->tcf_refcnt) - ref,
0212 .bindcnt = atomic_read(&s->tcf_bindcnt) - bind,
0213 };
0214 struct tcf_t t;
0215
0216 spin_lock_bh(&s->tcf_lock);
0217 opt.action = s->tcf_action;
0218 if (nla_put(skb, TCA_SAMPLE_PARMS, sizeof(opt), &opt))
0219 goto nla_put_failure;
0220
0221 tcf_tm_dump(&t, &s->tcf_tm);
0222 if (nla_put_64bit(skb, TCA_SAMPLE_TM, sizeof(t), &t, TCA_SAMPLE_PAD))
0223 goto nla_put_failure;
0224
0225 if (nla_put_u32(skb, TCA_SAMPLE_RATE, s->rate))
0226 goto nla_put_failure;
0227
0228 if (s->truncate)
0229 if (nla_put_u32(skb, TCA_SAMPLE_TRUNC_SIZE, s->trunc_size))
0230 goto nla_put_failure;
0231
0232 if (nla_put_u32(skb, TCA_SAMPLE_PSAMPLE_GROUP, s->psample_group_num))
0233 goto nla_put_failure;
0234 spin_unlock_bh(&s->tcf_lock);
0235
0236 return skb->len;
0237
0238 nla_put_failure:
0239 spin_unlock_bh(&s->tcf_lock);
0240 nlmsg_trim(skb, b);
0241 return -1;
0242 }
0243
0244 static int tcf_sample_walker(struct net *net, struct sk_buff *skb,
0245 struct netlink_callback *cb, int type,
0246 const struct tc_action_ops *ops,
0247 struct netlink_ext_ack *extack)
0248 {
0249 struct tc_action_net *tn = net_generic(net, sample_net_id);
0250
0251 return tcf_generic_walker(tn, skb, cb, type, ops, extack);
0252 }
0253
0254 static int tcf_sample_search(struct net *net, struct tc_action **a, u32 index)
0255 {
0256 struct tc_action_net *tn = net_generic(net, sample_net_id);
0257
0258 return tcf_idr_search(tn, a, index);
0259 }
0260
0261 static void tcf_psample_group_put(void *priv)
0262 {
0263 struct psample_group *group = priv;
0264
0265 psample_group_put(group);
0266 }
0267
0268 static struct psample_group *
0269 tcf_sample_get_group(const struct tc_action *a,
0270 tc_action_priv_destructor *destructor)
0271 {
0272 struct tcf_sample *s = to_sample(a);
0273 struct psample_group *group;
0274
0275 group = rcu_dereference_protected(s->psample_group,
0276 lockdep_is_held(&s->tcf_lock));
0277 if (group) {
0278 psample_group_take(group);
0279 *destructor = tcf_psample_group_put;
0280 }
0281
0282 return group;
0283 }
0284
0285 static void tcf_offload_sample_get_group(struct flow_action_entry *entry,
0286 const struct tc_action *act)
0287 {
0288 entry->sample.psample_group =
0289 act->ops->get_psample_group(act, &entry->destructor);
0290 entry->destructor_priv = entry->sample.psample_group;
0291 }
0292
0293 static int tcf_sample_offload_act_setup(struct tc_action *act, void *entry_data,
0294 u32 *index_inc, bool bind,
0295 struct netlink_ext_ack *extack)
0296 {
0297 if (bind) {
0298 struct flow_action_entry *entry = entry_data;
0299
0300 entry->id = FLOW_ACTION_SAMPLE;
0301 entry->sample.trunc_size = tcf_sample_trunc_size(act);
0302 entry->sample.truncate = tcf_sample_truncate(act);
0303 entry->sample.rate = tcf_sample_rate(act);
0304 tcf_offload_sample_get_group(entry, act);
0305 *index_inc = 1;
0306 } else {
0307 struct flow_offload_action *fl_action = entry_data;
0308
0309 fl_action->id = FLOW_ACTION_SAMPLE;
0310 }
0311
0312 return 0;
0313 }
0314
0315 static struct tc_action_ops act_sample_ops = {
0316 .kind = "sample",
0317 .id = TCA_ID_SAMPLE,
0318 .owner = THIS_MODULE,
0319 .act = tcf_sample_act,
0320 .stats_update = tcf_sample_stats_update,
0321 .dump = tcf_sample_dump,
0322 .init = tcf_sample_init,
0323 .cleanup = tcf_sample_cleanup,
0324 .walk = tcf_sample_walker,
0325 .lookup = tcf_sample_search,
0326 .get_psample_group = tcf_sample_get_group,
0327 .offload_act_setup = tcf_sample_offload_act_setup,
0328 .size = sizeof(struct tcf_sample),
0329 };
0330
0331 static __net_init int sample_init_net(struct net *net)
0332 {
0333 struct tc_action_net *tn = net_generic(net, sample_net_id);
0334
0335 return tc_action_net_init(net, tn, &act_sample_ops);
0336 }
0337
0338 static void __net_exit sample_exit_net(struct list_head *net_list)
0339 {
0340 tc_action_net_exit(net_list, sample_net_id);
0341 }
0342
0343 static struct pernet_operations sample_net_ops = {
0344 .init = sample_init_net,
0345 .exit_batch = sample_exit_net,
0346 .id = &sample_net_id,
0347 .size = sizeof(struct tc_action_net),
0348 };
0349
0350 static int __init sample_init_module(void)
0351 {
0352 return tcf_register_action(&act_sample_ops, &sample_net_ops);
0353 }
0354
0355 static void __exit sample_cleanup_module(void)
0356 {
0357 tcf_unregister_action(&act_sample_ops, &sample_net_ops);
0358 }
0359
0360 module_init(sample_init_module);
0361 module_exit(sample_cleanup_module);
0362
0363 MODULE_AUTHOR("Yotam Gigi <yotam.gi@gmail.com>");
0364 MODULE_DESCRIPTION("Packet sampling action");
0365 MODULE_LICENSE("GPL v2");