root / slirp / mbuf.c @ 64e58fe5
History | View | Annotate | Download (4.4 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 | 79383c9c | blueswir1 | #define SLIRP_MSIZE (IF_MTU + IF_MAXLINKHDR + sizeof(struct m_hdr ) + 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 | 79383c9c | blueswir1 | m->m_size = SLIRP_MSIZE - sizeof(struct m_hdr); |
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 | f0cbd3ec | bellard | end_error:
|
74 | f0cbd3ec | bellard | DEBUG_ARG("m = %lx", (long )m); |
75 | f0cbd3ec | bellard | return m;
|
76 | f0cbd3ec | bellard | } |
77 | f0cbd3ec | bellard | |
78 | f0cbd3ec | bellard | void
|
79 | 511d2b14 | blueswir1 | m_free(struct mbuf *m)
|
80 | f0cbd3ec | bellard | { |
81 | 5fafdf24 | ths | |
82 | f0cbd3ec | bellard | DEBUG_CALL("m_free");
|
83 | f0cbd3ec | bellard | DEBUG_ARG("m = %lx", (long )m); |
84 | 5fafdf24 | ths | |
85 | f0cbd3ec | bellard | if(m) {
|
86 | f0cbd3ec | bellard | /* Remove from m_usedlist */
|
87 | f0cbd3ec | bellard | if (m->m_flags & M_USEDLIST)
|
88 | f0cbd3ec | bellard | remque(m); |
89 | 5fafdf24 | ths | |
90 | f0cbd3ec | bellard | /* If it's M_EXT, free() it */
|
91 | f0cbd3ec | bellard | if (m->m_flags & M_EXT)
|
92 | f0cbd3ec | bellard | free(m->m_ext); |
93 | f0cbd3ec | bellard | |
94 | f0cbd3ec | bellard | /*
|
95 | f0cbd3ec | bellard | * Either free() it or put it on the free list
|
96 | f0cbd3ec | bellard | */
|
97 | f0cbd3ec | bellard | if (m->m_flags & M_DOFREE) {
|
98 | f0cbd3ec | bellard | free(m); |
99 | 460fec67 | Jan Kiszka | m->slirp->mbuf_alloced--; |
100 | f0cbd3ec | bellard | } else if ((m->m_flags & M_FREELIST) == 0) { |
101 | 460fec67 | Jan Kiszka | insque(m,&m->slirp->m_freelist); |
102 | f0cbd3ec | bellard | m->m_flags = M_FREELIST; /* Clobber other flags */
|
103 | f0cbd3ec | bellard | } |
104 | f0cbd3ec | bellard | } /* if(m) */
|
105 | f0cbd3ec | bellard | } |
106 | f0cbd3ec | bellard | |
107 | f0cbd3ec | bellard | /*
|
108 | f0cbd3ec | bellard | * Copy data from one mbuf to the end of
|
109 | f0cbd3ec | bellard | * the other.. if result is too big for one mbuf, malloc()
|
110 | f0cbd3ec | bellard | * an M_EXT data segment
|
111 | f0cbd3ec | bellard | */
|
112 | f0cbd3ec | bellard | void
|
113 | 511d2b14 | blueswir1 | m_cat(struct mbuf *m, struct mbuf *n) |
114 | f0cbd3ec | bellard | { |
115 | f0cbd3ec | bellard | /*
|
116 | f0cbd3ec | bellard | * If there's no room, realloc
|
117 | f0cbd3ec | bellard | */
|
118 | f0cbd3ec | bellard | if (M_FREEROOM(m) < n->m_len)
|
119 | f0cbd3ec | bellard | m_inc(m,m->m_size+MINCSIZE); |
120 | 5fafdf24 | ths | |
121 | f0cbd3ec | bellard | memcpy(m->m_data+m->m_len, n->m_data, n->m_len); |
122 | f0cbd3ec | bellard | m->m_len += n->m_len; |
123 | f0cbd3ec | bellard | |
124 | f0cbd3ec | bellard | m_free(n); |
125 | f0cbd3ec | bellard | } |
126 | f0cbd3ec | bellard | |
127 | f0cbd3ec | bellard | |
128 | f0cbd3ec | bellard | /* make m size bytes large */
|
129 | f0cbd3ec | bellard | void
|
130 | 511d2b14 | blueswir1 | m_inc(struct mbuf *m, int size) |
131 | f0cbd3ec | bellard | { |
132 | 4b6ccfde | bellard | int datasize;
|
133 | 4b6ccfde | bellard | |
134 | f0cbd3ec | bellard | /* some compiles throw up on gotos. This one we can fake. */
|
135 | f0cbd3ec | bellard | if(m->m_size>size) return; |
136 | f0cbd3ec | bellard | |
137 | f0cbd3ec | bellard | if (m->m_flags & M_EXT) {
|
138 | 4b6ccfde | bellard | datasize = m->m_data - m->m_ext; |
139 | f0cbd3ec | bellard | m->m_ext = (char *)realloc(m->m_ext,size);
|
140 | 4b6ccfde | bellard | m->m_data = m->m_ext + datasize; |
141 | f0cbd3ec | bellard | } else {
|
142 | f0cbd3ec | bellard | char *dat;
|
143 | f0cbd3ec | bellard | datasize = m->m_data - m->m_dat; |
144 | f0cbd3ec | bellard | dat = (char *)malloc(size);
|
145 | f0cbd3ec | bellard | memcpy(dat, m->m_dat, m->m_size); |
146 | 3b46e624 | ths | |
147 | f0cbd3ec | bellard | m->m_ext = dat; |
148 | f0cbd3ec | bellard | m->m_data = m->m_ext + datasize; |
149 | f0cbd3ec | bellard | m->m_flags |= M_EXT; |
150 | f0cbd3ec | bellard | } |
151 | 5fafdf24 | ths | |
152 | f0cbd3ec | bellard | m->m_size = size; |
153 | f0cbd3ec | bellard | |
154 | f0cbd3ec | bellard | } |
155 | f0cbd3ec | bellard | |
156 | f0cbd3ec | bellard | |
157 | f0cbd3ec | bellard | |
158 | f0cbd3ec | bellard | void
|
159 | 511d2b14 | blueswir1 | m_adj(struct mbuf *m, int len) |
160 | f0cbd3ec | bellard | { |
161 | f0cbd3ec | bellard | if (m == NULL) |
162 | f0cbd3ec | bellard | return;
|
163 | f0cbd3ec | bellard | if (len >= 0) { |
164 | f0cbd3ec | bellard | /* Trim from head */
|
165 | f0cbd3ec | bellard | m->m_data += len; |
166 | f0cbd3ec | bellard | m->m_len -= len; |
167 | f0cbd3ec | bellard | } else {
|
168 | f0cbd3ec | bellard | /* Trim from tail */
|
169 | f0cbd3ec | bellard | len = -len; |
170 | f0cbd3ec | bellard | m->m_len -= len; |
171 | f0cbd3ec | bellard | } |
172 | f0cbd3ec | bellard | } |
173 | f0cbd3ec | bellard | |
174 | f0cbd3ec | bellard | |
175 | f0cbd3ec | bellard | /*
|
176 | f0cbd3ec | bellard | * Copy len bytes from m, starting off bytes into n
|
177 | f0cbd3ec | bellard | */
|
178 | f0cbd3ec | bellard | int
|
179 | 511d2b14 | blueswir1 | m_copy(struct mbuf *n, struct mbuf *m, int off, int len) |
180 | f0cbd3ec | bellard | { |
181 | f0cbd3ec | bellard | if (len > M_FREEROOM(n))
|
182 | f0cbd3ec | bellard | return -1; |
183 | f0cbd3ec | bellard | |
184 | f0cbd3ec | bellard | memcpy((n->m_data + n->m_len), (m->m_data + off), len); |
185 | f0cbd3ec | bellard | n->m_len += len; |
186 | f0cbd3ec | bellard | return 0; |
187 | f0cbd3ec | bellard | } |
188 | f0cbd3ec | bellard | |
189 | f0cbd3ec | bellard | |
190 | f0cbd3ec | bellard | /*
|
191 | f0cbd3ec | bellard | * Given a pointer into an mbuf, return the mbuf
|
192 | f0cbd3ec | bellard | * XXX This is a kludge, I should eliminate the need for it
|
193 | f0cbd3ec | bellard | * Fortunately, it's not used often
|
194 | f0cbd3ec | bellard | */
|
195 | f0cbd3ec | bellard | struct mbuf *
|
196 | 460fec67 | Jan Kiszka | dtom(Slirp *slirp, void *dat)
|
197 | f0cbd3ec | bellard | { |
198 | f0cbd3ec | bellard | struct mbuf *m;
|
199 | 5fafdf24 | ths | |
200 | f0cbd3ec | bellard | DEBUG_CALL("dtom");
|
201 | f0cbd3ec | bellard | DEBUG_ARG("dat = %lx", (long )dat); |
202 | f0cbd3ec | bellard | |
203 | f0cbd3ec | bellard | /* bug corrected for M_EXT buffers */
|
204 | 460fec67 | Jan Kiszka | for (m = slirp->m_usedlist.m_next; m != &slirp->m_usedlist;
|
205 | 460fec67 | Jan Kiszka | m = m->m_next) { |
206 | f0cbd3ec | bellard | if (m->m_flags & M_EXT) {
|
207 | f0cbd3ec | bellard | if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) ) |
208 | f0cbd3ec | bellard | return m;
|
209 | f0cbd3ec | bellard | } else {
|
210 | f0cbd3ec | bellard | if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) ) |
211 | f0cbd3ec | bellard | return m;
|
212 | f0cbd3ec | bellard | } |
213 | f0cbd3ec | bellard | } |
214 | 5fafdf24 | ths | |
215 | f0cbd3ec | bellard | DEBUG_ERROR((dfd, "dtom failed"));
|
216 | 5fafdf24 | ths | |
217 | f0cbd3ec | bellard | return (struct mbuf *)0; |
218 | f0cbd3ec | bellard | } |