WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 14/22] TSO support.

This includes both TSO-send and TSO-receive support.

Signed-off-by: Steven Smith <steven.smith@xxxxxxxxxx>
---
 drivers/xen/netchannel2/chan.c             |    3 +-
 drivers/xen/netchannel2/netchannel2_core.h |    4 +++
 drivers/xen/netchannel2/offload.c          |   33 ++++++++++++++++++++++++++-
 drivers/xen/netchannel2/recv_packet.c      |   19 ++++++++++++++++
 drivers/xen/netchannel2/xmit_packet.c      |    8 ++++++
 include/xen/interface/io/netchannel2.h     |   19 +++++++++++----
 6 files changed, 78 insertions(+), 8 deletions(-)

diff --git a/drivers/xen/netchannel2/chan.c b/drivers/xen/netchannel2/chan.c
index 109f1b4..9bb7ce7 100644
--- a/drivers/xen/netchannel2/chan.c
+++ b/drivers/xen/netchannel2/chan.c
@@ -563,9 +563,10 @@ void nc2_detach_rings(struct netchannel2 *nc)
        nc->rings.irq = -1;
 
        /* Disable all offloads */
-       nc->net_device->features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG);
+       nc->net_device->features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG | 
NETIF_F_TSO);
        nc->allow_tx_csum_offload = 0;
        nc->rings.max_fragments_per_tx_packet = 1;
+       nc->allow_tso = 0;
 }
 
 #if defined(CONFIG_XEN_NETDEV2_BACKEND)
diff --git a/drivers/xen/netchannel2/netchannel2_core.h 
b/drivers/xen/netchannel2/netchannel2_core.h
index b3b063c..7be97ea 100644
--- a/drivers/xen/netchannel2/netchannel2_core.h
+++ b/drivers/xen/netchannel2/netchannel2_core.h
@@ -259,6 +259,10 @@ struct netchannel2 {
           Whether we actually use TX checksumming is controlled by
           the net device feature bits. */
        uint8_t allow_tx_csum_offload;
+       /* The remote endpoint allows us to use TSO for TCPv4.  As for
+          checksumming, we only actually use the feature if the net
+          device says to. */
+       uint8_t allow_tso;
        /* At some point in the past, we tried to tell the other end
           what our current offload policy is and failed.  Try again
           as soon as possible. */
diff --git a/drivers/xen/netchannel2/offload.c 
b/drivers/xen/netchannel2/offload.c
index 552b0ad..5e9c8d0 100644
--- a/drivers/xen/netchannel2/offload.c
+++ b/drivers/xen/netchannel2/offload.c
@@ -6,6 +6,7 @@
 
 static int nc2_set_tx_csum(struct net_device *nd, u32 val);
 static int nc2_set_sg(struct net_device *nd, u32 val);
+static int nc2_set_tso(struct net_device *nd, u32 val);
 
 /* ---------------- Interface to the other domain ----------------------- */
 void nc2_handle_set_offload(struct netchannel2 *nc,
@@ -35,6 +36,11 @@ void nc2_handle_set_offload(struct netchannel2 *nc,
                   manually enable it every time. */
                nc2_set_sg(nc->net_device, msg.csum);
        }
+
+       if (msg.tcpv4_segmentation_offload != nc->allow_tso) {
+               nc->allow_tso = msg.tcpv4_segmentation_offload;
+               nc2_set_tso(nc->net_device, msg.tcpv4_segmentation_offload);
+       }
 }
 
 /* Tell the other end what sort of offloads it's allowed to use. */
@@ -46,6 +52,14 @@ void advertise_offloads(struct netchannel2 *nc)
 
        if (nc2_can_send_payload_bytes(&nc->rings.prod_ring, sizeof(msg))) {
                msg.csum = nc->use_rx_csum;
+               /* We always claim to be able to accept TSO packets,
+                  and don't provide any way of turning it off through
+                  ethtool.  We used to use the LRO flag, but that's
+                  not quite right: receiving an LRO packet and
+                  receiving a TSO one are subtly different, due to
+                  the way they get packed into the skbuff
+                  structure. */
+               msg.tcpv4_segmentation_offload = 1;
                nc2_send_message(&nc->rings.prod_ring,
                                 NETCHANNEL2_MSG_SET_OFFLOAD,
                                 0, &msg, sizeof(msg));
@@ -142,11 +156,26 @@ static int nc2_set_sg(struct net_device *nd, u32 val)
        return 0;
 }
 
+static int nc2_set_tso(struct net_device *nd, u32 val)
+{
+       struct netchannel2 *nc = netdev_priv(nd);
+       /* We only allow ourselves to use TSO if the other end's
+          allowed us to use sufficiently many fragments per
+          packet. */
+       if (val != 0 &&
+           (!nc->allow_tso ||
+            nc->rings.max_fragments_per_tx_packet < MAX_SKB_FRAGS))
+               return -EOPNOTSUPP;
+       return ethtool_op_set_tso(nd, val);
+}
+
 struct ethtool_ops nc2_ethtool_ops = {
        .get_tx_csum = ethtool_op_get_tx_csum,
        .set_tx_csum = nc2_set_tx_csum,
        .get_rx_csum = nc2_get_rx_csum,
        .set_rx_csum = nc2_set_rx_csum,
-       .get_sg      = ethtool_op_get_sg,
-       .set_sg      = nc2_set_sg,
+       .get_sg      = ethtool_op_get_sg,
+       .set_sg      = nc2_set_sg,
+       .get_tso     = ethtool_op_get_tso,
+       .set_tso     = nc2_set_tso
 };
diff --git a/drivers/xen/netchannel2/recv_packet.c 
b/drivers/xen/netchannel2/recv_packet.c
index 958a3a6..80c5d5d 100644
--- a/drivers/xen/netchannel2/recv_packet.c
+++ b/drivers/xen/netchannel2/recv_packet.c
@@ -169,6 +169,25 @@ void nc2_handle_packet_msg(struct netchannel2 *nc,
                        break;
                }
 
+               switch (msg.segmentation_type) {
+               case NC2_PACKET_SEGMENTATION_TYPE_none:
+                       break;
+               case NC2_PACKET_SEGMENTATION_TYPE_tcpv4:
+                       if (msg.mss == 0) {
+                               pr_debug("TSO request with mss == 0?\n");
+                               goto err;
+                       }
+                       skb_shinfo(skb)->gso_type =
+                               SKB_GSO_TCPV4 | SKB_GSO_DODGY;
+                       skb_shinfo(skb)->gso_size = msg.mss;
+                       skb_shinfo(skb)->gso_segs = 0;
+                       break;
+               default:
+                       pr_debug("Unknown segmentation offload type %d!\n",
+                                msg.segmentation_type);
+                       goto err;
+               }
+
                __skb_queue_tail(pending_rx_queue, skb);
 
                if (ncrp->pending_rx_hypercalls.nr_pending_gops >=
diff --git a/drivers/xen/netchannel2/xmit_packet.c 
b/drivers/xen/netchannel2/xmit_packet.c
index 5cebca6..7eb845d 100644
--- a/drivers/xen/netchannel2/xmit_packet.c
+++ b/drivers/xen/netchannel2/xmit_packet.c
@@ -104,6 +104,14 @@ static void set_offload_flags(struct sk_buff *skb,
 
        if (skb->proto_data_valid)
                msg->flags |= NC2_PACKET_FLAG_data_validated;
+
+       if (skb_shinfo(skb)->gso_size != 0) {
+               msg->mss = skb_shinfo(skb)->gso_size;
+               msg->segmentation_type = NC2_PACKET_SEGMENTATION_TYPE_tcpv4;
+       } else {
+               msg->mss = 0;
+               msg->segmentation_type = NC2_PACKET_SEGMENTATION_TYPE_none;
+       }
 }
 
 /* Transmit a packet which has previously been prepared with
diff --git a/include/xen/interface/io/netchannel2.h 
b/include/xen/interface/io/netchannel2.h
index 11bb469..1cca607 100644
--- a/include/xen/interface/io/netchannel2.h
+++ b/include/xen/interface/io/netchannel2.h
@@ -54,13 +54,13 @@ struct netchannel2_msg_packet {
                        packet message. */
        uint8_t type;
        uint8_t flags;
-       uint8_t pad0;
-       uint8_t pad1;
+       uint8_t segmentation_type;
+       uint8_t pad;
        uint16_t prefix_size;
-       uint16_t pad2;
+       uint16_t mss;
        uint16_t csum_start;
        uint16_t csum_offset;
-       /* Variable-size array.  The number of elements is determined
+       /* Variable-size array.  The number of elements is determined
           by the size of the message. */
        struct netchannel2_fragment frags[0];
 };
@@ -112,6 +112,9 @@ struct netchannel2_msg_packet {
 #define NC2_PACKET_TYPE_receiver_copy 1
 #define NC2_PACKET_TYPE_small 4
 
+#define NC2_PACKET_SEGMENTATION_TYPE_none  0
+#define NC2_PACKET_SEGMENTATION_TYPE_tcpv4 1
+
 /* Tell the other end that we're finished with a message it sent us,
    and it can release the transmit buffers etc.         This must be sent in
    response to receiver_copy and receiver_map packets. It must not be
@@ -140,7 +143,13 @@ struct netchannel2_msg_set_offload {
         * the other end does not have to perform the calculation.
         */
        uint8_t csum;
-       uint8_t pad;
+       /* Segmentation offload.  If this is 0, the other end must not
+        * generate any packet messages with a segmentation type other
+        * than NC2_PACKET_SEGMENTATION_TYPE_none.  If it is 1, the
+        * other end may also generate packets with a type of
+        * NC2_PACKET_SEGMENTATION_TYPE_tcpv4.
+        */
+       uint8_t tcpv4_segmentation_offload;
        uint16_t reserved;
 };
 
-- 
1.6.3.1


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

<Prev in Thread] Current Thread [Next in Thread>