cregit-Linux how code gets into the kernel

Release 4.7 net/sched/act_police.c

Directory: net/sched
/*
 * net/sched/act_police.c       Input police filter
 *
 *              This program is free software; you can redistribute it and/or
 *              modify it under the terms of the GNU General Public License
 *              as published by the Free Software Foundation; either version
 *              2 of the License, or (at your option) any later version.
 *
 * Authors:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
 *              J Hadi Salim (action changes)
 */

#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <net/act_api.h>
#include <net/netlink.h>


struct tcf_police {
	
struct tcf_common	common;
	
int			tcfp_result;
	
u32			tcfp_ewma_rate;
	
s64			tcfp_burst;
	
u32			tcfp_mtu;
	
s64			tcfp_toks;
	
s64			tcfp_ptoks;
	
s64			tcfp_mtu_ptoks;
	
s64			tcfp_t_c;
	
struct psched_ratecfg	rate;
	
bool			rate_present;
	
struct psched_ratecfg	peak;
	
bool			peak_present;
};

#define to_police(pc)	\
	container_of(pc->priv, struct tcf_police, common)


#define POL_TAB_MASK     15

/* old policer structure from before tc actions */

struct tc_police_compat {
	
u32			index;
	
int			action;
	
u32			limit;
	
u32			burst;
	
u32			mtu;
	
struct tc_ratespec	rate;
	
struct tc_ratespec	peakrate;
};

/* Each policer is serialized by its individual spinlock */


static int police_net_id;


static int tcf_act_police_walker(struct net *net, struct sk_buff *skb, struct netlink_callback *cb, int type, struct tc_action *a) { struct tc_action_net *tn = net_generic(net, police_net_id); struct tcf_hashinfo *hinfo = tn->hinfo; struct hlist_head *head; struct tcf_common *p; int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; struct nlattr *nest; spin_lock_bh(&hinfo->lock); s_i = cb->args[0]; for (i = 0; i < (POL_TAB_MASK + 1); i++) { head = &hinfo->htab[tcf_hash(i, POL_TAB_MASK)]; hlist_for_each_entry_rcu(p, head, tcfc_head) { index++; if (index < s_i) continue; a->priv = p; a->order = index; nest = nla_nest_start(skb, a->order); if (nest == NULL) goto nla_put_failure; if (type == RTM_DELACTION) err = tcf_action_dump_1(skb, a, 0, 1); else err = tcf_action_dump_1(skb, a, 0, 0); if (err < 0) { index--; nla_nest_cancel(skb, nest); goto done; } nla_nest_end(skb, nest); n_i++; } } done: spin_unlock_bh(&hinfo->lock); if (n_i) cb->args[0] += n_i; return n_i; nla_put_failure: nla_nest_cancel(skb, nest); goto done; }

Contributors

PersonTokensPropCommitsCommitProp
jamal hadi salimjamal hadi salim18864.38%216.67%
americo wangamerico wang5217.81%433.33%
patrick mchardypatrick mchardy237.88%325.00%
pre-gitpre-git175.82%18.33%
david s. millerdavid s. miller103.42%18.33%
arnaldo carvalho de meloarnaldo carvalho de melo20.68%18.33%
Total292100.00%12100.00%

static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = { [TCA_POLICE_RATE] = { .len = TC_RTAB_SIZE }, [TCA_POLICE_PEAKRATE] = { .len = TC_RTAB_SIZE }, [TCA_POLICE_AVRATE] = { .type = NLA_U32 }, [TCA_POLICE_RESULT] = { .type = NLA_U32 }, };
static int tcf_act_police_locate(struct net *net, struct nlattr *nla, struct nlattr *est, struct tc_action *a, int ovr, int bind) { int ret = 0, err; struct nlattr *tb[TCA_POLICE_MAX + 1]; struct tc_police *parm; struct tcf_police *police; struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL; struct tc_action_net *tn = net_generic(net, police_net_id); int size; if (nla == NULL) return -EINVAL; err = nla_parse_nested(tb, TCA_POLICE_MAX, nla, police_policy); if (err < 0) return err; if (tb[TCA_POLICE_TBF] == NULL) return -EINVAL; size = nla_len(tb[TCA_POLICE_TBF]); if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat)) return -EINVAL; parm = nla_data(tb[TCA_POLICE_TBF]); if (parm->index) { if (tcf_hash_search(tn, a, parm->index)) { police = to_police(a); if (bind) { police->tcf_bindcnt += 1; police->tcf_refcnt += 1; return 0; } if (ovr) goto override; /* not replacing */ return -EEXIST; } } else { ret = tcf_hash_create(tn, parm->index, NULL, a, sizeof(*police), bind, false); if (ret) return ret; ret = ACT_P_CREATED; } police = to_police(a); override: if (parm->rate.rate) { err = -ENOMEM; R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]); if (R_tab == NULL) goto failure; if (parm->peakrate.rate) { P_tab = qdisc_get_rtab(&parm->peakrate, tb[TCA_POLICE_PEAKRATE]); if (P_tab == NULL) goto failure; } } spin_lock_bh(&police->tcf_lock); if (est) { err = gen_replace_estimator(&police->tcf_bstats, NULL, &police->tcf_rate_est, &police->tcf_lock, est); if (err) goto failure_unlock; } else if (tb[TCA_POLICE_AVRATE] && (ret == ACT_P_CREATED || !gen_estimator_active(&police->tcf_bstats, &police->tcf_rate_est))) { err = -EINVAL; goto failure_unlock; } /* No failure allowed after this point */ police->tcfp_mtu = parm->mtu; if (police->tcfp_mtu == 0) { police->tcfp_mtu = ~0; if (R_tab) police->tcfp_mtu = 255 << R_tab->rate.cell_log; } if (R_tab) { police->rate_present = true; psched_ratecfg_precompute(&police->rate, &R_tab->rate, 0); qdisc_put_rtab(R_tab); } else { police->rate_present = false; } if (P_tab) { police->peak_present = true; psched_ratecfg_precompute(&police->peak, &P_tab->rate, 0); qdisc_put_rtab(P_tab); } else { police->peak_present = false; } if (tb[TCA_POLICE_RESULT]) police->tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]); police->tcfp_burst = PSCHED_TICKS2NS(parm->burst); police->tcfp_toks = police->tcfp_burst; if (police->peak_present) { police->tcfp_mtu_ptoks = (s64) psched_l2t_ns(&police->peak, police->tcfp_mtu); police->tcfp_ptoks = police->tcfp_mtu_ptoks; } police->tcf_action = parm->action; if (tb[TCA_POLICE_AVRATE]) police->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]); spin_unlock_bh(&police->tcf_lock); if (ret != ACT_P_CREATED) return ret; police->tcfp_t_c = ktime_get_ns(); tcf_hash_insert(tn, a); return ret; failure_unlock: spin_unlock_bh(&police->tcf_lock); failure: qdisc_put_rtab(P_tab); qdisc_put_rtab(R_tab); if (ret == ACT_P_CREATED) tcf_hash_cleanup(a, est); return err; }

Contributors

PersonTokensPropCommitsCommitProp
jamal hadi salimjamal hadi salim26836.41%310.71%
patrick mchardypatrick mchardy13518.34%932.14%
jiri pirkojiri pirko10614.40%13.57%
stephen hemmingerstephen hemminger587.88%13.57%
americo wangamerico wang506.79%517.86%
david s. millerdavid s. miller435.84%13.57%
jarek poplawskijarek poplawski385.16%13.57%
thomas grafthomas graf233.12%13.57%
eric dumazeteric dumazet70.95%310.71%
benjamin lahaisebenjamin lahaise50.68%13.57%
john fastabendjohn fastabend20.27%13.57%
adrian bunkadrian bunk10.14%13.57%
Total736100.00%28100.00%


static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a, struct tcf_result *res) { struct tcf_police *police = a->priv; s64 now; s64 toks; s64 ptoks = 0; spin_lock(&police->tcf_lock); bstats_update(&police->tcf_bstats, skb); tcf_lastuse_update(&police->tcf_tm); if (police->tcfp_ewma_rate && police->tcf_rate_est.bps >= police->tcfp_ewma_rate) { police->tcf_qstats.overlimits++; if (police->tcf_action == TC_ACT_SHOT) police->tcf_qstats.drops++; spin_unlock(&police->tcf_lock); return police->tcf_action; } if (qdisc_pkt_len(skb) <= police->tcfp_mtu) { if (!police->rate_present) { spin_unlock(&police->tcf_lock); return police->tcfp_result; } now = ktime_get_ns(); toks = min_t(s64, now - police->tcfp_t_c, police->tcfp_burst); if (police->peak_present) { ptoks = toks + police->tcfp_ptoks; if (ptoks > police->tcfp_mtu_ptoks) ptoks = police->tcfp_mtu_ptoks; ptoks -= (s64) psched_l2t_ns(&police->peak, qdisc_pkt_len(skb)); } toks += police->tcfp_toks; if (toks > police->tcfp_burst) toks = police->tcfp_burst; toks -= (s64) psched_l2t_ns(&police->rate, qdisc_pkt_len(skb)); if ((toks|ptoks) >= 0) { police->tcfp_t_c = now; police->tcfp_toks = toks; police->tcfp_ptoks = ptoks; spin_unlock(&police->tcf_lock); return police->tcfp_result; } } police->tcf_qstats.overlimits++; if (police->tcf_action == TC_ACT_SHOT) police->tcf_qstats.drops++; spin_unlock(&police->tcf_lock); return police->tcf_action; }

Contributors

PersonTokensPropCommitsCommitProp
jamal hadi salimjamal hadi salim19857.89%214.29%
david s. millerdavid s. miller6117.84%17.14%
jarek poplawskijarek poplawski308.77%17.14%
jiri pirkojiri pirko267.60%17.14%
jussi kivilinnajussi kivilinna102.92%17.14%
patrick mchardypatrick mchardy102.92%428.57%
eric dumazeteric dumazet61.75%321.43%
adrian bunkadrian bunk10.29%17.14%
Total342100.00%14100.00%


static int tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) { unsigned char *b = skb_tail_pointer(skb); struct tcf_police *police = a->priv; struct tc_police opt = { .index = police->tcf_index, .action = police->tcf_action, .mtu = police->tcfp_mtu, .burst = PSCHED_NS2TICKS(police->tcfp_burst), .refcnt = police->tcf_refcnt - ref, .bindcnt = police->tcf_bindcnt - bind, }; struct tcf_t t; if (police->rate_present) psched_ratecfg_getrate(&opt.rate, &police->rate); if (police->peak_present) psched_ratecfg_getrate(&opt.peakrate, &police->peak); if (nla_put(skb, TCA_POLICE_TBF, sizeof(opt), &opt)) goto nla_put_failure; if (police->tcfp_result && nla_put_u32(skb, TCA_POLICE_RESULT, police->tcfp_result)) goto nla_put_failure; if (police->tcfp_ewma_rate && nla_put_u32(skb, TCA_POLICE_AVRATE, police->tcfp_ewma_rate)) goto nla_put_failure; t.install = jiffies_to_clock_t(jiffies - police->tcf_tm.install); t.lastuse = jiffies_to_clock_t(jiffies - police->tcf_tm.lastuse); t.expires = jiffies_to_clock_t(police->tcf_tm.expires); if (nla_put_64bit(skb, TCA_POLICE_TM, sizeof(t), &t, TCA_POLICE_PAD)) goto nla_put_failure; return skb->len; nla_put_failure: nlmsg_trim(skb, b); return -1; }

Contributors

PersonTokensPropCommitsCommitProp
jamal hadi salimjamal hadi salim17060.50%214.29%
david s. millerdavid s. miller5017.79%214.29%
pre-gitpre-git279.61%214.29%
jiri pirkojiri pirko103.56%17.14%
jeff mahoneyjeff mahoney93.20%17.14%
eric dumazeteric dumazet82.85%17.14%
arnaldo carvalho de meloarnaldo carvalho de melo41.42%214.29%
patrick mchardypatrick mchardy20.71%214.29%
adrian bunkadrian bunk10.36%17.14%
Total281100.00%14100.00%


static int tcf_police_search(struct net *net, struct tc_action *a, u32 index) { struct tc_action_net *tn = net_generic(net, police_net_id); return tcf_hash_search(tn, a, index); }

Contributors

PersonTokensPropCommitsCommitProp
americo wangamerico wang41100.00%1100.00%
Total41100.00%1100.00%

MODULE_AUTHOR("Alexey Kuznetsov"); MODULE_DESCRIPTION("Policing actions"); MODULE_LICENSE("GPL"); static struct tc_action_ops act_police_ops = { .kind = "police", .type = TCA_ID_POLICE, .owner = THIS_MODULE, .act = tcf_act_police, .dump = tcf_act_police_dump, .init = tcf_act_police_locate, .walk = tcf_act_police_walker, .lookup = tcf_police_search, };
static __net_init int police_init_net(struct net *net) { struct tc_action_net *tn = net_generic(net, police_net_id); return tc_action_net_init(tn, &act_police_ops, POL_TAB_MASK); }

Contributors

PersonTokensPropCommitsCommitProp
americo wangamerico wang3497.14%150.00%
pre-gitpre-git12.86%150.00%
Total35100.00%2100.00%


static void __net_exit police_exit_net(struct net *net) { struct tc_action_net *tn = net_generic(net, police_net_id); tc_action_net_exit(tn); }

Contributors

PersonTokensPropCommitsCommitProp
americo wangamerico wang29100.00%1100.00%
Total29100.00%1100.00%

static struct pernet_operations police_net_ops = { .init = police_init_net, .exit = police_exit_net, .id = &police_net_id, .size = sizeof(struct tc_action_net), };
static int __init police_init_module(void) { return tcf_register_action(&act_police_ops, &police_net_ops); }

Contributors

PersonTokensPropCommitsCommitProp
jamal hadi salimjamal hadi salim1052.63%120.00%
david s. millerdavid s. miller526.32%120.00%
americo wangamerico wang315.79%240.00%
pre-gitpre-git15.26%120.00%
Total19100.00%5100.00%


static void __exit police_cleanup_module(void) { tcf_unregister_action(&act_police_ops, &police_net_ops); }

Contributors

PersonTokensPropCommitsCommitProp
david s. millerdavid s. miller1583.33%150.00%
americo wangamerico wang316.67%150.00%
Total18100.00%2100.00%

module_init(police_init_module); module_exit(police_cleanup_module);

Overall Contributors

PersonTokensPropCommitsCommitProp
jamal hadi salimjamal hadi salim89342.91%611.76%
patrick mchardypatrick mchardy25612.30%1223.53%
americo wangamerico wang25512.25%713.73%
jiri pirkojiri pirko1979.47%35.88%
david s. millerdavid s. miller1969.42%23.92%
pre-gitpre-git693.32%23.92%
jarek poplawskijarek poplawski683.27%23.92%
stephen hemmingerstephen hemminger582.79%11.96%
thomas grafthomas graf241.15%23.92%
eric dumazeteric dumazet211.01%59.80%
arnaldo carvalho de meloarnaldo carvalho de melo120.58%35.88%
jussi kivilinnajussi kivilinna100.48%11.96%
jeff mahoneyjeff mahoney90.43%11.96%
benjamin lahaisebenjamin lahaise50.24%11.96%
tejun heotejun heo30.14%11.96%
adrian bunkadrian bunk30.14%11.96%
john fastabendjohn fastabend20.10%11.96%
Total2081100.00%51100.00%
Directory: net/sched
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}