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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [ethernet/] [lwIP/] [core/] [tcp_out.c] - Blame information for rev 615

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

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

powered by: WebSVN 2.1.0

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