|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-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)
_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |