[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.