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