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