Commit | Line | Data |
---|---|---|
17efd7fe MK |
1 | /* |
2 | $Log: rdp_subr.c,v $ | |
3 | * Revision 2.7 84/11/21 12:06:30 walsh | |
4 | * *** empty log message *** | |
5 | * | |
6 | * Revision 2.6 84/11/08 16:12:53 walsh | |
7 | * Added code to gather statistics on RDP traffic. This makes the RDPCB | |
8 | * too big unles you make mbufs 512 bytes large. RDP_CS should be turned off | |
9 | * unless you do. | |
10 | * | |
11 | * Revision 2.5 84/11/06 13:54:21 walsh | |
12 | * *** empty log message *** | |
13 | * | |
14 | * Revision 2.4 84/11/05 16:25:18 walsh | |
15 | * tied rdp to icmp source quenches. See icmp_quench and rdp_quench. | |
16 | * | |
17 | * Revision 2.3 84/11/05 15:55:13 walsh | |
18 | * update_nulltimer() macro began to look inappropriate with recent | |
19 | * changes, so its been stripped out and put in-line. | |
20 | * | |
21 | * Revision 2.2 84/11/02 18:25:47 walsh | |
22 | * Protocol specifiers want NULL message to have own sequence number in | |
23 | * case of slow (t>NULL msg timeout) packets. I don't see this as a problem, | |
24 | * and even if happened (dubious) would only delay discovery, but I | |
25 | * didn't win this one. Initially not designed for this, but fixes are | |
26 | * in almost neatly. | |
27 | * | |
28 | * Revision 2.1 84/11/02 10:15:35 walsh | |
29 | * Fixed to include RCS comments in checked out source. | |
30 | * | |
31 | * | |
32 | * description: | |
33 | * Some subroutines for manipulating the datagram q's for RDP. | |
34 | * | |
35 | * revision 1.11 | |
36 | * date: 84/07/20 10:30:42; author: walsh; state: Exp; lines added/del: 21/1 | |
37 | * Tied RDP acknowledgements to ping reduction, just like TCP. | |
38 | * | |
39 | * revision 1.10 | |
40 | * date: 84/07/19 10:22:33; author: walsh; state: Exp; lines added/del: 1/17 | |
41 | * Organized macros and classified their definitions in rdp_macros.h. | |
42 | * | |
43 | * revision 1.9 | |
44 | * date: 84/07/17 22:35:26; author: walsh; state: Exp; lines added/del: 3/0 | |
45 | * Ensure cannot bind port number greater than RDP_pMAX. | |
46 | * | |
47 | * revision 1.8 | |
48 | * date: 84/07/12 10:12:48; author: walsh; state: Exp; lines added/del: 14/18 | |
49 | * some small optimizations. | |
50 | * | |
51 | * revision 1.7 | |
52 | * date: 84/07/12 09:39:06; author: walsh; state: Exp; lines added/del: 2/4 | |
53 | * small optimizations. ( a = (a+1)%b quicker than a++; a %= b) | |
54 | * | |
55 | * revision 1.6 | |
56 | * date: 84/07/10 14:58:24; author: walsh; state: Exp; lines added/del: 10/3 | |
57 | * Now no unecessary wakeups of the user process are done. | |
58 | * | |
59 | * revision 1.5 | |
60 | * date: 84/07/10 10:38:24; author: walsh; state: Exp; lines added/del: 13/13 | |
61 | * added register declarations. | |
62 | * | |
63 | * revision 1.4 | |
64 | * date: 84/07/06 14:28:53; author: wjacobso; state: Exp; lines added/del: 6/6 | |
65 | * *** empty log message *** | |
66 | * | |
67 | * revision 1.3 | |
68 | * date: 84/07/06 14:17:02; author: wjacobso; state: Exp; lines added/del: 8/8 | |
69 | * added register var definitions | |
70 | * | |
71 | * revision 1.2 | |
72 | * date: 84/07/06 09:51:12; author: root; state: Exp; lines added/del: 2/1 | |
73 | * This version seems to run bug-free. | |
74 | * | |
75 | * revision 1.1 | |
76 | * date: 84/06/26 14:18:30; author: walsh; state: Exp; | |
77 | * Initial revision | |
78 | */ | |
79 | ||
80 | ||
81 | #ifdef RDP | |
82 | #include "../h/param.h" | |
83 | #include "../h/dir.h" | |
84 | #include "../h/user.h" | |
85 | #include "../h/kernel.h" | |
86 | #include "../h/inode.h" | |
87 | #include "../h/mbuf.h" | |
88 | #include "../h/socket.h" | |
89 | #include "../h/socketvar.h" | |
90 | #include "../h/syslog.h" | |
91 | ||
92 | #include "../net/if.h" | |
93 | #include "../net/route.h" | |
94 | ||
95 | #include "../bbnnet/in.h" | |
96 | #include "../bbnnet/net.h" | |
97 | #include "../bbnnet/in_pcb.h" | |
98 | #include "../bbnnet/in_var.h" | |
99 | #include "../bbnnet/ip.h" | |
100 | #include "../bbnnet/icmp.h" | |
101 | #include "../bbnnet/rdp.h" | |
102 | #include "../bbnnet/seq.h" | |
103 | #include "../bbnnet/rdp_macros.h" | |
104 | ||
105 | /* | |
106 | * Called on ACK of a message we sent. | |
107 | */ | |
108 | he_acked(rdpcb, msgnum) | |
109 | register RDPCB *rdpcb; | |
110 | rdpsequence msgnum; | |
111 | { | |
112 | register int index; | |
113 | register int i; | |
114 | register MBUF *m; | |
115 | ||
116 | index = msgnum - rdpcb->r_sendq.rq_baseseq; | |
117 | if (index < 0 || index >= rdpcb->r_sendq.rq_maxqlen) | |
118 | return; | |
119 | ||
120 | /* | |
121 | * an ACK is cumulative and may be for more than one message | |
122 | */ | |
123 | for (i=0; i<=index; i++) | |
124 | { | |
125 | register int j; | |
126 | ||
127 | j = (rdpcb->r_sendq.rq_front + i) % rdpcb->r_sendq.rq_maxqlen; | |
128 | m = rdpcb->r_sendq.rq_msgs[j]; | |
129 | /* | |
130 | * ignore redundant ACKs. May have been EACKed (RDP_DELIVERED). | |
131 | */ | |
132 | if (m) | |
133 | { | |
134 | if (m == RDP_NULLMSG) | |
135 | { | |
136 | /* and restart connection loss detection */ | |
137 | rdpcb->r_nullsent = 0; | |
138 | rdpcb->r_timers[RDP_tNULL] = rdpcb->r_tvnull; | |
139 | } | |
140 | else if (m != RDP_DELIVERED) | |
141 | { | |
142 | #ifdef RDP_CS | |
143 | /* count when acked, not queued */ | |
144 | rdpcb->r_sent.r_nbytes += (int) m->m_act; | |
145 | #endif | |
146 | m_freem(m); | |
147 | } | |
148 | rdpcb->r_sendq.rq_msgs[j] = NULL; | |
149 | } | |
150 | clear_rxtimer (rdpcb, j); | |
151 | } | |
152 | ||
153 | /* | |
154 | * Ensure front is always NULL or an undelivered (unacked) message. | |
155 | */ | |
156 | rdpcb->r_sendq.rq_front += (index +1); | |
157 | rdpcb->r_sendq.rq_front %= rdpcb->r_sendq.rq_maxqlen; | |
158 | rdpcb->r_sendq.rq_baseseq += (index +1); /* bumps r_snduna */ | |
159 | ||
160 | /* | |
161 | * and, did this ack allow us to measure current round trip time? | |
162 | */ | |
163 | if (rdpcb->r_rttiming) | |
164 | { | |
165 | if (SEQ_GT(rdpcb->r_sendq.rq_baseseq, rdpcb->r_rttimed)) | |
166 | { | |
167 | update_rttestimate(rdpcb); | |
168 | update_rxmitime(rdpcb); | |
169 | rdpcb->r_rttiming = FALSE; | |
170 | } | |
171 | } | |
172 | ||
173 | #ifdef BBNPING | |
174 | /* | |
175 | * We've sent him NEW data, perhaps by a gateway, that he | |
176 | * has successfully received. If that's the case, then | |
177 | * we know the route works and we don't have to ping that | |
178 | * gateway. | |
179 | * | |
180 | * see check_ping() | |
181 | */ | |
182 | { | |
183 | register struct rtentry *rt; | |
184 | ||
185 | if (rt = rdpcb->r_inpcb->inp_route.ro_rt) | |
186 | if (rt->rt_flags & RTF_GATEWAY) | |
187 | rt->irt_pings = (-1); | |
188 | } | |
189 | #endif | |
190 | ||
191 | /* | |
192 | * and let sender send more pkts now that we have space. | |
193 | */ | |
194 | sendbufhasspace(rdpcb); | |
195 | } | |
196 | ||
197 | /* | |
198 | * Called on EACK of a message we sent. | |
199 | */ | |
200 | he_eacked(rdpcb, msgnum) | |
201 | register RDPCB *rdpcb; | |
202 | rdpsequence msgnum; | |
203 | { | |
204 | register int index; | |
205 | register MBUF *m; | |
206 | ||
207 | index = msgnum - rdpcb->r_sendq.rq_baseseq; | |
208 | if (index < 0 || index >= rdpcb->r_sendq.rq_maxqlen) | |
209 | return; | |
210 | ||
211 | index = (index + rdpcb->r_sendq.rq_front) % rdpcb->r_sendq.rq_maxqlen; | |
212 | m = rdpcb->r_sendq.rq_msgs[index]; | |
213 | /* | |
214 | * ignore redundant EACKs | |
215 | */ | |
216 | if (m && (m != RDP_DELIVERED)) | |
217 | { | |
218 | if (m == RDP_NULLMSG) | |
219 | { | |
220 | /* and restart connection loss detection */ | |
221 | rdpcb->r_nullsent = 0; | |
222 | rdpcb->r_timers[RDP_tNULL] = rdpcb->r_tvnull; | |
8902c2d0 | 223 | log(LOG_INFO, "Incorrect ACK strategy on rdpcb 0x%x\n", rdpcb); |
17efd7fe MK |
224 | } |
225 | else | |
226 | { | |
227 | #ifdef RDP_CS | |
228 | rdpcb->r_sent.r_nbytes += (int) m->m_act; | |
229 | #endif | |
230 | m_freem(m); | |
231 | } | |
232 | rdpcb->r_sendq.rq_msgs[index] = RDP_DELIVERED; | |
233 | clear_rxtimer(rdpcb, index); | |
234 | ||
235 | /* | |
236 | * did this eack allow us to measure current round trip time? | |
237 | */ | |
238 | if (rdpcb->r_rttiming) | |
239 | { | |
240 | if (msgnum == rdpcb->r_rttimed) | |
241 | { | |
242 | update_rttestimate(rdpcb); | |
243 | update_rxmitime(rdpcb); | |
244 | rdpcb->r_rttiming = FALSE; | |
245 | } | |
246 | } | |
247 | } | |
248 | } | |
249 | ||
250 | ||
251 | /* | |
252 | * Grab a message for passing to the user. msgq is our rcvq. | |
253 | * Called on net reception if user recv q is empty. | |
254 | * Called on PRU_RECV after user picks up current packet on socket. | |
255 | * Only one packet is attached to the socket at a time. | |
256 | */ | |
257 | MBUF *rdp_qremove(msgq, async) | |
258 | register RDP_MSGQ *msgq; | |
259 | { | |
260 | MBUF *m; | |
261 | int index; | |
262 | int pass; | |
263 | ||
264 | index = msgq->rq_front; | |
265 | pass = msgq->rq_maxqlen; | |
266 | do | |
267 | { | |
268 | m = msgq->rq_msgs[index]; | |
269 | if (m && m != RDP_DELIVERED) | |
270 | { | |
271 | msgq->rq_msgs[index] = RDP_DELIVERED; | |
272 | return (m); | |
273 | } | |
274 | index = (index +1) % msgq->rq_maxqlen; | |
275 | } | |
276 | while (async && (--pass > 0)); | |
277 | ||
278 | return (NULL); | |
279 | } | |
280 | ||
281 | /* | |
282 | * rdp_qremove() grabbed a message to pass to the user. When he picks it up, | |
283 | * PRU_RCVD occurs. At that point, we bump front and we send an ACK. | |
284 | */ | |
285 | rdp_received(msgq) | |
286 | register RDP_MSGQ *msgq; | |
287 | { | |
288 | register MBUF *m; | |
289 | register int index; | |
290 | ||
291 | do | |
292 | { | |
293 | index = msgq->rq_front; | |
294 | m = msgq->rq_msgs[index]; | |
295 | if (m == RDP_DELIVERED) | |
296 | { | |
297 | msgq->rq_front = (msgq->rq_front +1) % msgq->rq_maxqlen; | |
298 | msgq->rq_baseseq ++; | |
299 | msgq->rq_msgs[index] = NULL; | |
300 | } | |
301 | } | |
302 | while (m == RDP_DELIVERED); | |
303 | } | |
304 | ||
305 | /* | |
306 | * Put a message on our send or rcv q. | |
307 | * | |
308 | * 0 internal error somewhere | |
309 | * 1 new message | |
310 | * -1 duplicate message | |
311 | */ | |
312 | rdp_qinsert(msgq, m, msgnum) | |
313 | register RDP_MSGQ *msgq; | |
314 | MBUF *m; | |
315 | rdpsequence msgnum; | |
316 | { | |
317 | register int index; | |
318 | int isdup; | |
319 | ||
320 | index = msgnum - msgq->rq_baseseq; | |
321 | if ((index < 0) || (index >= msgq->rq_maxqlen)) | |
322 | { | |
323 | m_freem(m); | |
324 | return(0); | |
325 | } | |
326 | ||
327 | index = (index + msgq->rq_front) % msgq->rq_maxqlen; | |
328 | if (msgq->rq_msgs[index] == RDP_DELIVERED) | |
329 | { | |
330 | /* rcvd duplicate of a message the user already has on socket */ | |
331 | m_freem(m); | |
332 | isdup = -1; | |
333 | } | |
334 | else | |
335 | { | |
336 | if (msgq->rq_msgs[index]) | |
337 | { | |
338 | m_freem(msgq->rq_msgs[index]); | |
339 | isdup = -1; | |
340 | } | |
341 | else | |
342 | isdup = 1; | |
343 | msgq->rq_msgs[index] = m; | |
344 | } | |
345 | return(isdup); | |
346 | } | |
347 | #endif |