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")
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 }
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