Thanks for the patch! Yet something to improve:

On Sat, Jan 31, 2026 at 11:55:10PM +0100, [email protected] 
wrote:
> From: Chia-Yu Chang <[email protected]>
> 
> Unlike RFC 3168 ECN, accurate ECN uses the CWR flag as part of the ACE
> field to count new packets with CE mark; however, it will be corrupted
> by the RFC 3168 ECN-aware TSO. Therefore, fallback shall be applied by
> seting NETIF_F_GSO_ACCECN to ensure that the CWR flag should not be
> changed within a super-skb.
> 
> To apply the aforementieond new AccECN GSO for virtio, new featue bits
> for host and guest are added for feature negotiation between driver and
> device. And the translation of Accurate ECN GSO flag between
> virtio_net_hdr and skb header for NETIF_F_GSO_ACCECN is also added to
> avoid CWR flag corruption due to RFC3168 ECN TSO.
> 
> Signed-off-by: Chia-Yu Chang <[email protected]>


To the best of my understanding, this is a new feature - support
for VIRTIO_NET_F_HOST_ACCECN, VIRTIO_NET_F_GUEST_ACCECN?
The commit log makes it sound like it fixes some behaviour for
existing hardware, but that is not the case.





> ---
> v2:
> - Replace VIRTIO_NET_HDR_GSO_ECN with VIRTIO_NET_HDR_GSO_ECN_FLAGS

but where is v2? this is v1...

> ---
>  drivers/net/virtio_net.c        | 14 +++++++++++---
>  drivers/vdpa/pds/debugfs.c      |  6 ++++++
>  include/linux/virtio_net.h      | 18 +++++++++++-------
>  include/uapi/linux/virtio_net.h |  5 +++++
>  4 files changed, 33 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index db88dcaefb20..103fb87c690e 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -75,6 +75,7 @@ static const unsigned long guest_offloads[] = {
>       VIRTIO_NET_F_GUEST_TSO4,
>       VIRTIO_NET_F_GUEST_TSO6,
>       VIRTIO_NET_F_GUEST_ECN,
> +     VIRTIO_NET_F_GUEST_ACCECN,
>       VIRTIO_NET_F_GUEST_UFO,
>       VIRTIO_NET_F_GUEST_CSUM,
>       VIRTIO_NET_F_GUEST_USO4,
> @@ -87,6 +88,7 @@ static const unsigned long guest_offloads[] = {
>  #define GUEST_OFFLOAD_GRO_HW_MASK ((1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
>                       (1ULL << VIRTIO_NET_F_GUEST_TSO6) | \
>                       (1ULL << VIRTIO_NET_F_GUEST_ECN)  | \
> +                     (1ULL << VIRTIO_NET_F_GUEST_ACCECN) | \
>                       (1ULL << VIRTIO_NET_F_GUEST_UFO)  | \
>                       (1ULL << VIRTIO_NET_F_GUEST_USO4) | \
>                       (1ULL << VIRTIO_NET_F_GUEST_USO6) | \
> @@ -5976,6 +5978,7 @@ static int virtnet_xdp_set(struct net_device *dev, 
> struct bpf_prog *prog,
>           && (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO4) ||
>               virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO6) ||
>               virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_ECN) ||
> +             virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_ACCECN) ||
>               virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_UFO) ||
>               virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_CSUM) ||
>               virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_USO4) ||
> @@ -6635,6 +6638,7 @@ static bool virtnet_check_guest_gso(const struct 
> virtnet_info *vi)
>       return virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO4) ||
>               virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO6) ||
>               virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_ECN) ||
> +             virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_ACCECN) ||
>               virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_UFO) ||
>               (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_USO4) &&
>               virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_USO6));
> @@ -6749,6 +6753,8 @@ static int virtnet_probe(struct virtio_device *vdev)
>                       dev->hw_features |= NETIF_F_TSO6;
>               if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN))
>                       dev->hw_features |= NETIF_F_TSO_ECN;
> +             if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ACCECN))
> +                     dev->hw_features |= NETIF_F_GSO_ACCECN;
>               if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_USO))
>                       dev->hw_features |= NETIF_F_GSO_UDP_L4;
>  
> @@ -7169,9 +7175,11 @@ static struct virtio_device_id id_table[] = {
>       VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM, \
>       VIRTIO_NET_F_MAC, \
>       VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, \
> -     VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, 
> VIRTIO_NET_F_GUEST_TSO6, \
> -     VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO, \
> -     VIRTIO_NET_F_HOST_USO, VIRTIO_NET_F_GUEST_USO4, 
> VIRTIO_NET_F_GUEST_USO6, \
> +     VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_HOST_ACCECN, \
> +     VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, \
> +     VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_ACCECN, \
> +     VIRTIO_NET_F_GUEST_UFO, VIRTIO_NET_F_HOST_USO, \
> +     VIRTIO_NET_F_GUEST_USO4, VIRTIO_NET_F_GUEST_USO6, \
>       VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ, \
>       VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN, \
>       VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, \
> diff --git a/drivers/vdpa/pds/debugfs.c b/drivers/vdpa/pds/debugfs.c
> index c328e694f6e7..90bd95db0245 100644
> --- a/drivers/vdpa/pds/debugfs.c
> +++ b/drivers/vdpa/pds/debugfs.c
> @@ -78,6 +78,9 @@ static void print_feature_bits_all(struct seq_file *seq, 
> u64 features)
>               case BIT_ULL(VIRTIO_NET_F_GUEST_ECN):
>                       seq_puts(seq, " VIRTIO_NET_F_GUEST_ECN");
>                       break;
> +             case BIT_ULL(VIRTIO_NET_F_GUEST_ACCECN):
> +                     seq_puts(seq, " VIRTIO_NET_F_GUEST_ACCECN");
> +                     break;
>               case BIT_ULL(VIRTIO_NET_F_GUEST_UFO):
>                       seq_puts(seq, " VIRTIO_NET_F_GUEST_UFO");
>                       break;
> @@ -90,6 +93,9 @@ static void print_feature_bits_all(struct seq_file *seq, 
> u64 features)
>               case BIT_ULL(VIRTIO_NET_F_HOST_ECN):
>                       seq_puts(seq, " VIRTIO_NET_F_HOST_ECN");
>                       break;
> +             case BIT_ULL(VIRTIO_NET_F_HOST_ACCECN):
> +                     seq_puts(seq, " VIRTIO_NET_F_HOST_ACCECN");
> +                     break;
>               case BIT_ULL(VIRTIO_NET_F_HOST_UFO):
>                       seq_puts(seq, " VIRTIO_NET_F_HOST_UFO");
>                       break;
> diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
> index 75dabb763c65..0cf86b026828 100644
> --- a/include/linux/virtio_net.h
> +++ b/include/linux/virtio_net.h
> @@ -11,7 +11,7 @@
>  
>  static inline bool virtio_net_hdr_match_proto(__be16 protocol, __u8 gso_type)
>  {
> -     switch (gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
> +     switch (gso_type & ~VIRTIO_NET_HDR_GSO_ECN_FLAGS) {
>       case VIRTIO_NET_HDR_GSO_TCPV4:
>               return protocol == cpu_to_be16(ETH_P_IP);
>       case VIRTIO_NET_HDR_GSO_TCPV6:
> @@ -31,7 +31,7 @@ static inline int virtio_net_hdr_set_proto(struct sk_buff 
> *skb,
>       if (skb->protocol)
>               return 0;
>  
> -     switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
> +     switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN_FLAGS) {
>       case VIRTIO_NET_HDR_GSO_TCPV4:
>       case VIRTIO_NET_HDR_GSO_UDP:
>       case VIRTIO_NET_HDR_GSO_UDP_L4:
> @@ -58,7 +58,7 @@ static inline int __virtio_net_hdr_to_skb(struct sk_buff 
> *skb,
>       unsigned int ip_proto;
>  
>       if (hdr_gso_type != VIRTIO_NET_HDR_GSO_NONE) {
> -             switch (hdr_gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
> +             switch (hdr_gso_type & ~VIRTIO_NET_HDR_GSO_ECN_FLAGS) {
>               case VIRTIO_NET_HDR_GSO_TCPV4:
>                       gso_type = SKB_GSO_TCPV4;
>                       ip_proto = IPPROTO_TCP;
> @@ -84,7 +84,9 @@ static inline int __virtio_net_hdr_to_skb(struct sk_buff 
> *skb,
>                       return -EINVAL;
>               }
>  
> -             if (hdr_gso_type & VIRTIO_NET_HDR_GSO_ECN)
> +             if (hdr_gso_type & VIRTIO_NET_HDR_GSO_ACCECN)
> +                     gso_type |= SKB_GSO_TCP_ACCECN;
> +             else if (hdr_gso_type & VIRTIO_NET_HDR_GSO_ECN)
>                       gso_type |= SKB_GSO_TCP_ECN;
>  
>               if (hdr->gso_size == 0)
> @@ -159,7 +161,7 @@ static inline int __virtio_net_hdr_to_skb(struct sk_buff 
> *skb,
>               unsigned int nh_off = p_off;
>               struct skb_shared_info *shinfo = skb_shinfo(skb);
>  
> -             switch (gso_type & ~SKB_GSO_TCP_ECN) {
> +             switch (gso_type & ~(SKB_GSO_TCP_ECN | SKB_GSO_TCP_ACCECN)) {
>               case SKB_GSO_UDP:
>                       /* UFO may not include transport header in gso_size. */
>                       nh_off -= thlen;
> @@ -231,7 +233,9 @@ static inline int virtio_net_hdr_from_skb(const struct 
> sk_buff *skb,
>                       hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP_L4;
>               else
>                       return -EINVAL;
> -             if (sinfo->gso_type & SKB_GSO_TCP_ECN)
> +             if (sinfo->gso_type & SKB_GSO_TCP_ACCECN)
> +                     hdr->gso_type |= VIRTIO_NET_HDR_GSO_ACCECN;
> +             else if (sinfo->gso_type & SKB_GSO_TCP_ECN)
>                       hdr->gso_type |= VIRTIO_NET_HDR_GSO_ECN;
>       } else
>               hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
> @@ -282,7 +286,7 @@ virtio_net_hdr_tnl_to_skb(struct sk_buff *skb,
>               return -EINVAL;
>  
>       /* The UDP tunnel must carry a GSO packet, but no UFO. */
> -     gso_inner_type = hdr->gso_type & ~(VIRTIO_NET_HDR_GSO_ECN |
> +     gso_inner_type = hdr->gso_type & ~(VIRTIO_NET_HDR_GSO_ECN_FLAGS |
>                                          VIRTIO_NET_HDR_GSO_UDP_TUNNEL);
>       if (!gso_inner_type || gso_inner_type == VIRTIO_NET_HDR_GSO_UDP)
>               return -EINVAL;
> diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h
> index 1db45b01532b..af5bfe45aa1f 100644
> --- a/include/uapi/linux/virtio_net.h
> +++ b/include/uapi/linux/virtio_net.h
> @@ -56,6 +56,8 @@
>  #define VIRTIO_NET_F_MQ      22      /* Device supports Receive Flow
>                                        * Steering */
>  #define VIRTIO_NET_F_CTRL_MAC_ADDR 23        /* Set MAC address */
> +#define VIRTIO_NET_F_HOST_ACCECN 25  /* Host can handle GSO of AccECN */
> +#define VIRTIO_NET_F_GUEST_ACCECN 26 /* Guest can handle GSO of AccECN */
>  #define VIRTIO_NET_F_DEVICE_STATS 50 /* Device can provide device-level 
> statistics. */
>  #define VIRTIO_NET_F_VQ_NOTF_COAL 52 /* Device supports virtqueue 
> notification coalescing */
>  #define VIRTIO_NET_F_NOTF_COAL       53      /* Device supports 
> notifications coalescing */
> @@ -165,6 +167,9 @@ struct virtio_net_hdr_v1 {
>  #define VIRTIO_NET_HDR_GSO_UDP_TUNNEL (VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV4 | \
>                                      VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV6)
>  #define VIRTIO_NET_HDR_GSO_ECN               0x80    /* TCP has ECN set */
> +#define VIRTIO_NET_HDR_GSO_ACCECN    0x10    /* TCP AccECN segmentation */
> +#define VIRTIO_NET_HDR_GSO_ECN_FLAGS (VIRTIO_NET_HDR_GSO_ECN | \
> +                                      VIRTIO_NET_HDR_GSO_ACCECN)
>       __u8 gso_type;
>       __virtio16 hdr_len;     /* Ethernet + IP + tcp/udp hdrs */
>       __virtio16 gso_size;    /* Bytes to append to hdr_len per frame */


UAPI changes need to be added to the virtio spec.
Pls get this approved by the virtio TC.
Thanks!


> -- 
> 2.34.1


Reply via email to