From: Ilpo Järvinen <i...@kernel.org>

With AccECN, there's one additional TCP flag to be used (AE)
and ACE field that overloads the definition of AE, CWR, and
ECE flags. As tcp_flags was previously only 1 byte, the
byte-order stuff needs to be added to it's handling.

Signed-off-by: Ilpo Järvinen <i...@kernel.org>
Signed-off-by: Chia-Yu Chang <chia-yu.ch...@nokia-bell-labs.com>
Reviewed-by: Eric Dumazet <eduma...@google.com>
---
 include/net/tcp.h             | 11 +++++++++--
 include/uapi/linux/tcp.h      |  9 ++++++---
 net/ipv4/tcp_ipv4.c           |  2 +-
 net/ipv4/tcp_output.c         |  8 ++++----
 net/ipv6/tcp_ipv6.c           |  2 +-
 net/netfilter/nf_log_syslog.c |  8 +++++---
 6 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/include/net/tcp.h b/include/net/tcp.h
index 99dcbb47eac0..c9bab41685cf 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -920,7 +920,14 @@ static inline u32 tcp_rsk_tsval(const struct 
tcp_request_sock *treq)
 #define TCPHDR_URG     BIT(5)
 #define TCPHDR_ECE     BIT(6)
 #define TCPHDR_CWR     BIT(7)
-
+#define TCPHDR_AE      BIT(8)
+#define TCPHDR_FLAGS_MASK (TCPHDR_FIN | TCPHDR_SYN | TCPHDR_RST | \
+                          TCPHDR_PSH | TCPHDR_ACK | TCPHDR_URG | \
+                          TCPHDR_ECE | TCPHDR_CWR | TCPHDR_AE)
+#define tcp_flags_ntohs(th) (ntohs(*(__be16 *)&tcp_flag_word(th)) & \
+                           TCPHDR_FLAGS_MASK)
+
+#define TCPHDR_ACE (TCPHDR_ECE | TCPHDR_CWR | TCPHDR_AE)
 #define TCPHDR_SYN_ECN (TCPHDR_SYN | TCPHDR_ECE | TCPHDR_CWR)
 
 /* State flags for sacked in struct tcp_skb_cb */
@@ -955,7 +962,7 @@ struct tcp_skb_cb {
                        u16     tcp_gso_size;
                };
        };
-       __u8            tcp_flags;      /* TCP header flags. (tcp[13])  */
+       __u16           tcp_flags;      /* TCP header flags (tcp[12-13])*/
 
        __u8            sacked;         /* State flags for SACK.        */
        __u8            ip_dsfield;     /* IPv4 tos or IPv6 dsfield     */
diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h
index dbf896f3146c..3fe08d7dddaf 100644
--- a/include/uapi/linux/tcp.h
+++ b/include/uapi/linux/tcp.h
@@ -28,7 +28,8 @@ struct tcphdr {
        __be32  seq;
        __be32  ack_seq;
 #if defined(__LITTLE_ENDIAN_BITFIELD)
-       __u16   res1:4,
+       __u16   ae:1,
+               res1:3,
                doff:4,
                fin:1,
                syn:1,
@@ -40,7 +41,8 @@ struct tcphdr {
                cwr:1;
 #elif defined(__BIG_ENDIAN_BITFIELD)
        __u16   doff:4,
-               res1:4,
+               res1:3,
+               ae:1,
                cwr:1,
                ece:1,
                urg:1,
@@ -70,6 +72,7 @@ union tcp_word_hdr {
 #define tcp_flag_word(tp) (((union tcp_word_hdr *)(tp))->words[3])
 
 enum {
+       TCP_FLAG_AE  = __constant_cpu_to_be32(0x01000000),
        TCP_FLAG_CWR = __constant_cpu_to_be32(0x00800000),
        TCP_FLAG_ECE = __constant_cpu_to_be32(0x00400000),
        TCP_FLAG_URG = __constant_cpu_to_be32(0x00200000),
@@ -78,7 +81,7 @@ enum {
        TCP_FLAG_RST = __constant_cpu_to_be32(0x00040000),
        TCP_FLAG_SYN = __constant_cpu_to_be32(0x00020000),
        TCP_FLAG_FIN = __constant_cpu_to_be32(0x00010000),
-       TCP_RESERVED_BITS = __constant_cpu_to_be32(0x0F000000),
+       TCP_RESERVED_BITS = __constant_cpu_to_be32(0x0E000000),
        TCP_DATA_OFFSET = __constant_cpu_to_be32(0xF0000000)
 };
 
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index e45222d5fc2e..b0b8bbfa9386 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2165,7 +2165,7 @@ static void tcp_v4_fill_cb(struct sk_buff *skb, const 
struct iphdr *iph,
        TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
                                    skb->len - th->doff * 4);
        TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
-       TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th);
+       TCP_SKB_CB(skb)->tcp_flags = tcp_flags_ntohs(th);
        TCP_SKB_CB(skb)->ip_dsfield = ipv4_get_dsfield(iph);
        TCP_SKB_CB(skb)->sacked  = 0;
        TCP_SKB_CB(skb)->has_rxtstamp =
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 0e5b9a654254..33e73cefcdbc 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -400,7 +400,7 @@ static void tcp_ecn_send(struct sock *sk, struct sk_buff 
*skb,
 /* Constructs common control bits of non-data skb. If SYN/FIN is present,
  * auto increment end seqno.
  */
-static void tcp_init_nondata_skb(struct sk_buff *skb, u32 seq, u8 flags)
+static void tcp_init_nondata_skb(struct sk_buff *skb, u32 seq, u16 flags)
 {
        skb->ip_summed = CHECKSUM_PARTIAL;
 
@@ -1384,7 +1384,7 @@ static int __tcp_transmit_skb(struct sock *sk, struct 
sk_buff *skb,
        th->seq                 = htonl(tcb->seq);
        th->ack_seq             = htonl(rcv_nxt);
        *(((__be16 *)th) + 6)   = htons(((tcp_header_size >> 2) << 12) |
-                                       tcb->tcp_flags);
+                                       (tcb->tcp_flags & TCPHDR_FLAGS_MASK));
 
        th->check               = 0;
        th->urg_ptr             = 0;
@@ -1605,8 +1605,8 @@ int tcp_fragment(struct sock *sk, enum tcp_queue 
tcp_queue,
        struct sk_buff *buff;
        int old_factor;
        long limit;
+       u16 flags;
        int nlen;
-       u8 flags;
 
        if (WARN_ON(len > skb->len))
                return -EINVAL;
@@ -2161,7 +2161,7 @@ static int tso_fragment(struct sock *sk, struct sk_buff 
*skb, unsigned int len,
 {
        int nlen = skb->len - len;
        struct sk_buff *buff;
-       u8 flags;
+       u16 flags;
 
        /* All of a TSO frame must be composed of paged data.  */
        DEBUG_NET_WARN_ON_ONCE(skb->len != skb->data_len);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 2debdf085a3b..e373ca997ee0 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1735,7 +1735,7 @@ static void tcp_v6_fill_cb(struct sk_buff *skb, const 
struct ipv6hdr *hdr,
        TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
                                    skb->len - th->doff*4);
        TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
-       TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th);
+       TCP_SKB_CB(skb)->tcp_flags = tcp_flags_ntohs(th);
        TCP_SKB_CB(skb)->ip_dsfield = ipv6_get_dsfield(hdr);
        TCP_SKB_CB(skb)->sacked = 0;
        TCP_SKB_CB(skb)->has_rxtstamp =
diff --git a/net/netfilter/nf_log_syslog.c b/net/netfilter/nf_log_syslog.c
index 58402226045e..86d5fc5d28e3 100644
--- a/net/netfilter/nf_log_syslog.c
+++ b/net/netfilter/nf_log_syslog.c
@@ -216,7 +216,9 @@ nf_log_dump_tcp_header(struct nf_log_buf *m,
        /* Max length: 9 "RES=0x3C " */
        nf_log_buf_add(m, "RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) &
                                            TCP_RESERVED_BITS) >> 22));
-       /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
+       /* Max length: 35 "AE CWR ECE URG ACK PSH RST SYN FIN " */
+       if (th->ae)
+               nf_log_buf_add(m, "AE ");
        if (th->cwr)
                nf_log_buf_add(m, "CWR ");
        if (th->ece)
@@ -516,7 +518,7 @@ dump_ipv4_packet(struct net *net, struct nf_log_buf *m,
 
        /* Proto    Max log string length */
        /* IP:      40+46+6+11+127 = 230 */
-       /* TCP:     10+max(25,20+30+13+9+32+11+127) = 252 */
+       /* TCP:     10+max(25,20+30+13+9+35+11+127) = 255 */
        /* UDP:     10+max(25,20) = 35 */
        /* UDPLITE: 14+max(25,20) = 39 */
        /* ICMP:    11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */
@@ -526,7 +528,7 @@ dump_ipv4_packet(struct net *net, struct nf_log_buf *m,
 
        /* (ICMP allows recursion one level deep) */
        /* maxlen =  IP + ICMP +  IP + max(TCP,UDP,ICMP,unknown) */
-       /* maxlen = 230+   91  + 230 + 252 = 803 */
+       /* maxlen = 230+   91  + 230 + 255 = 806 */
 }
 
 static noinline_for_stack void
-- 
2.34.1


Reply via email to