⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 em_meta.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * net/sched/em_meta.c	Metadata ematch * *		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:	Thomas Graf <tgraf@suug.ch> * * ========================================================================== * * 	The metadata ematch compares two meta objects where each object * 	represents either a meta value stored in the kernel or a static * 	value provided by userspace. The objects are not provided by * 	userspace itself but rather a definition providing the information * 	to build them. Every object is of a certain type which must be * 	equal to the object it is being compared to. * * 	The definition of a objects conists of the type (meta type), a * 	identifier (meta id) and additional type specific information. * 	The meta id is either TCF_META_TYPE_VALUE for values provided by * 	userspace or a index to the meta operations table consisting of * 	function pointers to type specific meta data collectors returning * 	the value of the requested meta value. * * 	         lvalue                                   rvalue * 	      +-----------+                           +-----------+ * 	      | type: INT |                           | type: INT | * 	 def  | id: DEV   |                           | id: VALUE | * 	      | data:     |                           | data: 3   | * 	      +-----------+                           +-----------+ * 	            |                                       | * 	            ---> meta_ops[INT][DEV](...)            | *	                      |                             | * 	            -----------                             | * 	            V                                       V * 	      +-----------+                           +-----------+ * 	      | type: INT |                           | type: INT | * 	 obj  | id: DEV |                             | id: VALUE | * 	      | data: 2   |<--data got filled out     | data: 3   | * 	      +-----------+                           +-----------+ * 	            |                                         | * 	            --------------> 2  equals 3 <-------------- * * 	This is a simplified schema, the complexity varies depending * 	on the meta type. Obviously, the length of the data must also * 	be provided for non-numeric types. * * 	Additionaly, type dependant modifiers such as shift operators * 	or mask may be applied to extend the functionaliy. As of now, * 	the variable length type supports shifting the byte string to * 	the right, eating up any number of octets and thus supporting * 	wildcard interface name comparisons such as "ppp%" matching * 	ppp0..9. * * 	NOTE: Certain meta values depend on other subsystems and are * 	      only available if that subsystem is enabled in the kernel. */#include <linux/module.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/skbuff.h>#include <linux/random.h>#include <linux/tc_ematch/tc_em_meta.h>#include <net/dst.h>#include <net/route.h>#include <net/pkt_cls.h>#include <net/sock.h>struct meta_obj{	unsigned long		value;	unsigned int		len;};struct meta_value{	struct tcf_meta_val	hdr;	unsigned long		val;	unsigned int		len;};struct meta_match{	struct meta_value	lvalue;	struct meta_value	rvalue;};static inline int meta_id(struct meta_value *v){	return TCF_META_ID(v->hdr.kind);}static inline int meta_type(struct meta_value *v){	return TCF_META_TYPE(v->hdr.kind);}#define META_COLLECTOR(FUNC) static void meta_##FUNC(struct sk_buff *skb, \	struct tcf_pkt_info *info, struct meta_value *v, \	struct meta_obj *dst, int *err)/************************************************************************** * System status & misc **************************************************************************/META_COLLECTOR(int_random){	get_random_bytes(&dst->value, sizeof(dst->value));}static inline unsigned long fixed_loadavg(int load){	int rnd_load = load + (FIXED_1/200);	int rnd_frac = ((rnd_load & (FIXED_1-1)) * 100) >> FSHIFT;	return ((rnd_load >> FSHIFT) * 100) + rnd_frac;}META_COLLECTOR(int_loadavg_0){	dst->value = fixed_loadavg(avenrun[0]);}META_COLLECTOR(int_loadavg_1){	dst->value = fixed_loadavg(avenrun[1]);}META_COLLECTOR(int_loadavg_2){	dst->value = fixed_loadavg(avenrun[2]);}/************************************************************************** * Device names & indices **************************************************************************/static inline int int_dev(struct net_device *dev, struct meta_obj *dst){	if (unlikely(dev == NULL))		return -1;	dst->value = dev->ifindex;	return 0;}static inline int var_dev(struct net_device *dev, struct meta_obj *dst){	if (unlikely(dev == NULL))		return -1;	dst->value = (unsigned long) dev->name;	dst->len = strlen(dev->name);	return 0;}META_COLLECTOR(int_dev){	*err = int_dev(skb->dev, dst);}META_COLLECTOR(var_dev){	*err = var_dev(skb->dev, dst);}/************************************************************************** * skb attributes **************************************************************************/META_COLLECTOR(int_priority){	dst->value = skb->priority;}META_COLLECTOR(int_protocol){	/* Let userspace take care of the byte ordering */	dst->value = skb->protocol;}META_COLLECTOR(int_pkttype){	dst->value = skb->pkt_type;}META_COLLECTOR(int_pktlen){	dst->value = skb->len;}META_COLLECTOR(int_datalen){	dst->value = skb->data_len;}META_COLLECTOR(int_maclen){	dst->value = skb->mac_len;}/************************************************************************** * Netfilter **************************************************************************/META_COLLECTOR(int_mark){	dst->value = skb->mark;}/************************************************************************** * Traffic Control **************************************************************************/META_COLLECTOR(int_tcindex){	dst->value = skb->tc_index;}/************************************************************************** * Routing **************************************************************************/META_COLLECTOR(int_rtclassid){	if (unlikely(skb->dst == NULL))		*err = -1;	else#ifdef CONFIG_NET_CLS_ROUTE		dst->value = skb->dst->tclassid;#else		dst->value = 0;#endif}META_COLLECTOR(int_rtiif){	if (unlikely(skb->dst == NULL))		*err = -1;	else		dst->value = ((struct rtable*) skb->dst)->fl.iif;}/************************************************************************** * Socket Attributes **************************************************************************/#define SKIP_NONLOCAL(skb)			\	if (unlikely(skb->sk == NULL)) {	\		*err = -1;			\		return;				\	}META_COLLECTOR(int_sk_family){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_family;}META_COLLECTOR(int_sk_state){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_state;}META_COLLECTOR(int_sk_reuse){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_reuse;}META_COLLECTOR(int_sk_bound_if){	SKIP_NONLOCAL(skb);	/* No error if bound_dev_if is 0, legal userspace check */	dst->value = skb->sk->sk_bound_dev_if;}META_COLLECTOR(var_sk_bound_if){	SKIP_NONLOCAL(skb);	 if (skb->sk->sk_bound_dev_if == 0) {		dst->value = (unsigned long) "any";		dst->len = 3;	 } else  {		struct net_device *dev;		dev = dev_get_by_index(&init_net, skb->sk->sk_bound_dev_if);		*err = var_dev(dev, dst);		if (dev)			dev_put(dev);	 }}META_COLLECTOR(int_sk_refcnt){	SKIP_NONLOCAL(skb);	dst->value = atomic_read(&skb->sk->sk_refcnt);}META_COLLECTOR(int_sk_rcvbuf){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_rcvbuf;}META_COLLECTOR(int_sk_shutdown){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_shutdown;}META_COLLECTOR(int_sk_proto){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_protocol;}META_COLLECTOR(int_sk_type){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_type;}META_COLLECTOR(int_sk_rmem_alloc){	SKIP_NONLOCAL(skb);	dst->value = atomic_read(&skb->sk->sk_rmem_alloc);}META_COLLECTOR(int_sk_wmem_alloc){	SKIP_NONLOCAL(skb);	dst->value = atomic_read(&skb->sk->sk_wmem_alloc);}META_COLLECTOR(int_sk_omem_alloc){	SKIP_NONLOCAL(skb);	dst->value = atomic_read(&skb->sk->sk_omem_alloc);}META_COLLECTOR(int_sk_rcv_qlen){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_receive_queue.qlen;}META_COLLECTOR(int_sk_snd_qlen){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_write_queue.qlen;}META_COLLECTOR(int_sk_wmem_queued){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_wmem_queued;}META_COLLECTOR(int_sk_fwd_alloc){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_forward_alloc;}META_COLLECTOR(int_sk_sndbuf){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_sndbuf;}META_COLLECTOR(int_sk_alloc){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_allocation;}META_COLLECTOR(int_sk_route_caps){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_route_caps;}META_COLLECTOR(int_sk_hash){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_hash;}META_COLLECTOR(int_sk_lingertime){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_lingertime / HZ;}META_COLLECTOR(int_sk_err_qlen){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_error_queue.qlen;}META_COLLECTOR(int_sk_ack_bl){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_ack_backlog;}META_COLLECTOR(int_sk_max_ack_bl){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_max_ack_backlog;}META_COLLECTOR(int_sk_prio){	SKIP_NONLOCAL(skb);	dst->value = skb->sk->sk_priority;}META_COLLECTOR(int_sk_rcvlowat)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -