]> www.infradead.org Git - users/hch/misc.git/commitdiff
tcp: extend TCP flags to allow AE bit/ACE field
authorIlpo Järvinen <ij@kernel.org>
Wed, 5 Mar 2025 22:38:44 +0000 (23:38 +0100)
committerDavid S. Miller <davem@davemloft.net>
Mon, 17 Mar 2025 13:49:46 +0000 (13:49 +0000)
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 <ij@kernel.org>
Signed-off-by: Chia-Yu Chang <chia-yu.chang@nokia-bell-labs.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/tcp.h
include/uapi/linux/tcp.h
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv6/tcp_ipv6.c
net/netfilter/nf_log_syslog.c

index d2315d69e01951aae4719ac9ef988bae021f69b6..4e11bdc864709c17594e9888c666d05448a7e8ff 100644 (file)
@@ -943,7 +943,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 */
@@ -978,7 +985,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     */
index 32a27b4a5020ad066d5e443b04a3a2e34fbf6178..92a2e79222ea551404ca6fc847327e5e7f617798 100644 (file)
@@ -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)
 };
 
index d9405b012dff079f7cafd9d422ff4445a27eb064..fab684221bf72ecb8c69e78a2c246d1c973dc27d 100644 (file)
@@ -2159,7 +2159,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 =
index 24e56bf96747253c1a508ddfe27ebd38da7c219e..efd3cb5e1ded06d1a55c8fc0b230fab2e703b563 100644 (file)
@@ -403,7 +403,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;
 
@@ -1395,7 +1395,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;
@@ -1616,8 +1616,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;
@@ -2171,7 +2171,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);
index 85c4820bfe1588e4553784129d13408dea70763a..a2fcc317a88e7b51b94d9804bda81d28bdcc3378 100644 (file)
@@ -1731,7 +1731,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 =
index 58402226045e84b7134b3c8a33919b5ea1f22f12..86d5fc5d28e3b6a9c2bc49374ff756aad5beffd1 100644 (file)
@@ -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