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

[Minios-devel] [UNIKRAFT PATCH v2 10/12] plat/xen/drivers/net: Start netfront device


  • To: minios-devel@xxxxxxxxxxxxx
  • From: Costin Lupu <costin.lupu@xxxxxxxxx>
  • Date: Mon, 1 Apr 2019 16:42:50 +0300
  • Cc: felipe.huici@xxxxxxxxx, Razvan Cojocaru <razvan.cojocaru93@xxxxxxxxx>, Florian.Schmidt@xxxxxxxxx, sharan.santhanam@xxxxxxxxx, simon.kuenzer@xxxxxxxxx, yuri.volchkov@xxxxxxxxx
  • Delivery-date: Mon, 01 Apr 2019 13:43:07 +0000
  • Ironport-phdr: 9a23:UxlmJR8RKSxV9/9uRHKM819IXTAuvvDOBiVQ1KB+0uIUIJqq85mqBkHD//Il1AaPAdyDraMYwLSK+4nbGkU4qa6bt34DdJEeHzQksu4x2zIaPcieFEfgJ+TrZSFpVO5LVVti4m3peRMNQJW2aFLduGC94iAPERvjKwV1Ov71GonPhMiryuy+4ZLebxhUiDanZb5/Ixq6oATeu8ILnYZsN6E9xwfTrHBVYepW32RoJVySnxb4+Mi9+YNo/jpTtfw86cNOSL32cKskQ7NWCjQmKH0169bwtRbfVwuP52ATXXsQnxFVHgXK9hD6XpP2sivnqupw3TSRMMPqQbwoXzmp8rxmQwH0higZKzE58XnXis1ug6JdvBKhvAF0z4rNbI2IKPZyYqbRcNUHTmRDQ8lRTTRMDIOiYYUSAeQPPuFWoIvzp1YVsReyGROhCP/1xzNUmnP727Ax3eQ7EQHB2QwtB8wDsHPPrNXpNacSV/2+wq/VzTXbcvNdxDDw55TPchA6vfGMXLRwfdDVyUkyDwPFk06dppD+Pz+PzuQNrnOU4/B6VeKokmMqrRx6rDu3xso0l4XEiZ8ZxkrH+Ch52oo5O8O0RUxhbdOqCJdcqi6XO5ZsTs4hQ2xkojg2x7MItJKhYSQHx4oryhjCYPKdaYeI+AjsVOOJLDd9g3JqZaywig6p8Uil1u38Ts600EtWriZdktnDqHQN1xvL58iZT/ty5Eah2TKV2w/P8eFIO1g0lbfAJJI72L4wkYIfsUXFHiDohEX7lLKae0o59uSy6OnqYq/qqoGCO4J2kA3zPLwimsmlDuQ5NggOUXKb+eO51LD74UL5R65KjuE3kqnfqpzaIdkbprakAwJOzokj8AyzDy+70NsDh3UHNlVFdAqdj4f1I1HOPOz4DfCnjlS2ijhqxu7GMafnApnXMnfDl7XhfbFh5EFG0goz0NRS6pxPB7EOJfL8QE7xtNjCAhAlNAy0xv7tCM9h2YMGRWKPHqiZPbvXsV+J4OIvIu6MZJQMtDngNfcl+eDhjXsilF8ZfKmpxocXaGuiEvVpPUqZZ2DggtAbEWcFpgA+VvDliEWeUT5PYHa/R6Iy5jU8CIK8DIfMXIatjKac0iinHp1WY2FGBU2QEXrzcYWLResDaCaILcB6iDALS6WhQZc71R6yrA/616ZnLu3M9y0Wq53j0Nl15/XNmh0o9Tx0EsWd3H2MT2xvmGMHWSM53KRlrkNm0FuMz7V4ieRCFdNP//NJThs6NZnEwuxhC9D9QBjBcc2PSFq8WdWpGzcxTs4xw9AUZUZyAdCigwvF3yW0H7AVk6aEC4cu/q3Cwnj7P9x9xGre1Kk9k1kmRdNCNXanhq568AjTAZTFk0aEl6m0c6Qd3TDC9H2YwGqIok5XTApwXr/eUnwFeETWsMzz5lneQL+2FbQnLgxBxNaCK6tXcN3pjE9KROnkONTaf22xm2SwBRGWxr6XaorlZXkS3CHHB0cfiQwc42uGZkACAXKkomTfCycrGV/xbkfE9ehltGj9XkIyiQaQYB5Pzb2wrzUSnuCdTbs3w6oZ8HMqrC5oHVD728/OFvKLvEx5Ya8ae9RrswQP7n7QqwEoZs/oFKtlnFNLNl0v504=
  • Ironport-sdr: GiNzXXaNnd+u4yy/4boOPQjd0hu6dysSjT+ksLAAT0QGO8rZev2STpItuVgTNrGRSZVOfEKwFW Sa30BBK1XTKQ==
  • List-id: Mini-os development list <minios-devel.lists.xenproject.org>

On device start netfront connects with backend.

Signed-off-by: Costin Lupu <costin.lupu@xxxxxxxxx>
Signed-off-by: Razvan Cojocaru <razvan.cojocaru93@xxxxxxxxx>
---
 plat/xen/drivers/net/netfront.c    |  20 +++
 plat/xen/drivers/net/netfront_xb.h |   3 +
 plat/xen/drivers/net/netfront_xs.c | 303 +++++++++++++++++++++++++++++++++++++
 3 files changed, 326 insertions(+)

diff --git a/plat/xen/drivers/net/netfront.c b/plat/xen/drivers/net/netfront.c
index fc256501..d7610748 100644
--- a/plat/xen/drivers/net/netfront.c
+++ b/plat/xen/drivers/net/netfront.c
@@ -472,6 +472,25 @@ out:
        return rc;
 }
 
+static int netfront_start(struct uk_netdev *n)
+{
+       struct netfront_dev *nfdev;
+       int rc;
+
+       UK_ASSERT(n != NULL);
+       nfdev = to_netfront_dev(n);
+
+       rc = netfront_xb_connect(nfdev);
+       if (rc) {
+               uk_pr_err("Error connecting to backend: %d\n", rc);
+               return rc;
+       }
+
+       uk_pr_info(DRIVER_NAME": %"__PRIu16" started\n", nfdev->uid);
+
+       return rc;
+}
+
 static void netfront_info_get(struct uk_netdev *n,
                struct uk_netdev_info *dev_info)
 {
@@ -541,6 +560,7 @@ static unsigned int netfront_promisc_get(struct uk_netdev 
*n)
 
 static const struct uk_netdev_ops netfront_ops = {
        .configure = netfront_configure,
+       .start = netfront_start,
        .txq_configure = netfront_txq_setup,
        .rxq_configure = netfront_rxq_setup,
        .rxq_intr_enable = netfront_rx_intr_enable,
diff --git a/plat/xen/drivers/net/netfront_xb.h 
b/plat/xen/drivers/net/netfront_xb.h
index 013c0e3c..5cc8f500 100644
--- a/plat/xen/drivers/net/netfront_xb.h
+++ b/plat/xen/drivers/net/netfront_xb.h
@@ -40,4 +40,7 @@
 int  netfront_xb_init(struct netfront_dev *netdev, struct uk_alloc *a);
 void netfront_xb_fini(struct netfront_dev *netdev, struct uk_alloc *a);
 
+int netfront_xb_connect(struct netfront_dev *netdev);
+int netfront_xb_disconnect(struct netfront_dev *netdev);
+
 #endif /* __NETFRONT_XB_H__ */
diff --git a/plat/xen/drivers/net/netfront_xs.c 
b/plat/xen/drivers/net/netfront_xs.c
index df675b79..84762739 100644
--- a/plat/xen/drivers/net/netfront_xs.c
+++ b/plat/xen/drivers/net/netfront_xs.c
@@ -31,6 +31,7 @@
  *
  * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
  */
+#define _GNU_SOURCE
 #include <inttypes.h>
 #include <stdio.h>
 #include <string.h>
@@ -38,9 +39,14 @@
 #include <uk/print.h>
 #include <uk/assert.h>
 #include <xenbus/xs.h>
+#include <xenbus/client.h>
 #include "netfront_xb.h"
 
 
+static int netfront_xb_wait_be_connect(struct netfront_dev *nfdev);
+static int netfront_xb_wait_be_disconnect(struct netfront_dev *nfdev);
+
+
 static int xs_read_backend_id(const char *nodename, domid_t *domid)
 {
        char path[strlen(nodename) + sizeof("/backend-id")];
@@ -217,3 +223,300 @@ void netfront_xb_fini(struct netfront_dev *nfdev, struct 
uk_alloc *a)
                xendev->otherend = NULL;
        }
 }
+
+static int xs_write_queue(struct netfront_dev *nfdev, uint16_t queue_id,
+               xenbus_transaction_t xbt, int write_hierarchical)
+{
+       struct xenbus_device *xendev = nfdev->xendev;
+       struct uk_netdev_tx_queue *txq = &nfdev->txqs[queue_id];
+       struct uk_netdev_rx_queue *rxq = &nfdev->rxqs[queue_id];
+       char *path;
+       int rc;
+
+       if (write_hierarchical) {
+               rc = asprintf(&path, "%s/queue-%u", xendev->nodename, queue_id);
+               if (rc < 0)
+                       goto out;
+       } else
+               path = xendev->nodename;
+
+       rc = xs_printf(xbt, path, "tx-ring-ref", "%u", txq->ring_ref);
+       if (rc < 0)
+               goto out_path;
+
+       rc = xs_printf(xbt, path, "rx-ring-ref", "%u", rxq->ring_ref);
+       if (rc < 0)
+               goto out_path;
+
+       if (nfdev->split_evtchn) {
+               /* split event channels */
+               rc = xs_printf(xbt, path, "event-channel-tx", "%u",
+                       txq->evtchn);
+               if (rc < 0)
+                       goto out_path;
+
+               rc = xs_printf(xbt, path, "event-channel-rx", "%u",
+                       rxq->evtchn);
+               if (rc < 0)
+                       goto out_path;
+       } else {
+               /* shared event channel */
+               rc = xs_printf(xbt, path, "event-channel", "%u",
+                       txq->evtchn);
+               if (rc < 0)
+                       goto out_path;
+       }
+
+       rc = 0;
+
+out_path:
+       if (write_hierarchical)
+               free(path);
+out:
+       return rc;
+}
+
+static void xs_delete_queue(struct netfront_dev *nfdev, uint16_t queue_id,
+               xenbus_transaction_t xbt, int write_hierarchical)
+{
+       struct xenbus_device *xendev = nfdev->xendev;
+       char *dir, *path;
+       int rc;
+
+       if (write_hierarchical) {
+               rc = asprintf(&dir, "%s/queue-%u", xendev->nodename, queue_id);
+               if (rc < 0)
+                       return;
+       } else
+               dir = xendev->nodename;
+
+       rc = asprintf(&path, "%s/tx-ring-ref", dir);
+       if (rc < 0)
+               goto out;
+       xs_rm(xbt, path);
+       free(path);
+
+       rc = asprintf(&path, "%s/rx-ring-ref", dir);
+       if (rc < 0)
+               goto out;
+       xs_rm(xbt, path);
+       free(path);
+
+       if (nfdev->split_evtchn) {
+               /* split event channels */
+               rc = asprintf(&path, "%s/event-channel-tx", dir);
+               if (rc < 0)
+                       goto out;
+               xs_rm(xbt, path);
+               free(path);
+               rc = asprintf(&path, "%s/event-channel-rx", dir);
+               if (rc < 0)
+                       goto out;
+               xs_rm(xbt, path);
+               free(path);
+       } else {
+               /* shared event channel */
+               rc = asprintf(&path, "%s/event-channel", dir);
+               if (rc < 0)
+                       goto out;
+               xs_rm(xbt, path);
+               free(path);
+       }
+
+out:
+       if (write_hierarchical)
+               free(dir);
+}
+
+static int netfront_xb_front_init(struct netfront_dev *nfdev,
+               xenbus_transaction_t xbt)
+{
+       struct xenbus_device *xendev = nfdev->xendev;
+       int rc, i;
+
+       if (nfdev->rxqs_num == 1) {
+               rc = xs_write_queue(nfdev, 0, xbt, 0);
+               if (rc)
+                       goto out;
+       } else {
+               for (i = 0; i < nfdev->rxqs_num; i++) {
+                       rc = xs_write_queue(nfdev, i, xbt, 1);
+                       if (rc)
+                               goto out;
+               }
+       }
+
+       rc = xs_printf(xbt, xendev->nodename, "request-rx-copy", "%u", 1);
+       if (rc < 0)
+               goto out;
+
+       rc = 0;
+
+out:
+       return rc;
+}
+
+static void netfront_xb_front_fini(struct netfront_dev *nfdev,
+               xenbus_transaction_t xbt)
+{
+       int i;
+
+       if (nfdev->rxqs_num == 1)
+               xs_delete_queue(nfdev, 0, xbt, 0);
+       else {
+               for (i = 0; i < nfdev->rxqs_num; i++)
+                       xs_delete_queue(nfdev, i, xbt, 1);
+       }
+}
+
+int netfront_xb_connect(struct netfront_dev *nfdev)
+{
+       struct xenbus_device *xendev;
+       xenbus_transaction_t xbt;
+       int rc;
+
+       UK_ASSERT(nfdev != NULL);
+
+       xendev = nfdev->xendev;
+       UK_ASSERT(xendev != NULL);
+
+again:
+       rc = xs_transaction_start(&xbt);
+       if (rc)
+               goto abort_transaction;
+
+       rc = netfront_xb_front_init(nfdev, xbt);
+       if (rc)
+               goto abort_transaction;
+
+       rc = xenbus_switch_state(xbt, xendev, XenbusStateConnected);
+       if (rc)
+               goto abort_transaction;
+
+       rc = xs_transaction_end(xbt, 0);
+       if (rc == -EAGAIN)
+               goto again;
+
+       rc = netfront_xb_wait_be_connect(nfdev);
+       if (rc)
+               netfront_xb_front_fini(nfdev, xbt);
+
+       return rc;
+
+abort_transaction:
+       xs_transaction_end(xbt, 1);
+
+       return rc;
+}
+
+int netfront_xb_disconnect(struct netfront_dev *nfdev)
+{
+       struct xenbus_device *xendev;
+       int rc;
+
+       UK_ASSERT(nfdev != NULL);
+
+       xendev = nfdev->xendev;
+       UK_ASSERT(xendev != NULL);
+
+       uk_pr_info("Close network: backend at %s\n", xendev->otherend);
+
+       rc = xenbus_switch_state(XBT_NIL, xendev, XenbusStateClosing);
+       if (rc)
+               goto out;
+
+       rc = netfront_xb_wait_be_disconnect(nfdev);
+       if (rc)
+               goto out;
+
+       netfront_xb_front_fini(nfdev, XBT_NIL);
+
+out:
+       return rc;
+}
+
+static int be_watch_start(struct xenbus_device *xendev, const char *path)
+{
+       struct xenbus_watch *watch;
+
+       watch = xs_watch_path(XBT_NIL, path);
+       if (PTRISERR(watch))
+               return PTR2ERR(watch);
+
+       xendev->otherend_watch = watch;
+
+       return 0;
+}
+
+static int be_watch_stop(struct xenbus_device *xendev)
+{
+       return xs_unwatch(XBT_NIL, xendev->otherend_watch);
+}
+
+#define WAIT_BE_STATE_CHANGE_WHILE_COND(state_cond) \
+       do { \
+               rc = xs_read_integer(XBT_NIL, be_state_path, \
+                       (int *) &be_state); \
+               if (rc) \
+                       goto out; \
+               while (!rc && (state_cond)) \
+                       rc = xenbus_wait_for_state_change(be_state_path, \
+                               &be_state, xendev->otherend_watch); \
+               if (rc) \
+                       goto out; \
+       } while (0)
+
+static int netfront_xb_wait_be_connect(struct netfront_dev *nfdev)
+{
+       struct xenbus_device *xendev = nfdev->xendev;
+       char be_state_path[strlen(xendev->otherend) + sizeof("/state")];
+       XenbusState be_state;
+       int rc;
+
+       sprintf(be_state_path, "%s/state", xendev->otherend);
+
+       rc = be_watch_start(xendev, be_state_path);
+       if (rc)
+               goto out;
+
+       WAIT_BE_STATE_CHANGE_WHILE_COND(be_state < XenbusStateConnected);
+
+       if (be_state != XenbusStateConnected) {
+               uk_pr_err("Backend not available, state=%s\n",
+                               xenbus_state_to_str(be_state));
+               be_watch_stop(xendev);
+       }
+
+out:
+       return rc;
+}
+
+static int netfront_xb_wait_be_disconnect(struct netfront_dev *nfdev)
+{
+       struct xenbus_device *xendev = nfdev->xendev;
+       char be_state_path[strlen(xendev->otherend) + sizeof("/state")];
+       XenbusState be_state;
+       int rc;
+
+       sprintf(be_state_path, "%s/state", xendev->otherend);
+
+       WAIT_BE_STATE_CHANGE_WHILE_COND(be_state < XenbusStateClosing);
+
+       rc = xenbus_switch_state(XBT_NIL, xendev, XenbusStateClosed);
+       if (rc)
+               goto out;
+
+       WAIT_BE_STATE_CHANGE_WHILE_COND(be_state < XenbusStateClosed);
+
+       rc = xenbus_switch_state(XBT_NIL, xendev, XenbusStateInitialising);
+       if (rc)
+               goto out;
+
+       WAIT_BE_STATE_CHANGE_WHILE_COND(be_state < XenbusStateInitWait ||
+                       be_state >= XenbusStateClosed);
+
+       be_watch_stop(xendev);
+
+out:
+       return rc;
+}
-- 
2.11.0


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

 


Rackspace

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