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

[Xen-devel] [4/4] [NET] front: Transmit TSO packets if supported



Hi:

[NET] front: Transmit TSO packets if supported

This patch adds TSO transmission support to the frontend.  This also fixes
a bug where SG may not be turned off correctly when migrating to an old
host.

Signed-off-by: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@xxxxxxxxxxxxxxxxxxx>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
diff -r fb922826baef -r ea33ffdb9973 
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Fri Jun 30 
22:28:09 2006 +1000
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Fri Jun 30 
22:44:18 2006 +1000
@@ -463,7 +463,7 @@ static int network_open(struct net_devic
 
 static inline int netfront_tx_slot_available(struct netfront_info *np)
 {
-       return RING_FREE_REQUESTS(&np->tx) >= MAX_SKB_FRAGS + 1;
+       return RING_FREE_REQUESTS(&np->tx) >= MAX_SKB_FRAGS + 2;
 }
 
 static inline void network_maybe_wake_tx(struct net_device *dev)
@@ -491,7 +491,13 @@ static void network_tx_buf_gc(struct net
                rmb(); /* Ensure we see responses up to 'rp'. */
 
                for (cons = np->tx.rsp_cons; cons != prod; cons++) {
-                       id  = RING_GET_RESPONSE(&np->tx, cons)->id;
+                       struct netif_tx_response *txrsp;
+
+                       txrsp = RING_GET_RESPONSE(&np->tx, cons);
+                       if (txrsp->status == NETIF_RSP_NULL)
+                               continue;
+
+                       id  = txrsp->id;
                        skb = np->tx_skbs[id];
                        if (unlikely(gnttab_query_foreign_access(
                                np->grant_tx_ref[id]) != 0)) {
@@ -719,6 +725,7 @@ static int network_start_xmit(struct sk_
        unsigned short id;
        struct netfront_info *np = netdev_priv(dev);
        struct netif_tx_request *tx;
+       struct netif_tx_extra *txtra;
        char *data = skb->data;
        RING_IDX i;
        grant_ref_t ref;
@@ -739,7 +746,8 @@ static int network_start_xmit(struct sk_
        spin_lock_irq(&np->tx_lock);
 
        if (unlikely(!netif_carrier_ok(dev) ||
-                    (frags > 1 && !xennet_can_sg(dev)))) {
+                    (frags > 1 && !xennet_can_sg(dev)) ||
+                    netif_needs_gso(dev, skb))) {
                spin_unlock_irq(&np->tx_lock);
                goto drop;
        }
@@ -762,10 +770,30 @@ static int network_start_xmit(struct sk_
        tx->size = len;
 
        tx->flags = 0;
+       txtra = NULL;
+
        if (skb->ip_summed == CHECKSUM_HW) /* local packet? */
                tx->flags |= NETTXF_csum_blank | NETTXF_data_validated;
        if (skb->proto_data_valid) /* remote but checksummed? */
                tx->flags |= NETTXF_data_validated;
+
+       if (skb_shinfo(skb)->gso_size) {
+               struct netif_tx_extra *gso =
+                       (struct netif_tx_extra *)RING_GET_REQUEST(&np->tx, ++i);
+
+               if (txtra)
+                       txtra->flags |= XEN_NETIF_TXTRA_MORE;
+               else
+                       tx->flags |= NETTXF_extra_info;
+
+               gso->gso.size = skb_shinfo(skb)->gso_size;
+               gso->gso.type =
+                       xen_gso_type_linux2xen(skb_shinfo(skb)->gso_type);
+
+               gso->type = XEN_NETIF_TXTRA_TYPE_GSO;
+               gso->flags = 0;
+               txtra = gso;
+       }
 
        np->tx.req_prod_pvt = i + 1;
 
@@ -1065,9 +1093,47 @@ static int xennet_set_sg(struct net_devi
        return ethtool_op_set_sg(dev, data);
 }
 
+static int xennet_set_tso(struct net_device *dev, u32 data)
+{
+       if (data) {
+               struct netfront_info *np = netdev_priv(dev);
+               int val;
+
+               if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-gso",
+                                "%d", &val) < 0)
+                       val = 0;
+               if (!(val & XEN_GSO_TCPV4))
+                       return -ENOSYS;
+       }
+
+       return ethtool_op_set_tso(dev, data);
+}
+
+static void xennet_set_gso(struct net_device *dev)
+{
+       struct netfront_info *np = netdev_priv(dev);
+       int allowed_types = SKB_GSO_TCPV4 | SKB_GSO_DODGY;
+       int val;
+
+       if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-gso",
+                        "%d", &val) < 0)
+               return;
+
+       /* Filter out things we don't understand. */
+       val = xen_gso_type_xen2linux(val) & allowed_types;
+
+       /* Turn on the advertised bits. */
+       dev->features |= val << NETIF_F_GSO_SHIFT;
+}
+
 static void xennet_set_features(struct net_device *dev)
 {
-       xennet_set_sg(dev, 1);
+       /* Turn off all negotiated bits. */
+       dev->features &= (1 << NETIF_F_GSO_SHIFT) - 1;
+       xennet_set_sg(dev, 0);
+
+       if (!xennet_set_sg(dev, 1))
+               xennet_set_gso(dev);
 }
 
 static void network_connect(struct net_device *dev)
@@ -1148,6 +1214,8 @@ static struct ethtool_ops network_ethtoo
        .set_tx_csum = ethtool_op_set_tx_csum,
        .get_sg = ethtool_op_get_sg,
        .set_sg = xennet_set_sg,
+       .get_tso = ethtool_op_get_tso,
+       .set_tso = xennet_set_tso,
 };
 
 #ifdef CONFIG_SYSFS

_______________________________________________
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®.