cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

act_police.c (15298B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * net/sched/act_police.c	Input police filter
      4 *
      5 * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
      6 * 		J Hadi Salim (action changes)
      7 */
      8
      9#include <linux/module.h>
     10#include <linux/types.h>
     11#include <linux/kernel.h>
     12#include <linux/string.h>
     13#include <linux/errno.h>
     14#include <linux/skbuff.h>
     15#include <linux/rtnetlink.h>
     16#include <linux/init.h>
     17#include <linux/slab.h>
     18#include <net/act_api.h>
     19#include <net/netlink.h>
     20#include <net/pkt_cls.h>
     21#include <net/tc_act/tc_police.h>
     22
     23/* Each policer is serialized by its individual spinlock */
     24
     25static unsigned int police_net_id;
     26static struct tc_action_ops act_police_ops;
     27
     28static int tcf_police_walker(struct net *net, struct sk_buff *skb,
     29				 struct netlink_callback *cb, int type,
     30				 const struct tc_action_ops *ops,
     31				 struct netlink_ext_ack *extack)
     32{
     33	struct tc_action_net *tn = net_generic(net, police_net_id);
     34
     35	return tcf_generic_walker(tn, skb, cb, type, ops, extack);
     36}
     37
     38static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
     39	[TCA_POLICE_RATE]	= { .len = TC_RTAB_SIZE },
     40	[TCA_POLICE_PEAKRATE]	= { .len = TC_RTAB_SIZE },
     41	[TCA_POLICE_AVRATE]	= { .type = NLA_U32 },
     42	[TCA_POLICE_RESULT]	= { .type = NLA_U32 },
     43	[TCA_POLICE_RATE64]     = { .type = NLA_U64 },
     44	[TCA_POLICE_PEAKRATE64] = { .type = NLA_U64 },
     45	[TCA_POLICE_PKTRATE64]  = { .type = NLA_U64, .min = 1 },
     46	[TCA_POLICE_PKTBURST64] = { .type = NLA_U64, .min = 1 },
     47};
     48
     49static int tcf_police_init(struct net *net, struct nlattr *nla,
     50			       struct nlattr *est, struct tc_action **a,
     51			       struct tcf_proto *tp, u32 flags,
     52			       struct netlink_ext_ack *extack)
     53{
     54	int ret = 0, tcfp_result = TC_ACT_OK, err, size;
     55	bool bind = flags & TCA_ACT_FLAGS_BIND;
     56	struct nlattr *tb[TCA_POLICE_MAX + 1];
     57	struct tcf_chain *goto_ch = NULL;
     58	struct tc_police *parm;
     59	struct tcf_police *police;
     60	struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
     61	struct tc_action_net *tn = net_generic(net, police_net_id);
     62	struct tcf_police_params *new;
     63	bool exists = false;
     64	u32 index;
     65	u64 rate64, prate64;
     66	u64 pps, ppsburst;
     67
     68	if (nla == NULL)
     69		return -EINVAL;
     70
     71	err = nla_parse_nested_deprecated(tb, TCA_POLICE_MAX, nla,
     72					  police_policy, NULL);
     73	if (err < 0)
     74		return err;
     75
     76	if (tb[TCA_POLICE_TBF] == NULL)
     77		return -EINVAL;
     78	size = nla_len(tb[TCA_POLICE_TBF]);
     79	if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat))
     80		return -EINVAL;
     81
     82	parm = nla_data(tb[TCA_POLICE_TBF]);
     83	index = parm->index;
     84	err = tcf_idr_check_alloc(tn, &index, a, bind);
     85	if (err < 0)
     86		return err;
     87	exists = err;
     88	if (exists && bind)
     89		return 0;
     90
     91	if (!exists) {
     92		ret = tcf_idr_create(tn, index, NULL, a,
     93				     &act_police_ops, bind, true, flags);
     94		if (ret) {
     95			tcf_idr_cleanup(tn, index);
     96			return ret;
     97		}
     98		ret = ACT_P_CREATED;
     99		spin_lock_init(&(to_police(*a)->tcfp_lock));
    100	} else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
    101		tcf_idr_release(*a, bind);
    102		return -EEXIST;
    103	}
    104	err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
    105	if (err < 0)
    106		goto release_idr;
    107
    108	police = to_police(*a);
    109	if (parm->rate.rate) {
    110		err = -ENOMEM;
    111		R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE], NULL);
    112		if (R_tab == NULL)
    113			goto failure;
    114
    115		if (parm->peakrate.rate) {
    116			P_tab = qdisc_get_rtab(&parm->peakrate,
    117					       tb[TCA_POLICE_PEAKRATE], NULL);
    118			if (P_tab == NULL)
    119				goto failure;
    120		}
    121	}
    122
    123	if (est) {
    124		err = gen_replace_estimator(&police->tcf_bstats,
    125					    police->common.cpu_bstats,
    126					    &police->tcf_rate_est,
    127					    &police->tcf_lock,
    128					    false, est);
    129		if (err)
    130			goto failure;
    131	} else if (tb[TCA_POLICE_AVRATE] &&
    132		   (ret == ACT_P_CREATED ||
    133		    !gen_estimator_active(&police->tcf_rate_est))) {
    134		err = -EINVAL;
    135		goto failure;
    136	}
    137
    138	if (tb[TCA_POLICE_RESULT]) {
    139		tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]);
    140		if (TC_ACT_EXT_CMP(tcfp_result, TC_ACT_GOTO_CHAIN)) {
    141			NL_SET_ERR_MSG(extack,
    142				       "goto chain not allowed on fallback");
    143			err = -EINVAL;
    144			goto failure;
    145		}
    146	}
    147
    148	if ((tb[TCA_POLICE_PKTRATE64] && !tb[TCA_POLICE_PKTBURST64]) ||
    149	    (!tb[TCA_POLICE_PKTRATE64] && tb[TCA_POLICE_PKTBURST64])) {
    150		NL_SET_ERR_MSG(extack,
    151			       "Both or neither packet-per-second burst and rate must be provided");
    152		err = -EINVAL;
    153		goto failure;
    154	}
    155
    156	if (tb[TCA_POLICE_PKTRATE64] && R_tab) {
    157		NL_SET_ERR_MSG(extack,
    158			       "packet-per-second and byte-per-second rate limits not allowed in same action");
    159		err = -EINVAL;
    160		goto failure;
    161	}
    162
    163	new = kzalloc(sizeof(*new), GFP_KERNEL);
    164	if (unlikely(!new)) {
    165		err = -ENOMEM;
    166		goto failure;
    167	}
    168
    169	/* No failure allowed after this point */
    170	new->tcfp_result = tcfp_result;
    171	new->tcfp_mtu = parm->mtu;
    172	if (!new->tcfp_mtu) {
    173		new->tcfp_mtu = ~0;
    174		if (R_tab)
    175			new->tcfp_mtu = 255 << R_tab->rate.cell_log;
    176	}
    177	if (R_tab) {
    178		new->rate_present = true;
    179		rate64 = tb[TCA_POLICE_RATE64] ?
    180			 nla_get_u64(tb[TCA_POLICE_RATE64]) : 0;
    181		psched_ratecfg_precompute(&new->rate, &R_tab->rate, rate64);
    182		qdisc_put_rtab(R_tab);
    183	} else {
    184		new->rate_present = false;
    185	}
    186	if (P_tab) {
    187		new->peak_present = true;
    188		prate64 = tb[TCA_POLICE_PEAKRATE64] ?
    189			  nla_get_u64(tb[TCA_POLICE_PEAKRATE64]) : 0;
    190		psched_ratecfg_precompute(&new->peak, &P_tab->rate, prate64);
    191		qdisc_put_rtab(P_tab);
    192	} else {
    193		new->peak_present = false;
    194	}
    195
    196	new->tcfp_burst = PSCHED_TICKS2NS(parm->burst);
    197	if (new->peak_present)
    198		new->tcfp_mtu_ptoks = (s64)psched_l2t_ns(&new->peak,
    199							 new->tcfp_mtu);
    200
    201	if (tb[TCA_POLICE_AVRATE])
    202		new->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]);
    203
    204	if (tb[TCA_POLICE_PKTRATE64]) {
    205		pps = nla_get_u64(tb[TCA_POLICE_PKTRATE64]);
    206		ppsburst = nla_get_u64(tb[TCA_POLICE_PKTBURST64]);
    207		new->pps_present = true;
    208		new->tcfp_pkt_burst = PSCHED_TICKS2NS(ppsburst);
    209		psched_ppscfg_precompute(&new->ppsrate, pps);
    210	}
    211
    212	spin_lock_bh(&police->tcf_lock);
    213	spin_lock_bh(&police->tcfp_lock);
    214	police->tcfp_t_c = ktime_get_ns();
    215	police->tcfp_toks = new->tcfp_burst;
    216	if (new->peak_present)
    217		police->tcfp_ptoks = new->tcfp_mtu_ptoks;
    218	spin_unlock_bh(&police->tcfp_lock);
    219	goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
    220	new = rcu_replace_pointer(police->params,
    221				  new,
    222				  lockdep_is_held(&police->tcf_lock));
    223	spin_unlock_bh(&police->tcf_lock);
    224
    225	if (goto_ch)
    226		tcf_chain_put_by_act(goto_ch);
    227	if (new)
    228		kfree_rcu(new, rcu);
    229
    230	return ret;
    231
    232failure:
    233	qdisc_put_rtab(P_tab);
    234	qdisc_put_rtab(R_tab);
    235	if (goto_ch)
    236		tcf_chain_put_by_act(goto_ch);
    237release_idr:
    238	tcf_idr_release(*a, bind);
    239	return err;
    240}
    241
    242static bool tcf_police_mtu_check(struct sk_buff *skb, u32 limit)
    243{
    244	u32 len;
    245
    246	if (skb_is_gso(skb))
    247		return skb_gso_validate_mac_len(skb, limit);
    248
    249	len = qdisc_pkt_len(skb);
    250	if (skb_at_tc_ingress(skb))
    251		len += skb->mac_len;
    252
    253	return len <= limit;
    254}
    255
    256static int tcf_police_act(struct sk_buff *skb, const struct tc_action *a,
    257			  struct tcf_result *res)
    258{
    259	struct tcf_police *police = to_police(a);
    260	s64 now, toks, ppstoks = 0, ptoks = 0;
    261	struct tcf_police_params *p;
    262	int ret;
    263
    264	tcf_lastuse_update(&police->tcf_tm);
    265	bstats_update(this_cpu_ptr(police->common.cpu_bstats), skb);
    266
    267	ret = READ_ONCE(police->tcf_action);
    268	p = rcu_dereference_bh(police->params);
    269
    270	if (p->tcfp_ewma_rate) {
    271		struct gnet_stats_rate_est64 sample;
    272
    273		if (!gen_estimator_read(&police->tcf_rate_est, &sample) ||
    274		    sample.bps >= p->tcfp_ewma_rate)
    275			goto inc_overlimits;
    276	}
    277
    278	if (tcf_police_mtu_check(skb, p->tcfp_mtu)) {
    279		if (!p->rate_present && !p->pps_present) {
    280			ret = p->tcfp_result;
    281			goto end;
    282		}
    283
    284		now = ktime_get_ns();
    285		spin_lock_bh(&police->tcfp_lock);
    286		toks = min_t(s64, now - police->tcfp_t_c, p->tcfp_burst);
    287		if (p->peak_present) {
    288			ptoks = toks + police->tcfp_ptoks;
    289			if (ptoks > p->tcfp_mtu_ptoks)
    290				ptoks = p->tcfp_mtu_ptoks;
    291			ptoks -= (s64)psched_l2t_ns(&p->peak,
    292						    qdisc_pkt_len(skb));
    293		}
    294		if (p->rate_present) {
    295			toks += police->tcfp_toks;
    296			if (toks > p->tcfp_burst)
    297				toks = p->tcfp_burst;
    298			toks -= (s64)psched_l2t_ns(&p->rate, qdisc_pkt_len(skb));
    299		} else if (p->pps_present) {
    300			ppstoks = min_t(s64, now - police->tcfp_t_c, p->tcfp_pkt_burst);
    301			ppstoks += police->tcfp_pkttoks;
    302			if (ppstoks > p->tcfp_pkt_burst)
    303				ppstoks = p->tcfp_pkt_burst;
    304			ppstoks -= (s64)psched_pkt2t_ns(&p->ppsrate, 1);
    305		}
    306		if ((toks | ptoks | ppstoks) >= 0) {
    307			police->tcfp_t_c = now;
    308			police->tcfp_toks = toks;
    309			police->tcfp_ptoks = ptoks;
    310			police->tcfp_pkttoks = ppstoks;
    311			spin_unlock_bh(&police->tcfp_lock);
    312			ret = p->tcfp_result;
    313			goto inc_drops;
    314		}
    315		spin_unlock_bh(&police->tcfp_lock);
    316	}
    317
    318inc_overlimits:
    319	qstats_overlimit_inc(this_cpu_ptr(police->common.cpu_qstats));
    320inc_drops:
    321	if (ret == TC_ACT_SHOT)
    322		qstats_drop_inc(this_cpu_ptr(police->common.cpu_qstats));
    323end:
    324	return ret;
    325}
    326
    327static void tcf_police_cleanup(struct tc_action *a)
    328{
    329	struct tcf_police *police = to_police(a);
    330	struct tcf_police_params *p;
    331
    332	p = rcu_dereference_protected(police->params, 1);
    333	if (p)
    334		kfree_rcu(p, rcu);
    335}
    336
    337static void tcf_police_stats_update(struct tc_action *a,
    338				    u64 bytes, u64 packets, u64 drops,
    339				    u64 lastuse, bool hw)
    340{
    341	struct tcf_police *police = to_police(a);
    342	struct tcf_t *tm = &police->tcf_tm;
    343
    344	tcf_action_update_stats(a, bytes, packets, drops, hw);
    345	tm->lastuse = max_t(u64, tm->lastuse, lastuse);
    346}
    347
    348static int tcf_police_dump(struct sk_buff *skb, struct tc_action *a,
    349			       int bind, int ref)
    350{
    351	unsigned char *b = skb_tail_pointer(skb);
    352	struct tcf_police *police = to_police(a);
    353	struct tcf_police_params *p;
    354	struct tc_police opt = {
    355		.index = police->tcf_index,
    356		.refcnt = refcount_read(&police->tcf_refcnt) - ref,
    357		.bindcnt = atomic_read(&police->tcf_bindcnt) - bind,
    358	};
    359	struct tcf_t t;
    360
    361	spin_lock_bh(&police->tcf_lock);
    362	opt.action = police->tcf_action;
    363	p = rcu_dereference_protected(police->params,
    364				      lockdep_is_held(&police->tcf_lock));
    365	opt.mtu = p->tcfp_mtu;
    366	opt.burst = PSCHED_NS2TICKS(p->tcfp_burst);
    367	if (p->rate_present) {
    368		psched_ratecfg_getrate(&opt.rate, &p->rate);
    369		if ((police->params->rate.rate_bytes_ps >= (1ULL << 32)) &&
    370		    nla_put_u64_64bit(skb, TCA_POLICE_RATE64,
    371				      police->params->rate.rate_bytes_ps,
    372				      TCA_POLICE_PAD))
    373			goto nla_put_failure;
    374	}
    375	if (p->peak_present) {
    376		psched_ratecfg_getrate(&opt.peakrate, &p->peak);
    377		if ((police->params->peak.rate_bytes_ps >= (1ULL << 32)) &&
    378		    nla_put_u64_64bit(skb, TCA_POLICE_PEAKRATE64,
    379				      police->params->peak.rate_bytes_ps,
    380				      TCA_POLICE_PAD))
    381			goto nla_put_failure;
    382	}
    383	if (p->pps_present) {
    384		if (nla_put_u64_64bit(skb, TCA_POLICE_PKTRATE64,
    385				      police->params->ppsrate.rate_pkts_ps,
    386				      TCA_POLICE_PAD))
    387			goto nla_put_failure;
    388		if (nla_put_u64_64bit(skb, TCA_POLICE_PKTBURST64,
    389				      PSCHED_NS2TICKS(p->tcfp_pkt_burst),
    390				      TCA_POLICE_PAD))
    391			goto nla_put_failure;
    392	}
    393	if (nla_put(skb, TCA_POLICE_TBF, sizeof(opt), &opt))
    394		goto nla_put_failure;
    395	if (p->tcfp_result &&
    396	    nla_put_u32(skb, TCA_POLICE_RESULT, p->tcfp_result))
    397		goto nla_put_failure;
    398	if (p->tcfp_ewma_rate &&
    399	    nla_put_u32(skb, TCA_POLICE_AVRATE, p->tcfp_ewma_rate))
    400		goto nla_put_failure;
    401
    402	tcf_tm_dump(&t, &police->tcf_tm);
    403	if (nla_put_64bit(skb, TCA_POLICE_TM, sizeof(t), &t, TCA_POLICE_PAD))
    404		goto nla_put_failure;
    405	spin_unlock_bh(&police->tcf_lock);
    406
    407	return skb->len;
    408
    409nla_put_failure:
    410	spin_unlock_bh(&police->tcf_lock);
    411	nlmsg_trim(skb, b);
    412	return -1;
    413}
    414
    415static int tcf_police_search(struct net *net, struct tc_action **a, u32 index)
    416{
    417	struct tc_action_net *tn = net_generic(net, police_net_id);
    418
    419	return tcf_idr_search(tn, a, index);
    420}
    421
    422static int tcf_police_act_to_flow_act(int tc_act, u32 *extval,
    423				      struct netlink_ext_ack *extack)
    424{
    425	int act_id = -EOPNOTSUPP;
    426
    427	if (!TC_ACT_EXT_OPCODE(tc_act)) {
    428		if (tc_act == TC_ACT_OK)
    429			act_id = FLOW_ACTION_ACCEPT;
    430		else if (tc_act ==  TC_ACT_SHOT)
    431			act_id = FLOW_ACTION_DROP;
    432		else if (tc_act == TC_ACT_PIPE)
    433			act_id = FLOW_ACTION_PIPE;
    434		else if (tc_act == TC_ACT_RECLASSIFY)
    435			NL_SET_ERR_MSG_MOD(extack, "Offload not supported when conform/exceed action is \"reclassify\"");
    436		else
    437			NL_SET_ERR_MSG_MOD(extack, "Unsupported conform/exceed action offload");
    438	} else if (TC_ACT_EXT_CMP(tc_act, TC_ACT_GOTO_CHAIN)) {
    439		act_id = FLOW_ACTION_GOTO;
    440		*extval = tc_act & TC_ACT_EXT_VAL_MASK;
    441	} else if (TC_ACT_EXT_CMP(tc_act, TC_ACT_JUMP)) {
    442		act_id = FLOW_ACTION_JUMP;
    443		*extval = tc_act & TC_ACT_EXT_VAL_MASK;
    444	} else if (tc_act == TC_ACT_UNSPEC) {
    445		act_id = FLOW_ACTION_CONTINUE;
    446	} else {
    447		NL_SET_ERR_MSG_MOD(extack, "Unsupported conform/exceed action offload");
    448	}
    449
    450	return act_id;
    451}
    452
    453static int tcf_police_offload_act_setup(struct tc_action *act, void *entry_data,
    454					u32 *index_inc, bool bind,
    455					struct netlink_ext_ack *extack)
    456{
    457	if (bind) {
    458		struct flow_action_entry *entry = entry_data;
    459		struct tcf_police *police = to_police(act);
    460		struct tcf_police_params *p;
    461		int act_id;
    462
    463		p = rcu_dereference_protected(police->params,
    464					      lockdep_is_held(&police->tcf_lock));
    465
    466		entry->id = FLOW_ACTION_POLICE;
    467		entry->police.burst = tcf_police_burst(act);
    468		entry->police.rate_bytes_ps =
    469			tcf_police_rate_bytes_ps(act);
    470		entry->police.peakrate_bytes_ps = tcf_police_peakrate_bytes_ps(act);
    471		entry->police.avrate = tcf_police_tcfp_ewma_rate(act);
    472		entry->police.overhead = tcf_police_rate_overhead(act);
    473		entry->police.burst_pkt = tcf_police_burst_pkt(act);
    474		entry->police.rate_pkt_ps =
    475			tcf_police_rate_pkt_ps(act);
    476		entry->police.mtu = tcf_police_tcfp_mtu(act);
    477
    478		act_id = tcf_police_act_to_flow_act(police->tcf_action,
    479						    &entry->police.exceed.extval,
    480						    extack);
    481		if (act_id < 0)
    482			return act_id;
    483
    484		entry->police.exceed.act_id = act_id;
    485
    486		act_id = tcf_police_act_to_flow_act(p->tcfp_result,
    487						    &entry->police.notexceed.extval,
    488						    extack);
    489		if (act_id < 0)
    490			return act_id;
    491
    492		entry->police.notexceed.act_id = act_id;
    493
    494		*index_inc = 1;
    495	} else {
    496		struct flow_offload_action *fl_action = entry_data;
    497
    498		fl_action->id = FLOW_ACTION_POLICE;
    499	}
    500
    501	return 0;
    502}
    503
    504MODULE_AUTHOR("Alexey Kuznetsov");
    505MODULE_DESCRIPTION("Policing actions");
    506MODULE_LICENSE("GPL");
    507
    508static struct tc_action_ops act_police_ops = {
    509	.kind		=	"police",
    510	.id		=	TCA_ID_POLICE,
    511	.owner		=	THIS_MODULE,
    512	.stats_update	=	tcf_police_stats_update,
    513	.act		=	tcf_police_act,
    514	.dump		=	tcf_police_dump,
    515	.init		=	tcf_police_init,
    516	.walk		=	tcf_police_walker,
    517	.lookup		=	tcf_police_search,
    518	.cleanup	=	tcf_police_cleanup,
    519	.offload_act_setup =	tcf_police_offload_act_setup,
    520	.size		=	sizeof(struct tcf_police),
    521};
    522
    523static __net_init int police_init_net(struct net *net)
    524{
    525	struct tc_action_net *tn = net_generic(net, police_net_id);
    526
    527	return tc_action_net_init(net, tn, &act_police_ops);
    528}
    529
    530static void __net_exit police_exit_net(struct list_head *net_list)
    531{
    532	tc_action_net_exit(net_list, police_net_id);
    533}
    534
    535static struct pernet_operations police_net_ops = {
    536	.init = police_init_net,
    537	.exit_batch = police_exit_net,
    538	.id   = &police_net_id,
    539	.size = sizeof(struct tc_action_net),
    540};
    541
    542static int __init police_init_module(void)
    543{
    544	return tcf_register_action(&act_police_ops, &police_net_ops);
    545}
    546
    547static void __exit police_cleanup_module(void)
    548{
    549	tcf_unregister_action(&act_police_ops, &police_net_ops);
    550}
    551
    552module_init(police_init_module);
    553module_exit(police_cleanup_module);