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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [lwip_tcpip/] [current/] [src/] [core/] [tcp_out.c] - Blame information for rev 865

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

Line No. Rev Author Line
1 786 skrzyp
/**
2
 * @file
3
 * Transmission Control Protocol, outgoing traffic
4
 *
5
 * The output functions of TCP.
6
 *
7
 */
8
 
9
/*
10
 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
11
 * All rights reserved.
12
 *
13
 * Redistribution and use in source and binary forms, with or without modification,
14
 * are permitted provided that the following conditions are met:
15
 *
16
 * 1. Redistributions of source code must retain the above copyright notice,
17
 *    this list of conditions and the following disclaimer.
18
 * 2. Redistributions in binary form must reproduce the above copyright notice,
19
 *    this list of conditions and the following disclaimer in the documentation
20
 *    and/or other materials provided with the distribution.
21
 * 3. The name of the author may not be used to endorse or promote products
22
 *    derived from this software without specific prior written permission.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
25
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
27
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
29
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
33
 * OF SUCH DAMAGE.
34
 *
35
 * This file is part of the lwIP TCP/IP stack.
36
 *
37
 * Author: Adam Dunkels <adam@sics.se>
38
 *
39
 */
40
 
41
#include "lwip/opt.h"
42
 
43
#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
44
 
45
#include "lwip/tcp.h"
46
#include "lwip/def.h"
47
#include "lwip/mem.h"
48
#include "lwip/memp.h"
49
#include "lwip/sys.h"
50
#include "lwip/ip_addr.h"
51
#include "lwip/netif.h"
52
#include "lwip/inet.h"
53
#include "lwip/inet_chksum.h"
54
#include "lwip/stats.h"
55
#include "lwip/snmp.h"
56
 
57
#include <string.h>
58
 
59
/* Forward declarations.*/
60
static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
61
 
62
static struct tcp_hdr *
63
tcp_output_set_header(struct tcp_pcb *pcb, struct pbuf *p, int optlen,
64
                      u32_t seqno_be /* already in network byte order */)
65
{
66
  struct tcp_hdr *tcphdr = p->payload;
67
  tcphdr->src = htons(pcb->local_port);
68
  tcphdr->dest = htons(pcb->remote_port);
69
  tcphdr->seqno = seqno_be;
70
  tcphdr->ackno = htonl(pcb->rcv_nxt);
71
  TCPH_FLAGS_SET(tcphdr, TCP_ACK);
72
  tcphdr->wnd = htons(pcb->rcv_ann_wnd);
73
  tcphdr->urgp = 0;
74
  TCPH_HDRLEN_SET(tcphdr, (5 + optlen / 4));
75
  tcphdr->chksum = 0;
76
 
77
  /* If we're sending a packet, update the announced right window edge */
78
  pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
79
 
80
  return tcphdr;
81
}
82
 
83
/**
84
 * Called by tcp_close() to send a segment including flags but not data.
85
 *
86
 * @param pcb the tcp_pcb over which to send a segment
87
 * @param flags the flags to set in the segment header
88
 * @return ERR_OK if sent, another err_t otherwise
89
 */
90
err_t
91
tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
92
{
93
  /* no data, no length, flags, copy=1, no optdata */
94
  return tcp_enqueue(pcb, NULL, 0, flags, TCP_WRITE_FLAG_COPY, 0);
95
}
96
 
97
/**
98
 * Write data for sending (but does not send it immediately).
99
 *
100
 * It waits in the expectation of more data being sent soon (as
101
 * it can send them more efficiently by combining them together).
102
 * To prompt the system to send data now, call tcp_output() after
103
 * calling tcp_write().
104
 *
105
 * @param pcb Protocol control block of the TCP connection to enqueue data for.
106
 * @param data pointer to the data to send
107
 * @param len length (in bytes) of the data to send
108
 * @param apiflags combination of following flags :
109
 * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack
110
 * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent,
111
 * @return ERR_OK if enqueued, another err_t on error
112
 *
113
 * @see tcp_write()
114
 */
115
err_t
116
tcp_write(struct tcp_pcb *pcb, const void *data, u16_t len, u8_t apiflags)
117
{
118
  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", (void *)pcb,
119
    data, len, (u16_t)apiflags));
120
  /* connection is in valid state for data transmission? */
121
  if (pcb->state == ESTABLISHED ||
122
     pcb->state == CLOSE_WAIT ||
123
     pcb->state == SYN_SENT ||
124
     pcb->state == SYN_RCVD) {
125
    if (len > 0) {
126
#if LWIP_TCP_TIMESTAMPS
127
      return tcp_enqueue(pcb, (void *)data, len, 0, apiflags,
128
                         pcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0);
129
#else
130
      return tcp_enqueue(pcb, (void *)data, len, 0, apiflags, 0);
131
#endif
132
    }
133
    return ERR_OK;
134
  } else {
135
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n"));
136
    return ERR_CONN;
137
  }
138
}
139
 
140
/**
141
 * Enqueue data and/or TCP options for transmission
142
 *
143
 * Called by tcp_connect(), tcp_listen_input(), tcp_send_ctrl() and tcp_write().
144
 *
145
 * @param pcb Protocol control block for the TCP connection to enqueue data for.
146
 * @param arg Pointer to the data to be enqueued for sending.
147
 * @param len Data length in bytes
148
 * @param flags tcp header flags to set in the outgoing segment
149
 * @param apiflags combination of following flags :
150
 * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack
151
 * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent,
152
 * @param optflags options to include in segment later on (see definition of struct tcp_seg)
153
 */
154
err_t
155
tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
156
            u8_t flags, u8_t apiflags, u8_t optflags)
157
{
158
  struct pbuf *p;
159
  struct tcp_seg *seg, *useg, *queue;
160
  u32_t seqno;
161
  u16_t left, seglen;
162
  void *ptr;
163
  u16_t queuelen;
164
  u8_t optlen;
165
 
166
  LWIP_DEBUGF(TCP_OUTPUT_DEBUG,
167
              ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", apiflags=%"U16_F")\n",
168
               (void *)pcb, arg, len, (u16_t)flags, (u16_t)apiflags));
169
  LWIP_ERROR("tcp_enqueue: packet needs payload, options, or SYN/FIN (programmer violates API)",
170
             ((len != 0) || (optflags != 0) || ((flags & (TCP_SYN | TCP_FIN)) != 0)),
171
             return ERR_ARG;);
172
  LWIP_ERROR("tcp_enqueue: len != 0 || arg == NULL (programmer violates API)",
173
             ((len != 0) || (arg == NULL)), return ERR_ARG;);
174
 
175
  /* fail on too much data */
176
  if (len > pcb->snd_buf) {
177
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_WARNING,
178
      ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf));
179
    pcb->flags |= TF_NAGLEMEMERR;
180
    return ERR_MEM;
181
  }
182
  left = len;
183
  ptr = arg;
184
 
185
  optlen = LWIP_TCP_OPT_LENGTH(optflags);
186
 
187
  /* seqno will be the sequence number of the first segment enqueued
188
   * by the call to this function. */
189
  seqno = pcb->snd_lbb;
190
 
191
  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
192
 
193
  /* If total number of pbufs on the unsent/unacked queues exceeds the
194
   * configured maximum, return an error */
195
  queuelen = pcb->snd_queuelen;
196
  /* check for configured max queuelen and possible overflow */
197
  if ((queuelen >= TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
198
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_WARNING,
199
      ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
200
    TCP_STATS_INC(tcp.memerr);
201
    pcb->flags |= TF_NAGLEMEMERR;
202
    return ERR_MEM;
203
  }
204
  if (queuelen != 0) {
205
    LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty",
206
      pcb->unacked != NULL || pcb->unsent != NULL);
207
  } else {
208
    LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty",
209
      pcb->unacked == NULL && pcb->unsent == NULL);
210
  }
211
 
212
  /* First, break up the data into segments and tuck them together in
213
   * the local "queue" variable. */
214
  useg = queue = seg = NULL;
215
  seglen = 0;
216
  while (queue == NULL || left > 0) {
217
    /* The segment length (including options) should be at most the MSS */
218
    seglen = left > (pcb->mss - optlen) ? (pcb->mss - optlen) : left;
219
 
220
    /* Allocate memory for tcp_seg, and fill in fields. */
221
    seg = memp_malloc(MEMP_TCP_SEG);
222
    if (seg == NULL) {
223
      LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
224
                  ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
225
      goto memerr;
226
    }
227
    seg->next = NULL;
228
    seg->p = NULL;
229
 
230
    /* first segment of to-be-queued data? */
231
    if (queue == NULL) {
232
      queue = seg;
233
    }
234
    /* subsequent segments of to-be-queued data */
235
    else {
236
      /* Attach the segment to the end of the queued segments */
237
      LWIP_ASSERT("useg != NULL", useg != NULL);
238
      useg->next = seg;
239
    }
240
    /* remember last segment of to-be-queued data for next iteration */
241
    useg = seg;
242
 
243
    /* If copy is set, memory should be allocated
244
     * and data copied into pbuf, otherwise data comes from
245
     * ROM or other static memory, and need not be copied.  */
246
    if (apiflags & TCP_WRITE_FLAG_COPY) {
247
      if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen + optlen, PBUF_RAM)) == NULL) {
248
        LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
249
                    ("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
250
        goto memerr;
251
      }
252
      LWIP_ASSERT("check that first pbuf can hold the complete seglen",
253
                  (seg->p->len >= seglen + optlen));
254
      queuelen += pbuf_clen(seg->p);
255
      if (arg != NULL) {
256
        MEMCPY((char *)seg->p->payload + optlen, ptr, seglen);
257
      }
258
      seg->dataptr = seg->p->payload;
259
    }
260
    /* do not copy data */
261
    else {
262
      /* First, allocate a pbuf for the headers. */
263
      if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
264
        LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
265
                    ("tcp_enqueue: could not allocate memory for header pbuf\n"));
266
        goto memerr;
267
      }
268
      queuelen += pbuf_clen(seg->p);
269
 
270
      /* Second, allocate a pbuf for holding the data.
271
       * since the referenced data is available at least until it is sent out on the
272
       * link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
273
       * instead of PBUF_REF here.
274
       */
275
      if (left > 0) {
276
        if ((p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
277
          /* If allocation fails, we have to deallocate the header pbuf as well. */
278
          pbuf_free(seg->p);
279
          seg->p = NULL;
280
          LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
281
                      ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
282
          goto memerr;
283
        }
284
        ++queuelen;
285
        /* reference the non-volatile payload data */
286
        p->payload = ptr;
287
        seg->dataptr = ptr;
288
 
289
        /* Concatenate the headers and data pbufs together. */
290
        pbuf_cat(seg->p/*header*/, p/*data*/);
291
        p = NULL;
292
      }
293
    }
294
 
295
    /* Now that there are more segments queued, we check again if the
296
    length of the queue exceeds the configured maximum or overflows. */
297
    if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
298
      LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
299
        ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
300
      goto memerr;
301
    }
302
 
303
    seg->len = seglen;
304
 
305
    /* build TCP header */
306
    if (pbuf_header(seg->p, TCP_HLEN)) {
307
      LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
308
      TCP_STATS_INC(tcp.err);
309
      goto memerr;
310
    }
311
    seg->tcphdr = seg->p->payload;
312
    seg->tcphdr->src = htons(pcb->local_port);
313
    seg->tcphdr->dest = htons(pcb->remote_port);
314
    seg->tcphdr->seqno = htonl(seqno);
315
    seg->tcphdr->urgp = 0;
316
    TCPH_FLAGS_SET(seg->tcphdr, flags);
317
    /* don't fill in tcphdr->ackno and tcphdr->wnd until later */
318
 
319
    seg->flags = optflags;
320
 
321
    /* Set the length of the header */
322
    TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
323
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_enqueue: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
324
      ntohl(seg->tcphdr->seqno),
325
      ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
326
      (u16_t)flags));
327
 
328
    left -= seglen;
329
    seqno += seglen;
330
    ptr = (void *)((u8_t *)ptr + seglen);
331
  }
332
 
333
  /* Now that the data to be enqueued has been broken up into TCP
334
  segments in the queue variable, we add them to the end of the
335
  pcb->unsent queue. */
336
  if (pcb->unsent == NULL) {
337
    useg = NULL;
338
  }
339
  else {
340
    for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
341
  }
342
  /* { useg is last segment on the unsent queue, NULL if list is empty } */
343
 
344
  /* If there is room in the last pbuf on the unsent queue,
345
  chain the first pbuf on the queue together with that. */
346
  if (useg != NULL &&
347
    TCP_TCPLEN(useg) != 0 &&
348
    !(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
349
    (!(flags & (TCP_SYN | TCP_FIN)) || (flags == TCP_FIN)) &&
350
    /* fit within max seg size */
351
    (useg->len + queue->len <= pcb->mss) &&
352
    /* only concatenate segments with the same options */
353
    (useg->flags == queue->flags) &&
354
    /* segments are consecutive */
355
    (ntohl(useg->tcphdr->seqno) + useg->len == ntohl(queue->tcphdr->seqno)) ) {
356
    /* Remove TCP header from first segment of our to-be-queued list */
357
    if(pbuf_header(queue->p, -(TCP_HLEN + optlen))) {
358
      /* Can we cope with this failing?  Just assert for now */
359
      LWIP_ASSERT("pbuf_header failed\n", 0);
360
      TCP_STATS_INC(tcp.err);
361
      goto memerr;
362
    }
363
    if (queue->p->len == 0) {
364
      /* free the first (header-only) pbuf if it is now empty (contained only headers) */
365
      struct pbuf *old_q = queue->p;
366
      queue->p = queue->p->next;
367
      old_q->next = NULL;
368
      queuelen--;
369
      pbuf_free(old_q);
370
    }
371
    if (flags & TCP_FIN) {
372
      /* the new segment contains only FIN, no data -> put the FIN into the last segment */
373
      LWIP_ASSERT("FIN enqueued together with data", queue->p == NULL && queue->len == 0);
374
      TCPH_SET_FLAG(useg->tcphdr, TCP_FIN);
375
    } else {
376
      LWIP_ASSERT("zero-length pbuf", (queue->p != NULL) && (queue->p->len > 0));
377
      pbuf_cat(useg->p, queue->p);
378
      useg->len += queue->len;
379
      useg->next = queue->next;
380
    }
381
 
382
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len));
383
    if (seg == queue) {
384
      seg = useg;
385
      seglen = useg->len;
386
    }
387
    memp_free(MEMP_TCP_SEG, queue);
388
  }
389
  else {
390
    /* empty list */
391
    if (useg == NULL) {
392
      /* initialize list with this segment */
393
      pcb->unsent = queue;
394
    }
395
    /* enqueue segment */
396
    else {
397
      useg->next = queue;
398
    }
399
  }
400
  if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
401
    ++len;
402
  }
403
  if (flags & TCP_FIN) {
404
    pcb->flags |= TF_FIN;
405
  }
406
  pcb->snd_lbb += len;
407
 
408
  pcb->snd_buf -= len;
409
 
410
  /* update number of segments on the queues */
411
  pcb->snd_queuelen = queuelen;
412
  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %"S16_F" (after enqueued)\n", pcb->snd_queuelen));
413
  if (pcb->snd_queuelen != 0) {
414
    LWIP_ASSERT("tcp_enqueue: valid queue length",
415
      pcb->unacked != NULL || pcb->unsent != NULL);
416
  }
417
 
418
  /* Set the PSH flag in the last segment that we enqueued, but only
419
  if the segment has data (indicated by seglen > 0). */
420
  if (seg != NULL && seglen > 0 && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) {
421
    TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
422
  }
423
 
424
  return ERR_OK;
425
memerr:
426
  pcb->flags |= TF_NAGLEMEMERR;
427
  TCP_STATS_INC(tcp.memerr);
428
 
429
  if (queue != NULL) {
430
    tcp_segs_free(queue);
431
  }
432
  if (pcb->snd_queuelen != 0) {
433
    LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
434
      pcb->unsent != NULL);
435
  }
436
  LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_enqueue: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
437
  return ERR_MEM;
438
}
439
 
440
 
441
#if LWIP_TCP_TIMESTAMPS
442
/* Build a timestamp option (12 bytes long) at the specified options pointer)
443
 *
444
 * @param pcb tcp_pcb
445
 * @param opts option pointer where to store the timestamp option
446
 */
447
static void
448
tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
449
{
450
  /* Pad with two NOP options to make everything nicely aligned */
451
  opts[0] = htonl(0x0101080A);
452
  opts[1] = htonl(sys_now());
453
  opts[2] = htonl(pcb->ts_recent);
454
}
455
#endif
456
 
457
/** Send an ACK without data.
458
 *
459
 * @param pcb Protocol control block for the TCP connection to send the ACK
460
 */
461
err_t
462
tcp_send_empty_ack(struct tcp_pcb *pcb)
463
{
464
  struct pbuf *p;
465
#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP
466
  struct tcp_hdr *tcphdr;
467
#endif
468
  u8_t optlen = 0;
469
 
470
#if LWIP_TCP_TIMESTAMPS
471
  if (pcb->flags & TF_TIMESTAMP) {
472
    optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
473
  }
474
#endif
475
  p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen, PBUF_RAM);
476
  if (p == NULL) {
477
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
478
    return ERR_BUF;
479
  }
480
  LWIP_DEBUGF(TCP_OUTPUT_DEBUG,
481
              ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
482
  /* remove ACK flags from the PCB, as we send an empty ACK now */
483
  pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
484
#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP
485
  tcphdr =
486
#endif
487
  tcp_output_set_header(pcb, p, optlen, htonl(pcb->snd_nxt));
488
 
489
  /* NB. MSS option is only sent on SYNs, so ignore it here */
490
#if LWIP_TCP_TIMESTAMPS
491
  pcb->ts_lastacksent = pcb->rcv_nxt;
492
 
493
  if (pcb->flags & TF_TIMESTAMP) {
494
    tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1));
495
  }
496
#endif 
497
 
498
#if CHECKSUM_GEN_TCP
499
  tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
500
        IP_PROTO_TCP, p->tot_len);
501
#endif
502
#if LWIP_NETIF_HWADDRHINT
503
  ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
504
      IP_PROTO_TCP, &(pcb->addr_hint));
505
#else /* LWIP_NETIF_HWADDRHINT*/
506
  ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
507
      IP_PROTO_TCP);
508
#endif /* LWIP_NETIF_HWADDRHINT*/
509
  pbuf_free(p);
510
 
511
  return ERR_OK;
512
}
513
 
514
/**
515
 * Find out what we can send and send it
516
 *
517
 * @param pcb Protocol control block for the TCP connection to send data
518
 * @return ERR_OK if data has been sent or nothing to send
519
 *         another err_t on error
520
 */
521
err_t
522
tcp_output(struct tcp_pcb *pcb)
523
{
524
  struct tcp_seg *seg, *useg;
525
  u32_t wnd, snd_nxt;
526
#if TCP_CWND_DEBUG
527
  s16_t i = 0;
528
#endif /* TCP_CWND_DEBUG */
529
 
530
  /* First, check if we are invoked by the TCP input processing
531
     code. If so, we do not output anything. Instead, we rely on the
532
     input processing code to call us when input processing is done
533
     with. */
534
  if (tcp_input_pcb == pcb) {
535
    return ERR_OK;
536
  }
537
 
538
  wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
539
 
540
  seg = pcb->unsent;
541
 
542
  /* If the TF_ACK_NOW flag is set and no data will be sent (either
543
   * because the ->unsent queue is empty or because the window does
544
   * not allow it), construct an empty ACK segment and send it.
545
   *
546
   * If data is to be sent, we will just piggyback the ACK (see below).
547
   */
548
  if (pcb->flags & TF_ACK_NOW &&
549
     (seg == NULL ||
550
      ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
551
     return tcp_send_empty_ack(pcb);
552
  }
553
 
554
  /* useg should point to last segment on unacked queue */
555
  useg = pcb->unacked;
556
  if (useg != NULL) {
557
    for (; useg->next != NULL; useg = useg->next);
558
  }
559
 
560
#if TCP_OUTPUT_DEBUG
561
  if (seg == NULL) {
562
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n",
563
                                   (void*)pcb->unsent));
564
  }
565
#endif /* TCP_OUTPUT_DEBUG */
566
#if TCP_CWND_DEBUG
567
  if (seg == NULL) {
568
    LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F
569
                                 ", cwnd %"U16_F", wnd %"U32_F
570
                                 ", seg == NULL, ack %"U32_F"\n",
571
                                 pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack));
572
  } else {
573
    LWIP_DEBUGF(TCP_CWND_DEBUG,
574
                ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F
575
                 ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",
576
                 pcb->snd_wnd, pcb->cwnd, wnd,
577
                 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
578
                 ntohl(seg->tcphdr->seqno), pcb->lastack));
579
  }
580
#endif /* TCP_CWND_DEBUG */
581
  /* data available and window allows it to be sent? */
582
  while (seg != NULL &&
583
         ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
584
    LWIP_ASSERT("RST not expected here!",
585
                (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
586
    /* Stop sending if the nagle algorithm would prevent it
587
     * Don't stop:
588
     * - if tcp_enqueue had a memory error before (prevent delayed ACK timeout) or
589
     * - if FIN was already enqueued for this PCB (SYN is always alone in a segment -
590
     *   either seg->next != NULL or pcb->unacked == NULL;
591
     *   RST is no sent using tcp_enqueue/tcp_output.
592
     */
593
    if((tcp_do_output_nagle(pcb) == 0) &&
594
      ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){
595
      break;
596
    }
597
#if TCP_CWND_DEBUG
598
    LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n",
599
                            pcb->snd_wnd, pcb->cwnd, wnd,
600
                            ntohl(seg->tcphdr->seqno) + seg->len -
601
                            pcb->lastack,
602
                            ntohl(seg->tcphdr->seqno), pcb->lastack, i));
603
    ++i;
604
#endif /* TCP_CWND_DEBUG */
605
 
606
    pcb->unsent = seg->next;
607
 
608
    if (pcb->state != SYN_SENT) {
609
      TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
610
      pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
611
    }
612
 
613
    tcp_output_segment(seg, pcb);
614
    snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
615
    if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
616
      pcb->snd_nxt = snd_nxt;
617
    }
618
    /* put segment on unacknowledged list if length > 0 */
619
    if (TCP_TCPLEN(seg) > 0) {
620
      seg->next = NULL;
621
      /* unacked list is empty? */
622
      if (pcb->unacked == NULL) {
623
        pcb->unacked = seg;
624
        useg = seg;
625
      /* unacked list is not empty? */
626
      } else {
627
        /* In the case of fast retransmit, the packet should not go to the tail
628
         * of the unacked queue, but rather somewhere before it. We need to check for
629
         * this case. -STJ Jul 27, 2004 */
630
        if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
631
          /* add segment to before tail of unacked list, keeping the list sorted */
632
          struct tcp_seg **cur_seg = &(pcb->unacked);
633
          while (*cur_seg &&
634
            TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
635
              cur_seg = &((*cur_seg)->next );
636
          }
637
          seg->next = (*cur_seg);
638
          (*cur_seg) = seg;
639
        } else {
640
          /* add segment to tail of unacked list */
641
          useg->next = seg;
642
          useg = useg->next;
643
        }
644
      }
645
    /* do not queue empty segments on the unacked list */
646
    } else {
647
      tcp_seg_free(seg);
648
    }
649
    seg = pcb->unsent;
650
  }
651
 
652
  if (seg != NULL && pcb->persist_backoff == 0 &&
653
      ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > pcb->snd_wnd) {
654
    /* prepare for persist timer */
655
    pcb->persist_cnt = 0;
656
    pcb->persist_backoff = 1;
657
  }
658
 
659
  pcb->flags &= ~TF_NAGLEMEMERR;
660
  return ERR_OK;
661
}
662
 
663
/**
664
 * Called by tcp_output() to actually send a TCP segment over IP.
665
 *
666
 * @param seg the tcp_seg to send
667
 * @param pcb the tcp_pcb for the TCP connection used to send the segment
668
 */
669
static void
670
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
671
{
672
  u16_t len;
673
  struct netif *netif;
674
  u32_t *opts;
675
 
676
  /** @bug Exclude retransmitted segments from this count. */
677
  snmp_inc_tcpoutsegs();
678
 
679
  /* The TCP header has already been constructed, but the ackno and
680
   wnd fields remain. */
681
  seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
682
 
683
  /* advertise our receive window size in this TCP segment */
684
  seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd);
685
 
686
  pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
687
 
688
  /* Add any requested options.  NB MSS option is only set on SYN
689
     packets, so ignore it here */
690
  opts = (u32_t *)(seg->tcphdr + 1);
691
  if (seg->flags & TF_SEG_OPTS_MSS) {
692
    TCP_BUILD_MSS_OPTION(*opts);
693
    opts += 1;
694
  }
695
#if LWIP_TCP_TIMESTAMPS
696
  pcb->ts_lastacksent = pcb->rcv_nxt;
697
 
698
  if (seg->flags & TF_SEG_OPTS_TS) {
699
    tcp_build_timestamp_option(pcb, opts);
700
    opts += 3;
701
  }
702
#endif
703
 
704
  /* If we don't have a local IP address, we get one by
705
     calling ip_route(). */
706
  if (ip_addr_isany(&(pcb->local_ip))) {
707
    netif = ip_route(&(pcb->remote_ip));
708
    if (netif == NULL) {
709
      return;
710
    }
711
    ip_addr_set(&(pcb->local_ip), &(netif->ip_addr));
712
  }
713
 
714
  /* Set retransmission timer running if it is not currently enabled */
715
  if(pcb->rtime == -1)
716
    pcb->rtime = 0;
717
 
718
  if (pcb->rttest == 0) {
719
    pcb->rttest = tcp_ticks;
720
    pcb->rtseq = ntohl(seg->tcphdr->seqno);
721
 
722
    LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
723
  }
724
  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
725
          htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
726
          seg->len));
727
 
728
  len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
729
 
730
  seg->p->len -= len;
731
  seg->p->tot_len -= len;
732
 
733
  seg->p->payload = seg->tcphdr;
734
 
735
  seg->tcphdr->chksum = 0;
736
#if CHECKSUM_GEN_TCP
737
  seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
738
             &(pcb->local_ip),
739
             &(pcb->remote_ip),
740
             IP_PROTO_TCP, seg->p->tot_len);
741
#endif
742
  TCP_STATS_INC(tcp.xmit);
743
 
744
#if LWIP_NETIF_HWADDRHINT
745
  ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
746
      IP_PROTO_TCP, &(pcb->addr_hint));
747
#else /* LWIP_NETIF_HWADDRHINT*/
748
  ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
749
      IP_PROTO_TCP);
750
#endif /* LWIP_NETIF_HWADDRHINT*/
751
}
752
 
753
/**
754
 * Send a TCP RESET packet (empty segment with RST flag set) either to
755
 * abort a connection or to show that there is no matching local connection
756
 * for a received segment.
757
 *
758
 * Called by tcp_abort() (to abort a local connection), tcp_input() (if no
759
 * matching local pcb was found), tcp_listen_input() (if incoming segment
760
 * has ACK flag set) and tcp_process() (received segment in the wrong state)
761
 *
762
 * Since a RST segment is in most cases not sent for an active connection,
763
 * tcp_rst() has a number of arguments that are taken from a tcp_pcb for
764
 * most other segment output functions.
765
 *
766
 * @param seqno the sequence number to use for the outgoing segment
767
 * @param ackno the acknowledge number to use for the outgoing segment
768
 * @param local_ip the local IP address to send the segment from
769
 * @param remote_ip the remote IP address to send the segment to
770
 * @param local_port the local TCP port to send the segment from
771
 * @param remote_port the remote TCP port to send the segment to
772
 */
773
void
774
tcp_rst(u32_t seqno, u32_t ackno,
775
  struct ip_addr *local_ip, struct ip_addr *remote_ip,
776
  u16_t local_port, u16_t remote_port)
777
{
778
  struct pbuf *p;
779
  struct tcp_hdr *tcphdr;
780
  p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
781
  if (p == NULL) {
782
      LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
783
      return;
784
  }
785
  LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
786
              (p->len >= sizeof(struct tcp_hdr)));
787
 
788
  tcphdr = p->payload;
789
  tcphdr->src = htons(local_port);
790
  tcphdr->dest = htons(remote_port);
791
  tcphdr->seqno = htonl(seqno);
792
  tcphdr->ackno = htonl(ackno);
793
  TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
794
  tcphdr->wnd = htons(TCP_WND);
795
  tcphdr->urgp = 0;
796
  TCPH_HDRLEN_SET(tcphdr, 5);
797
 
798
  tcphdr->chksum = 0;
799
#if CHECKSUM_GEN_TCP
800
  tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
801
              IP_PROTO_TCP, p->tot_len);
802
#endif
803
  TCP_STATS_INC(tcp.xmit);
804
  snmp_inc_tcpoutrsts();
805
   /* Send output with hardcoded TTL since we have no access to the pcb */
806
  ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
807
  pbuf_free(p);
808
  LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
809
}
810
 
811
/**
812
 * Requeue all unacked segments for retransmission
813
 *
814
 * Called by tcp_slowtmr() for slow retransmission.
815
 *
816
 * @param pcb the tcp_pcb for which to re-enqueue all unacked segments
817
 */
818
void
819
tcp_rexmit_rto(struct tcp_pcb *pcb)
820
{
821
  struct tcp_seg *seg;
822
 
823
  if (pcb->unacked == NULL) {
824
    return;
825
  }
826
 
827
  /* Move all unacked segments to the head of the unsent queue */
828
  for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
829
  /* concatenate unsent queue after unacked queue */
830
  seg->next = pcb->unsent;
831
  /* unsent queue is the concatenated queue (of unacked, unsent) */
832
  pcb->unsent = pcb->unacked;
833
  /* unacked queue is now empty */
834
  pcb->unacked = NULL;
835
 
836
  /* increment number of retransmissions */
837
  ++pcb->nrtx;
838
 
839
  /* Don't take any RTT measurements after retransmitting. */
840
  pcb->rttest = 0;
841
 
842
  /* Do the actual retransmission */
843
  tcp_output(pcb);
844
}
845
 
846
/**
847
 * Requeue the first unacked segment for retransmission
848
 *
849
 * Called by tcp_receive() for fast retramsmit.
850
 *
851
 * @param pcb the tcp_pcb for which to retransmit the first unacked segment
852
 */
853
void
854
tcp_rexmit(struct tcp_pcb *pcb)
855
{
856
  struct tcp_seg *seg;
857
  struct tcp_seg **cur_seg;
858
 
859
  if (pcb->unacked == NULL) {
860
    return;
861
  }
862
 
863
  /* Move the first unacked segment to the unsent queue */
864
  /* Keep the unsent queue sorted. */
865
  seg = pcb->unacked;
866
  pcb->unacked = seg->next;
867
 
868
  cur_seg = &(pcb->unsent);
869
  while (*cur_seg &&
870
    TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
871
      cur_seg = &((*cur_seg)->next );
872
  }
873
  seg->next = *cur_seg;
874
  *cur_seg = seg;
875
 
876
  ++pcb->nrtx;
877
 
878
  /* Don't take any rtt measurements after retransmitting. */
879
  pcb->rttest = 0;
880
 
881
  /* Do the actual retransmission. */
882
  snmp_inc_tcpretranssegs();
883
  /* No need to call tcp_output: we are always called from tcp_input()
884
     and thus tcp_output directly returns. */
885
}
886
 
887
 
888
/**
889
 * Handle retransmission after three dupacks received
890
 *
891
 * @param pcb the tcp_pcb for which to retransmit the first unacked segment
892
 */
893
void
894
tcp_rexmit_fast(struct tcp_pcb *pcb)
895
{
896
  if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) {
897
    /* This is fast retransmit. Retransmit the first unacked segment. */
898
    LWIP_DEBUGF(TCP_FR_DEBUG,
899
                ("tcp_receive: dupacks %"U16_F" (%"U32_F
900
                 "), fast retransmit %"U32_F"\n",
901
                 (u16_t)pcb->dupacks, pcb->lastack,
902
                 ntohl(pcb->unacked->tcphdr->seqno)));
903
    tcp_rexmit(pcb);
904
 
905
    /* Set ssthresh to half of the minimum of the current
906
     * cwnd and the advertised window */
907
    if (pcb->cwnd > pcb->snd_wnd)
908
      pcb->ssthresh = pcb->snd_wnd / 2;
909
    else
910
      pcb->ssthresh = pcb->cwnd / 2;
911
 
912
    /* The minimum value for ssthresh should be 2 MSS */
913
    if (pcb->ssthresh < 2*pcb->mss) {
914
      LWIP_DEBUGF(TCP_FR_DEBUG,
915
                  ("tcp_receive: The minimum value for ssthresh %"U16_F
916
                   " should be min 2 mss %"U16_F"...\n",
917
                   pcb->ssthresh, 2*pcb->mss));
918
      pcb->ssthresh = 2*pcb->mss;
919
    }
920
 
921
    pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
922
    pcb->flags |= TF_INFR;
923
  }
924
}
925
 
926
 
927
/**
928
 * Send keepalive packets to keep a connection active although
929
 * no data is sent over it.
930
 *
931
 * Called by tcp_slowtmr()
932
 *
933
 * @param pcb the tcp_pcb for which to send a keepalive packet
934
 */
935
void
936
tcp_keepalive(struct tcp_pcb *pcb)
937
{
938
  struct pbuf *p;
939
#if CHECKSUM_GEN_TCP
940
  struct tcp_hdr *tcphdr;
941
#endif
942
  LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
943
                          ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
944
                          ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
945
 
946
  LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F"   pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
947
                          tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
948
 
949
  p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
950
 
951
  if(p == NULL) {
952
    LWIP_DEBUGF(TCP_DEBUG,
953
                ("tcp_keepalive: could not allocate memory for pbuf\n"));
954
    return;
955
  }
956
  LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
957
              (p->len >= sizeof(struct tcp_hdr)));
958
#if CHECKSUM_GEN_TCP
959
  tcphdr =
960
#endif
961
  tcp_output_set_header(pcb, p, 0, htonl(pcb->snd_nxt - 1));
962
 
963
#if CHECKSUM_GEN_TCP
964
  tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
965
                                      IP_PROTO_TCP, p->tot_len);
966
#endif
967
  TCP_STATS_INC(tcp.xmit);
968
 
969
  /* Send output to IP */
970
#if LWIP_NETIF_HWADDRHINT
971
  ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
972
    &(pcb->addr_hint));
973
#else /* LWIP_NETIF_HWADDRHINT*/
974
  ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
975
#endif /* LWIP_NETIF_HWADDRHINT*/
976
 
977
  pbuf_free(p);
978
 
979
  LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n",
980
                          pcb->snd_nxt - 1, pcb->rcv_nxt));
981
}
982
 
983
 
984
/**
985
 * Send persist timer zero-window probes to keep a connection active
986
 * when a window update is lost.
987
 *
988
 * Called by tcp_slowtmr()
989
 *
990
 * @param pcb the tcp_pcb for which to send a zero-window probe packet
991
 */
992
void
993
tcp_zero_window_probe(struct tcp_pcb *pcb)
994
{
995
  struct pbuf *p;
996
  struct tcp_hdr *tcphdr;
997
  struct tcp_seg *seg;
998
  u16_t len;
999
  u8_t is_fin;
1000
 
1001
  LWIP_DEBUGF(TCP_DEBUG,
1002
              ("tcp_zero_window_probe: sending ZERO WINDOW probe to %"
1003
               U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
1004
               ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
1005
               ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
1006
 
1007
  LWIP_DEBUGF(TCP_DEBUG,
1008
              ("tcp_zero_window_probe: tcp_ticks %"U32_F
1009
               "   pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
1010
               tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
1011
 
1012
  seg = pcb->unacked;
1013
 
1014
  if(seg == NULL)
1015
    seg = pcb->unsent;
1016
 
1017
  if(seg == NULL)
1018
    return;
1019
 
1020
  is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
1021
  len = is_fin ? TCP_HLEN : TCP_HLEN + 1;
1022
 
1023
  p = pbuf_alloc(PBUF_IP, len, PBUF_RAM);
1024
  if(p == NULL) {
1025
    LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n"));
1026
    return;
1027
  }
1028
  LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
1029
              (p->len >= sizeof(struct tcp_hdr)));
1030
 
1031
  tcphdr = tcp_output_set_header(pcb, p, 0, seg->tcphdr->seqno);
1032
 
1033
  if (is_fin) {
1034
    /* FIN segment, no data */
1035
    TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
1036
  } else {
1037
    /* Data segment, copy in one byte from the head of the unacked queue */
1038
    *((char *)p->payload + sizeof(struct tcp_hdr)) = *(char *)seg->dataptr;
1039
  }
1040
 
1041
#if CHECKSUM_GEN_TCP
1042
  tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
1043
                                      IP_PROTO_TCP, p->tot_len);
1044
#endif
1045
  TCP_STATS_INC(tcp.xmit);
1046
 
1047
  /* Send output to IP */
1048
#if LWIP_NETIF_HWADDRHINT
1049
  ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
1050
    &(pcb->addr_hint));
1051
#else /* LWIP_NETIF_HWADDRHINT*/
1052
  ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
1053
#endif /* LWIP_NETIF_HWADDRHINT*/
1054
 
1055
  pbuf_free(p);
1056
 
1057
  LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F
1058
                          " ackno %"U32_F".\n",
1059
                          pcb->snd_nxt - 1, pcb->rcv_nxt));
1060
}
1061
#endif /* LWIP_TCP */

powered by: WebSVN 2.1.0

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