1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-or-later */ 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * cls_cgroup.h Control Group Classifier 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Authors: Thomas Graf <tgraf@suug.ch> 6*4882a593Smuzhiyun */ 7*4882a593Smuzhiyun 8*4882a593Smuzhiyun #ifndef _NET_CLS_CGROUP_H 9*4882a593Smuzhiyun #define _NET_CLS_CGROUP_H 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun #include <linux/cgroup.h> 12*4882a593Smuzhiyun #include <linux/hardirq.h> 13*4882a593Smuzhiyun #include <linux/rcupdate.h> 14*4882a593Smuzhiyun #include <net/sock.h> 15*4882a593Smuzhiyun #include <net/inet_sock.h> 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun #ifdef CONFIG_CGROUP_NET_CLASSID 18*4882a593Smuzhiyun struct cgroup_cls_state { 19*4882a593Smuzhiyun struct cgroup_subsys_state css; 20*4882a593Smuzhiyun u32 classid; 21*4882a593Smuzhiyun }; 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun struct cgroup_cls_state *task_cls_state(struct task_struct *p); 24*4882a593Smuzhiyun task_cls_classid(struct task_struct * p)25*4882a593Smuzhiyunstatic inline u32 task_cls_classid(struct task_struct *p) 26*4882a593Smuzhiyun { 27*4882a593Smuzhiyun u32 classid; 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun if (in_interrupt()) 30*4882a593Smuzhiyun return 0; 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun rcu_read_lock(); 33*4882a593Smuzhiyun classid = container_of(task_css(p, net_cls_cgrp_id), 34*4882a593Smuzhiyun struct cgroup_cls_state, css)->classid; 35*4882a593Smuzhiyun rcu_read_unlock(); 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun return classid; 38*4882a593Smuzhiyun } 39*4882a593Smuzhiyun sock_update_classid(struct sock_cgroup_data * skcd)40*4882a593Smuzhiyunstatic inline void sock_update_classid(struct sock_cgroup_data *skcd) 41*4882a593Smuzhiyun { 42*4882a593Smuzhiyun u32 classid; 43*4882a593Smuzhiyun 44*4882a593Smuzhiyun classid = task_cls_classid(current); 45*4882a593Smuzhiyun sock_cgroup_set_classid(skcd, classid); 46*4882a593Smuzhiyun } 47*4882a593Smuzhiyun __task_get_classid(struct task_struct * task)48*4882a593Smuzhiyunstatic inline u32 __task_get_classid(struct task_struct *task) 49*4882a593Smuzhiyun { 50*4882a593Smuzhiyun return task_cls_state(task)->classid; 51*4882a593Smuzhiyun } 52*4882a593Smuzhiyun task_get_classid(const struct sk_buff * skb)53*4882a593Smuzhiyunstatic inline u32 task_get_classid(const struct sk_buff *skb) 54*4882a593Smuzhiyun { 55*4882a593Smuzhiyun u32 classid = __task_get_classid(current); 56*4882a593Smuzhiyun 57*4882a593Smuzhiyun /* Due to the nature of the classifier it is required to ignore all 58*4882a593Smuzhiyun * packets originating from softirq context as accessing `current' 59*4882a593Smuzhiyun * would lead to false results. 60*4882a593Smuzhiyun * 61*4882a593Smuzhiyun * This test assumes that all callers of dev_queue_xmit() explicitly 62*4882a593Smuzhiyun * disable bh. Knowing this, it is possible to detect softirq based 63*4882a593Smuzhiyun * calls by looking at the number of nested bh disable calls because 64*4882a593Smuzhiyun * softirqs always disables bh. 65*4882a593Smuzhiyun */ 66*4882a593Smuzhiyun if (in_serving_softirq()) { 67*4882a593Smuzhiyun struct sock *sk = skb_to_full_sk(skb); 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun /* If there is an sock_cgroup_classid we'll use that. */ 70*4882a593Smuzhiyun if (!sk || !sk_fullsock(sk)) 71*4882a593Smuzhiyun return 0; 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun classid = sock_cgroup_classid(&sk->sk_cgrp_data); 74*4882a593Smuzhiyun } 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun return classid; 77*4882a593Smuzhiyun } 78*4882a593Smuzhiyun #else /* !CONFIG_CGROUP_NET_CLASSID */ sock_update_classid(struct sock_cgroup_data * skcd)79*4882a593Smuzhiyunstatic inline void sock_update_classid(struct sock_cgroup_data *skcd) 80*4882a593Smuzhiyun { 81*4882a593Smuzhiyun } 82*4882a593Smuzhiyun task_get_classid(const struct sk_buff * skb)83*4882a593Smuzhiyunstatic inline u32 task_get_classid(const struct sk_buff *skb) 84*4882a593Smuzhiyun { 85*4882a593Smuzhiyun return 0; 86*4882a593Smuzhiyun } 87*4882a593Smuzhiyun #endif /* CONFIG_CGROUP_NET_CLASSID */ 88*4882a593Smuzhiyun #endif /* _NET_CLS_CGROUP_H */ 89