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