Statistics
| Branch: | Revision:

root / slirp / mbuf.c @ 8fe3046f

History | View | Annotate | Download (4.4 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
/*
36
 * Get an mbuf from the free list, if there are none
37
 * malloc one
38
 *
39
 * Because fragmentation can occur if we alloc new mbufs and
40
 * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,
41
 * which tells m_free to actually free() it
42
 */
43
struct mbuf *
44
m_get(Slirp *slirp)
45
{
46
        register struct mbuf *m;
47
        int flags = 0;
48

    
49
        DEBUG_CALL("m_get");
50

    
51
        if (slirp->m_freelist.m_next == &slirp->m_freelist) {
52
                m = (struct mbuf *)malloc(SLIRP_MSIZE);
53
                if (m == NULL) goto end_error;
54
                slirp->mbuf_alloced++;
55
                if (slirp->mbuf_alloced > MBUF_THRESH)
56
                        flags = M_DOFREE;
57
                m->slirp = slirp;
58
        } else {
59
                m = slirp->m_freelist.m_next;
60
                remque(m);
61
        }
62

    
63
        /* Insert it in the used list */
64
        insque(m,&slirp->m_usedlist);
65
        m->m_flags = (flags | M_USEDLIST);
66

    
67
        /* Initialise it */
68
        m->m_size = SLIRP_MSIZE - offsetof(struct mbuf, m_dat);
69
        m->m_data = m->m_dat;
70
        m->m_len = 0;
71
        m->m_nextpkt = NULL;
72
        m->m_prevpkt = NULL;
73
end_error:
74
        DEBUG_ARG("m = %lx", (long )m);
75
        return m;
76
}
77

    
78
void
79
m_free(struct mbuf *m)
80
{
81

    
82
  DEBUG_CALL("m_free");
83
  DEBUG_ARG("m = %lx", (long )m);
84

    
85
  if(m) {
86
        /* Remove from m_usedlist */
87
        if (m->m_flags & M_USEDLIST)
88
           remque(m);
89

    
90
        /* If it's M_EXT, free() it */
91
        if (m->m_flags & M_EXT)
92
           free(m->m_ext);
93

    
94
        /*
95
         * Either free() it or put it on the free list
96
         */
97
        if (m->m_flags & M_DOFREE) {
98
                m->slirp->mbuf_alloced--;
99
                free(m);
100
        } else if ((m->m_flags & M_FREELIST) == 0) {
101
                insque(m,&m->slirp->m_freelist);
102
                m->m_flags = M_FREELIST; /* Clobber other flags */
103
        }
104
  } /* if(m) */
105
}
106

    
107
/*
108
 * Copy data from one mbuf to the end of
109
 * the other.. if result is too big for one mbuf, malloc()
110
 * an M_EXT data segment
111
 */
112
void
113
m_cat(struct mbuf *m, struct mbuf *n)
114
{
115
        /*
116
         * If there's no room, realloc
117
         */
118
        if (M_FREEROOM(m) < n->m_len)
119
                m_inc(m,m->m_size+MINCSIZE);
120

    
121
        memcpy(m->m_data+m->m_len, n->m_data, n->m_len);
122
        m->m_len += n->m_len;
123

    
124
        m_free(n);
125
}
126

    
127

    
128
/* make m size bytes large */
129
void
130
m_inc(struct mbuf *m, int size)
131
{
132
        int datasize;
133

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

    
137
        if (m->m_flags & M_EXT) {
138
          datasize = m->m_data - m->m_ext;
139
          m->m_ext = (char *)realloc(m->m_ext,size);
140
          m->m_data = m->m_ext + datasize;
141
        } else {
142
          char *dat;
143
          datasize = m->m_data - m->m_dat;
144
          dat = (char *)malloc(size);
145
          memcpy(dat, m->m_dat, m->m_size);
146

    
147
          m->m_ext = dat;
148
          m->m_data = m->m_ext + datasize;
149
          m->m_flags |= M_EXT;
150
        }
151

    
152
        m->m_size = size;
153

    
154
}
155

    
156

    
157

    
158
void
159
m_adj(struct mbuf *m, int len)
160
{
161
        if (m == NULL)
162
                return;
163
        if (len >= 0) {
164
                /* Trim from head */
165
                m->m_data += len;
166
                m->m_len -= len;
167
        } else {
168
                /* Trim from tail */
169
                len = -len;
170
                m->m_len -= len;
171
        }
172
}
173

    
174

    
175
/*
176
 * Copy len bytes from m, starting off bytes into n
177
 */
178
int
179
m_copy(struct mbuf *n, struct mbuf *m, int off, int len)
180
{
181
        if (len > M_FREEROOM(n))
182
                return -1;
183

    
184
        memcpy((n->m_data + n->m_len), (m->m_data + off), len);
185
        n->m_len += len;
186
        return 0;
187
}
188

    
189

    
190
/*
191
 * Given a pointer into an mbuf, return the mbuf
192
 * XXX This is a kludge, I should eliminate the need for it
193
 * Fortunately, it's not used often
194
 */
195
struct mbuf *
196
dtom(Slirp *slirp, void *dat)
197
{
198
        struct mbuf *m;
199

    
200
        DEBUG_CALL("dtom");
201
        DEBUG_ARG("dat = %lx", (long )dat);
202

    
203
        /* bug corrected for M_EXT buffers */
204
        for (m = slirp->m_usedlist.m_next; m != &slirp->m_usedlist;
205
             m = m->m_next) {
206
          if (m->m_flags & M_EXT) {
207
            if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) )
208
              return m;
209
          } else {
210
            if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) )
211
              return m;
212
          }
213
        }
214

    
215
        DEBUG_ERROR((dfd, "dtom failed"));
216

    
217
        return (struct mbuf *)0;
218
}