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

[Minios-devel] [UNIKRAFT/CLICK PATCH v2 02/11] Initial public release: click.cc



This is taken from from kohler/click/minios/, with an updated copyright
header.

Signed-off-by: Florian Schmidt <florian.schmidt@xxxxxxxxx>
Reviewed-by: Felipe Huici <felipe.huici@xxxxxxxxx>
---
 click.cc | 384 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 384 insertions(+)
 create mode 100644 click.cc

diff --git a/click.cc b/click.cc
new file mode 100644
index 0000000..25bc524
--- /dev/null
+++ b/click.cc
@@ -0,0 +1,384 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2014 NEC Europe Ltd,
+ *               2019, NEC Laboratories Europe GmbH, NEC Corporation.
+ *               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.
+ *
+ * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
+ */
+
+#include <click/config.h>
+#include <click/lexer.hh>
+#include <click/router.hh>
+#include <click/master.hh>
+#include <click/error.hh>
+#include <click/timer.hh>
+#include <click/string.hh>
+#include <click/straccum.hh>
+#include <click/driver.hh>
+
+extern "C"{
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <mini-os/xenbus.h>
+#include <mini-os/shutdown.h>
+#include <mini-os/sched.h>
+}
+
+void *__dso_handle = NULL;
+
+#define NLOG(fmt, ...)
+#define LOG(fmt, ...) \
+       printf("[%s:%d] " fmt "\n", \
+               __FUNCTION__, __LINE__, ##__VA_ARGS__)
+
+/**
+ * xenstore helpers
+ */
+#define PATH_ROOT      "clickos"
+#define PATH_MAX_LEN   1024
+
+struct xenstore_dev {
+       domid_t dom;
+       char *nodename;
+       xenbus_event_queue events;
+} *xsdev = NULL;
+
+uint32_t domid = -1;
+u_int _shutdown = 0;
+u_int _reason = 0;
+
+char*
+event_token(char **key)
+{
+       char *p = *key, *p2;
+       char *token;
+       u_int sz;
+
+       p2 = strchr(++p, '/');
+       sz = (p2 != NULL ? p2 - p : strlen(p));
+       token = strndup(p, sz);
+       *key = (p+sz);
+
+       return token;
+}
+
+char*
+read_rid(char *path)
+{
+       char *id = strdup(path + 1);
+       char *id_end = strchr(id, '/');
+       *id_end = '\0';
+       return id;
+}
+
+String *
+read_config(u_int rid = 0)
+{
+       char path[PATH_MAX_LEN];
+       String *cfg = new String();
+       char *token;
+
+       for (int i = 0;; i++) {
+               snprintf(path, PATH_MAX_LEN, "%s/%d/config/%d",
+                               PATH_ROOT, rid, i);
+               xenbus_read(XBT_NIL, path, &token);
+               if (token == NULL)
+                       break;
+               *cfg += token;
+       }
+
+       return cfg;
+}
+
+/*
+ * click glue
+ */
+
+#define MAX_ROUTERS    64
+static ErrorHandler *errh;
+static Master master(1);
+
+struct router_instance {
+       Router *r;
+       u_int f_stop;
+} router_list[MAX_ROUTERS];
+
+void
+router_thread(void *thread_data)
+{
+       u_int *rid = (u_int*) thread_data;
+       String *config = read_config(*rid);
+       struct router_instance *ri = &router_list[*rid];
+
+       ri->r = click_read_router(*config, true, errh, false, &master);
+       if (ri->r->initialize(errh) < 0) {
+               LOG("Router init failed!");
+               ri->f_stop = 1;
+               return;
+       }
+
+       ri->r->use();
+       ri->r->activate(errh);
+
+       LOG("Starting driver...\n\n");
+       ri->r->master()->thread(0)->driver();
+
+       LOG("Stopping driver...\n\n");
+       ri->r->unuse();
+       ri->f_stop = 1;
+
+       LOG("Master/driver stopped, closing router_thread");
+       free(config);
+       free(rid);
+}
+
+void
+router_stop(int n = MAX_ROUTERS)
+{
+       LOG("Stopping all routers...\n\n");
+       for (int i = n - 1; i >= 0; --i) {
+               Router *r = router_list[i].r;
+
+               if (router_list[i].f_stop)
+                       continue;
+
+               LOG("Stopping instance = %d...\n\n", i);
+
+               do {
+                       r->please_stop_driver();
+                       schedule();
+               } while (!(router_list[i].f_stop));
+       }
+       LOG("Stopped all routers...\n\n");
+}
+
+void
+router_suspend(int n = MAX_ROUTERS)
+{
+}
+
+void
+router_resume(int n = MAX_ROUTERS)
+{
+}
+
+u_int
+on_status(int rid, char *key, void *data)
+{
+       String status = (char *) data;
+       struct router_instance *r = &router_list[rid];
+
+       LOG("router id %d", rid);
+       LOG("status change to %s", data);
+       if (status == "Running") {
+               u_int *arg0;
+
+               if (!r->f_stop)
+                       goto status_err;
+
+               arg0 = (u_int*) malloc(sizeof(u_int));
+               *arg0 = rid;
+               r->f_stop = 0;
+               create_thread((char*)"click", router_thread, arg0);
+       } else if (status == "Halted") {
+               if (r->f_stop)
+                       goto status_err;
+
+               router_stop(rid);
+       }
+
+       return 0;
+status_err:
+       return -EINVAL;
+}
+
+static void
+read_cname(char *path, Element **e, const Handler **h, int rid)
+{
+       int sep = strchr(path, '/') - path;
+       String ename(path, sep), hname(path + sep + 1);
+       Router *r = router_list[rid].r;
+
+       NLOG("sep=%d element=%s handler=%s", sep,
+                       ename.c_str(), hname.c_str());
+
+       *e = r->find(ename);
+       *h = Router::handler(*e, hname);
+       NLOG("ename %s=%p hname %s=%p", ename.c_str(), e, hname.c_str(), h);
+}
+
+u_int
+on_elem_readh(int rid, char *key, void *data)
+{
+       Element *e;
+       const Handler* h;
+       String val, h_path, lock_path;
+       int f_stop = router_list[rid].f_stop;
+
+       if (strncmp(key, "/read/", 6))
+               return 0;
+
+       if (f_stop)
+               return 0;
+
+       read_cname(key+6, &e, &h, rid);
+
+       if (!h || !h->readable())
+               return EINVAL;
+
+       val = h->call_read(e, "", ErrorHandler::default_handler());
+       h_path = String(PATH_ROOT) + "/0/elements/" + e->name() + "/" + 
h->name();
+       lock_path = h_path + "/lock";
+
+       xenbus_write(XBT_NIL, h_path.c_str(), val.c_str());
+       xenbus_write(XBT_NIL, lock_path.c_str(), "0");
+
+       NLOG("element handler read %s", val.c_str());
+       return 0;
+}
+
+u_int
+on_elem_writeh(int rid, char *key, void *data)
+{
+       Element *e;
+       const Handler* h;
+       int f_stop = router_list[rid].f_stop;
+
+       if (f_stop || strlen((char *) data) == 0)
+               return 0;
+
+       read_cname(key+1, &e, &h, rid);
+
+       if (!h || !h->writable())
+               return EINVAL;
+
+       h->call_write(String(data), e, ErrorHandler::default_handler());
+       NLOG("element handler write %s value %s", data, "");
+       return 0;
+}
+
+u_int
+on_router(char *key, void *data)
+{
+       char *p = key;
+       String rev;
+       u_int rid;
+
+       if (strlen(key) == 0)
+               return 0;
+
+       rid = atoi(event_token(&p));
+       rev = event_token(&p);
+
+       if (rev == "control")
+               on_elem_readh(rid, p, data);
+       else if (rev == "elements")
+               on_elem_writeh(rid, p, data);
+       else if (rev == "status")
+               on_status(rid, key, data);
+
+       return 0;
+}
+
+/* runs the event loop */
+int main(int argc, char **argv)
+{
+       size_t len = sizeof(struct xenstore_dev);
+
+       click_static_initialize();
+       errh = ErrorHandler::default_handler();
+
+       xsdev = (struct xenstore_dev*) malloc(len);
+       memset(xsdev, 0, len);
+       memset(router_list, 0, MAX_ROUTERS * sizeof(struct router_instance));
+       for (int i = 0; i < MAX_ROUTERS; ++i) {
+               router_list[i].f_stop = 1;
+       }
+
+       xenbus_watch_path_token(XBT_NIL, PATH_ROOT, "router-watch",
+                       &xsdev->events);
+
+       while (!_shutdown) {
+               String value;
+               char *err, *val, **path;
+
+               path = xenbus_wait_for_watch_return(&xsdev->events);
+               if (!path || _shutdown)
+                       continue;
+
+               err = xenbus_read(XBT_NIL, *path, &val);
+               if (err)
+                       continue;
+
+               on_router((*path + strlen(PATH_ROOT)), val);
+       }
+
+       LOG("Shutting down...");
+       xenbus_unwatch_path_token(XBT_NIL, PATH_ROOT, "router-watch");
+
+       fini_xenbus();
+       free(xsdev);
+
+       return _reason;
+}
+
+/* app shutdown hook from minios */
+extern "C" {
+int app_shutdown(unsigned reason)
+{
+       switch (reason) {
+       case SHUTDOWN_poweroff:
+               LOG("Requested shutdown reason=poweroff");
+               _shutdown = 1;
+               _reason = reason;
+               router_stop();
+               xenbus_release_wait_for_watch(&xsdev->events);
+               break;
+       case SHUTDOWN_reboot:
+               LOG("Requested shutdown reason=reboot");
+               _shutdown = 1;
+               _reason = reason;
+               router_stop();
+               xenbus_release_wait_for_watch(&xsdev->events);
+               break;
+       case SHUTDOWN_suspend:
+               LOG("Requested shutdown reason=suspend");
+               router_suspend();
+               kernel_suspend();
+               router_resume();
+       default:
+               LOG("Requested shutdown with invalid reason (%d)", reason);
+               break;
+       }
+
+       return 0;
+}
+}
-- 
2.21.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®.