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

[Xen-devel] [PATCH RFC 15/16] Save/Restore Support: Add suspend/restore support for netfront



Performed an additional cleanup to make the file more syntactically consistent.

Signed-off-by: Bruno Alvisio <bruno.alvisio@xxxxxxxxx>
---
 include/netfront.h |   8 +-
 kernel.c           |   8 ++
 netfront.c         | 242 +++++++++++++++++++++++++++++++++++++++++------------
 3 files changed, 204 insertions(+), 54 deletions(-)

diff --git a/include/netfront.h b/include/netfront.h
index 2b95da9..1164d50 100644
--- a/include/netfront.h
+++ b/include/netfront.h
@@ -3,9 +3,15 @@
 #include <lwip/netif.h>
 #endif
 struct netfront_dev;
-struct netfront_dev *init_netfront(char *nodename, void (*netif_rx)(unsigned 
char *data, int len), unsigned char rawmac[6], char **ip);
+struct netfront_dev *init_netfront(char *nodename,
+                                   void (*netif_rx)(unsigned char *data,
+                                                    int len, void* arg),
+                                   unsigned char rawmac[6],
+                                   char **ip);
 void netfront_xmit(struct netfront_dev *dev, unsigned char* data,int len);
 void shutdown_netfront(struct netfront_dev *dev);
+void suspend_netfront(void);
+void resume_netfront(void);
 #ifdef HAVE_LIBC
 int netfront_tap_open(char *nodename);
 ssize_t netfront_receive(struct netfront_dev *dev, unsigned char *data, size_t 
len);
diff --git a/kernel.c b/kernel.c
index bc2394f..805539e 100644
--- a/kernel.c
+++ b/kernel.c
@@ -119,6 +119,10 @@ void start_kernel(void* par)
 
 void pre_suspend(void)
 {
+#ifdef CONFIG_NETFRONT
+    suspend_netfront();
+#endif
+
 #ifdef CONFIG_XENBUS
     suspend_xenbus();
 #endif
@@ -147,6 +151,10 @@ void post_suspend(int canceled)
 #ifdef CONFIG_XENBUS
     resume_xenbus(canceled);
 #endif
+
+#ifdef CONFIG_NETFRONT
+    resume_netfront();
+#endif
 }
 
 void stop_kernel(void)
diff --git a/netfront.c b/netfront.c
index b8fac62..9aef42b 100644
--- a/netfront.c
+++ b/netfront.c
@@ -63,10 +63,29 @@ struct netfront_dev {
     size_t rlen;
 #endif
 
-    void (*netif_rx)(unsigned char* data, int len);
+    void (*netif_rx)(unsigned char* data, int len, void* arg);
+    void *netif_rx_arg;
 };
 
+struct netfront_dev_list {
+       struct netfront_dev *dev;
+       unsigned char rawmac[6];
+       char *ip;
+
+       int refcount;
+
+       struct netfront_dev_list *next;
+};
+
+static struct netfront_dev_list *dev_list = NULL;
+
 void init_rx_buffers(struct netfront_dev *dev);
+static struct netfront_dev *_init_netfront(struct netfront_dev *dev,
+                                          unsigned char rawmac[6], char **ip);
+static void _shutdown_netfront(struct netfront_dev *dev);
+void netfront_set_rx_handler(struct netfront_dev *dev,
+                                        void (*thenetif_rx)(unsigned char 
*data, int len,
+                                        void *arg), void *arg);
 
 static inline void add_id_to_freelist(unsigned int id,unsigned short* freelist)
 {
@@ -81,7 +100,7 @@ static inline unsigned short get_id_from_freelist(unsigned 
short* freelist)
     return id;
 }
 
-__attribute__((weak)) void netif_rx(unsigned char* data,int len)
+__attribute__((weak)) void netif_rx(unsigned char* data, int len, void *arg)
 {
     printk("%d bytes incoming at %p\n",len,data);
 }
@@ -134,7 +153,7 @@ moretodo:
                dobreak = 1;
            } else
 #endif
-               dev->netif_rx(page+rx->offset,rx->status);
+               dev->netif_rx(page+rx->offset, rx->status, dev->netif_rx_arg);
         }
     }
     dev->rx.rsp_cons=cons;
@@ -282,19 +301,16 @@ static void free_netfront(struct netfront_dev *dev)
     free(dev);
 }
 
-struct netfront_dev *init_netfront(char *_nodename, void 
(*thenetif_rx)(unsigned char* data, int len), unsigned char rawmac[6], char 
**ip)
+struct netfront_dev *init_netfront(char *_nodename,
+                                   void (*thenetif_rx)(unsigned char* data,
+                                                       int len, void* arg),
+                                   unsigned char rawmac[6],
+                                   char **ip)
 {
-    xenbus_transaction_t xbt;
-    char* err;
-    char* message=NULL;
-    struct netif_tx_sring *txs;
-    struct netif_rx_sring *rxs;
-    int retry=0;
-    int i;
-    char* msg = NULL;
     char nodename[256];
-    char path[256];
     struct netfront_dev *dev;
+    struct netfront_dev_list *ldev = NULL;
+    struct netfront_dev_list *list = NULL;
     static int netfrontends = 0;
 
     if (!_nodename)
@@ -303,10 +319,20 @@ struct netfront_dev *init_netfront(char *_nodename, void 
(*thenetif_rx)(unsigned
         strncpy(nodename, _nodename, sizeof(nodename) - 1);
         nodename[sizeof(nodename) - 1] = 0;
     }
-    netfrontends++;
+
+    /* Check if the device is already initialized */
+    for (list = dev_list; list != NULL; list = list->next) {
+        if (strcmp(nodename, list->dev->nodename) == 0) {
+            list->refcount++;
+            dev = list->dev;
+            if (thenetif_rx)
+                netfront_set_rx_handler(dev, thenetif_rx, NULL);
+            goto out;
+        }
+    }
 
     if (!thenetif_rx)
-       thenetif_rx = netif_rx;
+        thenetif_rx = netif_rx;
 
     printk("************************ NETFRONT for %s **********\n\n\n", 
nodename);
 
@@ -316,23 +342,77 @@ struct netfront_dev *init_netfront(char *_nodename, void 
(*thenetif_rx)(unsigned
 #ifdef HAVE_LIBC
     dev->fd = -1;
 #endif
+    dev->netif_rx = thenetif_rx;
+
+    ldev = malloc(sizeof(struct netfront_dev_list));
+    memset(ldev, 0, sizeof(struct netfront_dev_list));
+
+    if (_init_netfront(dev, ldev->rawmac, &(ldev->ip))) {
+           ldev->dev = dev;
+               ldev->refcount = 1;
+               ldev->next = NULL;
+
+               if (!dev_list) {
+            dev_list = ldev;
+               } else {
+            for (list = dev_list; list->next != NULL; list = list->next);
+            list->next = ldev;
+               }
+        netfrontends++;
+       } else {
+        free(dev->nodename);
+        free(dev);
+        free(ldev);
+        dev = NULL;
+        goto err;
+    }
+
+out:
+    if (rawmac) {
+        rawmac[0] = ldev->rawmac[0];
+        rawmac[1] = ldev->rawmac[1];
+        rawmac[2] = ldev->rawmac[2];
+        rawmac[3] = ldev->rawmac[3];
+        rawmac[4] = ldev->rawmac[4];
+        rawmac[5] = ldev->rawmac[5];
+       }
+    if (ip) {
+           *ip = malloc(strlen(ldev->ip) + 1);
+           strncpy(*ip, ldev->ip, strlen(ldev->ip) + 1);
+    }
+
+err:
+    return dev;
+}
+
+static struct netfront_dev *_init_netfront(struct netfront_dev *dev,
+                                          unsigned char rawmac[6],
+                                          char **ip)
+{
+    xenbus_transaction_t xbt;
+    char* err = NULL;
+    char* message=NULL;
+    struct netif_tx_sring *txs;
+    struct netif_rx_sring *rxs;
+    char* msg = NULL;
+    int retry=0;
+    int i;
+    char path[256];
 
     printk("net TX ring size %lu\n", (unsigned long) NET_TX_RING_SIZE);
     printk("net RX ring size %lu\n", (unsigned long) NET_RX_RING_SIZE);
     init_SEMAPHORE(&dev->tx_sem, NET_TX_RING_SIZE);
-    for(i=0;i<NET_TX_RING_SIZE;i++)
-    {
-       add_id_to_freelist(i,dev->tx_freelist);
+    for (i = 0; i < NET_TX_RING_SIZE; i++) {
+           add_id_to_freelist(i,dev->tx_freelist);
         dev->tx_buffers[i].page = NULL;
     }
 
-    for(i=0;i<NET_RX_RING_SIZE;i++)
-    {
-       /* TODO: that's a lot of memory */
+    for (i = 0; i < NET_RX_RING_SIZE; i++) {
+           /* TODO: that's a lot of memory */
         dev->rx_buffers[i].page = (char*)alloc_page();
     }
 
-    snprintf(path, sizeof(path), "%s/backend-id", nodename);
+    snprintf(path, sizeof(path), "%s/backend-id", dev->nodename);
     dev->dom = xenbus_read_integer(path);
 #ifdef HAVE_LIBC
     if (thenetif_rx == NETIF_SELECT_RX)
@@ -343,22 +423,19 @@ struct netfront_dev *init_netfront(char *_nodename, void 
(*thenetif_rx)(unsigned
 
     txs = (struct netif_tx_sring *) alloc_page();
     rxs = (struct netif_rx_sring *) alloc_page();
-    memset(txs,0,PAGE_SIZE);
-    memset(rxs,0,PAGE_SIZE);
-
+    memset(txs, 0, PAGE_SIZE);
+    memset(rxs, 0, PAGE_SIZE);
 
     SHARED_RING_INIT(txs);
     SHARED_RING_INIT(rxs);
     FRONT_RING_INIT(&dev->tx, txs, PAGE_SIZE);
     FRONT_RING_INIT(&dev->rx, rxs, PAGE_SIZE);
 
-    dev->tx_ring_ref = gnttab_grant_access(dev->dom,virt_to_mfn(txs),0);
-    dev->rx_ring_ref = gnttab_grant_access(dev->dom,virt_to_mfn(rxs),0);
+    dev->tx_ring_ref = gnttab_grant_access(dev->dom, virt_to_mfn(txs), 0);
+    dev->rx_ring_ref = gnttab_grant_access(dev->dom, virt_to_mfn(rxs), 0);
 
     init_rx_buffers(dev);
 
-    dev->netif_rx = thenetif_rx;
-
     dev->events = NULL;
 
 again:
@@ -368,33 +445,31 @@ again:
         free(err);
     }
 
-    err = xenbus_printf(xbt, nodename, "tx-ring-ref","%u",
-                dev->tx_ring_ref);
+    err = xenbus_printf(xbt, dev->nodename, "tx-ring-ref","%u",
+                        dev->tx_ring_ref);
     if (err) {
         message = "writing tx ring-ref";
         goto abort_transaction;
     }
-    err = xenbus_printf(xbt, nodename, "rx-ring-ref","%u",
-                dev->rx_ring_ref);
+    err = xenbus_printf(xbt, dev->nodename, "rx-ring-ref","%u",
+                        dev->rx_ring_ref);
     if (err) {
         message = "writing rx ring-ref";
         goto abort_transaction;
     }
-    err = xenbus_printf(xbt, nodename,
-                "event-channel", "%u", dev->evtchn);
+    err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", 
dev->evtchn);
     if (err) {
         message = "writing event-channel";
         goto abort_transaction;
     }
 
-    err = xenbus_printf(xbt, nodename, "request-rx-copy", "%u", 1);
-
+    err = xenbus_printf(xbt, dev->nodename, "request-rx-copy", "%u", 1);
     if (err) {
         message = "writing request-rx-copy";
         goto abort_transaction;
     }
 
-    snprintf(path, sizeof(path), "%s/state", nodename);
+    snprintf(path, sizeof(path), "%s/state", dev->nodename);
     err = xenbus_switch_state(xbt, path, XenbusStateConnected);
     if (err) {
         message = "switching state";
@@ -404,7 +479,7 @@ again:
     err = xenbus_transaction_end(xbt, 0, &retry);
     free(err);
     if (retry) {
-            goto again;
+        goto again;
         printk("completing transaction\n");
     }
 
@@ -417,10 +492,9 @@ abort_transaction:
     goto error;
 
 done:
-
-    snprintf(path, sizeof(path), "%s/backend", nodename);
+    snprintf(path, sizeof(path), "%s/backend", dev->nodename);
     msg = xenbus_read(XBT_NIL, path, &dev->backend);
-    snprintf(path, sizeof(path), "%s/mac", nodename);
+    snprintf(path, sizeof(path), "%s/mac", dev->nodename);
     msg = xenbus_read(XBT_NIL, path, &dev->mac);
 
     if ((dev->backend == NULL) || (dev->mac == NULL)) {
@@ -428,8 +502,8 @@ done:
         goto error;
     }
 
-    printk("backend at %s\n",dev->backend);
-    printk("mac is %s\n",dev->mac);
+    printk("backend at %s\n", dev->backend);
+    printk("mac is %s\n", dev->mac);
 
     {
         XenbusState state;
@@ -458,18 +532,20 @@ done:
 
     unmask_evtchn(dev->evtchn);
 
-        /* Special conversion specifier 'hh' needed for __ia64__. Without
-           this mini-os panics with 'Unaligned reference'. */
+    /* Special conversion specifier 'hh' needed for __ia64__. Without
+     * this mini-os panics with 'Unaligned reference'.
+     */
     if (rawmac)
-       sscanf(dev->mac,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
-            &rawmac[0],
-            &rawmac[1],
-            &rawmac[2],
-            &rawmac[3],
-            &rawmac[4],
-            &rawmac[5]);
+           sscanf(dev->mac,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+               &rawmac[0],
+               &rawmac[1],
+               &rawmac[2],
+               &rawmac[3],
+               &rawmac[4],
+               &rawmac[5]);
 
     return dev;
+
 error:
     free(msg);
     free(err);
@@ -496,6 +572,40 @@ int netfront_tap_open(char *nodename) {
 
 void shutdown_netfront(struct netfront_dev *dev)
 {
+    struct netfront_dev_list *list = NULL;
+    struct netfront_dev_list *to_del = NULL;
+
+    /* Check this is a valid device */
+    for (list = dev_list; list != NULL; list = list->next) {
+           if (list->dev == dev)
+                   break;
+    }
+
+    if (!list) {
+           printk("Trying to shutdown an invalid netfront device (%p)\n", dev);
+        return;
+    }
+
+    list->refcount--;
+    if (list->refcount == 0) {
+           _shutdown_netfront(dev);
+           free(dev->nodename);
+           free(dev);
+
+           to_del = list;
+        if (to_del == dev_list) {
+            free(to_del);
+                       dev_list = NULL;
+        } else {
+               for (list = dev_list; list->next != to_del; list = list->next);
+               list->next = to_del->next;
+            free(to_del);
+        }
+    }
+}
+
+static void _shutdown_netfront(struct netfront_dev *dev)
+{
     char* err = NULL, *err2;
     XenbusState state;
 
@@ -559,6 +669,21 @@ close:
         free_netfront(dev);
 }
 
+void suspend_netfront(void)
+{
+    struct netfront_dev_list *list;
+
+    for (list = dev_list; list != NULL; list = list->next)
+        _shutdown_netfront(list->dev);
+}
+
+void resume_netfront(void)
+{
+    struct netfront_dev_list *list;
+
+    for (list = dev_list; list != NULL; list = list->next)
+        _init_netfront(list->dev, NULL, NULL);
+}
 
 void init_rx_buffers(struct netfront_dev *dev)
 {
@@ -665,3 +790,14 @@ ssize_t netfront_receive(struct netfront_dev *dev, 
unsigned char *data, size_t l
     return dev->rlen;
 }
 #endif
+
+void netfront_set_rx_handler(struct netfront_dev *dev,
+                                        void (*thenetif_rx)(unsigned char 
*data, int len,
+                                        void *arg), void *arg)
+{
+    if (dev->netif_rx && dev->netif_rx != netif_rx)
+        printk("Replacing netif_rx handler for dev %s\n", dev->nodename);
+
+    dev->netif_rx = thenetif_rx;
+    dev->netif_rx_arg = arg;
+}
-- 
2.3.2 (Apple Git-55)


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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