snmp.h 6.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 *
 *		SNMP MIB entries for the IP subsystem.
 *		
 *		Alan Cox <gw4pts@gw4pts.ampr.org>
 *
 *		We don't chose to implement SNMP in the kernel (this would
 *		be silly as SNMP is a pain in the backside in places). We do
 *		however need to collect the MIB statistics and export them
 *		out of /proc (eventually)
 *
 *		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.
 *
 */
 
#ifndef _SNMP_H
#define _SNMP_H

#include <linux/cache.h>
#include <linux/snmp.h>
24
#include <linux/smp.h>
L
Linus Torvalds 已提交
25 26 27 28 29 30 31 32 33 34

/*
 * Mibs are stored in array of unsigned long.
 */
/*
 * struct snmp_mib{}
 *  - list of entries for particular API (such as /proc/net/snmp)
 *  - name of entries.
 */
struct snmp_mib {
A
Alexey Dobriyan 已提交
35
	const char *name;
L
Linus Torvalds 已提交
36 37 38 39 40 41 42 43 44 45 46 47 48 49
	int entry;
};

#define SNMP_MIB_ITEM(_name,_entry)	{	\
	.name = _name,				\
	.entry = _entry,			\
}

#define SNMP_MIB_SENTINEL {	\
	.name = NULL,		\
	.entry = 0,		\
}

/*
50
 * We use unsigned longs for most mibs but u64 for ipstats.
L
Linus Torvalds 已提交
51
 */
52
#include <linux/u64_stats_sync.h>
L
Linus Torvalds 已提交
53 54 55 56

/* IPstats */
#define IPSTATS_MIB_MAX	__IPSTATS_MIB_MAX
struct ipstats_mib {
57 58 59
	/* mibs[] must be first field of struct ipstats_mib */
	u64		mibs[IPSTATS_MIB_MAX];
	struct u64_stats_sync syncp;
E
Eric Dumazet 已提交
60
};
L
Linus Torvalds 已提交
61 62

/* ICMP */
63
#define ICMP_MIB_MAX	__ICMP_MIB_MAX
L
Linus Torvalds 已提交
64 65
struct icmp_mib {
	unsigned long	mibs[ICMP_MIB_MAX];
E
Eric Dumazet 已提交
66
};
L
Linus Torvalds 已提交
67

68 69 70
#define ICMPMSG_MIB_MAX	__ICMPMSG_MIB_MAX
struct icmpmsg_mib {
	unsigned long	mibs[ICMPMSG_MIB_MAX];
E
Eric Dumazet 已提交
71
};
72

L
Linus Torvalds 已提交
73 74 75 76
/* ICMP6 (IPv6-ICMP) */
#define ICMP6_MIB_MAX	__ICMP6_MIB_MAX
struct icmpv6_mib {
	unsigned long	mibs[ICMP6_MIB_MAX];
E
Eric Dumazet 已提交
77
};
L
Linus Torvalds 已提交
78

79 80 81
#define ICMP6MSG_MIB_MAX  __ICMP6MSG_MIB_MAX
struct icmpv6msg_mib {
	unsigned long	mibs[ICMP6MSG_MIB_MAX];
E
Eric Dumazet 已提交
82
};
83 84


L
Linus Torvalds 已提交
85 86 87 88
/* TCP */
#define TCP_MIB_MAX	__TCP_MIB_MAX
struct tcp_mib {
	unsigned long	mibs[TCP_MIB_MAX];
E
Eric Dumazet 已提交
89
};
L
Linus Torvalds 已提交
90 91 92 93 94

/* UDP */
#define UDP_MIB_MAX	__UDP_MIB_MAX
struct udp_mib {
	unsigned long	mibs[UDP_MIB_MAX];
E
Eric Dumazet 已提交
95
};
L
Linus Torvalds 已提交
96 97 98 99 100 101 102

/* Linux */
#define LINUX_MIB_MAX	__LINUX_MIB_MAX
struct linux_mib {
	unsigned long	mibs[LINUX_MIB_MAX];
};

103 104 105 106 107
/* Linux Xfrm */
#define LINUX_MIB_XFRMMAX	__LINUX_MIB_XFRMMAX
struct linux_xfrm_mib {
	unsigned long	mibs[LINUX_MIB_XFRMMAX];
};
L
Linus Torvalds 已提交
108 109 110 111 112 113 114 115

/* 
 * FIXME: On x86 and some other CPUs the split into user and softirq parts
 * is not needed because addl $1,memory is atomic against interrupts (but 
 * atomic_inc would be overkill because of the lock cycles). Wants new 
 * nonlocked_atomic_inc() primitives -AK
 */ 
#define DEFINE_SNMP_STAT(type, name)	\
116
	__typeof__(type) __percpu *name[2]
L
Linus Torvalds 已提交
117
#define DECLARE_SNMP_STAT(type, name)	\
118
	extern __typeof__(type) __percpu *name[2]
L
Linus Torvalds 已提交
119 120 121 122

#define SNMP_STAT_BHPTR(name)	(name[0])
#define SNMP_STAT_USRPTR(name)	(name[1])

123 124 125 126 127 128 129 130 131 132 133 134
#define SNMP_INC_STATS_BH(mib, field)	\
			__this_cpu_inc(mib[0]->mibs[field])
#define SNMP_INC_STATS_USER(mib, field)	\
			this_cpu_inc(mib[1]->mibs[field])
#define SNMP_INC_STATS(mib, field)	\
			this_cpu_inc(mib[!in_softirq()]->mibs[field])
#define SNMP_DEC_STATS(mib, field)	\
			this_cpu_dec(mib[!in_softirq()]->mibs[field])
#define SNMP_ADD_STATS_BH(mib, field, addend)	\
			__this_cpu_add(mib[0]->mibs[field], addend)
#define SNMP_ADD_STATS_USER(mib, field, addend)	\
			this_cpu_add(mib[1]->mibs[field], addend)
135
#define SNMP_ADD_STATS(mib, field, addend)	\
E
Eric Dumazet 已提交
136
			this_cpu_add(mib[!in_softirq()]->mibs[field], addend)
137 138 139 140
/*
 * Use "__typeof__(*mib[0]) *ptr" instead of "__typeof__(mib[0]) ptr"
 * to make @ptr a non-percpu pointer.
 */
141 142
#define SNMP_UPD_PO_STATS(mib, basefield, addend)	\
	do { \
143
		__typeof__(*mib[0]) *ptr; \
144 145
		preempt_disable(); \
		ptr = this_cpu_ptr((mib)[!in_softirq()]); \
146 147
		ptr->mibs[basefield##PKTS]++; \
		ptr->mibs[basefield##OCTETS] += addend;\
148
		preempt_enable(); \
149 150 151
	} while (0)
#define SNMP_UPD_PO_STATS_BH(mib, basefield, addend)	\
	do { \
152
		__typeof__(*mib[0]) *ptr = \
153
			__this_cpu_ptr((mib)[!in_softirq()]); \
154 155 156
		ptr->mibs[basefield##PKTS]++; \
		ptr->mibs[basefield##OCTETS] += addend;\
	} while (0)
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 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


#if BITS_PER_LONG==32

#define SNMP_ADD_STATS64_BH(mib, field, addend) 			\
	do {								\
		__typeof__(*mib[0]) *ptr = __this_cpu_ptr((mib)[0]);	\
		u64_stats_update_begin(&ptr->syncp);			\
		ptr->mibs[field] += addend;				\
		u64_stats_update_end(&ptr->syncp);			\
	} while (0)
#define SNMP_ADD_STATS64_USER(mib, field, addend) 			\
	do {								\
		__typeof__(*mib[0]) *ptr;				\
		preempt_disable();					\
		ptr = __this_cpu_ptr((mib)[1]);				\
		u64_stats_update_begin(&ptr->syncp);			\
		ptr->mibs[field] += addend;				\
		u64_stats_update_end(&ptr->syncp);			\
		preempt_enable();					\
	} while (0)
#define SNMP_ADD_STATS64(mib, field, addend)				\
	do {								\
		__typeof__(*mib[0]) *ptr;				\
		preempt_disable();					\
		ptr = __this_cpu_ptr((mib)[!in_softirq()]);		\
		u64_stats_update_begin(&ptr->syncp);			\
		ptr->mibs[field] += addend;				\
		u64_stats_update_end(&ptr->syncp);			\
		preempt_enable();					\
	} while (0)
#define SNMP_INC_STATS64_BH(mib, field) SNMP_ADD_STATS64_BH(mib, field, 1)
#define SNMP_INC_STATS64_USER(mib, field) SNMP_ADD_STATS64_USER(mib, field, 1)
#define SNMP_INC_STATS64(mib, field) SNMP_ADD_STATS64(mib, field, 1)
#define SNMP_UPD_PO_STATS64(mib, basefield, addend)			\
	do {								\
		__typeof__(*mib[0]) *ptr;				\
		preempt_disable();					\
		ptr = __this_cpu_ptr((mib)[!in_softirq()]);		\
		u64_stats_update_begin(&ptr->syncp);			\
		ptr->mibs[basefield##PKTS]++;				\
		ptr->mibs[basefield##OCTETS] += addend;			\
		u64_stats_update_end(&ptr->syncp);			\
		preempt_enable();					\
	} while (0)
#define SNMP_UPD_PO_STATS64_BH(mib, basefield, addend)			\
	do {								\
		__typeof__(*mib[0]) *ptr;				\
		ptr = __this_cpu_ptr((mib)[!in_softirq()]);		\
		u64_stats_update_begin(&ptr->syncp);			\
		ptr->mibs[basefield##PKTS]++;				\
		ptr->mibs[basefield##OCTETS] += addend;			\
		u64_stats_update_end(&ptr->syncp);			\
	} while (0)
#else
#define SNMP_INC_STATS64_BH(mib, field)		SNMP_INC_STATS_BH(mib, field)
#define SNMP_INC_STATS64_USER(mib, field)	SNMP_INC_STATS_USER(mib, field)
#define SNMP_INC_STATS64(mib, field)		SNMP_INC_STATS(mib, field)
#define SNMP_DEC_STATS64(mib, field)		SNMP_DEC_STATS(mib, field)
#define SNMP_ADD_STATS64_BH(mib, field, addend) SNMP_ADD_STATS_BH(mib, field, addend)
#define SNMP_ADD_STATS64_USER(mib, field, addend) SNMP_ADD_STATS_USER(mib, field, addend)
#define SNMP_ADD_STATS64(mib, field, addend)	SNMP_ADD_STATS(mib, field, addend)
#define SNMP_UPD_PO_STATS64(mib, basefield, addend) SNMP_UPD_PO_STATS(mib, basefield, addend)
#define SNMP_UPD_PO_STATS64_BH(mib, basefield, addend) SNMP_UPD_PO_STATS_BH(mib, basefield, addend)
#endif

L
Linus Torvalds 已提交
223
#endif