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

[Xen-devel] [PATCH v2 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>
Reviewed-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxx>
---
 include/netfront.h |   8 +-
 kernel.c           |   8 ++
 netfront.c         | 309 ++++++++++++++++++++++++++++++++++++++---------------
 3 files changed, 236 insertions(+), 89 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 1393d15..301273d 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..50b3a57 100644
--- a/netfront.c
+++ b/netfront.c
@@ -63,10 +63,30 @@ 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 +101,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);
 }
@@ -120,21 +140,20 @@ moretodo:
         page = (unsigned char*)buf->page;
         gnttab_end_access(buf->gref);
 
-        if (rx->status > NETIF_RSP_NULL)
-        {
+        if (rx->status > NETIF_RSP_NULL) {
 #ifdef HAVE_LIBC
-           if (dev->netif_rx == NETIF_SELECT_RX) {
-               int len = rx->status;
-               ASSERT(current == main_thread);
-               if (len > dev->len)
-                   len = dev->len;
-               memcpy(dev->data, page+rx->offset, len);
-               dev->rlen = len;
-               /* No need to receive the rest for now */
-               dobreak = 1;
-           } else
+            if (dev->netif_rx == NETIF_SELECT_RX) {
+                int len = rx->status;
+                ASSERT(current == main_thread);
+                if (len > dev->len)
+                    len = dev->len;
+                memcpy(dev->data, page+rx->offset, len);
+                dev->rlen = len;
+                /* No need to receive the rest for now */
+                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;
@@ -144,17 +163,16 @@ moretodo:
 
     req_prod = dev->rx.req_prod_pvt;
 
-    for(i=0; i<nr_consumed; i++)
-    {
+    for (i = 0; i < nr_consumed; i++) {
         int id = xennet_rxidx(req_prod + i);
         netif_rx_request_t *req = RING_GET_REQUEST(&dev->rx, req_prod + i);
         struct net_buffer* buf = &dev->rx_buffers[id];
         void* page = buf->page;
 
         /* We are sure to have free gnttab entries since they got released 
above */
-        buf->gref = req->gref = 
-            gnttab_grant_access(dev->dom,virt_to_mfn(page),0);
-
+        buf->gref = req->gref = gnttab_grant_access(dev->dom,
+                                                    virt_to_mfn(page),
+                                                    0);
         req->id = id;
     }
 
@@ -165,13 +183,10 @@ moretodo:
     RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->rx, notify);
     if (notify)
         notify_remote_via_evtchn(dev->evtchn);
-
 }
 
 void network_tx_buf_gc(struct netfront_dev *dev)
 {
-
-
     RING_IDX cons, prod;
     unsigned short id;
 
@@ -197,8 +212,8 @@ void network_tx_buf_gc(struct netfront_dev *dev)
             gnttab_end_access(buf->gref);
             buf->gref=GRANT_INVALID_REF;
 
-           add_id_to_freelist(id,dev->tx_freelist);
-           up(&dev->tx_sem);
+            add_id_to_freelist(id,dev->tx_freelist);
+            up(&dev->tx_sem);
         }
 
         dev->tx.rsp_cons = prod;
@@ -215,8 +230,6 @@ void network_tx_buf_gc(struct netfront_dev *dev)
             prod + ((dev->tx.sring->req_prod - prod) >> 1) + 1;
         mb();
     } while ((cons == prod) && (prod != dev->tx.sring->rsp_prod));
-
-
 }
 
 void netfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
@@ -253,8 +266,8 @@ static void free_netfront(struct netfront_dev *dev)
 {
     int i;
 
-    for(i=0;i<NET_TX_RING_SIZE;i++)
-       down(&dev->tx_sem);
+    for(i = 0; i < NET_TX_RING_SIZE; i++)
+        down(&dev->tx_sem);
 
     mask_evtchn(dev->evtchn);
 
@@ -269,32 +282,31 @@ static void free_netfront(struct netfront_dev *dev)
 
     unbind_evtchn(dev->evtchn);
 
-    for(i=0;i<NET_RX_RING_SIZE;i++) {
-       gnttab_end_access(dev->rx_buffers[i].gref);
-       free_page(dev->rx_buffers[i].page);
+    for (i = 0; i < NET_RX_RING_SIZE; i++) {
+        if (dev->rx_buffers[i].page) {
+            gnttab_end_access(dev->rx_buffers[i].gref);
+            free_page(dev->rx_buffers[i].page);
+        }
     }
 
-    for(i=0;i<NET_TX_RING_SIZE;i++)
-       if (dev->tx_buffers[i].page)
-           free_page(dev->tx_buffers[i].page);
+    for (i = 0; i < NET_TX_RING_SIZE; i++)
+        if (dev->tx_buffers[i].page)
+            free_page(dev->tx_buffers[i].page);
 
     free(dev->nodename);
     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 +315,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,26 +338,79 @@ struct netfront_dev *init_netfront(char *_nodename, void 
(*thenetif_rx)(unsigned
 #ifdef HAVE_LIBC
     dev->fd = -1;
 #endif
+    dev->netif_rx = thenetif_rx;
+    dev->netif_rx_arg = NULL;
+
+    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(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 = strdup(ldev->ip);
+
+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();
+        BUG_ON(dev->rx_buffers[i].page == NULL);
     }
 
-    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)
+    if (dev->netif_rx == NETIF_SELECT_RX)
         evtchn_alloc_unbound(dev->dom, netfront_select_handler, dev, 
&dev->evtchn);
     else
 #endif
@@ -343,22 +418,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 +440,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 +474,7 @@ again:
     err = xenbus_transaction_end(xbt, 0, &retry);
     free(err);
     if (retry) {
-            goto again;
+        goto again;
         printk("completing transaction\n");
     }
 
@@ -417,10 +487,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 +497,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 +527,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 +567,41 @@ 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 +665,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)
 {
@@ -653,8 +774,8 @@ ssize_t netfront_receive(struct netfront_dev *dev, unsigned 
char *data, size_t l
     local_irq_save(flags);
     network_rx(dev);
     if (!dev->rlen && fd != -1)
-       /* No data for us, make select stop returning */
-       files[fd].read = 0;
+        /* No data for us, make select stop returning */
+        files[fd].read = 0;
     /* Before re-enabling the interrupts, in case a packet just arrived in the
      * meanwhile. */
     local_irq_restore(flags);
@@ -665,3 +786,15 @@ 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®.