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