act_api.h 6.8 KB
Newer Older
1
/* SPDX-License-Identifier: GPL-2.0 */
L
Linus Torvalds 已提交
2 3 4 5
#ifndef __NET_ACT_API_H
#define __NET_ACT_API_H

/*
6 7
 * Public action API for classifiers/qdiscs
*/
L
Linus Torvalds 已提交
8

9
#include <linux/refcount.h>
L
Linus Torvalds 已提交
10 11
#include <net/sch_generic.h>
#include <net/pkt_sched.h>
12 13
#include <net/net_namespace.h>
#include <net/netns/generic.h>
L
Linus Torvalds 已提交
14

15 16 17
struct tcf_idrinfo {
	spinlock_t	lock;
	struct idr	action_idr;
18 19 20 21 22 23
};

struct tc_action_ops;

struct tc_action {
	const struct tc_action_ops	*ops;
24 25 26
	__u32				type; /* for backward compat(TCA_OLD_COMPAT) */
	__u32				order;
	struct list_head		list;
27
	struct tcf_idrinfo		*idrinfo;
28

29
	u32				tcfa_index;
30 31
	refcount_t			tcfa_refcnt;
	atomic_t			tcfa_bindcnt;
32 33 34 35 36
	u32				tcfa_capab;
	int				tcfa_action;
	struct tcf_t			tcfa_tm;
	struct gnet_stats_basic_packed	tcfa_bstats;
	struct gnet_stats_queue		tcfa_qstats;
37
	struct net_rate_estimator __rcu *tcfa_rate_est;
38
	spinlock_t			tcfa_lock;
39 40
	struct gnet_stats_basic_cpu __percpu *cpu_bstats;
	struct gnet_stats_queue __percpu *cpu_qstats;
41
	struct tc_cookie	__rcu *act_cookie;
42
	struct tcf_chain	*goto_chain;
43
};
44 45 46 47 48 49 50 51 52 53
#define tcf_index	common.tcfa_index
#define tcf_refcnt	common.tcfa_refcnt
#define tcf_bindcnt	common.tcfa_bindcnt
#define tcf_capab	common.tcfa_capab
#define tcf_action	common.tcfa_action
#define tcf_tm		common.tcfa_tm
#define tcf_bstats	common.tcfa_bstats
#define tcf_qstats	common.tcfa_qstats
#define tcf_rate_est	common.tcfa_rate_est
#define tcf_lock	common.tcfa_lock
54

55 56 57 58 59 60 61 62 63
/* Update lastuse only if needed, to avoid dirtying a cache line.
 * We use a temp variable to avoid fetching jiffies twice.
 */
static inline void tcf_lastuse_update(struct tcf_t *tm)
{
	unsigned long now = jiffies;

	if (tm->lastuse != now)
		tm->lastuse = now;
64 65
	if (unlikely(!tm->firstuse))
		tm->firstuse = now;
66 67
}

68 69 70 71 72 73 74 75
static inline void tcf_tm_dump(struct tcf_t *dtm, const struct tcf_t *stm)
{
	dtm->install = jiffies_to_clock_t(jiffies - stm->install);
	dtm->lastuse = jiffies_to_clock_t(jiffies - stm->lastuse);
	dtm->firstuse = jiffies_to_clock_t(jiffies - stm->firstuse);
	dtm->expires = jiffies_to_clock_t(stm->expires);
}

76 77 78 79 80
#ifdef CONFIG_NET_CLS_ACT

#define ACT_P_CREATED 1
#define ACT_P_DELETED 1

81
struct tc_action_ops {
82
	struct list_head head;
L
Linus Torvalds 已提交
83 84
	char    kind[IFNAMSIZ];
	__u32   type; /* TBD to match kind */
85
	size_t	size;
L
Linus Torvalds 已提交
86
	struct module		*owner;
87 88
	int     (*act)(struct sk_buff *, const struct tc_action *,
		       struct tcf_result *);
89
	int     (*dump)(struct sk_buff *, struct tc_action *, int, int);
90
	void	(*cleanup)(struct tc_action *);
91 92
	int     (*lookup)(struct net *net, struct tc_action **a, u32 index,
			  struct netlink_ext_ack *extack);
93
	int     (*init)(struct net *net, struct nlattr *nla,
94
			struct nlattr *est, struct tc_action **act, int ovr,
95 96
			int bind, bool rtnl_held,
			struct netlink_ext_ack *extack);
97
	int     (*walk)(struct net *, struct sk_buff *,
98
			struct netlink_callback *, int,
99 100
			const struct tc_action_ops *,
			struct netlink_ext_ack *);
101
	void	(*stats_update)(struct tc_action *, u64, u32, u64);
102
	size_t  (*get_fill_size)(const struct tc_action *act);
103
	struct net_device *(*get_dev)(const struct tc_action *a);
104
	int     (*delete)(struct net *net, u32 index);
105 106 107
};

struct tc_action_net {
108
	struct tcf_idrinfo *idrinfo;
109
	const struct tc_action_ops *ops;
L
Linus Torvalds 已提交
110 111
};

112
static inline
113
int tc_action_net_init(struct tc_action_net *tn,
114
		       const struct tc_action_ops *ops)
115 116 117
{
	int err = 0;

118 119
	tn->idrinfo = kmalloc(sizeof(*tn->idrinfo), GFP_KERNEL);
	if (!tn->idrinfo)
120 121
		return -ENOMEM;
	tn->ops = ops;
122 123
	spin_lock_init(&tn->idrinfo->lock);
	idr_init(&tn->idrinfo->action_idr);
124 125 126
	return err;
}

127 128
void tcf_idrinfo_destroy(const struct tc_action_ops *ops,
			 struct tcf_idrinfo *idrinfo);
129

130 131
static inline void tc_action_net_exit(struct list_head *net_list,
				      unsigned int id)
132
{
133 134
	struct net *net;

135
	rtnl_lock();
136 137 138 139 140 141
	list_for_each_entry(net, net_list, exit_list) {
		struct tc_action_net *tn = net_generic(net, id);

		tcf_idrinfo_destroy(tn->ops, tn->idrinfo);
		kfree(tn->idrinfo);
	}
142
	rtnl_unlock();
143 144 145 146
}

int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
		       struct netlink_callback *cb, int type,
147 148
		       const struct tc_action_ops *ops,
		       struct netlink_ext_ack *extack);
149 150
int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index);
bool tcf_idr_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
151
		    int bind);
152 153 154 155
int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
		   struct tc_action **a, const struct tc_action_ops *ops,
		   int bind, bool cpustats);
void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a);
156

157
int tcf_idr_delete_index(struct tc_action_net *tn, u32 index);
158
int __tcf_idr_release(struct tc_action *a, bool bind, bool strict);
159

160
static inline int tcf_idr_release(struct tc_action *a, bool bind)
161
{
162
	return __tcf_idr_release(a, bind, false);
163 164
}

165
int tcf_register_action(struct tc_action_ops *a, struct pernet_operations *ops);
166 167
int tcf_unregister_action(struct tc_action_ops *a,
			  struct pernet_operations *ops);
168
int tcf_action_destroy(struct list_head *actions, int bind);
169 170
int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,
		    int nr_actions, struct tcf_result *res);
171 172
int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
		    struct nlattr *est, char *name, int ovr, int bind,
173
		    struct list_head *actions, size_t *attr_size,
174
		    bool rtnl_held, struct netlink_ext_ack *extack);
175 176
struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
				    struct nlattr *nla, struct nlattr *est,
177
				    char *name, int ovr, int bind,
178
				    bool rtnl_held,
179
				    struct netlink_ext_ack *extack);
180
int tcf_action_dump(struct sk_buff *skb, struct list_head *, int, int);
181 182 183
int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
int tcf_action_copy_stats(struct sk_buff *, struct tc_action *, int);
184

185
#endif /* CONFIG_NET_CLS_ACT */
186

187 188 189
static inline void tcf_action_stats_update(struct tc_action *a, u64 bytes,
					   u64 packets, u64 lastuse)
{
190
#ifdef CONFIG_NET_CLS_ACT
191 192 193 194
	if (!a->ops->stats_update)
		return;

	a->ops->stats_update(a, bytes, packets, lastuse);
195
#endif
196 197
}

198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
#ifdef CONFIG_NET_CLS_ACT
int tc_setup_cb_egdev_register(const struct net_device *dev,
			       tc_setup_cb_t *cb, void *cb_priv);
void tc_setup_cb_egdev_unregister(const struct net_device *dev,
				  tc_setup_cb_t *cb, void *cb_priv);
int tc_setup_cb_egdev_call(const struct net_device *dev,
			   enum tc_setup_type type, void *type_data,
			   bool err_stop);
#else
static inline
int tc_setup_cb_egdev_register(const struct net_device *dev,
			       tc_setup_cb_t *cb, void *cb_priv)
{
	return 0;
}

static inline
void tc_setup_cb_egdev_unregister(const struct net_device *dev,
				  tc_setup_cb_t *cb, void *cb_priv)
{
}

static inline
int tc_setup_cb_egdev_call(const struct net_device *dev,
			   enum tc_setup_type type, void *type_data,
			   bool err_stop)
{
	return 0;
}
#endif

L
Linus Torvalds 已提交
229
#endif