1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright 2017 Duncan Hare, all rights reserved.
9 * TCP support for the wget command, for fast file downloading.
13 * Prerequisites: - own ethernet address
17 * - TCP application (eg wget)
23 #include <env_internal.h>
29 * TCP sliding window control used by us to request re-TX
31 static struct tcp_sack_v tcp_lost
;
33 /* TCP option timestamp */
34 static u32 loc_timestamp
;
35 static u32 rmt_timestamp
;
37 static u32 tcp_seq_init
;
38 static u32 tcp_ack_edge
;
40 static int tcp_activity_count
;
43 * Search for TCP_SACK and review the comments before the code section
44 * TCP_SACK is the number of packets at the front of the stream
47 enum pkt_state
{PKT
, NOPKT
};
53 static struct sack_r edge_a
[TCP_SACK
];
54 static unsigned int sack_idx
;
55 static unsigned int prev_len
;
58 * TCP lengths are stored as a rounded up number of 32 bit words.
59 * Add 3 to length round up, rounded, then divided into the
60 * length in 32 bit words.
62 #define LEN_B_TO_DW(x) ((x) >> 2)
63 #define ROUND_TCPHDR_LEN(x) (LEN_B_TO_DW((x) + 3))
64 #define SHIFT_TO_TCPHDRLEN_FIELD(x) ((x) << 4)
65 #define GET_TCP_HDR_LEN_IN_BYTES(x) ((x) >> 2)
67 /* TCP connection state */
68 static enum tcp_state current_tcp_state
;
70 /* Current TCP RX packet handler */
71 static rxhand_tcp
*tcp_packet_handler
;
74 * tcp_get_tcp_state() - get current TCP state
76 * Return: Current TCP state
78 enum tcp_state
tcp_get_tcp_state(void)
80 return current_tcp_state
;
84 * tcp_set_tcp_state() - set current TCP state
85 * @new_state: new TCP state
87 void tcp_set_tcp_state(enum tcp_state new_state
)
89 current_tcp_state
= new_state
;
92 static void dummy_handler(uchar
*pkt
, u16 dport
,
93 struct in_addr sip
, u16 sport
,
94 u32 tcp_seq_num
, u32 tcp_ack_num
,
95 u8 action
, unsigned int len
)
100 * tcp_set_tcp_handler() - set a handler to receive data
103 void tcp_set_tcp_handler(rxhand_tcp
*f
)
105 debug_cond(DEBUG_INT_STATE
, "--- net_loop TCP handler set (%p)\n", f
);
107 tcp_packet_handler
= dummy_handler
;
109 tcp_packet_handler
= f
;
113 * tcp_set_pseudo_header() - set TCP pseudo header
115 * @src: source IP address
116 * @dest: destinaion IP address
117 * @tcp_len: tcp length
118 * @pkt_len: packet length
120 * Return: the checksum of the packet
122 u16
tcp_set_pseudo_header(uchar
*pkt
, struct in_addr src
, struct in_addr dest
,
123 int tcp_len
, int pkt_len
)
125 union tcp_build_pkt
*b
= (union tcp_build_pkt
*)pkt
;
131 * Zero the byte after the last byte so that the header checksum
136 net_copy_ip((void *)&b
->ph
.p_src
, &src
);
137 net_copy_ip((void *)&b
->ph
.p_dst
, &dest
);
139 b
->ph
.p
= IPPROTO_TCP
;
140 b
->ph
.len
= htons(tcp_len
);
141 checksum_len
= tcp_len
+ PSEUDO_HDR_SIZE
;
143 debug_cond(DEBUG_DEV_PKT
,
144 "TCP Pesudo Header (to=%pI4, from=%pI4, Len=%d)\n",
145 &b
->ph
.p_dst
, &b
->ph
.p_src
, checksum_len
);
147 return compute_ip_checksum(pkt
+ PSEUDO_PAD_SIZE
, checksum_len
);
151 * net_set_ack_options() - set TCP options in acknowledge packets
154 * Return: TCP header length
156 int net_set_ack_options(union tcp_build_pkt
*b
)
158 b
->sack
.hdr
.tcp_hlen
= SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE
));
160 b
->sack
.t_opt
.kind
= TCP_O_TS
;
161 b
->sack
.t_opt
.len
= TCP_OPT_LEN_A
;
162 b
->sack
.t_opt
.t_snd
= htons(loc_timestamp
);
163 b
->sack
.t_opt
.t_rcv
= rmt_timestamp
;
164 b
->sack
.sack_v
.kind
= TCP_1_NOP
;
165 b
->sack
.sack_v
.len
= 0;
167 if (IS_ENABLED(CONFIG_PROT_TCP_SACK
)) {
168 if (tcp_lost
.len
> TCP_OPT_LEN_2
) {
169 debug_cond(DEBUG_DEV_PKT
, "TCP ack opt lost.len %x\n",
171 b
->sack
.sack_v
.len
= tcp_lost
.len
;
172 b
->sack
.sack_v
.kind
= TCP_V_SACK
;
173 b
->sack
.sack_v
.hill
[0].l
= htonl(tcp_lost
.hill
[0].l
);
174 b
->sack
.sack_v
.hill
[0].r
= htonl(tcp_lost
.hill
[0].r
);
177 * These SACK structures are initialized with NOPs to
178 * provide TCP header alignment padding. There are 4
179 * SACK structures used for both header padding and
182 b
->sack
.sack_v
.hill
[1].l
= htonl(tcp_lost
.hill
[1].l
);
183 b
->sack
.sack_v
.hill
[1].r
= htonl(tcp_lost
.hill
[1].r
);
184 b
->sack
.sack_v
.hill
[2].l
= htonl(tcp_lost
.hill
[2].l
);
185 b
->sack
.sack_v
.hill
[2].r
= htonl(tcp_lost
.hill
[2].r
);
186 b
->sack
.sack_v
.hill
[3].l
= TCP_O_NOP
;
187 b
->sack
.sack_v
.hill
[3].r
= TCP_O_NOP
;
190 b
->sack
.hdr
.tcp_hlen
= SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE
+
194 b
->sack
.sack_v
.kind
= 0;
195 b
->sack
.hdr
.tcp_hlen
= SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE
+
200 * This returns the actual rounded up length of the
201 * TCP header to add to the total packet length
204 return GET_TCP_HDR_LEN_IN_BYTES(b
->sack
.hdr
.tcp_hlen
);
208 * net_set_ack_options() - set TCP options in SYN packets
211 void net_set_syn_options(union tcp_build_pkt
*b
)
213 if (IS_ENABLED(CONFIG_PROT_TCP_SACK
))
216 b
->ip
.hdr
.tcp_hlen
= 0xa0;
218 b
->ip
.mss
.kind
= TCP_O_MSS
;
219 b
->ip
.mss
.len
= TCP_OPT_LEN_4
;
220 b
->ip
.mss
.mss
= htons(TCP_MSS
);
221 b
->ip
.scale
.kind
= TCP_O_SCL
;
222 b
->ip
.scale
.scale
= TCP_SCALE
;
223 b
->ip
.scale
.len
= TCP_OPT_LEN_3
;
224 if (IS_ENABLED(CONFIG_PROT_TCP_SACK
)) {
225 b
->ip
.sack_p
.kind
= TCP_P_SACK
;
226 b
->ip
.sack_p
.len
= TCP_OPT_LEN_2
;
228 b
->ip
.sack_p
.kind
= TCP_1_NOP
;
229 b
->ip
.sack_p
.len
= TCP_1_NOP
;
231 b
->ip
.t_opt
.kind
= TCP_O_TS
;
232 b
->ip
.t_opt
.len
= TCP_OPT_LEN_A
;
233 loc_timestamp
= get_ticks();
235 b
->ip
.t_opt
.t_snd
= 0;
236 b
->ip
.t_opt
.t_rcv
= 0;
237 b
->ip
.end
= TCP_O_END
;
240 int tcp_set_tcp_header(uchar
*pkt
, int dport
, int sport
, int payload_len
,
241 u8 action
, u32 tcp_seq_num
, u32 tcp_ack_num
)
243 union tcp_build_pkt
*b
= (union tcp_build_pkt
*)pkt
;
249 * Header: 5 32 bit words. 4 bits TCP header Length,
250 * 4 bits reserved options
252 b
->ip
.hdr
.tcp_flags
= action
;
253 pkt_hdr_len
= IP_TCP_HDR_SIZE
;
254 b
->ip
.hdr
.tcp_hlen
= SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE
));
258 debug_cond(DEBUG_DEV_PKT
,
259 "TCP Hdr:SYN (%pI4, %pI4, sq=%u, ak=%u)\n",
260 &net_server_ip
, &net_ip
,
261 tcp_seq_num
, tcp_ack_num
);
262 tcp_activity_count
= 0;
263 net_set_syn_options(b
);
266 pkt_hdr_len
= IP_TCP_O_SIZE
;
267 if (current_tcp_state
== TCP_SYN_SENT
) { /* Too many SYNs */
269 current_tcp_state
= TCP_FIN_WAIT_1
;
271 current_tcp_state
= TCP_SYN_SENT
;
274 case TCP_SYN
| TCP_ACK
:
276 pkt_hdr_len
= IP_HDR_SIZE
+ net_set_ack_options(b
);
277 b
->ip
.hdr
.tcp_flags
= action
;
278 debug_cond(DEBUG_DEV_PKT
,
279 "TCP Hdr:ACK (%pI4, %pI4, s=%u, a=%u, A=%x)\n",
280 &net_server_ip
, &net_ip
, tcp_seq_num
, tcp_ack_num
,
284 debug_cond(DEBUG_DEV_PKT
,
285 "TCP Hdr:FIN (%pI4, %pI4, s=%u, a=%u)\n",
286 &net_server_ip
, &net_ip
, tcp_seq_num
, tcp_ack_num
);
288 pkt_hdr_len
= IP_TCP_HDR_SIZE
;
289 current_tcp_state
= TCP_FIN_WAIT_1
;
291 case TCP_RST
| TCP_ACK
:
293 debug_cond(DEBUG_DEV_PKT
,
294 "TCP Hdr:RST (%pI4, %pI4, s=%u, a=%u)\n",
295 &net_server_ip
, &net_ip
, tcp_seq_num
, tcp_ack_num
);
296 current_tcp_state
= TCP_CLOSED
;
298 /* Notify connection closing */
299 case (TCP_FIN
| TCP_ACK
):
300 case (TCP_FIN
| TCP_ACK
| TCP_PUSH
):
301 if (current_tcp_state
== TCP_CLOSE_WAIT
)
302 current_tcp_state
= TCP_CLOSING
;
304 debug_cond(DEBUG_DEV_PKT
,
305 "TCP Hdr:FIN ACK PSH(%pI4, %pI4, s=%u, a=%u, A=%x)\n",
306 &net_server_ip
, &net_ip
,
307 tcp_seq_num
, tcp_ack_num
, action
);
310 pkt_hdr_len
= IP_HDR_SIZE
+ net_set_ack_options(b
);
311 b
->ip
.hdr
.tcp_flags
= action
| TCP_PUSH
| TCP_ACK
;
312 debug_cond(DEBUG_DEV_PKT
,
313 "TCP Hdr:dft (%pI4, %pI4, s=%u, a=%u, A=%x)\n",
314 &net_server_ip
, &net_ip
,
315 tcp_seq_num
, tcp_ack_num
, action
);
318 pkt_len
= pkt_hdr_len
+ payload_len
;
319 tcp_len
= pkt_len
- IP_HDR_SIZE
;
321 tcp_ack_edge
= tcp_ack_num
;
323 b
->ip
.hdr
.tcp_ack
= htonl(tcp_ack_edge
);
324 b
->ip
.hdr
.tcp_src
= htons(sport
);
325 b
->ip
.hdr
.tcp_dst
= htons(dport
);
326 b
->ip
.hdr
.tcp_seq
= htonl(tcp_seq_num
);
329 * TCP window size - TCP header variable tcp_win.
330 * Change tcp_win only if you have an understanding of network
331 * overrun, congestion, TCP segment sizes, TCP windows, TCP scale,
332 * queuing theory and packet buffering. If there are too few buffers,
333 * there will be data loss, recovery may work or the sending TCP,
334 * the server, could abort the stream transmission.
335 * MSS is governed by maximum Ethernet frame length.
336 * The number of buffers is governed by the desire to have a queue of
337 * full buffers to be processed at the destination to maximize
338 * throughput. Temporary memory use for the boot phase on modern
339 * SOCs is may not be considered a constraint to buffer space, if
340 * it is, then the u-boot tftp or nfs kernel netboot should be
343 b
->ip
.hdr
.tcp_win
= htons(PKTBUFSRX
* TCP_MSS
>> TCP_SCALE
);
345 b
->ip
.hdr
.tcp_xsum
= 0;
346 b
->ip
.hdr
.tcp_ugr
= 0;
348 b
->ip
.hdr
.tcp_xsum
= tcp_set_pseudo_header(pkt
, net_ip
, net_server_ip
,
351 net_set_ip_header((uchar
*)&b
->ip
, net_server_ip
, net_ip
,
352 pkt_len
, IPPROTO_TCP
);
358 * tcp_hole() - Selective Acknowledgment (Essential for fast stream transfer)
359 * @tcp_seq_num: TCP sequence start number
360 * @len: the length of sequence numbers
362 void tcp_hole(u32 tcp_seq_num
, u32 len
)
364 u32 idx_sack
, sack_in
;
365 u32 sack_end
= TCP_SACK
- 1;
367 enum pkt_state expect
= PKT
;
368 u32 seq
= tcp_seq_num
- tcp_seq_init
;
369 u32 hol_l
= tcp_ack_edge
- tcp_seq_init
;
372 /* Place new seq number in correct place in receive array */
376 idx_sack
= sack_idx
+ ((tcp_seq_num
- tcp_ack_edge
) / prev_len
);
377 if (idx_sack
< TCP_SACK
) {
378 edge_a
[idx_sack
].se
.l
= tcp_seq_num
;
379 edge_a
[idx_sack
].se
.r
= tcp_seq_num
+ len
;
380 edge_a
[idx_sack
].st
= PKT
;
383 * The fin (last) packet is not the same length as data
384 * packets, and if it's length is recorded and used for
385 * array index calculation, calculation breaks.
391 debug_cond(DEBUG_DEV_PKT
,
392 "TCP 1 seq %d, edg %d, len %d, sack_idx %d, sack_end %d\n",
393 seq
, hol_l
, len
, sack_idx
, sack_end
);
395 /* Right edge of contiguous stream, is the left edge of first hill */
396 hol_l
= tcp_seq_num
- tcp_seq_init
;
399 if (IS_ENABLED(CONFIG_PROT_TCP_SACK
))
400 tcp_lost
.len
= TCP_OPT_LEN_2
;
402 debug_cond(DEBUG_DEV_PKT
,
403 "TCP 1 in %d, seq %d, pkt_l %d, pkt_r %d, sack_idx %d, sack_end %d\n",
404 idx_sack
, seq
, hol_l
, hol_r
, sack_idx
, sack_end
);
406 for (sack_in
= sack_idx
; sack_in
< sack_end
&& hill
< TCP_SACK_HILLS
;
410 switch (edge_a
[sack_in
].st
) {
412 debug_cond(DEBUG_INT_STATE
, "N");
415 debug_cond(DEBUG_INT_STATE
, "n");
416 if (IS_ENABLED(CONFIG_PROT_TCP_SACK
)) {
417 tcp_lost
.hill
[hill
].l
=
418 edge_a
[sack_in
].se
.l
;
419 tcp_lost
.hill
[hill
].r
=
420 edge_a
[sack_in
].se
.r
;
427 switch (edge_a
[sack_in
].st
) {
429 debug_cond(DEBUG_INT_STATE
, "p");
430 if (sack_in
> sack_idx
&&
431 hill
< TCP_SACK_HILLS
) {
433 if (IS_ENABLED(CONFIG_PROT_TCP_SACK
))
434 tcp_lost
.len
+= TCP_OPT_LEN_8
;
439 debug_cond(DEBUG_INT_STATE
, "P");
441 if (tcp_ack_edge
== edge_a
[sack_in
].se
.l
) {
442 tcp_ack_edge
= edge_a
[sack_in
].se
.r
;
443 edge_a
[sack_in
].st
= NOPKT
;
446 if (IS_ENABLED(CONFIG_PROT_TCP_SACK
) &&
447 hill
< TCP_SACK_HILLS
)
448 tcp_lost
.hill
[hill
].r
=
449 edge_a
[sack_in
].se
.r
;
450 if (IS_ENABLED(CONFIG_PROT_TCP_SACK
) &&
451 sack_in
== sack_end
- 1)
452 tcp_lost
.hill
[hill
].r
=
453 edge_a
[sack_in
].se
.r
;
460 debug_cond(DEBUG_INT_STATE
, "\n");
461 if (!IS_ENABLED(CONFIG_PROT_TCP_SACK
) || tcp_lost
.len
<= TCP_OPT_LEN_2
)
466 * tcp_parse_options() - parsing TCP options
467 * @o: pointer to the option field.
468 * @o_len: length of the option field.
470 void tcp_parse_options(uchar
*o
, int o_len
)
472 struct tcp_t_opt
*tsopt
;
476 * NOPs are options with a zero length, and thus are special.
477 * All other options have length fields.
479 for (p
= o
; p
< (o
+ o_len
); p
= p
+ p
[1]) {
481 return; /* Finished processing options */
492 tsopt
= (struct tcp_t_opt
*)p
;
493 rmt_timestamp
= tsopt
->t_snd
;
497 /* Process optional NOPs */
498 if (p
[0] == TCP_O_NOP
)
503 static u8
tcp_state_machine(u8 tcp_flags
, u32 tcp_seq_num
, int payload_len
)
505 u8 tcp_fin
= tcp_flags
& TCP_FIN
;
506 u8 tcp_syn
= tcp_flags
& TCP_SYN
;
507 u8 tcp_rst
= tcp_flags
& TCP_RST
;
508 u8 tcp_push
= tcp_flags
& TCP_PUSH
;
509 u8 tcp_ack
= tcp_flags
& TCP_ACK
;
510 u8 action
= TCP_DATA
;
514 * tcp_flags are examined to determine TX action in a given state
515 * tcp_push is interpreted to mean "inform the app"
516 * urg, ece, cer and nonce flags are not supported.
518 * exe and crw are use to signal and confirm knowledge of congestion.
519 * This TCP only sends a file request and acks. If it generates
520 * congestion, the network is broken.
522 debug_cond(DEBUG_INT_STATE
, "TCP STATE ENTRY %x\n", action
);
525 current_tcp_state
= TCP_CLOSED
;
526 net_set_state(NETLOOP_FAIL
);
527 debug_cond(DEBUG_INT_STATE
, "TCP Reset %x\n", tcp_flags
);
531 switch (current_tcp_state
) {
533 debug_cond(DEBUG_INT_STATE
, "TCP CLOSED %x\n", tcp_flags
);
535 action
= TCP_SYN
| TCP_ACK
;
536 tcp_seq_init
= tcp_seq_num
;
537 tcp_ack_edge
= tcp_seq_num
+ 1;
538 current_tcp_state
= TCP_SYN_RECEIVED
;
539 } else if (tcp_ack
|| tcp_fin
) {
543 case TCP_SYN_RECEIVED
:
545 debug_cond(DEBUG_INT_STATE
, "TCP_SYN_SENT | TCP_SYN_RECEIVED %x, %u\n",
546 tcp_flags
, tcp_seq_num
);
548 action
= action
| TCP_PUSH
;
549 current_tcp_state
= TCP_CLOSE_WAIT
;
550 } else if (tcp_ack
|| (tcp_syn
&& tcp_ack
)) {
552 tcp_seq_init
= tcp_seq_num
;
553 tcp_ack_edge
= tcp_seq_num
+ 1;
555 edge_a
[sack_idx
].se
.l
= tcp_ack_edge
;
556 edge_a
[sack_idx
].se
.r
= tcp_ack_edge
;
558 current_tcp_state
= TCP_ESTABLISHED
;
559 for (i
= 0; i
< TCP_SACK
; i
++)
560 edge_a
[i
].st
= NOPKT
;
562 if (tcp_syn
&& tcp_ack
)
568 case TCP_ESTABLISHED
:
569 debug_cond(DEBUG_INT_STATE
, "TCP_ESTABLISHED %x\n", tcp_flags
);
570 if (payload_len
> 0) {
571 tcp_hole(tcp_seq_num
, payload_len
);
572 tcp_fin
= TCP_DATA
; /* cause standalone FIN */
576 (!IS_ENABLED(CONFIG_PROT_TCP_SACK
) ||
577 tcp_lost
.len
<= TCP_OPT_LEN_2
)) {
578 action
= action
| TCP_FIN
| TCP_PUSH
| TCP_ACK
;
579 current_tcp_state
= TCP_CLOSE_WAIT
;
580 } else if (tcp_ack
) {
585 action
= TCP_ACK
+ TCP_RST
;
587 action
= action
| TCP_PUSH
;
590 debug_cond(DEBUG_INT_STATE
, "TCP_CLOSE_WAIT (%x)\n", tcp_flags
);
594 debug_cond(DEBUG_INT_STATE
, "TCP_FIN_WAIT_2 (%x)\n", tcp_flags
);
596 action
= TCP_PUSH
| TCP_ACK
;
597 current_tcp_state
= TCP_CLOSED
;
599 } else if (tcp_syn
) {
601 } else if (tcp_fin
) {
606 debug_cond(DEBUG_INT_STATE
, "TCP_FIN_WAIT_1 (%x)\n", tcp_flags
);
609 action
= TCP_ACK
| TCP_FIN
;
610 current_tcp_state
= TCP_FIN_WAIT_2
;
615 current_tcp_state
= TCP_CLOSED
;
618 debug_cond(DEBUG_INT_STATE
, "TCP_CLOSING (%x)\n", tcp_flags
);
621 current_tcp_state
= TCP_CLOSED
;
623 } else if (tcp_syn
) {
625 } else if (tcp_fin
) {
634 * rxhand_tcp_f() - process receiving data and call data handler.
636 * @pkt_len: the length of packet.
638 void rxhand_tcp_f(union tcp_build_pkt
*b
, unsigned int pkt_len
)
640 int tcp_len
= pkt_len
- IP_HDR_SIZE
;
641 u16 tcp_rx_xsum
= b
->ip
.hdr
.ip_sum
;
642 u8 tcp_action
= TCP_DATA
;
643 u32 tcp_seq_num
, tcp_ack_num
;
644 int tcp_hdr_len
, payload_len
;
646 /* Verify IP header */
647 debug_cond(DEBUG_DEV_PKT
,
648 "TCP RX in RX Sum (to=%pI4, from=%pI4, len=%d)\n",
649 &b
->ip
.hdr
.ip_src
, &b
->ip
.hdr
.ip_dst
, pkt_len
);
651 b
->ip
.hdr
.ip_src
= net_server_ip
;
652 b
->ip
.hdr
.ip_dst
= net_ip
;
653 b
->ip
.hdr
.ip_sum
= 0;
654 if (tcp_rx_xsum
!= compute_ip_checksum(b
, IP_HDR_SIZE
)) {
655 debug_cond(DEBUG_DEV_PKT
,
656 "TCP RX IP xSum Error (%pI4, =%pI4, len=%d)\n",
657 &net_ip
, &net_server_ip
, pkt_len
);
661 /* Build pseudo header and verify TCP header */
662 tcp_rx_xsum
= b
->ip
.hdr
.tcp_xsum
;
663 b
->ip
.hdr
.tcp_xsum
= 0;
664 if (tcp_rx_xsum
!= tcp_set_pseudo_header((uchar
*)b
, b
->ip
.hdr
.ip_src
,
665 b
->ip
.hdr
.ip_dst
, tcp_len
,
667 debug_cond(DEBUG_DEV_PKT
,
668 "TCP RX TCP xSum Error (%pI4, %pI4, len=%d)\n",
669 &net_ip
, &net_server_ip
, tcp_len
);
673 tcp_hdr_len
= GET_TCP_HDR_LEN_IN_BYTES(b
->ip
.hdr
.tcp_hlen
);
674 payload_len
= tcp_len
- tcp_hdr_len
;
676 if (tcp_hdr_len
> TCP_HDR_SIZE
)
677 tcp_parse_options((uchar
*)b
+ IP_TCP_HDR_SIZE
,
678 tcp_hdr_len
- TCP_HDR_SIZE
);
680 * Incoming sequence and ack numbers are server's view of the numbers.
681 * The app must swap the numbers when responding.
683 tcp_seq_num
= ntohl(b
->ip
.hdr
.tcp_seq
);
684 tcp_ack_num
= ntohl(b
->ip
.hdr
.tcp_ack
);
686 /* Packets are not ordered. Send to app as received. */
687 tcp_action
= tcp_state_machine(b
->ip
.hdr
.tcp_flags
,
688 tcp_seq_num
, payload_len
);
690 tcp_activity_count
++;
691 if (tcp_activity_count
> TCP_ACTIVITY
) {
693 tcp_activity_count
= 0;
696 if ((tcp_action
& TCP_PUSH
) || payload_len
> 0) {
697 debug_cond(DEBUG_DEV_PKT
,
698 "TCP Notify (action=%x, Seq=%u,Ack=%u,Pay%d)\n",
699 tcp_action
, tcp_seq_num
, tcp_ack_num
, payload_len
);
701 (*tcp_packet_handler
) ((uchar
*)b
+ pkt_len
- payload_len
, b
->ip
.hdr
.tcp_dst
,
702 b
->ip
.hdr
.ip_src
, b
->ip
.hdr
.tcp_src
, tcp_seq_num
,
703 tcp_ack_num
, tcp_action
, payload_len
);
705 } else if (tcp_action
!= TCP_DATA
) {
706 debug_cond(DEBUG_DEV_PKT
,
707 "TCP Action (action=%x,Seq=%u,Ack=%u,Pay=%d)\n",
708 tcp_action
, tcp_ack_num
, tcp_ack_edge
, payload_len
);
711 * Warning: Incoming Ack & Seq sequence numbers are transposed
712 * here to outgoing Seq & Ack sequence numbers
714 net_send_tcp_packet(0, ntohs(b
->ip
.hdr
.tcp_src
),
715 ntohs(b
->ip
.hdr
.tcp_dst
),
716 (tcp_action
& (~TCP_PUSH
)),
717 tcp_ack_num
, tcp_ack_edge
);