Revision 5fafdf24 slirp/if.c
b/slirp/if.c | ||
---|---|---|
77 | 77 |
{ |
78 | 78 |
int ret; |
79 | 79 |
int total; |
80 |
|
|
80 |
|
|
81 | 81 |
/* This should succeed most of the time */ |
82 | 82 |
ret = send(fd, bptr, n,0); |
83 | 83 |
if (ret == n || ret <= 0) |
84 | 84 |
return ret; |
85 |
|
|
85 |
|
|
86 | 86 |
/* Didn't write everything, go into the loop */ |
87 | 87 |
total = ret; |
88 | 88 |
while (n > total) { |
... | ... | |
97 | 97 |
/* |
98 | 98 |
* if_input - read() the tty, do "top level" processing (ie: check for any escapes), |
99 | 99 |
* and pass onto (*ttyp->if_input) |
100 |
*
|
|
100 |
* |
|
101 | 101 |
* XXXXX Any zeros arriving by themselves are NOT placed into the arriving packet. |
102 | 102 |
*/ |
103 | 103 |
#define INBUFF_SIZE 2048 /* XXX */ |
... | ... | |
107 | 107 |
{ |
108 | 108 |
u_char if_inbuff[INBUFF_SIZE]; |
109 | 109 |
int if_n; |
110 |
|
|
110 |
|
|
111 | 111 |
DEBUG_CALL("if_input"); |
112 | 112 |
DEBUG_ARG("ttyp = %lx", (long)ttyp); |
113 |
|
|
113 |
|
|
114 | 114 |
if_n = recv(ttyp->fd, (char *)if_inbuff, INBUFF_SIZE,0); |
115 |
|
|
115 |
|
|
116 | 116 |
DEBUG_MISC((dfd, " read %d bytes\n", if_n)); |
117 |
|
|
117 |
|
|
118 | 118 |
if (if_n <= 0) { |
119 | 119 |
if (if_n == 0 || (errno != EINTR && errno != EAGAIN)) { |
120 | 120 |
if (ttyp->up) |
... | ... | |
138 | 138 |
} |
139 | 139 |
} |
140 | 140 |
ttyp->ones = ttyp->zeros = 0; |
141 |
|
|
141 |
|
|
142 | 142 |
(*ttyp->if_input)(ttyp, if_inbuff, if_n); |
143 | 143 |
} |
144 |
#endif
|
|
145 |
|
|
144 |
#endif |
|
145 |
|
|
146 | 146 |
/* |
147 | 147 |
* if_output: Queue packet into an output queue. |
148 |
* There are 2 output queue's, if_fastq and if_batchq.
|
|
148 |
* There are 2 output queue's, if_fastq and if_batchq. |
|
149 | 149 |
* Each output queue is a doubly linked list of double linked lists |
150 | 150 |
* of mbufs, each list belonging to one "session" (socket). This |
151 | 151 |
* way, we can output packets fairly by sending one packet from each |
152 | 152 |
* session, instead of all the packets from one session, then all packets |
153 |
* from the next session, etc. Packets on the if_fastq get absolute
|
|
153 |
* from the next session, etc. Packets on the if_fastq get absolute |
|
154 | 154 |
* priority, but if one session hogs the link, it gets "downgraded" |
155 | 155 |
* to the batchq until it runs out of packets, then it'll return |
156 | 156 |
* to the fastq (eg. if the user does an ls -alR in a telnet session, |
... | ... | |
163 | 163 |
{ |
164 | 164 |
struct mbuf *ifq; |
165 | 165 |
int on_fastq = 1; |
166 |
|
|
166 |
|
|
167 | 167 |
DEBUG_CALL("if_output"); |
168 | 168 |
DEBUG_ARG("so = %lx", (long)so); |
169 | 169 |
DEBUG_ARG("ifm = %lx", (long)ifm); |
170 |
|
|
170 |
|
|
171 | 171 |
/* |
172 | 172 |
* First remove the mbuf from m_usedlist, |
173 | 173 |
* since we're gonna use m_next and m_prev ourselves |
... | ... | |
177 | 177 |
remque(ifm); |
178 | 178 |
ifm->m_flags &= ~M_USEDLIST; |
179 | 179 |
} |
180 |
|
|
180 |
|
|
181 | 181 |
/* |
182 |
* See if there's already a batchq list for this session.
|
|
182 |
* See if there's already a batchq list for this session. |
|
183 | 183 |
* This can include an interactive session, which should go on fastq, |
184 | 184 |
* but gets too greedy... hence it'll be downgraded from fastq to batchq. |
185 | 185 |
* We mustn't put this packet back on the fastq (or we'll send it out of order) |
... | ... | |
193 | 193 |
goto diddit; |
194 | 194 |
} |
195 | 195 |
} |
196 |
|
|
196 |
|
|
197 | 197 |
/* No match, check which queue to put it on */ |
198 | 198 |
if (so && (so->so_iptos & IPTOS_LOWDELAY)) { |
199 | 199 |
ifq = if_fastq.ifq_prev; |
... | ... | |
209 | 209 |
} |
210 | 210 |
} else |
211 | 211 |
ifq = if_batchq.ifq_prev; |
212 |
|
|
212 |
|
|
213 | 213 |
/* Create a new doubly linked list for this session */ |
214 | 214 |
ifm->ifq_so = so; |
215 | 215 |
ifs_init(ifm); |
216 | 216 |
insque(ifm, ifq); |
217 |
|
|
217 |
|
|
218 | 218 |
diddit: |
219 | 219 |
++if_queued; |
220 |
|
|
220 |
|
|
221 | 221 |
if (so) { |
222 | 222 |
/* Update *_queued */ |
223 | 223 |
so->so_queued++; |
... | ... | |
229 | 229 |
* have been sent over the link |
230 | 230 |
* (XXX These are arbitrary numbers, probably not optimal..) |
231 | 231 |
*/ |
232 |
if (on_fastq && ((so->so_nqueued >= 6) &&
|
|
232 |
if (on_fastq && ((so->so_nqueued >= 6) && |
|
233 | 233 |
(so->so_nqueued - so->so_queued) >= 3)) { |
234 |
|
|
234 |
|
|
235 | 235 |
/* Remove from current queue... */ |
236 | 236 |
remque(ifm->ifs_next); |
237 |
|
|
237 |
|
|
238 | 238 |
/* ...And insert in the new. That'll teach ya! */ |
239 | 239 |
insque(ifm->ifs_next, &if_batchq); |
240 | 240 |
} |
... | ... | |
267 | 267 |
if_start(void) |
268 | 268 |
{ |
269 | 269 |
struct mbuf *ifm, *ifqt; |
270 |
|
|
270 |
|
|
271 | 271 |
DEBUG_CALL("if_start"); |
272 |
|
|
272 |
|
|
273 | 273 |
if (if_queued == 0) |
274 | 274 |
return; /* Nothing to do */ |
275 |
|
|
275 |
|
|
276 | 276 |
again: |
277 | 277 |
/* check if we can really output */ |
278 | 278 |
if (!slirp_can_output()) |
... | ... | |
290 | 290 |
ifm = next_m; |
291 | 291 |
else |
292 | 292 |
ifm = if_batchq.ifq_next; |
293 |
|
|
293 |
|
|
294 | 294 |
/* Set which packet to send on next iteration */ |
295 | 295 |
next_m = ifm->ifq_next; |
296 | 296 |
} |
... | ... | |
298 | 298 |
ifqt = ifm->ifq_prev; |
299 | 299 |
remque(ifm); |
300 | 300 |
--if_queued; |
301 |
|
|
301 |
|
|
302 | 302 |
/* If there are more packets for this session, re-queue them */ |
303 | 303 |
if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) { |
304 | 304 |
insque(ifm->ifs_next, ifqt); |
305 | 305 |
ifs_remque(ifm); |
306 | 306 |
} |
307 |
|
|
307 |
|
|
308 | 308 |
/* Update so_queued */ |
309 | 309 |
if (ifm->ifq_so) { |
310 | 310 |
if (--ifm->ifq_so->so_queued == 0) |
311 | 311 |
/* If there's no more queued, reset nqueued */ |
312 | 312 |
ifm->ifq_so->so_nqueued = 0; |
313 | 313 |
} |
314 |
|
|
314 |
|
|
315 | 315 |
/* Encapsulate the packet for sending */ |
316 | 316 |
if_encap(ifm->m_data, ifm->m_len); |
317 | 317 |
|
Also available in: Unified diff