ng_sscop_cust.h revision 137199
1/*
2 * Copyright (c) 2001-2003
3 *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4 * 	All rights reserved.
5 *
6 * Author: Harti Brandt <harti@freebsd.org>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD: head/sys/netgraph/atm/sscop/ng_sscop_cust.h 137199 2004-11-04 12:33:55Z harti $
30 *
31 * Customisation of the SSCOP code to ng_sscop.
32 */
33
34#include <sys/param.h>
35#include <sys/types.h>
36#include <sys/kernel.h>
37#include <sys/lock.h>
38#include <sys/mutex.h>
39#include <sys/mbuf.h>
40#include <sys/queue.h>
41#include <sys/systm.h>
42#include <sys/malloc.h>
43#include <netgraph/ng_message.h>
44#include <netgraph/netgraph.h>
45#include <machine/stdarg.h>
46
47#include <netnatm/saal/sscopdef.h>
48
49/*
50 * Allocate zeroed or non-zeroed memory of some size and cast it.
51 * Return NULL on failure.
52 */
53#ifndef SSCOP_DEBUG
54
55#define	MEMINIT() \
56	MALLOC_DECLARE(M_NG_SSCOP); \
57	DECL_MSGQ_GET \
58	DECL_SIGQ_GET \
59	DECL_MBUF_ALLOC
60
61#define	MEMZALLOC(PTR, CAST, SIZE) \
62	((PTR) = (CAST)malloc((SIZE), M_NG_SSCOP, M_NOWAIT | M_ZERO))
63#define	MEMFREE(PTR) \
64	free((PTR), M_NG_SSCOP)
65
66#define	MSG_ALLOC(PTR) \
67	MEMZALLOC(PTR, struct sscop_msg *, sizeof(struct sscop_msg))
68#define	MSG_FREE(PTR) \
69	MEMFREE(PTR)
70
71#define	SIG_ALLOC(PTR) \
72	MEMZALLOC(PTR, struct sscop_sig *, sizeof(struct sscop_sig))
73#define	SIG_FREE(PTR) \
74	MEMFREE(PTR)
75
76#else
77
78#define	MEMINIT() 							\
79	MALLOC_DEFINE(M_NG_SSCOP_INS, "sscop_ins", "SSCOP instances");	\
80	MALLOC_DEFINE(M_NG_SSCOP_MSG, "sscop_msg", "SSCOP buffers");	\
81	MALLOC_DEFINE(M_NG_SSCOP_SIG, "sscop_sig", "SSCOP signals");	\
82	DECL_MSGQ_GET \
83	DECL_SIGQ_GET \
84	DECL_MBUF_ALLOC
85
86#define	MEMZALLOC(PTR, CAST, SIZE)					\
87	((PTR) = (CAST)malloc((SIZE), M_NG_SSCOP_INS, M_NOWAIT | M_ZERO))
88#define	MEMFREE(PTR)							\
89	free((PTR), M_NG_SSCOP_INS)
90
91#define	MSG_ALLOC(PTR)							\
92	((PTR) = malloc(sizeof(struct sscop_msg),			\
93	    M_NG_SSCOP_MSG, M_NOWAIT | M_ZERO))
94#define	MSG_FREE(PTR)							\
95	free((PTR), M_NG_SSCOP_MSG)
96
97#define	SIG_ALLOC(PTR)							\
98	((PTR) = malloc(sizeof(struct sscop_sig),			\
99	    M_NG_SSCOP_SIG, M_NOWAIT | M_ZERO))
100#define	SIG_FREE(PTR)							\
101	free((PTR), M_NG_SSCOP_SIG)
102
103#endif
104
105/*
106 * Timer support.
107 */
108typedef struct callout sscop_timer_t;
109#define	TIMER_INIT(S, T)	ng_callout_init(&(S)->t_##T)
110#define	TIMER_STOP(S,T)	do {						\
111	ng_untimeout(&(S)->t_##T, (S)->aarg);				\
112    } while (0)
113#define	TIMER_RESTART(S, T) do {					\
114	ng_timeout(&(S)->t_##T, (S)->aarg, NULL,			\
115	    hz * (S)->timer##T / 1000, T##_func, (S), 0);		\
116    } while (0)
117#define	TIMER_ISACT(S, T) ((S)->t_##T.c_flags & (CALLOUT_PENDING))
118
119/*
120 * This assumes, that the user argument is the node pointer.
121 */
122#define	TIMER_FUNC(T,N)							\
123static void								\
124T##_func(node_p node, hook_p hook, void *arg1, int arg2)		\
125{									\
126	struct sscop *sscop = arg1;					\
127									\
128	VERBOSE(sscop, SSCOP_DBG_TIMER, (sscop, sscop->aarg,		\
129	    "timer_" #T " expired"));					\
130	sscop_signal(sscop, SIG_T_##N, NULL);				\
131}
132
133
134/*
135 * Message queues
136 */
137typedef TAILQ_ENTRY(sscop_msg) sscop_msgq_link_t;
138typedef TAILQ_HEAD(sscop_msgq, sscop_msg) sscop_msgq_head_t;
139#define	MSGQ_EMPTY(Q)		TAILQ_EMPTY(Q)
140#define	MSGQ_INIT(Q)		TAILQ_INIT(Q)
141#define	MSGQ_FOREACH(P, Q)	TAILQ_FOREACH(P, Q, link)
142#define	MSGQ_REMOVE(Q, M)	TAILQ_REMOVE(Q, M, link)
143#define	MSGQ_INSERT_BEFORE(B, M) TAILQ_INSERT_BEFORE(B, M, link)
144#define	MSGQ_APPEND(Q, M)	TAILQ_INSERT_TAIL(Q, M, link)
145#define	MSGQ_PEEK(Q)		TAILQ_FIRST((Q))
146
147#define	MSGQ_GET(Q) ng_sscop_msgq_get((Q))
148
149#define DECL_MSGQ_GET							\
150static __inline struct sscop_msg *					\
151ng_sscop_msgq_get(struct sscop_msgq *q)					\
152{									\
153	struct sscop_msg *m;						\
154									\
155	m = TAILQ_FIRST(q);						\
156	if (m != NULL)							\
157		TAILQ_REMOVE(q, m, link);				\
158	return (m);							\
159}
160
161#define	MSGQ_CLEAR(Q)							\
162	do {								\
163		struct sscop_msg *_m1, *_m2;				\
164									\
165		_m1 = TAILQ_FIRST(Q);					\
166		while (_m1 != NULL) {					\
167			_m2 = TAILQ_NEXT(_m1, link);			\
168			SSCOP_MSG_FREE(_m1);				\
169			_m1 = _m2;					\
170		}							\
171		TAILQ_INIT((Q));					\
172	} while (0)
173
174/*
175 * Signal queues
176 */
177typedef TAILQ_ENTRY(sscop_sig) sscop_sigq_link_t;
178typedef TAILQ_HEAD(sscop_sigq, sscop_sig) sscop_sigq_head_t;
179#define	SIGQ_INIT(Q) 		TAILQ_INIT(Q)
180#define	SIGQ_APPEND(Q, S)	TAILQ_INSERT_TAIL(Q, S, link)
181#define	SIGQ_EMPTY(Q)		TAILQ_EMPTY(Q)
182
183#define	SIGQ_GET(Q)	ng_sscop_sigq_get((Q))
184#define	DECL_SIGQ_GET							\
185static __inline struct sscop_sig *					\
186ng_sscop_sigq_get(struct sscop_sigq *q)					\
187{									\
188	struct sscop_sig *s;						\
189									\
190	s = TAILQ_FIRST(q);						\
191	if (s != NULL)							\
192		TAILQ_REMOVE(q, s, link);				\
193	return (s);							\
194}
195
196#define	SIGQ_MOVE(F, T)							\
197    do {								\
198	struct sscop_sig *_s;						\
199									\
200	while (!TAILQ_EMPTY(F)) {					\
201		_s = TAILQ_FIRST(F);					\
202		TAILQ_REMOVE(F, _s, link);				\
203		TAILQ_INSERT_TAIL(T, _s, link);				\
204	}								\
205    } while (0)
206
207#define	SIGQ_PREPEND(F, T)						\
208    do {								\
209	struct sscop_sig *_s;						\
210									\
211	while (!TAILQ_EMPTY(F)) {					\
212		_s = TAILQ_LAST(F, sscop_sigq);				\
213		TAILQ_REMOVE(F, _s, link);				\
214		TAILQ_INSERT_HEAD(T, _s, link);				\
215	}								\
216    } while (0)
217
218#define	SIGQ_CLEAR(Q)							\
219    do {								\
220	struct sscop_sig *_s1, *_s2;					\
221									\
222	_s1 = TAILQ_FIRST(Q);						\
223	while (_s1 != NULL) {						\
224		_s2 = TAILQ_NEXT(_s1, link);				\
225		SSCOP_MSG_FREE(_s1->msg);				\
226		SIG_FREE(_s1);						\
227		_s1 = _s2;						\
228	}								\
229	TAILQ_INIT(Q);							\
230    } while (0)
231
232/*
233 * Message buffers
234 */
235#define	MBUF_FREE(M)	do { if ((M)) m_freem((M)); } while(0)
236#define	MBUF_DUP(M)	m_copypacket((M), M_NOWAIT)
237#define	MBUF_LEN(M) 	((size_t)(M)->m_pkthdr.len)
238
239/*
240 * Return the i-th word counted from the end of the buffer.
241 * i=-1 will return the last 32bit word, i=-2 the 2nd last.
242 * Assumes that there is enough space.
243 */
244#define	MBUF_TRAIL32(M ,I) ng_sscop_mbuf_trail32((M), (I))
245
246static uint32_t __inline
247ng_sscop_mbuf_trail32(const struct mbuf *m, int i)
248{
249	uint32_t w;
250
251	m_copydata(m, m->m_pkthdr.len + 4 * i, 4, (caddr_t)&w);
252	return (ntohl(w));
253}
254
255/*
256 * Strip 32bit value from the end
257 */
258#define	MBUF_STRIP32(M) ng_sscop_mbuf_strip32((M))
259
260static uint32_t __inline
261ng_sscop_mbuf_strip32(struct mbuf *m)
262{
263	uint32_t w;
264
265	m_copydata(m, m->m_pkthdr.len - 4, 4, (caddr_t)&w);
266	m_adj(m, -4);
267	return (ntohl(w));
268}
269
270#define	MBUF_GET32(M) ng_sscop_mbuf_get32((M))
271
272static uint32_t __inline
273ng_sscop_mbuf_get32(struct mbuf *m)
274{
275	uint32_t w;
276
277	m_copydata(m, 0, 4, (caddr_t)&w);
278	m_adj(m, 4);
279	return (ntohl(w));
280}
281
282/*
283 * Append a 32bit value to an mbuf. Failures are ignored.
284 */
285#define	MBUF_APPEND32(M, W)						\
286     do {								\
287	uint32_t _w = (W);						\
288									\
289	_w = htonl(_w);							\
290	m_copyback((M), (M)->m_pkthdr.len, 4, (caddr_t)&_w);		\
291    } while (0)
292
293/*
294 * Pad a message to a multiple of four byte and return the amount of padding
295 * Failures are ignored.
296 */
297#define	MBUF_PAD4(M) ng_sscop_mbuf_pad4((M))
298
299static u_int __inline
300ng_sscop_mbuf_pad4(struct mbuf *m)
301{
302	static u_char pad[4] = { 0, 0, 0, 0 };
303	int len = m->m_pkthdr.len;
304	int npad = 3 - ((len + 3) & 3);
305
306	if (npad != 0)
307		m_copyback(m, len, npad, (caddr_t)pad);
308	return (npad);
309}
310
311#define	MBUF_UNPAD(M, P) do { if( (P) > 0) m_adj((M), -(P)); } while (0)
312
313/*
314 * Allocate a message that will probably hold N bytes.
315 */
316#define	MBUF_ALLOC(N) ng_sscop_mbuf_alloc((N))
317
318#define	DECL_MBUF_ALLOC							\
319static __inline struct mbuf *						\
320ng_sscop_mbuf_alloc(size_t n)						\
321{									\
322	struct mbuf *m;							\
323									\
324	MGETHDR(m, M_NOWAIT, MT_DATA);					\
325	if (m != NULL) {						\
326		m->m_len = 0;						\
327		m->m_pkthdr.len = 0;					\
328		if (n > MHLEN) {					\
329			MCLGET(m, M_NOWAIT);				\
330			if (!(m->m_flags & M_EXT)){			\
331				m_free(m);				\
332				m = NULL;				\
333			}						\
334		}							\
335	}								\
336	return (m);							\
337}
338
339#ifdef SSCOP_DEBUG
340#define	ASSERT(X)	KASSERT(X, (#X))
341#else
342#define	ASSERT(X)
343#endif
344