[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |