virtio specification introduced support for outer network
header offset broadcast.

This patch implements the needed defines and virtio header
parsing capabilities.

Signed-off-by: Kommula Shiva Shankar <[email protected]>
---
 include/linux/virtio_net.h      | 40 +++++++++++++++++++++++++++++++++
 include/uapi/linux/virtio_net.h |  8 +++++++
 2 files changed, 48 insertions(+)

diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index 20e0584db1dd..e6153e9106d3 100644
--- a/include/linux/virtio_net.h
+++ b/include/linux/virtio_net.h
@@ -374,6 +374,46 @@ static inline int virtio_net_handle_csum_offload(struct 
sk_buff *skb,
        return 0;
 }
 
+static inline int
+virtio_net_out_net_header_to_skb(struct sk_buff *skb,
+                                struct 
virtio_net_hdr_v1_hash_tunnel_out_net_hdr *vhdr,
+                                bool out_net_hdr_negotiated,
+                                bool little_endian)
+{
+       unsigned int out_net_hdr_off;
+
+       if (!out_net_hdr_negotiated)
+               return 0;
+
+       if (vhdr->outer_nh_offset) {
+               out_net_hdr_off = __virtio16_to_cpu(little_endian, 
vhdr->outer_nh_offset);
+               skb_set_network_header(skb, out_net_hdr_off);
+       }
+
+       return 0;
+}
+
+static inline int
+virtio_net_out_net_header_from_skb(const struct sk_buff *skb,
+                                  struct 
virtio_net_hdr_v1_hash_tunnel_out_net_hdr *vhdr,
+                                  bool out_net_hdr_negotiated,
+                                  bool little_endian)
+{
+       unsigned int out_net_hdr_off;
+
+       if (!out_net_hdr_negotiated) {
+               vhdr->outer_nh_offset = 0;
+               return 0;
+       }
+
+       out_net_hdr_off = skb_network_offset(skb);
+       if (out_net_hdr_off && skb->protocol == htons(ETH_P_IP))
+               vhdr->outer_nh_offset = __cpu_to_virtio16(little_endian,
+                                                         out_net_hdr_off);
+
+       return 0;
+}
+
 /*
  * vlan_hlen always refers to the outermost MAC header. That also
  * means it refers to the only MAC header, if the packet does not carry
diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h
index 8bf27ab8bcb4..6032b9e443bb 100644
--- a/include/uapi/linux/virtio_net.h
+++ b/include/uapi/linux/virtio_net.h
@@ -86,6 +86,7 @@
                                                  * packets with partial csum
                                                  * for the outer header
                                                  */
+#define VIRTIO_NET_F_OUT_NET_HEADER 69 /* Outer network header offset */
 
 /* Offloads bits corresponding to VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO{,_CSUM}
  * features
@@ -214,6 +215,13 @@ struct virtio_net_hdr_v1_hash_tunnel {
        __le16 inner_nh_offset;
 };
 
+/* outer network header */
+struct virtio_net_hdr_v1_hash_tunnel_out_net_hdr {
+       struct virtio_net_hdr_v1_hash_tunnel tnl_hdr;
+       __le16 outer_nh_offset;
+       __u8 padding_reserved_2[6];
+};
+
 #ifndef VIRTIO_NET_NO_LEGACY
 /* This header comes first in the scatter-gather list.
  * For legacy virtio, if VIRTIO_F_ANY_LAYOUT is not negotiated, it must
-- 
2.48.1


Reply via email to