Declare function before use, reduces compiler warning noise.
[qemu] / slirp / mbuf.c
1 /*
2  * Copyright (c) 1995 Danny Gasparovski
3  *
4  * Please read the file COPYRIGHT for the
5  * terms and conditions of the copyright.
6  */
7
8 /*
9  * mbuf's in SLiRP are much simpler than the real mbufs in
10  * FreeBSD.  They are fixed size, determined by the MTU,
11  * so that one whole packet can fit.  Mbuf's cannot be
12  * chained together.  If there's more data than the mbuf
13  * could hold, an external malloced buffer is pointed to
14  * by m_ext (and the data pointers) and M_EXT is set in
15  * the flags
16  */
17
18 #include <slirp.h>
19
20 struct  mbuf *mbutl;
21 char    *mclrefcnt;
22 int mbuf_alloced = 0;
23 struct mbuf m_freelist, m_usedlist;
24 #define MBUF_THRESH 30
25 int mbuf_max = 0;
26
27 /*
28  * Find a nice value for msize
29  * XXX if_maxlinkhdr already in mtu
30  */
31 #define MSIZE (IF_MTU + IF_MAXLINKHDR + sizeof(struct m_hdr ) + 6)
32
33 void
34 m_init()
35 {
36         m_freelist.m_next = m_freelist.m_prev = &m_freelist;
37         m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist;
38 }
39
40 /*
41  * Get an mbuf from the free list, if there are none
42  * malloc one
43  *
44  * Because fragmentation can occur if we alloc new mbufs and
45  * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,
46  * which tells m_free to actually free() it
47  */
48 struct mbuf *
49 m_get()
50 {
51         register struct mbuf *m;
52         int flags = 0;
53
54         DEBUG_CALL("m_get");
55
56         if (m_freelist.m_next == &m_freelist) {
57                 m = (struct mbuf *)malloc(MSIZE);
58                 if (m == NULL) goto end_error;
59                 mbuf_alloced++;
60                 if (mbuf_alloced > MBUF_THRESH)
61                         flags = M_DOFREE;
62                 if (mbuf_alloced > mbuf_max)
63                         mbuf_max = mbuf_alloced;
64         } else {
65                 m = m_freelist.m_next;
66                 remque(m);
67         }
68
69         /* Insert it in the used list */
70         insque(m,&m_usedlist);
71         m->m_flags = (flags | M_USEDLIST);
72
73         /* Initialise it */
74         m->m_size = MSIZE - sizeof(struct m_hdr);
75         m->m_data = m->m_dat;
76         m->m_len = 0;
77         m->m_nextpkt = 0;
78         m->m_prevpkt = 0;
79 end_error:
80         DEBUG_ARG("m = %lx", (long )m);
81         return m;
82 }
83
84 void
85 m_free(m)
86         struct mbuf *m;
87 {
88
89   DEBUG_CALL("m_free");
90   DEBUG_ARG("m = %lx", (long )m);
91
92   if(m) {
93         /* Remove from m_usedlist */
94         if (m->m_flags & M_USEDLIST)
95            remque(m);
96
97         /* If it's M_EXT, free() it */
98         if (m->m_flags & M_EXT)
99            free(m->m_ext);
100
101         /*
102          * Either free() it or put it on the free list
103          */
104         if (m->m_flags & M_DOFREE) {
105                 free(m);
106                 mbuf_alloced--;
107         } else if ((m->m_flags & M_FREELIST) == 0) {
108                 insque(m,&m_freelist);
109                 m->m_flags = M_FREELIST; /* Clobber other flags */
110         }
111   } /* if(m) */
112 }
113
114 /*
115  * Copy data from one mbuf to the end of
116  * the other.. if result is too big for one mbuf, malloc()
117  * an M_EXT data segment
118  */
119 void
120 m_cat(m, n)
121         register struct mbuf *m, *n;
122 {
123         /*
124          * If there's no room, realloc
125          */
126         if (M_FREEROOM(m) < n->m_len)
127                 m_inc(m,m->m_size+MINCSIZE);
128
129         memcpy(m->m_data+m->m_len, n->m_data, n->m_len);
130         m->m_len += n->m_len;
131
132         m_free(n);
133 }
134
135
136 /* make m size bytes large */
137 void
138 m_inc(m, size)
139         struct mbuf *m;
140         int size;
141 {
142         int datasize;
143
144         /* some compiles throw up on gotos.  This one we can fake. */
145         if(m->m_size>size) return;
146
147         if (m->m_flags & M_EXT) {
148           datasize = m->m_data - m->m_ext;
149           m->m_ext = (char *)realloc(m->m_ext,size);
150 /*              if (m->m_ext == NULL)
151  *                      return (struct mbuf *)NULL;
152  */
153           m->m_data = m->m_ext + datasize;
154         } else {
155           char *dat;
156           datasize = m->m_data - m->m_dat;
157           dat = (char *)malloc(size);
158 /*              if (dat == NULL)
159  *                      return (struct mbuf *)NULL;
160  */
161           memcpy(dat, m->m_dat, m->m_size);
162
163           m->m_ext = dat;
164           m->m_data = m->m_ext + datasize;
165           m->m_flags |= M_EXT;
166         }
167
168         m->m_size = size;
169
170 }
171
172
173
174 void
175 m_adj(m, len)
176         struct mbuf *m;
177         int len;
178 {
179         if (m == NULL)
180                 return;
181         if (len >= 0) {
182                 /* Trim from head */
183                 m->m_data += len;
184                 m->m_len -= len;
185         } else {
186                 /* Trim from tail */
187                 len = -len;
188                 m->m_len -= len;
189         }
190 }
191
192
193 /*
194  * Copy len bytes from m, starting off bytes into n
195  */
196 int
197 m_copy(n, m, off, len)
198         struct mbuf *n, *m;
199         int off, len;
200 {
201         if (len > M_FREEROOM(n))
202                 return -1;
203
204         memcpy((n->m_data + n->m_len), (m->m_data + off), len);
205         n->m_len += len;
206         return 0;
207 }
208
209
210 /*
211  * Given a pointer into an mbuf, return the mbuf
212  * XXX This is a kludge, I should eliminate the need for it
213  * Fortunately, it's not used often
214  */
215 struct mbuf *
216 dtom(dat)
217         void *dat;
218 {
219         struct mbuf *m;
220
221         DEBUG_CALL("dtom");
222         DEBUG_ARG("dat = %lx", (long )dat);
223
224         /* bug corrected for M_EXT buffers */
225         for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) {
226           if (m->m_flags & M_EXT) {
227             if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) )
228               return m;
229           } else {
230             if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) )
231               return m;
232           }
233         }
234
235         DEBUG_ERROR((dfd, "dtom failed"));
236
237         return (struct mbuf *)0;
238 }
239