]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/netgraph/atm/sscop/ng_sscop_cust.h
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / netgraph / atm / sscop / ng_sscop_cust.h
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$
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  */
108 typedef 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_uncallout(&(S)->t_##T, (S)->aarg);                           \
112     } while (0)
113 #define TIMER_RESTART(S, T) do {                                        \
114         TIMER_STOP(S, T);                                               \
115         ng_callout(&(S)->t_##T, (S)->aarg, NULL,                        \
116             hz * (S)->timer##T / 1000, T##_func, (S), 0);               \
117     } while (0)
118 #define TIMER_ISACT(S, T) ((S)->t_##T.c_flags & (CALLOUT_PENDING))
119
120 /*
121  * This assumes, that the user argument is the node pointer.
122  */
123 #define TIMER_FUNC(T,N)                                                 \
124 static void                                                             \
125 T##_func(node_p node, hook_p hook, void *arg1, int arg2)                \
126 {                                                                       \
127         struct sscop *sscop = arg1;                                     \
128                                                                         \
129         VERBOSE(sscop, SSCOP_DBG_TIMER, (sscop, sscop->aarg,            \
130             "timer_" #T " expired"));                                   \
131         sscop_signal(sscop, SIG_T_##N, NULL);                           \
132 }
133
134
135 /*
136  * Message queues
137  */
138 typedef TAILQ_ENTRY(sscop_msg) sscop_msgq_link_t;
139 typedef TAILQ_HEAD(sscop_msgq, sscop_msg) sscop_msgq_head_t;
140 #define MSGQ_EMPTY(Q)           TAILQ_EMPTY(Q)
141 #define MSGQ_INIT(Q)            TAILQ_INIT(Q)
142 #define MSGQ_FOREACH(P, Q)      TAILQ_FOREACH(P, Q, link)
143 #define MSGQ_REMOVE(Q, M)       TAILQ_REMOVE(Q, M, link)
144 #define MSGQ_INSERT_BEFORE(B, M) TAILQ_INSERT_BEFORE(B, M, link)
145 #define MSGQ_APPEND(Q, M)       TAILQ_INSERT_TAIL(Q, M, link)
146 #define MSGQ_PEEK(Q)            TAILQ_FIRST((Q))
147
148 #define MSGQ_GET(Q) ng_sscop_msgq_get((Q))
149
150 #define DECL_MSGQ_GET                                                   \
151 static __inline struct sscop_msg *                                      \
152 ng_sscop_msgq_get(struct sscop_msgq *q)                                 \
153 {                                                                       \
154         struct sscop_msg *m;                                            \
155                                                                         \
156         m = TAILQ_FIRST(q);                                             \
157         if (m != NULL)                                                  \
158                 TAILQ_REMOVE(q, m, link);                               \
159         return (m);                                                     \
160 }
161
162 #define MSGQ_CLEAR(Q)                                                   \
163         do {                                                            \
164                 struct sscop_msg *_m1, *_m2;                            \
165                                                                         \
166                 _m1 = TAILQ_FIRST(Q);                                   \
167                 while (_m1 != NULL) {                                   \
168                         _m2 = TAILQ_NEXT(_m1, link);                    \
169                         SSCOP_MSG_FREE(_m1);                            \
170                         _m1 = _m2;                                      \
171                 }                                                       \
172                 TAILQ_INIT((Q));                                        \
173         } while (0)
174
175 /*
176  * Signal queues
177  */
178 typedef TAILQ_ENTRY(sscop_sig) sscop_sigq_link_t;
179 typedef TAILQ_HEAD(sscop_sigq, sscop_sig) sscop_sigq_head_t;
180 #define SIGQ_INIT(Q)            TAILQ_INIT(Q)
181 #define SIGQ_APPEND(Q, S)       TAILQ_INSERT_TAIL(Q, S, link)
182 #define SIGQ_EMPTY(Q)           TAILQ_EMPTY(Q)
183
184 #define SIGQ_GET(Q)     ng_sscop_sigq_get((Q))
185 #define DECL_SIGQ_GET                                                   \
186 static __inline struct sscop_sig *                                      \
187 ng_sscop_sigq_get(struct sscop_sigq *q)                                 \
188 {                                                                       \
189         struct sscop_sig *s;                                            \
190                                                                         \
191         s = TAILQ_FIRST(q);                                             \
192         if (s != NULL)                                                  \
193                 TAILQ_REMOVE(q, s, link);                               \
194         return (s);                                                     \
195 }
196
197 #define SIGQ_MOVE(F, T)                                                 \
198     do {                                                                \
199         struct sscop_sig *_s;                                           \
200                                                                         \
201         while (!TAILQ_EMPTY(F)) {                                       \
202                 _s = TAILQ_FIRST(F);                                    \
203                 TAILQ_REMOVE(F, _s, link);                              \
204                 TAILQ_INSERT_TAIL(T, _s, link);                         \
205         }                                                               \
206     } while (0)
207
208 #define SIGQ_PREPEND(F, T)                                              \
209     do {                                                                \
210         struct sscop_sig *_s;                                           \
211                                                                         \
212         while (!TAILQ_EMPTY(F)) {                                       \
213                 _s = TAILQ_LAST(F, sscop_sigq);                         \
214                 TAILQ_REMOVE(F, _s, link);                              \
215                 TAILQ_INSERT_HEAD(T, _s, link);                         \
216         }                                                               \
217     } while (0)
218
219 #define SIGQ_CLEAR(Q)                                                   \
220     do {                                                                \
221         struct sscop_sig *_s1, *_s2;                                    \
222                                                                         \
223         _s1 = TAILQ_FIRST(Q);                                           \
224         while (_s1 != NULL) {                                           \
225                 _s2 = TAILQ_NEXT(_s1, link);                            \
226                 SSCOP_MSG_FREE(_s1->msg);                               \
227                 SIG_FREE(_s1);                                          \
228                 _s1 = _s2;                                              \
229         }                                                               \
230         TAILQ_INIT(Q);                                                  \
231     } while (0)
232
233 /*
234  * Message buffers
235  */
236 #define MBUF_FREE(M)    do { if ((M)) m_freem((M)); } while(0)
237 #define MBUF_DUP(M)     m_copypacket((M), M_NOWAIT)
238 #define MBUF_LEN(M)     ((size_t)(M)->m_pkthdr.len)
239
240 /*
241  * Return the i-th word counted from the end of the buffer.
242  * i=-1 will return the last 32bit word, i=-2 the 2nd last.
243  * Assumes that there is enough space.
244  */
245 #define MBUF_TRAIL32(M ,I) ng_sscop_mbuf_trail32((M), (I))
246
247 static uint32_t __inline        
248 ng_sscop_mbuf_trail32(const struct mbuf *m, int i)
249 {
250         uint32_t w;
251
252         m_copydata(m, m->m_pkthdr.len + 4 * i, 4, (caddr_t)&w);
253         return (ntohl(w));
254 }
255
256 /*
257  * Strip 32bit value from the end
258  */
259 #define MBUF_STRIP32(M) ng_sscop_mbuf_strip32((M))
260
261 static uint32_t __inline
262 ng_sscop_mbuf_strip32(struct mbuf *m)
263 {
264         uint32_t w;
265
266         m_copydata(m, m->m_pkthdr.len - 4, 4, (caddr_t)&w);
267         m_adj(m, -4);
268         return (ntohl(w));
269 }
270
271 #define MBUF_GET32(M) ng_sscop_mbuf_get32((M))
272
273 static uint32_t __inline
274 ng_sscop_mbuf_get32(struct mbuf *m)
275 {
276         uint32_t w;
277
278         m_copydata(m, 0, 4, (caddr_t)&w);
279         m_adj(m, 4);
280         return (ntohl(w));
281 }
282
283 /*
284  * Append a 32bit value to an mbuf. Failures are ignored.
285  */
286 #define MBUF_APPEND32(M, W)                                             \
287      do {                                                               \
288         uint32_t _w = (W);                                              \
289                                                                         \
290         _w = htonl(_w);                                                 \
291         m_copyback((M), (M)->m_pkthdr.len, 4, (caddr_t)&_w);            \
292     } while (0)
293
294 /*
295  * Pad a message to a multiple of four byte and return the amount of padding
296  * Failures are ignored.
297  */
298 #define MBUF_PAD4(M) ng_sscop_mbuf_pad4((M))
299
300 static u_int __inline
301 ng_sscop_mbuf_pad4(struct mbuf *m)
302 {
303         static u_char pad[4] = { 0, 0, 0, 0 };
304         int len = m->m_pkthdr.len;
305         int npad = 3 - ((len + 3) & 3);
306
307         if (npad != 0)
308                 m_copyback(m, len, npad, (caddr_t)pad);
309         return (npad);
310 }
311
312 #define MBUF_UNPAD(M, P) do { if( (P) > 0) m_adj((M), -(P)); } while (0)
313
314 /*
315  * Allocate a message that will probably hold N bytes.
316  */
317 #define MBUF_ALLOC(N) ng_sscop_mbuf_alloc((N))
318
319 #define DECL_MBUF_ALLOC                                                 \
320 static __inline struct mbuf *                                           \
321 ng_sscop_mbuf_alloc(size_t n)                                           \
322 {                                                                       \
323         struct mbuf *m;                                                 \
324                                                                         \
325         MGETHDR(m, M_NOWAIT, MT_DATA);                                  \
326         if (m != NULL) {                                                \
327                 m->m_len = 0;                                           \
328                 m->m_pkthdr.len = 0;                                    \
329                 if (n > MHLEN) {                                        \
330                         MCLGET(m, M_NOWAIT);                            \
331                         if (!(m->m_flags & M_EXT)){                     \
332                                 m_free(m);                              \
333                                 m = NULL;                               \
334                         }                                               \
335                 }                                                       \
336         }                                                               \
337         return (m);                                                     \
338 }
339
340 #ifdef SSCOP_DEBUG
341 #define ASSERT(X)       KASSERT(X, (#X))
342 #else
343 #define ASSERT(X)
344 #endif