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