]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
plat/xen/drivers/net: Configure netfront device
authorCostin Lupu <costin.lupu@cs.pub.ro>
Tue, 17 Nov 2020 08:38:41 +0000 (10:38 +0200)
committerSimon Kuenzer <simon.kuenzer@neclab.eu>
Fri, 14 May 2021 13:49:57 +0000 (15:49 +0200)
The information needed for configuring netfront devices is in the Xenstore. For
now, we only retrieve the MAC and IP addresses from there in order to
initialize the device.

This patch introduces the `netfront_dev` structure which integrates both netdev
and Xenbus device information and also keeps the configuration parameters.

Signed-off-by: Costin Lupu <costin.lupu@cs.pub.ro>
Signed-off-by: Razvan Cojocaru <razvan.cojocaru93@gmail.com>
Reviewed-by: Simon Kuenzer <simon.kuenzer@neclab.eu>
plat/xen/Makefile.uk
plat/xen/drivers/net/netfront.c
plat/xen/drivers/net/netfront.h [new file with mode: 0644]
plat/xen/drivers/net/netfront_xb.h [new file with mode: 0644]
plat/xen/drivers/net/netfront_xs.c [new file with mode: 0644]

index 339b1b21d8b186aec300025fc1ea5443b5e93b6a..dfca58fe23d79764a02a6962869a319ec7f57f85 100644 (file)
@@ -121,6 +121,7 @@ LIBXENNETFRONT_ASINCLUDES-y    += $(LIBXENPLAT_ASINCLUDES-y)
 LIBXENNETFRONT_CFLAGS-y        += $(LIBXENPLAT_CFLAGS-y)
 LIBXENNETFRONT_CINCLUDES-y     += $(LIBXENPLAT_CINCLUDES-y)
 LIBXENNETFRONT_SRCS-y          += $(LIBXENPLAT_BASE)/drivers/net/netfront.c
+LIBXENNETFRONT_SRCS-y          += $(LIBXENPLAT_BASE)/drivers/net/netfront_xs.c
 endif
 
 ifeq ($(CONFIG_XEN_BLKFRONT),y)
index e6e73bca0cdfb057d589460788ffbcb3012f4576..ebd18b65b684c08e77fa1c4af16ee4f28ef402a8 100644 (file)
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <uk/assert.h>
+#include <uk/print.h>
+#include <uk/alloc.h>
+#include <uk/netdev_driver.h>
 #include <xenbus/xenbus.h>
+#include "netfront.h"
+#include "netfront_xb.h"
 
 
 #define DRIVER_NAME  "xen-netfront"
 
+#define to_netfront_dev(dev) \
+       __containerof(dev, struct netfront_dev, netdev)
+
 static struct uk_alloc *drv_allocator;
 
+static const void *netfront_einfo_get(struct uk_netdev *n,
+               enum uk_netdev_einfo_type einfo_type)
+{
+       struct netfront_dev *nfdev;
+
+       UK_ASSERT(n != NULL);
+
+       nfdev = to_netfront_dev(n);
+       switch (einfo_type) {
+       case UK_NETDEV_IPV4_ADDR_STR:
+               return nfdev->econf.ipv4addr;
+       case UK_NETDEV_IPV4_MASK_STR:
+               return nfdev->econf.ipv4mask;
+       case UK_NETDEV_IPV4_GW_STR:
+               return nfdev->econf.ipv4gw;
+       default:
+               break;
+       }
+
+       /* type not supported */
+       return NULL;
+}
+
+static const struct uk_hwaddr *netfront_mac_get(struct uk_netdev *n)
+{
+       struct netfront_dev *nfdev;
+
+       UK_ASSERT(n != NULL);
+       nfdev = to_netfront_dev(n);
+       return &nfdev->hw_addr;
+}
+
+static uint16_t netfront_mtu_get(struct uk_netdev *n)
+{
+       struct netfront_dev *nfdev;
+
+       UK_ASSERT(n != NULL);
+       nfdev = to_netfront_dev(n);
+       return nfdev->mtu;
+}
+
+static unsigned int netfront_promisc_get(struct uk_netdev *n)
+{
+       struct netfront_dev *nfdev;
+
+       UK_ASSERT(n != NULL);
+       nfdev = to_netfront_dev(n);
+       return nfdev->promisc;
+}
+
+static const struct uk_netdev_ops netfront_ops = {
+       .einfo_get = netfront_einfo_get,
+       .hwaddr_get = netfront_mac_get,
+       .mtu_get = netfront_mtu_get,
+       .promiscuous_get = netfront_promisc_get,
+};
 
 static int netfront_add_dev(struct xenbus_device *xendev)
 {
+       struct netfront_dev *nfdev;
        int rc = 0;
 
        UK_ASSERT(xendev != NULL);
 
+       nfdev = uk_calloc(drv_allocator, 1, sizeof(*nfdev));
+       if (!nfdev) {
+               rc = -ENOMEM;
+               goto err_out;
+       }
+
+       nfdev->xendev = xendev;
+       nfdev->mtu = UK_ETH_PAYLOAD_MAXLEN;
+
+       /* Xenbus initialization */
+       rc = netfront_xb_init(nfdev, drv_allocator);
+       if (rc) {
+               uk_pr_err("Error initializing Xenbus data: %d\n", rc);
+               goto err_xenbus;
+       }
+
+       /* register netdev */
+       nfdev->netdev.ops = &netfront_ops;
+       rc = uk_netdev_drv_register(&nfdev->netdev, drv_allocator, DRIVER_NAME);
+       if (rc < 0) {
+               uk_pr_err("Failed to register %s device with libuknetdev\n",
+                       DRIVER_NAME);
+               goto err_register;
+       }
+       nfdev->uid = rc;
+       rc = 0;
+
+out:
        return rc;
+err_register:
+       netfront_xb_fini(nfdev, drv_allocator);
+err_xenbus:
+       uk_free(drv_allocator, nfdev);
+err_out:
+       goto out;
 }
 
 static int netfront_drv_init(struct uk_alloc *allocator)
diff --git a/plat/xen/drivers/net/netfront.h b/plat/xen/drivers/net/netfront.h
new file mode 100644 (file)
index 0000000..89a8028
--- /dev/null
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Costin Lupu <costin.lupu@cs.pub.ro>
+ *          Razvan Cojocaru <razvan.cojocaru93@gmail.com>
+ *
+ * Copyright (c) 2020, University Politehnica of Bucharest. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __NETFRONT_H__
+#define __NETFRONT_H__
+
+#include <uk/netdev.h>
+
+struct xs_econf {
+       char *ipv4addr;
+       char *ipv4mask;
+       char *ipv4gw;
+};
+
+struct netfront_dev {
+       /* Xenbus device */
+       struct xenbus_device *xendev;
+       /* Network device */
+       struct uk_netdev netdev;
+
+       /* Configuration parameters */
+       struct xs_econf econf;
+
+       /* The netdevice identifier */
+       uint16_t uid;
+       /* The mtu */
+       uint16_t mtu;
+       /* The hw address of the netdevice */
+       struct uk_hwaddr hw_addr;
+       /* RX promiscuous mode. */
+       uint8_t promisc : 1;
+};
+
+#endif /* __NETFRONT_H__ */
diff --git a/plat/xen/drivers/net/netfront_xb.h b/plat/xen/drivers/net/netfront_xb.h
new file mode 100644 (file)
index 0000000..2bcb294
--- /dev/null
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Costin Lupu <costin.lupu@cs.pub.ro>
+ *
+ * Copyright (c) 2020, University Politehnica of Bucharest. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __NETFRONT_XB_H__
+#define __NETFRONT_XB_H__
+
+#include "netfront.h"
+
+int  netfront_xb_init(struct netfront_dev *netdev, struct uk_alloc *a);
+void netfront_xb_fini(struct netfront_dev *netdev, struct uk_alloc *a);
+
+#endif /* __NETFRONT_XB_H__ */
diff --git a/plat/xen/drivers/net/netfront_xs.c b/plat/xen/drivers/net/netfront_xs.c
new file mode 100644 (file)
index 0000000..470ae11
--- /dev/null
@@ -0,0 +1,205 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Costin Lupu <costin.lupu@cs.pub.ro>
+ *
+ * Copyright (c) 2020, University Politehnica of Bucharest. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <uk/errptr.h>
+#include <uk/print.h>
+#include <uk/assert.h>
+#include <xenbus/xs.h>
+#include "netfront_xb.h"
+
+
+static int xs_read_backend_id(const char *nodename, domid_t *domid)
+{
+       char path[strlen(nodename) + sizeof("/backend-id")];
+       int value, rc;
+
+       snprintf(path, sizeof(path), "%s/backend-id", nodename);
+
+       rc = xs_read_integer(XBT_NIL, path, &value);
+       if (!rc)
+               *domid = (domid_t) value;
+
+       return rc;
+}
+
+static void xs_econf_fini(struct xs_econf *econf,
+               struct uk_alloc *a)
+{
+       if (econf->ipv4addr) {
+               uk_free(a, econf->ipv4addr);
+               econf->ipv4addr = NULL;
+       }
+       if (econf->ipv4mask) {
+               uk_free(a, econf->ipv4mask);
+               econf->ipv4mask = NULL;
+       }
+       if (econf->ipv4gw) {
+               uk_free(a, econf->ipv4gw);
+               econf->ipv4gw = NULL;
+       }
+}
+
+static int xs_econf_init(struct xs_econf *econf, char *ip_str,
+               struct uk_alloc *a)
+{
+       int rc = -1;
+       char *ip_addr = NULL, *ip_gw_str = NULL, *ip_mask_str = NULL;
+
+       /* IP */
+       ip_addr = strtok(ip_str, " ");
+       if (ip_addr == NULL)
+               goto out_err;
+       econf->ipv4addr = uk_malloc(a, strlen(ip_addr) + 1);
+       if (!econf->ipv4addr) {
+               uk_pr_err("Error allocating ip config.\n");
+               goto out_err;
+       }
+       memcpy(econf->ipv4addr, ip_addr, strlen(ip_addr) + 1);
+
+       /* Mask */
+       ip_mask_str = strtok(NULL, " ");
+       if (ip_mask_str == NULL)
+               goto out_err;
+       econf->ipv4mask = uk_malloc(a, strlen(ip_mask_str) + 1);
+       if (!econf->ipv4mask) {
+               uk_pr_err("Error allocating ip mask config.\n");
+               goto out_err;
+       }
+       memcpy(econf->ipv4mask, ip_mask_str, strlen(ip_mask_str) + 1);
+
+       /* Gateway */
+       ip_gw_str = strtok(NULL, " ");
+       if (ip_gw_str == NULL)
+               goto out_err;
+       econf->ipv4gw = uk_malloc(a, strlen(ip_gw_str) + 1);
+       if (!econf->ipv4gw) {
+               uk_pr_err("Error allocating ip gateway config.\n");
+               goto out_err;
+       }
+       memcpy(econf->ipv4gw, ip_gw_str, strlen(ip_gw_str) + 1);
+
+       rc = 0;
+out:
+       return rc;
+out_err:
+       xs_econf_fini(econf, a);
+       goto out;
+}
+
+int netfront_xb_init(struct netfront_dev *nfdev, struct uk_alloc *a)
+{
+       struct xenbus_device *xendev;
+       char *mac_str, *p, *ip_str;
+       int rc;
+
+       UK_ASSERT(nfdev != NULL);
+
+       xendev = nfdev->xendev;
+       UK_ASSERT(xendev != NULL);
+       UK_ASSERT(xendev->nodename != NULL);
+
+       rc = xs_read_backend_id(xendev->nodename, &xendev->otherend_id);
+       if (rc)
+               goto out;
+
+       /* read backend path */
+       xendev->otherend = xs_read(XBT_NIL, xendev->nodename, "backend");
+       if (PTRISERR(xendev->otherend)) {
+               uk_pr_err("Error reading backend path.\n");
+               rc = PTR2ERR(xendev->otherend);
+               xendev->otherend = NULL;
+               goto out;
+       }
+
+       /* read MAC address */
+       mac_str = xs_read(XBT_NIL, xendev->nodename, "mac");
+       if (PTRISERR(mac_str)) {
+               uk_pr_err("Error reading MAC address.\n");
+               rc = PTR2ERR(mac_str);
+               goto no_conf;
+       }
+       uk_pr_info("\tMAC %s\n", mac_str);
+
+       p = mac_str;
+       for (int i = 0; i < UK_NETDEV_HWADDR_LEN; i++) {
+               nfdev->hw_addr.addr_bytes[i] = (uint8_t) strtoul(p, &p, 16);
+               p++;
+       }
+       free(mac_str);
+
+       /* read IP address */
+       ip_str = xs_read(XBT_NIL, xendev->otherend, "ip");
+       if (PTRISERR(ip_str)) {
+               uk_pr_err("Error reading IP address.\n");
+               rc = PTR2ERR(ip_str);
+               goto no_conf;
+       }
+       uk_pr_info("\tIP: %s\n", ip_str);
+
+       rc = xs_econf_init(&nfdev->econf, ip_str, a);
+       if (rc)
+               goto no_conf;
+       free(ip_str);
+
+       /* TODO spit event channels */
+
+       /* TODO netmap */
+
+out:
+       return rc;
+no_conf:
+       if (xendev->otherend) {
+               free(xendev->otherend);
+               xendev->otherend = NULL;
+       }
+       goto out;
+}
+
+void netfront_xb_fini(struct netfront_dev *nfdev, struct uk_alloc *a)
+{
+       struct xenbus_device *xendev;
+
+       UK_ASSERT(nfdev != NULL);
+
+       xendev = nfdev->xendev;
+       UK_ASSERT(xendev != NULL);
+
+       xs_econf_fini(&nfdev->econf, a);
+
+       if (xendev->otherend) {
+               free(xendev->otherend);
+               xendev->otherend = NULL;
+       }
+}