[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [mini-os master] Save/Restore Support: Add suspend/restore support for netfront
commit d225f4012d69a1935dc824ac22f5b636b9a428b8 Author: Bruno Alvisio <bruno.alvisio@xxxxxxxxx> AuthorDate: Mon Dec 11 08:23:15 2017 -0800 Commit: Wei Liu <wei.liu2@xxxxxxxxxx> CommitDate: Wed Mar 21 09:16:49 2018 +0000 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; +} -- generated by git-patchbot for /home/xen/git/mini-os.git#master _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |