1139823Simp/*-
2121461Sharti * Copyright (c) 2001-2003
3121461Sharti *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4121461Sharti * 	All rights reserved.
5121461Sharti *
6121461Sharti * Author: Harti Brandt <harti@freebsd.org>
7121461Sharti *
8121461Sharti * Redistribution and use in source and binary forms, with or without
9121461Sharti * modification, are permitted provided that the following conditions
10121461Sharti * are met:
11121461Sharti * 1. Redistributions of source code must retain the above copyright
12121461Sharti *    notice, this list of conditions and the following disclaimer.
13121461Sharti * 2. Redistributions in binary form must reproduce the above copyright
14121461Sharti *    notice, this list of conditions and the following disclaimer in the
15121461Sharti *    documentation and/or other materials provided with the distribution.
16121461Sharti *
17121461Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18121461Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19121461Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20121461Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21121461Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22121461Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23121461Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24121461Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25121461Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26121461Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27121461Sharti * SUCH DAMAGE.
28121461Sharti *
29121461Sharti * $FreeBSD$
30121461Sharti *
31121461Sharti * Customisation of the SSCOP code to ng_sscop.
32121461Sharti */
33121461Sharti
34121461Sharti#include <sys/param.h>
35121461Sharti#include <sys/types.h>
36121461Sharti#include <sys/kernel.h>
37121461Sharti#include <sys/lock.h>
38121461Sharti#include <sys/mutex.h>
39121461Sharti#include <sys/mbuf.h>
40121461Sharti#include <sys/queue.h>
41121461Sharti#include <sys/systm.h>
42121461Sharti#include <sys/malloc.h>
43121461Sharti#include <netgraph/ng_message.h>
44121461Sharti#include <netgraph/netgraph.h>
45121461Sharti#include <machine/stdarg.h>
46121461Sharti
47121461Sharti#include <netnatm/saal/sscopdef.h>
48121461Sharti
49121461Sharti/*
50121461Sharti * Allocate zeroed or non-zeroed memory of some size and cast it.
51121461Sharti * Return NULL on failure.
52121461Sharti */
53121461Sharti#ifndef SSCOP_DEBUG
54121461Sharti
55121461Sharti#define	MEMINIT() \
56121461Sharti	MALLOC_DECLARE(M_NG_SSCOP); \
57121461Sharti	DECL_MSGQ_GET \
58121461Sharti	DECL_SIGQ_GET \
59121461Sharti	DECL_MBUF_ALLOC
60121461Sharti
61121461Sharti#define	MEMZALLOC(PTR, CAST, SIZE) \
62121461Sharti	((PTR) = (CAST)malloc((SIZE), M_NG_SSCOP, M_NOWAIT | M_ZERO))
63121461Sharti#define	MEMFREE(PTR) \
64121461Sharti	free((PTR), M_NG_SSCOP)
65121461Sharti
66121461Sharti#define	MSG_ALLOC(PTR) \
67121461Sharti	MEMZALLOC(PTR, struct sscop_msg *, sizeof(struct sscop_msg))
68121461Sharti#define	MSG_FREE(PTR) \
69121461Sharti	MEMFREE(PTR)
70121461Sharti
71121461Sharti#define	SIG_ALLOC(PTR) \
72121461Sharti	MEMZALLOC(PTR, struct sscop_sig *, sizeof(struct sscop_sig))
73121461Sharti#define	SIG_FREE(PTR) \
74121461Sharti	MEMFREE(PTR)
75121461Sharti
76121461Sharti#else
77121461Sharti
78121461Sharti#define	MEMINIT() 							\
79121461Sharti	MALLOC_DEFINE(M_NG_SSCOP_INS, "sscop_ins", "SSCOP instances");	\
80121461Sharti	MALLOC_DEFINE(M_NG_SSCOP_MSG, "sscop_msg", "SSCOP buffers");	\
81121461Sharti	MALLOC_DEFINE(M_NG_SSCOP_SIG, "sscop_sig", "SSCOP signals");	\
82121461Sharti	DECL_MSGQ_GET \
83121461Sharti	DECL_SIGQ_GET \
84121461Sharti	DECL_MBUF_ALLOC
85121461Sharti
86121461Sharti#define	MEMZALLOC(PTR, CAST, SIZE)					\
87121461Sharti	((PTR) = (CAST)malloc((SIZE), M_NG_SSCOP_INS, M_NOWAIT | M_ZERO))
88121461Sharti#define	MEMFREE(PTR)							\
89121461Sharti	free((PTR), M_NG_SSCOP_INS)
90121461Sharti
91121461Sharti#define	MSG_ALLOC(PTR)							\
92121461Sharti	((PTR) = malloc(sizeof(struct sscop_msg),			\
93121461Sharti	    M_NG_SSCOP_MSG, M_NOWAIT | M_ZERO))
94121461Sharti#define	MSG_FREE(PTR)							\
95121461Sharti	free((PTR), M_NG_SSCOP_MSG)
96121461Sharti
97121461Sharti#define	SIG_ALLOC(PTR)							\
98121461Sharti	((PTR) = malloc(sizeof(struct sscop_sig),			\
99121461Sharti	    M_NG_SSCOP_SIG, M_NOWAIT | M_ZERO))
100121461Sharti#define	SIG_FREE(PTR)							\
101121461Sharti	free((PTR), M_NG_SSCOP_SIG)
102121461Sharti
103121461Sharti#endif
104121461Sharti
105121461Sharti/*
106121461Sharti * Timer support.
107121461Sharti */
108137199Shartitypedef struct callout sscop_timer_t;
109137199Sharti#define	TIMER_INIT(S, T)	ng_callout_init(&(S)->t_##T)
110121461Sharti#define	TIMER_STOP(S,T)	do {						\
111138268Sglebius	ng_uncallout(&(S)->t_##T, (S)->aarg);				\
112121461Sharti    } while (0)
113121461Sharti#define	TIMER_RESTART(S, T) do {					\
114137897Sglebius	TIMER_STOP(S, T);						\
115138268Sglebius	ng_callout(&(S)->t_##T, (S)->aarg, NULL,			\
116121461Sharti	    hz * (S)->timer##T / 1000, T##_func, (S), 0);		\
117121461Sharti    } while (0)
118280785Srrs#define	TIMER_ISACT(S, T) (callout_pending(&(S)->t_##T))
119121461Sharti
120121461Sharti/*
121121461Sharti * This assumes, that the user argument is the node pointer.
122121461Sharti */
123121461Sharti#define	TIMER_FUNC(T,N)							\
124121461Shartistatic void								\
125121461ShartiT##_func(node_p node, hook_p hook, void *arg1, int arg2)		\
126121461Sharti{									\
127121461Sharti	struct sscop *sscop = arg1;					\
128121461Sharti									\
129121461Sharti	VERBOSE(sscop, SSCOP_DBG_TIMER, (sscop, sscop->aarg,		\
130121461Sharti	    "timer_" #T " expired"));					\
131121461Sharti	sscop_signal(sscop, SIG_T_##N, NULL);				\
132121461Sharti}
133121461Sharti
134121461Sharti
135121461Sharti/*
136121461Sharti * Message queues
137121461Sharti */
138121461Shartitypedef TAILQ_ENTRY(sscop_msg) sscop_msgq_link_t;
139121461Shartitypedef TAILQ_HEAD(sscop_msgq, sscop_msg) sscop_msgq_head_t;
140121461Sharti#define	MSGQ_EMPTY(Q)		TAILQ_EMPTY(Q)
141121461Sharti#define	MSGQ_INIT(Q)		TAILQ_INIT(Q)
142121461Sharti#define	MSGQ_FOREACH(P, Q)	TAILQ_FOREACH(P, Q, link)
143121461Sharti#define	MSGQ_REMOVE(Q, M)	TAILQ_REMOVE(Q, M, link)
144121461Sharti#define	MSGQ_INSERT_BEFORE(B, M) TAILQ_INSERT_BEFORE(B, M, link)
145121461Sharti#define	MSGQ_APPEND(Q, M)	TAILQ_INSERT_TAIL(Q, M, link)
146121461Sharti#define	MSGQ_PEEK(Q)		TAILQ_FIRST((Q))
147121461Sharti
148121461Sharti#define	MSGQ_GET(Q) ng_sscop_msgq_get((Q))
149121461Sharti
150121461Sharti#define DECL_MSGQ_GET							\
151121461Shartistatic __inline struct sscop_msg *					\
152121461Sharting_sscop_msgq_get(struct sscop_msgq *q)					\
153121461Sharti{									\
154121461Sharti	struct sscop_msg *m;						\
155121461Sharti									\
156121461Sharti	m = TAILQ_FIRST(q);						\
157121461Sharti	if (m != NULL)							\
158121461Sharti		TAILQ_REMOVE(q, m, link);				\
159121461Sharti	return (m);							\
160121461Sharti}
161121461Sharti
162121461Sharti#define	MSGQ_CLEAR(Q)							\
163121461Sharti	do {								\
164121461Sharti		struct sscop_msg *_m1, *_m2;				\
165121461Sharti									\
166121461Sharti		_m1 = TAILQ_FIRST(Q);					\
167121461Sharti		while (_m1 != NULL) {					\
168121461Sharti			_m2 = TAILQ_NEXT(_m1, link);			\
169121461Sharti			SSCOP_MSG_FREE(_m1);				\
170121461Sharti			_m1 = _m2;					\
171121461Sharti		}							\
172121461Sharti		TAILQ_INIT((Q));					\
173121461Sharti	} while (0)
174121461Sharti
175121461Sharti/*
176121461Sharti * Signal queues
177121461Sharti */
178121461Shartitypedef TAILQ_ENTRY(sscop_sig) sscop_sigq_link_t;
179121461Shartitypedef TAILQ_HEAD(sscop_sigq, sscop_sig) sscop_sigq_head_t;
180121461Sharti#define	SIGQ_INIT(Q) 		TAILQ_INIT(Q)
181121461Sharti#define	SIGQ_APPEND(Q, S)	TAILQ_INSERT_TAIL(Q, S, link)
182121461Sharti#define	SIGQ_EMPTY(Q)		TAILQ_EMPTY(Q)
183121461Sharti
184121461Sharti#define	SIGQ_GET(Q)	ng_sscop_sigq_get((Q))
185121461Sharti#define	DECL_SIGQ_GET							\
186121461Shartistatic __inline struct sscop_sig *					\
187121461Sharting_sscop_sigq_get(struct sscop_sigq *q)					\
188121461Sharti{									\
189121461Sharti	struct sscop_sig *s;						\
190121461Sharti									\
191121461Sharti	s = TAILQ_FIRST(q);						\
192121461Sharti	if (s != NULL)							\
193121461Sharti		TAILQ_REMOVE(q, s, link);				\
194121461Sharti	return (s);							\
195121461Sharti}
196121461Sharti
197121461Sharti#define	SIGQ_MOVE(F, T)							\
198121461Sharti    do {								\
199121461Sharti	struct sscop_sig *_s;						\
200121461Sharti									\
201121461Sharti	while (!TAILQ_EMPTY(F)) {					\
202121461Sharti		_s = TAILQ_FIRST(F);					\
203121461Sharti		TAILQ_REMOVE(F, _s, link);				\
204121461Sharti		TAILQ_INSERT_TAIL(T, _s, link);				\
205121461Sharti	}								\
206121461Sharti    } while (0)
207121461Sharti
208121461Sharti#define	SIGQ_PREPEND(F, T)						\
209121461Sharti    do {								\
210121461Sharti	struct sscop_sig *_s;						\
211121461Sharti									\
212121461Sharti	while (!TAILQ_EMPTY(F)) {					\
213121461Sharti		_s = TAILQ_LAST(F, sscop_sigq);				\
214121461Sharti		TAILQ_REMOVE(F, _s, link);				\
215121461Sharti		TAILQ_INSERT_HEAD(T, _s, link);				\
216121461Sharti	}								\
217121461Sharti    } while (0)
218121461Sharti
219121461Sharti#define	SIGQ_CLEAR(Q)							\
220121461Sharti    do {								\
221121461Sharti	struct sscop_sig *_s1, *_s2;					\
222121461Sharti									\
223121461Sharti	_s1 = TAILQ_FIRST(Q);						\
224121461Sharti	while (_s1 != NULL) {						\
225121461Sharti		_s2 = TAILQ_NEXT(_s1, link);				\
226121461Sharti		SSCOP_MSG_FREE(_s1->msg);				\
227121461Sharti		SIG_FREE(_s1);						\
228121461Sharti		_s1 = _s2;						\
229121461Sharti	}								\
230121461Sharti	TAILQ_INIT(Q);							\
231121461Sharti    } while (0)
232121461Sharti
233121461Sharti/*
234121461Sharti * Message buffers
235121461Sharti */
236121461Sharti#define	MBUF_FREE(M)	do { if ((M)) m_freem((M)); } while(0)
237121461Sharti#define	MBUF_DUP(M)	m_copypacket((M), M_NOWAIT)
238121461Sharti#define	MBUF_LEN(M) 	((size_t)(M)->m_pkthdr.len)
239121461Sharti
240121461Sharti/*
241121461Sharti * Return the i-th word counted from the end of the buffer.
242121461Sharti * i=-1 will return the last 32bit word, i=-2 the 2nd last.
243121461Sharti * Assumes that there is enough space.
244121461Sharti */
245121461Sharti#define	MBUF_TRAIL32(M ,I) ng_sscop_mbuf_trail32((M), (I))
246121461Sharti
247121461Shartistatic uint32_t __inline
248121461Sharting_sscop_mbuf_trail32(const struct mbuf *m, int i)
249121461Sharti{
250121461Sharti	uint32_t w;
251121461Sharti
252121461Sharti	m_copydata(m, m->m_pkthdr.len + 4 * i, 4, (caddr_t)&w);
253121461Sharti	return (ntohl(w));
254121461Sharti}
255121461Sharti
256121461Sharti/*
257121461Sharti * Strip 32bit value from the end
258121461Sharti */
259121461Sharti#define	MBUF_STRIP32(M) ng_sscop_mbuf_strip32((M))
260121461Sharti
261121461Shartistatic uint32_t __inline
262121461Sharting_sscop_mbuf_strip32(struct mbuf *m)
263121461Sharti{
264121461Sharti	uint32_t w;
265121461Sharti
266121461Sharti	m_copydata(m, m->m_pkthdr.len - 4, 4, (caddr_t)&w);
267121461Sharti	m_adj(m, -4);
268121461Sharti	return (ntohl(w));
269121461Sharti}
270121461Sharti
271121461Sharti#define	MBUF_GET32(M) ng_sscop_mbuf_get32((M))
272121461Sharti
273121461Shartistatic uint32_t __inline
274121461Sharting_sscop_mbuf_get32(struct mbuf *m)
275121461Sharti{
276121461Sharti	uint32_t w;
277121461Sharti
278121461Sharti	m_copydata(m, 0, 4, (caddr_t)&w);
279121461Sharti	m_adj(m, 4);
280121461Sharti	return (ntohl(w));
281121461Sharti}
282121461Sharti
283121461Sharti/*
284121461Sharti * Append a 32bit value to an mbuf. Failures are ignored.
285121461Sharti */
286121461Sharti#define	MBUF_APPEND32(M, W)						\
287121461Sharti     do {								\
288121461Sharti	uint32_t _w = (W);						\
289121461Sharti									\
290121461Sharti	_w = htonl(_w);							\
291121461Sharti	m_copyback((M), (M)->m_pkthdr.len, 4, (caddr_t)&_w);		\
292121461Sharti    } while (0)
293121461Sharti
294121461Sharti/*
295121461Sharti * Pad a message to a multiple of four byte and return the amount of padding
296121461Sharti * Failures are ignored.
297121461Sharti */
298121461Sharti#define	MBUF_PAD4(M) ng_sscop_mbuf_pad4((M))
299121461Sharti
300121461Shartistatic u_int __inline
301121461Sharting_sscop_mbuf_pad4(struct mbuf *m)
302121461Sharti{
303121461Sharti	static u_char pad[4] = { 0, 0, 0, 0 };
304121461Sharti	int len = m->m_pkthdr.len;
305121461Sharti	int npad = 3 - ((len + 3) & 3);
306121461Sharti
307121461Sharti	if (npad != 0)
308121461Sharti		m_copyback(m, len, npad, (caddr_t)pad);
309121461Sharti	return (npad);
310121461Sharti}
311121461Sharti
312121461Sharti#define	MBUF_UNPAD(M, P) do { if( (P) > 0) m_adj((M), -(P)); } while (0)
313121461Sharti
314121461Sharti/*
315121461Sharti * Allocate a message that will probably hold N bytes.
316121461Sharti */
317121461Sharti#define	MBUF_ALLOC(N) ng_sscop_mbuf_alloc((N))
318121461Sharti
319121461Sharti#define	DECL_MBUF_ALLOC							\
320121461Shartistatic __inline struct mbuf *						\
321121461Sharting_sscop_mbuf_alloc(size_t n)						\
322121461Sharti{									\
323121461Sharti	struct mbuf *m;							\
324121461Sharti									\
325121461Sharti	MGETHDR(m, M_NOWAIT, MT_DATA);					\
326121461Sharti	if (m != NULL) {						\
327121461Sharti		m->m_len = 0;						\
328121461Sharti		m->m_pkthdr.len = 0;					\
329121461Sharti		if (n > MHLEN) {					\
330276750Srwatson			if (!(MCLGET(m, M_NOWAIT))){			\
331121461Sharti				m_free(m);				\
332121461Sharti				m = NULL;				\
333121461Sharti			}						\
334121461Sharti		}							\
335121461Sharti	}								\
336121461Sharti	return (m);							\
337121461Sharti}
338121461Sharti
339121461Sharti#ifdef SSCOP_DEBUG
340121461Sharti#define	ASSERT(X)	KASSERT(X, (#X))
341121461Sharti#else
342121461Sharti#define	ASSERT(X)
343121461Sharti#endif
344