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

[Xen-devel] [3/4] [NET] back: Make extra info slot more generic



Hi:

[NET] back: Make extra info slot more generic

Based on suggestions by Keir Fraser, this patch makes the extra slot more
generic by allowing it to be chained and giving each slot a type field.

This makes it easier to add new extra slots such as checksum offset.

I've also added GSO type constants specific for Xen.  For now the conversion
function between them and Linux is a noop.  When and if they do diverge we
can modify them accordingly.

The types are now checked in the backend to ensure that they only contain
bits that we advertised.  We will also advertise the bits as feature-gso
instead of feature-tso.

This patch also gets rid of gso_segs which is now always recomputed for
SKB_GSO_DODGY packets.

Last but not least netback now actually sets SKB_GSO_DODGY.

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 f6806ad757d5 -r fb922826baef 
linux-2.6-xen-sparse/drivers/xen/netback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Fri Jun 30 22:16:02 
2006 +1000
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Fri Jun 30 22:28:09 
2006 +1000
@@ -88,8 +88,13 @@ typedef struct netif_st {
        /* Miscellaneous private stuff. */
        enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
        int active;
+
        struct list_head list;  /* scheduling list */
+
        atomic_t         refcnt;
+       /* Bit mask of allowed GSO types. */
+       int              gso_types;
+
        struct net_device *dev;
        struct net_device_stats stats;
 
diff -r f6806ad757d5 -r fb922826baef 
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c        Fri Jun 30 
22:16:02 2006 +1000
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c        Fri Jun 30 
22:28:09 2006 +1000
@@ -663,6 +663,35 @@ static void netbk_fill_frags(struct sk_b
        }
 }
 
+int netbk_get_txtras(netif_t *netif, struct netif_tx_extra *txtras,
+                    int work_to_do)
+{
+       struct netif_tx_extra *txtra;
+       int i = netif->tx.req_cons;
+
+       do {
+
+               if (unlikely(work_to_do-- <= 0)) {
+                       DPRINTK("Missing extra info\n");
+                       return -EBADR;
+               }
+
+               txtra = (struct netif_tx_extra *)RING_GET_REQUEST(&netif->tx,
+                                                                 i);
+               if (unlikely(!txtra->type ||
+                            txtra->type >= XEN_NETIF_TXTRA_TYPE_MAX)) {
+                       netif->tx.req_cons = ++i;
+                       DPRINTK("Invalid extra type: %d\n", txtra->type);
+                       return -EINVAL;
+               }
+
+               memcpy(txtras + txtra->type - 1, txtra, sizeof(*txtra));
+               netif->tx.req_cons = ++i;
+       } while (txtra->flags & XEN_NETIF_TXTRA_MORE);
+
+       return work_to_do;
+}
+
 /* Called after netfront has transmitted */
 static void net_tx_action(unsigned long unused)
 {
@@ -670,7 +699,8 @@ static void net_tx_action(unsigned long 
        struct sk_buff *skb;
        netif_t *netif;
        netif_tx_request_t txreq;
-       struct netif_tx_extra txtra;
+       struct netif_tx_extra txtras[XEN_NETIF_TXTRA_TYPE_MAX - 1];
+       struct netif_tx_extra *gso;
        u16 pending_idx;
        RING_IDX i;
        gnttab_map_grant_ref_t *mop;
@@ -732,16 +762,15 @@ static void net_tx_action(unsigned long 
                work_to_do--;
                netif->tx.req_cons = ++i;
 
+               memset(txtras, 0, sizeof(txtras));
                if (txreq.flags & NETTXF_extra_info) {
-                       if (work_to_do-- <= 0) {
-                               DPRINTK("Missing extra info\n");
-                               netbk_tx_err(netif, &txreq, i);
+                       work_to_do = netbk_get_txtras(netif, txtras,
+                                                     work_to_do);
+                       if (unlikely(work_to_do < 0)) {
+                               netbk_tx_err(netif, &txreq, 0);
                                continue;
                        }
-
-                       memcpy(&txtra, RING_GET_REQUEST(&netif->tx, i),
-                              sizeof(txtra));
-                       netif->tx.req_cons = ++i;
+                       i = netif->tx.req_cons;
                }
 
                ret = netbk_count_requests(netif, &txreq, work_to_do);
@@ -772,6 +801,29 @@ static void net_tx_action(unsigned long 
                        continue;
                }
 
+               gso = NULL;
+               if (txtras[XEN_NETIF_TXTRA_TYPE_GSO - 1].type) {
+                       unsigned type;
+
+                       gso = &txtras[XEN_NETIF_TXTRA_TYPE_GSO - 1];
+                       if (!gso->gso.size) {
+                               DPRINTK("GSO size must not be zero\n");
+                               netbk_tx_err(netif, &txreq, i);
+                               continue; 
+                       }
+
+                       type = xen_gso_type_xen2linux(gso->gso.type);
+                       if (!type || (type & netif->gso_types) != type) {
+                               DPRINTK("Bogus GSO type: 0x%x\n",
+                                       gso->gso.type);
+                               netbk_tx_err(netif, &txreq, i);
+                               continue; 
+                       }
+
+                       /* Whoever gets this needs to verify the header. */
+                       gso->gso.type = type | SKB_GSO_DODGY;
+               }
+
                pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
 
                data_len = (txreq.size > PKT_PROT_LEN &&
@@ -788,10 +840,9 @@ static void net_tx_action(unsigned long 
                /* Packets passed to netif_rx() must have some headroom. */
                skb_reserve(skb, 16);
 
-               if (txreq.flags & NETTXF_gso) {
-                       skb_shinfo(skb)->gso_size = txtra.u.gso.size;
-                       skb_shinfo(skb)->gso_segs = txtra.u.gso.segs;
-                       skb_shinfo(skb)->gso_type = txtra.u.gso.type;
+               if (gso) {
+                       skb_shinfo(skb)->gso_size = gso->gso.size;
+                       skb_shinfo(skb)->gso_type = gso->gso.type;
                }
 
                gnttab_set_map_op(mop, MMAP_VADDR(pending_idx),
diff -r f6806ad757d5 -r fb922826baef 
linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Fri Jun 30 22:16:02 
2006 +1000
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Fri Jun 30 22:28:09 
2006 +1000
@@ -34,6 +34,9 @@ struct backend_info
        netif_t *netif;
        struct xenbus_watch backend_watch;
        enum xenbus_state frontend_state;
+
+       /* Bit mask of allowed GSO types. */
+       int gso_types;
 };
 
 static int connect_rings(struct backend_info *);
@@ -83,6 +86,9 @@ static int netback_probe(struct xenbus_d
        be->dev = dev;
        dev->dev.driver_data = be;
 
+       /* In future this will be retrieved from Linux. */
+       be->gso_types = SKB_GSO_TCPV4 | SKB_GSO_DODGY;
+
        err = xenbus_watch_path2(dev, dev->nodename, "handle",
                                 &be->backend_watch, backend_changed);
        if (err)
@@ -101,9 +107,10 @@ static int netback_probe(struct xenbus_d
                        goto abort_transaction;
                }
 
-               err = xenbus_printf(xbt, dev->nodename, "feature-tso", "%d", 1);
+               err = xenbus_printf(xbt, dev->nodename, "feature-gso", "%d",
+                                   be->gso_types);
                if (err) {
-                       message = "writing feature-tso";
+                       message = "writing feature-gso";
                        goto abort_transaction;
                }
 
@@ -205,6 +212,8 @@ static void backend_changed(struct xenbu
                        xenbus_dev_fatal(dev, err, "creating interface");
                        return;
                }
+
+               be->netif->gso_types = be->gso_types;
 
                kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE);
 
diff -r f6806ad757d5 -r fb922826baef xen/include/public/io/netif.h
--- a/xen/include/public/io/netif.h     Fri Jun 30 22:16:02 2006 +1000
+++ b/xen/include/public/io/netif.h     Fri Jun 30 22:28:09 2006 +1000
@@ -41,12 +41,28 @@
 #define _NETTXF_more_data      (2)
 #define  NETTXF_more_data      (1U<<_NETTXF_more_data)
 
-/* Packet has GSO fields in the following descriptor (netif_tx_extra.u.gso). */
-#define _NETTXF_gso            (3)
-#define  NETTXF_gso            (1U<<_NETTXF_gso)
+/* Packet to be folloed by extra descritptor. */
+#define _NETTXF_extra_info     (3)
+#define  NETTXF_extra_info     (1U<<_NETTXF_extra_info)
 
-/* This descriptor is followed by an extra-info descriptor (netif_tx_extra). */
-#define  NETTXF_extra_info     (NETTXF_gso)
+enum {
+    XEN_NETIF_TXTRA_TYPE_GSO = 1,
+    XEN_NETIF_TXTRA_TYPE_MAX,
+};
+
+enum {
+    XEN_NETIF_TXTRA_MORE = 1 << 0,
+};
+
+enum {
+    /* TCP over IPv4. */
+    XEN_GSO_TCPV4 = 1 << 0,
+    /* UDP over IPv4. */
+    XEN_GSO_UDPV4 = 1 << 1,
+
+    /* Packet header must be verified. */
+    XEN_GSO_DODGY = 1 << 2,
+};
 
 struct netif_tx_request {
     grant_ref_t gref;      /* Reference to buffer page */
@@ -57,16 +73,29 @@ struct netif_tx_request {
 };
 typedef struct netif_tx_request netif_tx_request_t;
 
-/* This structure needs to fit within netif_tx_request for compatibility. */
+/*
+ * This structure needs to fit within both netif_tx_request and
+ * netif_rx_response for compatibility.
+ */
 struct netif_tx_extra {
+    /* Type of extra info. */
+    uint8_t type;
+    /* Flags for this info. */
+    uint8_t flags;
+
     union {
-        /* NETTXF_gso: Generic Segmentation Offload. */
-        struct netif_tx_gso {
-            uint16_t size;        /* GSO MSS. */
-            uint16_t segs;        /* GSO segment count. */
-            uint16_t type;        /* GSO type. */
-        } gso;
-    } u;
+       /*
+        * Maximum payload size of each segment.  For example, for TCP this is
+        * just the path MSS.
+        */
+       uint16_t size;
+
+       /*
+        * GSO type.  This determines the protocol of the packet and any extra
+        * features required to segment the packet properly.
+        */
+       uint16_t type;
+    } gso;
 };
 
 struct netif_tx_response {
@@ -110,6 +139,17 @@ DEFINE_RING_TYPES(netif_rx, struct netif
 /* No response: used for auxiliary requests (e.g., netif_tx_extra). */
 #define NETIF_RSP_NULL             1
 
+/* For now the GSO types are identical. */
+static inline int xen_gso_type_linux2xen(int type)
+{
+       return type;
+}
+
+static inline int xen_gso_type_xen2linux(int type)
+{
+       return type;
+}
+
 #endif
 
 /*

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