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

Subversion Repositories openrisc

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

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

powered by: WebSVN 2.1.0

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