TCP ECN source code

2020-07-17 08:00发布

问题:

I had problem understanding Linux Source Code of TCP (net/ipv4/tcp_input.c) in include/net/tcp.h it already defined TCP_ECN_OK = 1 but what really means

tp->ecn_flags & TCP_ECN_OK

Besides, please explain between socket, sock, tcp_sock, sk_buff.

Is there any references that explain more detailed or make it clearer.

Thank you.

Update:

The networking part of the kernel uses mainly two data structures: one to keep the state of a connection called sock (for "socket"), and another to keep the data and the status of both incoming and outgoing packets called sk_buff (for "socket buffer"). Both of them are described in this section. We also include a brief description of tcp_opt, a structure that is part of the sock structure and is used to maintain the TCP connection state. (from "A Map of the Networking Code in Linux Kernel 2.4.20")

回答1:

TCP_ECN_OK is bit flag from linuxkernel's internal struct tcp_sock as (field ecn_flags). There are several bitflags in it (include/net/tcp.h file from linux kernel sources):

398 #define TCP_ECN_OK              1
399 #define TCP_ECN_QUEUE_CWR       2
400 #define TCP_ECN_DEMAND_CWR      4
401 #define TCP_ECN_SEEN            8

Expression tp->ecn_flags & TCP_ECN_OK is the logic test, is the TCP_ECN_OK still set or not.

Update: I think that TCP_ECN_OK bit is set when the tcp socket is open (if the current settings of sysctl enables ECN support in Linux), and it will stay set if the other side of socket supports ECN too.

As said in wikipedia http://en.wikipedia.org/wiki/Explicit_Congestion_Notification

ECN is an optional feature that is only used when both endpoints support it and are willing to use it.

... skip to Linux section

The Linux kernel supports three working modes of the ECN for TCP, as configured by value of the /proc/sys/net/ipv4/tcp_ecn variable, through the sysctl interface:[11 - tcp_ecn in Documentation/networking/ip-sysctl.txt]

  • 0 – disable ECN and neither initiate nor accept it
  • 1 – enable ECN when requested by incoming connections, and also request ECN on outgoing connection attempts
  • 2 – enable ECN when requested by incoming connections, but do not request ECN on outgoing connections. // DEFAULT in 3.14 //

The default value is 2, meaning that by default ECN is enabled when requested by incoming connections, but it is not requested on outgoing connections. Anyway, ECN is used by the Linux kernel only when both ends of the TCP connection indicate support for it.[11]

For example, when we send SYN in beginning of outgoing socket connection, and sysctl tcp_ecn is enabled for outgoing connections ("sysctl_tcp_ecn" flag is 1), we set ECE bit in tcp header and set TCP_ECN_OK. net/ipv4/tcp_output.c Line 315

315 /* Packet ECN state for a SYN.  */
316 static inline void TCP_ECN_send_syn(struct sock *sk, struct sk_buff *skb)
....
320         tp->ecn_flags = 0;
321         if (sock_net(sk)->ipv4.sysctl_tcp_ecn == 1) {
322                 TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_ECE | TCPHDR_CWR;
323                 tp->ecn_flags = TCP_ECN_OK;
324         }

Later, if the other side of connection have no support of ECN or it is disabled, we will unset TCP_ECN_OK flag. net/ipv4/tcp_input.c Line 246

246 static inline void TCP_ECN_rcv_synack(struct tcp_sock *tp, const struct tcphdr *th)
247 {
248         if ((tp->ecn_flags & TCP_ECN_OK) && (!th->ece || th->cwr))
249                 tp->ecn_flags &= ~TCP_ECN_OK;
250 }

For incoming connections, we unset TCP_ECN_OK, if in incoming SYN there was no ECE tcp header flag (read more about flags and ECN in RFC3168 "The Addition of Explicit Congestion Notification (ECN) to IP")

252 static inline void TCP_ECN_rcv_syn(struct tcp_sock *tp, const struct tcphdr *th)
253 {
254         if ((tp->ecn_flags & TCP_ECN_OK) && (!th->ece || !th->cwr))
255                 tp->ecn_flags &= ~TCP_ECN_OK;
256 }


回答2:

A good reference for explaining in details Linux Networking Source Code can be found here at A Map of the Networking Code in Linux Kernel 2.4.20