Statistics
| Branch: | Revision:

root / slirp / mbuf.c @ 5b50e790

History | View | Annotate | Download (4.9 kB)

1
/*
2
 * Copyright (c) 1995 Danny Gasparovski
3
 *
4
 * Please read the file COPYRIGHT for the
5
 * terms and conditions of the copyright.
6
 */
7

    
8
/*
9
 * mbuf's in SLiRP are much simpler than the real mbufs in
10
 * FreeBSD.  They are fixed size, determined by the MTU,
11
 * so that one whole packet can fit.  Mbuf's cannot be
12
 * chained together.  If there's more data than the mbuf
13
 * could hold, an external malloced buffer is pointed to
14
 * by m_ext (and the data pointers) and M_EXT is set in
15
 * the flags
16
 */
17

    
18
#include <slirp.h>
19

    
20
#define MBUF_THRESH 30
21

    
22
/*
23
 * Find a nice value for msize
24
 * XXX if_maxlinkhdr already in mtu
25
 */
26
#define SLIRP_MSIZE (IF_MTU + IF_MAXLINKHDR + offsetof(struct mbuf, m_dat) + 6)
27

    
28
void
29
m_init(Slirp *slirp)
30
{
31
    slirp->m_freelist.m_next = slirp->m_freelist.m_prev = &slirp->m_freelist;
32
    slirp->m_usedlist.m_next = slirp->m_usedlist.m_prev = &slirp->m_usedlist;
33
}
34

    
35
void m_cleanup(Slirp *slirp)
36
{
37
    struct mbuf *m, *next;
38

    
39
    m = slirp->m_usedlist.m_next;
40
    while (m != &slirp->m_usedlist) {
41
        next = m->m_next;
42
        if (m->m_flags & M_EXT) {
43
            free(m->m_ext);
44
        }
45
        free(m);
46
        m = next;
47
    }
48
    m = slirp->m_freelist.m_next;
49
    while (m != &slirp->m_freelist) {
50
        next = m->m_next;
51
        free(m);
52
        m = next;
53
    }
54
}
55

    
56
/*
57
 * Get an mbuf from the free list, if there are none
58
 * malloc one
59
 *
60
 * Because fragmentation can occur if we alloc new mbufs and
61
 * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,
62
 * which tells m_free to actually free() it
63
 */
64
struct mbuf *
65
m_get(Slirp *slirp)
66
{
67
        register struct mbuf *m;
68
        int flags = 0;
69

    
70
        DEBUG_CALL("m_get");
71

    
72
        if (slirp->m_freelist.m_next == &slirp->m_freelist) {
73
                m = (struct mbuf *)malloc(SLIRP_MSIZE);
74
                if (m == NULL) goto end_error;
75
                slirp->mbuf_alloced++;
76
                if (slirp->mbuf_alloced > MBUF_THRESH)
77
                        flags = M_DOFREE;
78
                m->slirp = slirp;
79
        } else {
80
                m = slirp->m_freelist.m_next;
81
                remque(m);
82
        }
83

    
84
        /* Insert it in the used list */
85
        insque(m,&slirp->m_usedlist);
86
        m->m_flags = (flags | M_USEDLIST);
87

    
88
        /* Initialise it */
89
        m->m_size = SLIRP_MSIZE - offsetof(struct mbuf, m_dat);
90
        m->m_data = m->m_dat;
91
        m->m_len = 0;
92
        m->m_nextpkt = NULL;
93
        m->m_prevpkt = NULL;
94
        m->arp_requested = false;
95
        m->expiration_date = (uint64_t)-1;
96
end_error:
97
        DEBUG_ARG("m = %lx", (long )m);
98
        return m;
99
}
100

    
101
void
102
m_free(struct mbuf *m)
103
{
104

    
105
  DEBUG_CALL("m_free");
106
  DEBUG_ARG("m = %lx", (long )m);
107

    
108
  if(m) {
109
        /* Remove from m_usedlist */
110
        if (m->m_flags & M_USEDLIST)
111
           remque(m);
112

    
113
        /* If it's M_EXT, free() it */
114
        if (m->m_flags & M_EXT)
115
           free(m->m_ext);
116

    
117
        /*
118
         * Either free() it or put it on the free list
119
         */
120
        if (m->m_flags & M_DOFREE) {
121
                m->slirp->mbuf_alloced--;
122
                free(m);
123
        } else if ((m->m_flags & M_FREELIST) == 0) {
124
                insque(m,&m->slirp->m_freelist);
125
                m->m_flags = M_FREELIST; /* Clobber other flags */
126
        }
127
  } /* if(m) */
128
}
129

    
130
/*
131
 * Copy data from one mbuf to the end of
132
 * the other.. if result is too big for one mbuf, malloc()
133
 * an M_EXT data segment
134
 */
135
void
136
m_cat(struct mbuf *m, struct mbuf *n)
137
{
138
        /*
139
         * If there's no room, realloc
140
         */
141
        if (M_FREEROOM(m) < n->m_len)
142
                m_inc(m,m->m_size+MINCSIZE);
143

    
144
        memcpy(m->m_data+m->m_len, n->m_data, n->m_len);
145
        m->m_len += n->m_len;
146

    
147
        m_free(n);
148
}
149

    
150

    
151
/* make m size bytes large */
152
void
153
m_inc(struct mbuf *m, int size)
154
{
155
        int datasize;
156

    
157
        /* some compiles throw up on gotos.  This one we can fake. */
158
        if(m->m_size>size) return;
159

    
160
        if (m->m_flags & M_EXT) {
161
          datasize = m->m_data - m->m_ext;
162
          m->m_ext = (char *)realloc(m->m_ext,size);
163
          m->m_data = m->m_ext + datasize;
164
        } else {
165
          char *dat;
166
          datasize = m->m_data - m->m_dat;
167
          dat = (char *)malloc(size);
168
          memcpy(dat, m->m_dat, m->m_size);
169

    
170
          m->m_ext = dat;
171
          m->m_data = m->m_ext + datasize;
172
          m->m_flags |= M_EXT;
173
        }
174

    
175
        m->m_size = size;
176

    
177
}
178

    
179

    
180

    
181
void
182
m_adj(struct mbuf *m, int len)
183
{
184
        if (m == NULL)
185
                return;
186
        if (len >= 0) {
187
                /* Trim from head */
188
                m->m_data += len;
189
                m->m_len -= len;
190
        } else {
191
                /* Trim from tail */
192
                len = -len;
193
                m->m_len -= len;
194
        }
195
}
196

    
197

    
198
/*
199
 * Copy len bytes from m, starting off bytes into n
200
 */
201
int
202
m_copy(struct mbuf *n, struct mbuf *m, int off, int len)
203
{
204
        if (len > M_FREEROOM(n))
205
                return -1;
206

    
207
        memcpy((n->m_data + n->m_len), (m->m_data + off), len);
208
        n->m_len += len;
209
        return 0;
210
}
211

    
212

    
213
/*
214
 * Given a pointer into an mbuf, return the mbuf
215
 * XXX This is a kludge, I should eliminate the need for it
216
 * Fortunately, it's not used often
217
 */
218
struct mbuf *
219
dtom(Slirp *slirp, void *dat)
220
{
221
        struct mbuf *m;
222

    
223
        DEBUG_CALL("dtom");
224
        DEBUG_ARG("dat = %lx", (long )dat);
225

    
226
        /* bug corrected for M_EXT buffers */
227
        for (m = slirp->m_usedlist.m_next; m != &slirp->m_usedlist;
228
             m = m->m_next) {
229
          if (m->m_flags & M_EXT) {
230
            if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) )
231
              return m;
232
          } else {
233
            if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) )
234
              return m;
235
          }
236
        }
237

    
238
        DEBUG_ERROR((dfd, "dtom failed"));
239

    
240
        return (struct mbuf *)0;
241
}