@@ -58,6 +58,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,
@@ -68,6 +69,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))
@@ -5886,6 +5888,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) ||
@@ -6549,6 +6552,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));
@@ -6663,6 +6667,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;
@@ -7061,9 +7067,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, \
@@ -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;
@@ -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)
@@ -158,7 +160,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;
@@ -223,7 +225,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;
@@ -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 Accurate ECN */
+#define VIRTIO_NET_F_GUEST_ACCECN 26 /* Guest can handle GSO of Accurate ECN */
#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 */
@@ -137,7 +139,10 @@ struct virtio_net_hdr_v1 {
#define VIRTIO_NET_HDR_GSO_UDP 3 /* GSO frame, IPv4 UDP (UFO) */
#define VIRTIO_NET_HDR_GSO_TCPV6 4 /* GSO frame, IPv6 TCP */
#define VIRTIO_NET_HDR_GSO_UDP_L4 5 /* GSO frame, IPv4& IPv6 UDP (USO) */
+#define VIRTIO_NET_HDR_GSO_ACCECN 0x40 /* TCP AccECN segmentation */
#define VIRTIO_NET_HDR_GSO_ECN 0x80 /* TCP has ECN set */
+#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 */