OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [lwIP_MCF5235_GCC/] [lwip/] [src/] [core/] [tcp_out.c] - Blame information for rev 605

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 583 jeremybenn
/**
2
 * @file
3
 *
4
 * Transmission Control Protocol, outgoing traffic
5
 *
6
 * The output functions of TCP.
7
 *
8
 */
9
 
10
/*
11
 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
12
 * All rights reserved.
13
 *
14
 * Redistribution and use in source and binary forms, with or without modification,
15
 * are permitted provided that the following conditions are met:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions and the following disclaimer.
19
 * 2. Redistributions in binary form must reproduce the above copyright notice,
20
 *    this list of conditions and the following disclaimer in the documentation
21
 *    and/or other materials provided with the distribution.
22
 * 3. The name of the author may not be used to endorse or promote products
23
 *    derived from this software without specific prior written permission.
24
 *
25
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
26
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
28
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
30
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34
 * OF SUCH DAMAGE.
35
 *
36
 * This file is part of the lwIP TCP/IP stack.
37
 *
38
 * Author: Adam Dunkels <adam@sics.se>
39
 *
40
 */
41
 
42
#include <string.h>
43
 
44
#include "lwip/def.h"
45
#include "lwip/opt.h"
46
#include "lwip/mem.h"
47
#include "lwip/memp.h"
48
#include "lwip/sys.h"
49
#include "lwip/ip_addr.h"
50
#include "lwip/netif.h"
51
#include "lwip/inet.h"
52
#include "lwip/tcp.h"
53
#include "lwip/stats.h"
54
 
55
#if LWIP_TCP
56
 
57
/* Forward declarations.*/
58
static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
59
 
60
err_t
61
tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
62
{
63
  /* no data, no length, flags, copy=1, no optdata, no optdatalen */
64
  return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
65
}
66
 
67
/**
68
 * Write data for sending (but does not send it immediately).
69
 *
70
 * It waits in the expectation of more data being sent soon (as
71
 * it can send them more efficiently by combining them together).
72
 * To prompt the system to send data now, call tcp_output() after
73
 * calling tcp_write().
74
 *
75
 * @arg pcb Protocol control block of the TCP connection to enqueue data for.
76
 *
77
 * @see tcp_write()
78
 */
79
 
80
err_t
81
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
82
{
83
  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%"U16_F", copy=%"U16_F")\n", (void *)pcb,
84
    arg, len, (u16_t)copy));
85
  /* connection is in valid state for data transmission? */
86
  if (pcb->state == ESTABLISHED ||
87
     pcb->state == CLOSE_WAIT ||
88
     pcb->state == SYN_SENT ||
89
     pcb->state == SYN_RCVD) {
90
    if (len > 0) {
91
      return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
92
    }
93
    return ERR_OK;
94
  } else {
95
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_STATE | 3, ("tcp_write() called in invalid state\n"));
96
    return ERR_CONN;
97
  }
98
}
99
 
100
/**
101
 * Enqueue either data or TCP options (but not both) for tranmission
102
 *
103
 *
104
 *
105
 * @arg pcb Protocol control block for the TCP connection to enqueue data for.
106
 * @arg arg Pointer to the data to be enqueued for sending.
107
 * @arg len Data length in bytes
108
 * @arg flags
109
 * @arg copy 1 if data must be copied, 0 if data is non-volatile and can be
110
 * referenced.
111
 * @arg optdata
112
 * @arg optlen
113
 */
114
err_t
115
tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
116
  u8_t flags, u8_t copy,
117
  u8_t *optdata, u8_t optlen)
118
{
119
  struct pbuf *p;
120
  struct tcp_seg *seg, *useg, *queue;
121
  u32_t left, seqno;
122
  u16_t seglen;
123
  void *ptr;
124
  u8_t queuelen;
125
 
126
  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", copy=%"U16_F")\n",
127
    (void *)pcb, arg, len, (u16_t)flags, (u16_t)copy));
128
  LWIP_ASSERT("tcp_enqueue: len == 0 || optlen == 0 (programmer violates API)",
129
      len == 0 || optlen == 0);
130
  LWIP_ASSERT("tcp_enqueue: arg == NULL || optdata == NULL (programmer violates API)",
131
      arg == NULL || optdata == NULL);
132
  /* fail on too much data */
133
  if (len > pcb->snd_buf) {
134
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf));
135
    return ERR_MEM;
136
  }
137
  left = len;
138
  ptr = arg;
139
 
140
  /* seqno will be the sequence number of the first segment enqueued
141
   * by the call to this function. */
142
  seqno = pcb->snd_lbb;
143
 
144
  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
145
 
146
  /* If total number of pbufs on the unsent/unacked queues exceeds the
147
   * configured maximum, return an error */
148
  queuelen = pcb->snd_queuelen;
149
  if (queuelen >= TCP_SND_QUEUELEN) {
150
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
151
    TCP_STATS_INC(tcp.memerr);
152
    return ERR_MEM;
153
  }
154
  if (queuelen != 0) {
155
    LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty",
156
      pcb->unacked != NULL || pcb->unsent != NULL);
157
  } else {
158
    LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty",
159
      pcb->unacked == NULL && pcb->unsent == NULL);
160
  }
161
 
162
  /* First, break up the data into segments and tuck them together in
163
   * the local "queue" variable. */
164
  useg = queue = seg = NULL;
165
  seglen = 0;
166
  while (queue == NULL || left > 0) {
167
 
168
    /* The segment length should be the MSS if the data to be enqueued
169
     * is larger than the MSS. */
170
    seglen = left > pcb->mss? pcb->mss: left;
171
 
172
    /* Allocate memory for tcp_seg, and fill in fields. */
173
    seg = memp_malloc(MEMP_TCP_SEG);
174
    if (seg == NULL) {
175
      LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
176
      goto memerr;
177
    }
178
    seg->next = NULL;
179
    seg->p = NULL;
180
 
181
    /* first segment of to-be-queued data? */
182
    if (queue == NULL) {
183
      queue = seg;
184
    }
185
    /* subsequent segments of to-be-queued data */
186
    else {
187
      /* Attach the segment to the end of the queued segments */
188
      LWIP_ASSERT("useg != NULL", useg != NULL);
189
      useg->next = seg;
190
    }
191
    /* remember last segment of to-be-queued data for next iteration */
192
    useg = seg;
193
 
194
    /* If copy is set, memory should be allocated
195
     * and data copied into pbuf, otherwise data comes from
196
     * ROM or other static memory, and need not be copied. If
197
     * optdata is != NULL, we have options instead of data. */
198
 
199
    /* options? */
200
    if (optdata != NULL) {
201
      if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
202
        goto memerr;
203
      }
204
      ++queuelen;
205
      seg->dataptr = seg->p->payload;
206
    }
207
    /* copy from volatile memory? */
208
    else if (copy) {
209
      if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) {
210
        LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
211
        goto memerr;
212
      }
213
      ++queuelen;
214
      if (arg != NULL) {
215
        memcpy(seg->p->payload, ptr, seglen);
216
      }
217
      seg->dataptr = seg->p->payload;
218
    }
219
    /* do not copy data */
220
    else {
221
      /* First, allocate a pbuf for holding the data.
222
       * since the referenced data is available at least until it is sent out on the
223
       * link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
224
       * instead of PBUF_REF here.
225
       */
226
      if ((p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
227
        LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
228
        goto memerr;
229
      }
230
      ++queuelen;
231
      /* reference the non-volatile payload data */
232
      p->payload = ptr;
233
      seg->dataptr = ptr;
234
 
235
      /* Second, allocate a pbuf for the headers. */
236
      if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM)) == NULL) {
237
        /* If allocation fails, we have to deallocate the data pbuf as
238
         * well. */
239
        pbuf_free(p);
240
        LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for header pbuf\n"));
241
        goto memerr;
242
      }
243
      ++queuelen;
244
 
245
      /* Concatenate the headers and data pbufs together. */
246
      pbuf_cat(seg->p/*header*/, p/*data*/);
247
      p = NULL;
248
    }
249
 
250
    /* Now that there are more segments queued, we check again if the
251
    length of the queue exceeds the configured maximum. */
252
    if (queuelen > TCP_SND_QUEUELEN) {
253
      LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
254
      goto memerr;
255
    }
256
 
257
    seg->len = seglen;
258
 
259
    /* build TCP header */
260
    if (pbuf_header(seg->p, TCP_HLEN)) {
261
      LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
262
      TCP_STATS_INC(tcp.err);
263
      goto memerr;
264
    }
265
    seg->tcphdr = seg->p->payload;
266
    seg->tcphdr->src = htons(pcb->local_port);
267
    seg->tcphdr->dest = htons(pcb->remote_port);
268
    seg->tcphdr->seqno = htonl(seqno);
269
    seg->tcphdr->urgp = 0;
270
    TCPH_FLAGS_SET(seg->tcphdr, flags);
271
    /* don't fill in tcphdr->ackno and tcphdr->wnd until later */
272
 
273
    /* Copy the options into the header, if they are present. */
274
    if (optdata == NULL) {
275
      TCPH_HDRLEN_SET(seg->tcphdr, 5);
276
    }
277
    else {
278
      TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
279
      /* Copy options into data portion of segment.
280
       Options can thus only be sent in non data carrying
281
       segments such as SYN|ACK. */
282
      memcpy(seg->dataptr, optdata, optlen);
283
    }
284
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
285
      ntohl(seg->tcphdr->seqno),
286
      ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
287
      (u16_t)flags));
288
 
289
    left -= seglen;
290
    seqno += seglen;
291
    ptr = (void *)((u8_t *)ptr + seglen);
292
  }
293
 
294
  /* Now that the data to be enqueued has been broken up into TCP
295
  segments in the queue variable, we add them to the end of the
296
  pcb->unsent queue. */
297
  if (pcb->unsent == NULL) {
298
    useg = NULL;
299
  }
300
  else {
301
    for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
302
  }
303
  /* { useg is last segment on the unsent queue, NULL if list is empty } */
304
 
305
  /* If there is room in the last pbuf on the unsent queue,
306
  chain the first pbuf on the queue together with that. */
307
  if (useg != NULL &&
308
    TCP_TCPLEN(useg) != 0 &&
309
    !(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
310
    !(flags & (TCP_SYN | TCP_FIN)) &&
311
    /* fit within max seg size */
312
    useg->len + queue->len <= pcb->mss) {
313
    /* Remove TCP header from first segment of our to-be-queued list */
314
    pbuf_header(queue->p, -TCP_HLEN);
315
    pbuf_cat(useg->p, queue->p);
316
    useg->len += queue->len;
317
    useg->next = queue->next;
318
 
319
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len));
320
    if (seg == queue) {
321
      seg = NULL;
322
    }
323
    memp_free(MEMP_TCP_SEG, queue);
324
  }
325
  else {
326
    /* empty list */
327
    if (useg == NULL) {
328
      /* initialize list with this segment */
329
      pcb->unsent = queue;
330
    }
331
    /* enqueue segment */
332
    else {
333
      useg->next = queue;
334
    }
335
  }
336
  if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
337
    ++len;
338
  }
339
  pcb->snd_lbb += len;
340
 
341
  pcb->snd_buf -= len;
342
 
343
  /* update number of segments on the queues */
344
  pcb->snd_queuelen = queuelen;
345
  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %"S16_F" (after enqueued)\n", pcb->snd_queuelen));
346
  if (pcb->snd_queuelen != 0) {
347
    LWIP_ASSERT("tcp_enqueue: valid queue length",
348
      pcb->unacked != NULL || pcb->unsent != NULL);
349
  }
350
 
351
  /* Set the PSH flag in the last segment that we enqueued, but only
352
  if the segment has data (indicated by seglen > 0). */
353
  if (seg != NULL && seglen > 0 && seg->tcphdr != NULL) {
354
    TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
355
  }
356
 
357
  return ERR_OK;
358
memerr:
359
  TCP_STATS_INC(tcp.memerr);
360
 
361
  if (queue != NULL) {
362
    tcp_segs_free(queue);
363
  }
364
  if (pcb->snd_queuelen != 0) {
365
    LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
366
      pcb->unsent != NULL);
367
  }
368
  LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
369
  return ERR_MEM;
370
}
371
 
372
/* find out what we can send and send it */
373
err_t
374
tcp_output(struct tcp_pcb *pcb)
375
{
376
  struct pbuf *p;
377
  struct tcp_hdr *tcphdr;
378
  struct tcp_seg *seg, *useg;
379
  u32_t wnd;
380
#if TCP_CWND_DEBUG
381
  s16_t i = 0;
382
#endif /* TCP_CWND_DEBUG */
383
 
384
  /* First, check if we are invoked by the TCP input processing
385
     code. If so, we do not output anything. Instead, we rely on the
386
     input processing code to call us when input processing is done
387
     with. */
388
  if (tcp_input_pcb == pcb) {
389
    return ERR_OK;
390
  }
391
 
392
  wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
393
 
394
  seg = pcb->unsent;
395
 
396
  /* useg should point to last segment on unacked queue */
397
  useg = pcb->unacked;
398
  if (useg != NULL) {
399
    for (; useg->next != NULL; useg = useg->next);
400
  }
401
 
402
  /* If the TF_ACK_NOW flag is set and no data will be sent (either
403
   * because the ->unsent queue is empty or because the window does
404
   * not allow it), construct an empty ACK segment and send it.
405
   *
406
   * If data is to be sent, we will just piggyback the ACK (see below).
407
   */
408
  if (pcb->flags & TF_ACK_NOW &&
409
     (seg == NULL ||
410
      ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
411
    p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
412
    if (p == NULL) {
413
      LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
414
      return ERR_BUF;
415
    }
416
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
417
    /* remove ACK flags from the PCB, as we send an empty ACK now */
418
    pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
419
 
420
    tcphdr = p->payload;
421
    tcphdr->src = htons(pcb->local_port);
422
    tcphdr->dest = htons(pcb->remote_port);
423
    tcphdr->seqno = htonl(pcb->snd_nxt);
424
    tcphdr->ackno = htonl(pcb->rcv_nxt);
425
    TCPH_FLAGS_SET(tcphdr, TCP_ACK);
426
    tcphdr->wnd = htons(pcb->rcv_wnd);
427
    tcphdr->urgp = 0;
428
    TCPH_HDRLEN_SET(tcphdr, 5);
429
 
430
    tcphdr->chksum = 0;
431
#if CHECKSUM_GEN_TCP
432
    tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
433
          IP_PROTO_TCP, p->tot_len);
434
#endif
435
    ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
436
        IP_PROTO_TCP);
437
    pbuf_free(p);
438
 
439
    return ERR_OK;
440
  }
441
 
442
#if TCP_OUTPUT_DEBUG
443
  if (seg == NULL) {
444
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", (void*)pcb->unsent));
445
  }
446
#endif /* TCP_OUTPUT_DEBUG */
447
#if TCP_CWND_DEBUG
448
  if (seg == NULL) {
449
    LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", seg == NULL, ack %"U32_F"\n",
450
                            pcb->snd_wnd, pcb->cwnd, wnd,
451
                            pcb->lastack));
452
  } else {
453
    LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",
454
                            pcb->snd_wnd, pcb->cwnd, wnd,
455
                            ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
456
                            ntohl(seg->tcphdr->seqno), pcb->lastack));
457
  }
458
#endif /* TCP_CWND_DEBUG */
459
  /* data available and window allows it to be sent? */
460
  while (seg != NULL &&
461
  ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
462
#if TCP_CWND_DEBUG
463
    LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n",
464
                            pcb->snd_wnd, pcb->cwnd, wnd,
465
                            ntohl(seg->tcphdr->seqno) + seg->len -
466
                            pcb->lastack,
467
                            ntohl(seg->tcphdr->seqno), pcb->lastack, i));
468
    ++i;
469
#endif /* TCP_CWND_DEBUG */
470
 
471
    pcb->unsent = seg->next;
472
 
473
    if (pcb->state != SYN_SENT) {
474
      TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
475
      pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
476
    }
477
 
478
    tcp_output_segment(seg, pcb);
479
    pcb->snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
480
    if (TCP_SEQ_LT(pcb->snd_max, pcb->snd_nxt)) {
481
      pcb->snd_max = pcb->snd_nxt;
482
    }
483
    /* put segment on unacknowledged list if length > 0 */
484
    if (TCP_TCPLEN(seg) > 0) {
485
      seg->next = NULL;
486
      /* unacked list is empty? */
487
      if (pcb->unacked == NULL) {
488
        pcb->unacked = seg;
489
        useg = seg;
490
      /* unacked list is not empty? */
491
      } else {
492
        /* In the case of fast retransmit, the packet should not go to the tail
493
         * of the unacked queue, but rather at the head. We need to check for
494
         * this case. -STJ Jul 27, 2004 */
495
        if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
496
          /* add segment to head of unacked list */
497
          seg->next = pcb->unacked;
498
          pcb->unacked = seg;
499
        } else {
500
          /* add segment to tail of unacked list */
501
          useg->next = seg;
502
          useg = useg->next;
503
        }
504
      }
505
    /* do not queue empty segments on the unacked list */
506
    } else {
507
      tcp_seg_free(seg);
508
    }
509
    seg = pcb->unsent;
510
  }
511
  return ERR_OK;
512
}
513
 
514
/**
515
 * Actually send a TCP segment over IP
516
 */
517
static void
518
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
519
{
520
  u16_t len;
521
  struct netif *netif;
522
 
523
  /* The TCP header has already been constructed, but the ackno and
524
   wnd fields remain. */
525
  seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
526
 
527
  /* silly window avoidance */
528
  if (pcb->rcv_wnd < pcb->mss) {
529
    seg->tcphdr->wnd = 0;
530
  } else {
531
    /* advertise our receive window size in this TCP segment */
532
    seg->tcphdr->wnd = htons(pcb->rcv_wnd);
533
  }
534
 
535
  /* If we don't have a local IP address, we get one by
536
     calling ip_route(). */
537
  if (ip_addr_isany(&(pcb->local_ip))) {
538
    netif = ip_route(&(pcb->remote_ip));
539
    if (netif == NULL) {
540
      return;
541
    }
542
    ip_addr_set(&(pcb->local_ip), &(netif->ip_addr));
543
  }
544
 
545
  pcb->rtime = 0;
546
 
547
  if (pcb->rttest == 0) {
548
    pcb->rttest = tcp_ticks;
549
    pcb->rtseq = ntohl(seg->tcphdr->seqno);
550
 
551
    LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
552
  }
553
  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
554
          htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
555
          seg->len));
556
 
557
  len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
558
 
559
  seg->p->len -= len;
560
  seg->p->tot_len -= len;
561
 
562
  seg->p->payload = seg->tcphdr;
563
 
564
  seg->tcphdr->chksum = 0;
565
#if CHECKSUM_GEN_TCP
566
  seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
567
             &(pcb->local_ip),
568
             &(pcb->remote_ip),
569
             IP_PROTO_TCP, seg->p->tot_len);
570
#endif
571
  TCP_STATS_INC(tcp.xmit);
572
 
573
  ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
574
      IP_PROTO_TCP);
575
}
576
 
577
void
578
tcp_rst(u32_t seqno, u32_t ackno,
579
  struct ip_addr *local_ip, struct ip_addr *remote_ip,
580
  u16_t local_port, u16_t remote_port)
581
{
582
  struct pbuf *p;
583
  struct tcp_hdr *tcphdr;
584
  p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
585
  if (p == NULL) {
586
      LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
587
      return;
588
  }
589
 
590
  tcphdr = p->payload;
591
  tcphdr->src = htons(local_port);
592
  tcphdr->dest = htons(remote_port);
593
  tcphdr->seqno = htonl(seqno);
594
  tcphdr->ackno = htonl(ackno);
595
  TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
596
  tcphdr->wnd = htons(TCP_WND);
597
  tcphdr->urgp = 0;
598
  TCPH_HDRLEN_SET(tcphdr, 5);
599
 
600
  tcphdr->chksum = 0;
601
#if CHECKSUM_GEN_TCP
602
  tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
603
              IP_PROTO_TCP, p->tot_len);
604
#endif
605
  TCP_STATS_INC(tcp.xmit);
606
   /* Send output with hardcoded TTL since we have no access to the pcb */
607
  ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
608
  pbuf_free(p);
609
  LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
610
}
611
 
612
/* requeue all unacked segments for retransmission */
613
void
614
tcp_rexmit_rto(struct tcp_pcb *pcb)
615
{
616
  struct tcp_seg *seg;
617
 
618
  if (pcb->unacked == NULL) {
619
    return;
620
  }
621
 
622
  /* Move all unacked segments to the head of the unsent queue */
623
  for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
624
  /* concatenate unsent queue after unacked queue */
625
  seg->next = pcb->unsent;
626
  /* unsent queue is the concatenated queue (of unacked, unsent) */
627
  pcb->unsent = pcb->unacked;
628
  /* unacked queue is now empty */
629
  pcb->unacked = NULL;
630
 
631
  pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
632
  /* increment number of retransmissions */
633
  ++pcb->nrtx;
634
 
635
  /* Don't take any RTT measurements after retransmitting. */
636
  pcb->rttest = 0;
637
 
638
  /* Do the actual retransmission */
639
  tcp_output(pcb);
640
}
641
 
642
void
643
tcp_rexmit(struct tcp_pcb *pcb)
644
{
645
  struct tcp_seg *seg;
646
 
647
  if (pcb->unacked == NULL) {
648
    return;
649
  }
650
 
651
  /* Move the first unacked segment to the unsent queue */
652
  seg = pcb->unacked->next;
653
  pcb->unacked->next = pcb->unsent;
654
  pcb->unsent = pcb->unacked;
655
  pcb->unacked = seg;
656
 
657
  pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
658
 
659
  ++pcb->nrtx;
660
 
661
  /* Don't take any rtt measurements after retransmitting. */
662
  pcb->rttest = 0;
663
 
664
  /* Do the actual retransmission. */
665
  tcp_output(pcb);
666
 
667
}
668
 
669
 
670
void
671
tcp_keepalive(struct tcp_pcb *pcb)
672
{
673
   struct pbuf *p;
674
   struct tcp_hdr *tcphdr;
675
 
676
   LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
677
                           ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
678
                           ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
679
 
680
   LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F"   pcb->tmr %"U32_F"  pcb->keep_cnt %"U16_F"\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));
681
 
682
   p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
683
 
684
   if(p == NULL) {
685
      LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: could not allocate memory for pbuf\n"));
686
      return;
687
   }
688
 
689
   tcphdr = p->payload;
690
   tcphdr->src = htons(pcb->local_port);
691
   tcphdr->dest = htons(pcb->remote_port);
692
   tcphdr->seqno = htonl(pcb->snd_nxt - 1);
693
   tcphdr->ackno = htonl(pcb->rcv_nxt);
694
   tcphdr->wnd = htons(pcb->rcv_wnd);
695
   tcphdr->urgp = 0;
696
   TCPH_HDRLEN_SET(tcphdr, 5);
697
 
698
   tcphdr->chksum = 0;
699
#if CHECKSUM_GEN_TCP
700
   tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_TCP, p->tot_len);
701
#endif
702
  TCP_STATS_INC(tcp.xmit);
703
 
704
   /* Send output to IP */
705
  ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
706
 
707
  pbuf_free(p);
708
 
709
  LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
710
}
711
 
712
#endif /* LWIP_TCP */
713
 
714
 
715
 
716
 
717
 
718
 
719
 
720
 
721
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.