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

[Xen-devel] [PATCH 3 of 5] tools/libxl: setup/teardown Remus network buffering



# HG changeset patch
# User Shriram Rajagopalan <rshriram@xxxxxxxxx>
# Date 1377473609 25200
# Node ID 4b23104828c09218aa7f9fbde1578bb6706e13d6
# Parent  4d24d36d30c37e4fb5985952db92c1e789c90894
tools/libxl: setup/teardown Remus network buffering

Setup/teardown remus network buffering for a given guest, when
libxl_domain_remus_start API is invoked.

This patch does the following during setup:
 a) call the hotplug script for each vif to setup its network buffer

 b) establish a dedicated remus context containing libnl related
    state (netlink sockets, qdisc caches, etc.,)

 c) Obtain handles to plug qdiscs installed on the IFB devices
    chosen by the hotplug scripts.

During teardown, the hotplug scripts are called to remove the IFB
devices. This is followed by releasing netlink resources.

Signed-off-by: Shriram Rajagopalan <rshriram@xxxxxxxxx>

diff -r 4d24d36d30c3 -r 4b23104828c0 tools/libxl/Makefile
--- a/tools/libxl/Makefile      Sun Aug 25 16:33:27 2013 -0700
+++ b/tools/libxl/Makefile      Sun Aug 25 16:33:29 2013 -0700
@@ -40,6 +40,13 @@ LIBXL_OBJS-y += libxl_blktap2.o
 else
 LIBXL_OBJS-y += libxl_noblktap2.o
 endif
+
+ifeq ($(CONFIG_REMUS_NETBUF),y)
+LIBXL_OBJS-y += libxl_netbuffer.o
+else
+LIBXL_OBJS-y += libxl_nonetbuffer.o
+endif
+
 LIBXL_OBJS-$(CONFIG_X86) += libxl_cpuid.o libxl_x86.o
 LIBXL_OBJS-$(CONFIG_IA64) += libxl_nocpuid.o libxl_noarch.o
 LIBXL_OBJS-$(CONFIG_ARM) += libxl_nocpuid.o libxl_noarch.o
diff -r 4d24d36d30c3 -r 4b23104828c0 tools/libxl/libxl.c
--- a/tools/libxl/libxl.c       Sun Aug 25 16:33:27 2013 -0700
+++ b/tools/libxl/libxl.c       Sun Aug 25 16:33:29 2013 -0700
@@ -692,8 +692,9 @@ libxl_vminfo * libxl_list_vm(libxl_ctx *
     return ptr;
 }
 
-static void remus_failover_cb(libxl__egc *egc,
-                              libxl__domain_suspend_state *dss, int rc);
+static void remus_replication_failure_cb(libxl__egc *egc,
+                                         libxl__domain_suspend_state *dss,
+                                         int rc);
 
 /* TODO: Explicit Checkpoint acknowledgements via recv_fd. */
 int libxl_domain_remus_start(libxl_ctx *ctx, libxl_domain_remus_info *info,
@@ -712,18 +713,44 @@ int libxl_domain_remus_start(libxl_ctx *
 
     GCNEW(dss);
     dss->ao = ao;
-    dss->callback = remus_failover_cb;
+    dss->callback = remus_replication_failure_cb;
     dss->domid = domid;
     dss->fd = send_fd;
     /* TODO do something with recv_fd */
     dss->type = type;
     dss->live = 1;
     dss->debug = 0;
-    dss->remus = info;
 
     assert(info);
 
-    /* TBD: Remus setup - i.e. attach qdisc, enable disk buffering, etc */
+    GCNEW(dss->remus_ctx);
+
+    /* convenience shorthand */
+    libxl__remus_ctx *remus_ctx = dss->remus_ctx;
+    remus_ctx->blackhole = info->blackhole;
+    remus_ctx->interval = info->interval;
+    remus_ctx->compression = info->compression;
+
+    /* Setup network buffering before invoking domain_suspend */
+    if (info->netbuf) {
+        if (info->netbufscript) {
+            remus_ctx->netbufscript =
+                libxl__strdup(gc, info->netbufscript);
+        } else {
+            remus_ctx->netbufscript =
+                libxl__sprintf(gc, "%s/remus-netbuf-setup",
+                              libxl__xen_script_dir_path());
+        }
+
+        if (libxl__remus_netbuf_setup(gc, domid, remus_ctx)) {
+            LOG(ERROR, "Remus: failed to setup network buffering"
+                " for guest with domid %u", domid);
+            rc = ERROR_FAIL;
+            goto out;
+        }
+    }
+
+    /* TBD: enable disk buffering */
 
     /* Point of no return */
     libxl__domain_suspend(egc, dss);
@@ -733,8 +760,9 @@ int libxl_domain_remus_start(libxl_ctx *
     return AO_ABORT(rc);
 }
 
-static void remus_failover_cb(libxl__egc *egc,
-                              libxl__domain_suspend_state *dss, int rc)
+static void remus_replication_failure_cb(libxl__egc *egc,
+                                         libxl__domain_suspend_state *dss,
+                                         int rc)
 {
     STATE_AO_GC(dss->ao);
     /*
@@ -743,9 +771,10 @@ static void remus_failover_cb(libxl__egc
      * from sending checkpoints.
      */
 
-    /* TBD: Remus cleanup - i.e. detach qdisc, release other
-     * resources.
-     */
+    /* Teardown the network buffers and release netlink resources. */
+    if (dss->remus_ctx && dss->remus_ctx->netbuf_ctx)
+        libxl__remus_netbuf_teardown(gc, dss->domid, dss->remus_ctx);
+
     libxl__ao_complete(egc, ao, rc);
 }
 
diff -r 4d24d36d30c3 -r 4b23104828c0 tools/libxl/libxl_dom.c
--- a/tools/libxl/libxl_dom.c   Sun Aug 25 16:33:27 2013 -0700
+++ b/tools/libxl/libxl_dom.c   Sun Aug 25 16:33:29 2013 -0700
@@ -1259,7 +1259,7 @@ static void remus_checkpoint_dm_saved(li
     /* REMUS TODO: Wait for disk and memory ack, release network buffer */
     /* REMUS TODO: make this asynchronous */
     assert(!rc); /* REMUS TODO handle this error properly */
-    usleep(dss->interval * 1000);
+    usleep(dss->remus_ctx->interval * 1000);
     libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, 1);
 }
 
@@ -1277,7 +1277,6 @@ void libxl__domain_suspend(libxl__egc *e
     const libxl_domain_type type = dss->type;
     const int live = dss->live;
     const int debug = dss->debug;
-    const libxl_domain_remus_info *const r_info = dss->remus;
     libxl__srm_save_autogen_callbacks *const callbacks =
         &dss->shs.callbacks.save.a;
 
@@ -1312,9 +1311,8 @@ void libxl__domain_suspend(libxl__egc *e
     dss->guest_responded = 0;
     dss->dm_savefile = libxl__device_model_savefile(gc, domid);
 
-    if (r_info != NULL) {
-        dss->interval = r_info->interval;
-        if (r_info->compression)
+    if (dss->remus_ctx != NULL) {
+        if (dss->remus_ctx->compression)
             dss->xcflags |= XCFLAGS_CHECKPOINT_COMPRESS;
     }
 
@@ -1335,7 +1333,7 @@ void libxl__domain_suspend(libxl__egc *e
     }
 
     memset(callbacks, 0, sizeof(*callbacks));
-    if (r_info != NULL) {
+    if (dss->remus_ctx != NULL) {
         callbacks->suspend = libxl__remus_domain_suspend_callback;
         callbacks->postcopy = libxl__remus_domain_resume_callback;
         callbacks->checkpoint = libxl__remus_domain_checkpoint_callback;
diff -r 4d24d36d30c3 -r 4b23104828c0 tools/libxl/libxl_internal.h
--- a/tools/libxl/libxl_internal.h      Sun Aug 25 16:33:27 2013 -0700
+++ b/tools/libxl/libxl_internal.h      Sun Aug 25 16:33:29 2013 -0700
@@ -2242,6 +2242,29 @@ typedef struct libxl__logdirty_switch {
     libxl__ev_time timeout;
 } libxl__logdirty_switch;
 
+typedef struct libxl__remus_ctx {
+    /* checkpoint interval */
+    int interval;
+    int blackhole;
+    int compression;
+    /* Script to setup/teardown network buffers */
+    const char *netbufscript;
+    /* Opaque context containing network buffer related stuff */
+    void *netbuf_ctx;
+} libxl__remus_ctx;
+
+_hidden int libxl__remus_netbuf_setup(libxl__gc *gc, uint32_t domid,
+                                     libxl__remus_ctx *remus_ctx);
+
+_hidden int libxl__remus_netbuf_teardown(libxl__gc *gc, uint32_t domid,
+                                        libxl__remus_ctx *remus_ctx);
+
+_hidden int libxl__remus_netbuf_start_new_epoch(libxl__gc *gc, uint32_t domid,
+                                               libxl__remus_ctx *remus_ctx);
+
+_hidden int libxl__remus_netbuf_release_prev_epoch(libxl__gc *gc, uint32_t 
domid,
+                                                  libxl__remus_ctx *remus_ctx);
+
 struct libxl__domain_suspend_state {
     /* set by caller of libxl__domain_suspend */
     libxl__ao *ao;
@@ -2252,7 +2275,7 @@ struct libxl__domain_suspend_state {
     libxl_domain_type type;
     int live;
     int debug;
-    const libxl_domain_remus_info *remus;
+    libxl__remus_ctx *remus_ctx;
     /* private */
     xc_evtchn *xce; /* event channel handle */
     int suspend_eventchn;
@@ -2260,7 +2283,6 @@ struct libxl__domain_suspend_state {
     int xcflags;
     int guest_responded;
     const char *dm_savefile;
-    int interval; /* checkpoint interval (for Remus) */
     libxl__save_helper_state shs;
     libxl__logdirty_switch logdirty;
     /* private for libxl__domain_save_device_model */
diff -r 4d24d36d30c3 -r 4b23104828c0 tools/libxl/libxl_netbuffer.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_netbuffer.c     Sun Aug 25 16:33:29 2013 -0700
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2013
+ * Author Shriram Rajagopalan <rshriram@xxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h" /* must come before any other headers */
+
+#include "libxl_internal.h"
+
+#include <netlink/cache.h>
+#include <netlink/socket.h>
+#include <netlink/attr.h>
+#include <netlink/route/link.h>
+#include <netlink/route/route.h>
+#include <netlink/route/qdisc.h>
+#include <netlink/route/qdisc/plug.h>
+
+typedef struct libxl__remus_netbuf_ctx {
+    struct rtnl_qdisc **netbuf_qdisc_list;
+    struct nl_sock *nlsock;
+    struct nl_cache *qdisc_cache;
+    char **vif_list;
+    char **ifb_list;
+    uint32_t num_netbufs;
+    uint32_t unused;
+} libxl__remus_netbuf_ctx;
+
+/* If the device has a vifname, then use that instead of
+ * the vifX.Y format.
+ */
+static char *get_vifname(libxl__gc *gc, uint32_t domid,
+                         libxl_device_nic *nic)
+{
+    char *vifname = NULL;
+    vifname = libxl__xs_read(gc, XBT_NULL,
+                             libxl__sprintf(gc,
+                                            "%s/backend/vif/%d/%d/vifname",
+                                            libxl__xs_get_dompath(gc, 0),
+                                            domid, nic->devid));
+    if (!vifname) {
+        vifname = (char *)libxl__device_nic_devname(gc, domid,
+                                                    nic->devid,
+                                                    nic->nictype);
+    }
+
+    return vifname;
+}
+
+static char **get_guest_vif_list(libxl__gc *gc, uint32_t domid,
+                                 int *num_vifs)
+{
+    libxl_device_nic *nics;
+    int nb, i = 0;
+    char **vif_list = NULL;
+
+    nics = libxl_device_nic_list(CTX, domid, &nb);
+    if (!nics) {
+        *num_vifs = 0;
+        return NULL;
+    }
+
+    vif_list = libxl__calloc(gc, nb, sizeof(char *));
+    for (i = 0; i < nb; ++i) {
+        vif_list[i] = get_vifname(gc, domid, &nics[i]);
+        libxl_device_nic_dispose(&nics[i]);
+    }
+    free(nics);
+
+    *num_vifs = nb;
+    return vif_list;
+}
+
+static void netbuf_script_child_death_cb(libxl__egc *egc,
+                                         libxl__ev_child *child,
+                                         pid_t pid, int status)
+{
+    /* No-op. hotplug-error will be read in setup/teardown_ifb */
+    return;
+}
+
+/* the script needs the following env & args
+ * $vifname
+ * $XENBUS_PATH (/libxl/<domid>/remus/netbuf/<devid>/)
+ * setup/teardown as command line arg.
+ * In return, the script writes the name of IFB device to be used for
+ * output buffering into XENBUS_PATH/ifb
+ *
+ * The setup and teardown ops are synchronous, as they are executed during
+ * the context of an asynchronous API call (libxl_domain_remus_start).
+ */
+static int libxl__exec_netbuf_script(libxl__gc *gc, uint32_t domid,
+                                     int devid, char *vif, char *script,
+                                     char *op)
+{
+    int arraysize, nr;
+    char **env = NULL, **args = NULL;
+    pid_t pid;
+    libxl__ev_child childw_out;
+
+    arraysize = 5; nr = 0;
+    GCNEW_ARRAY(env, arraysize);
+    env[nr++] = "vifname";
+    env[nr++] = vif;
+    env[nr++] = "XENBUS_PATH";
+    env[nr++] = GCSPRINTF("%s/remus/netbuf/%d",
+                          libxl__xs_libxl_path(gc, domid), devid);
+    env[nr++] = NULL;
+    assert(nr <= arraysize);
+
+    arraysize = 3; nr = 0;
+    GCNEW_ARRAY(args, arraysize);
+    args[nr++] = script;
+    args[nr++] = op;
+    args[nr++] = NULL;
+    assert(nr == arraysize);
+
+    libxl__ev_child_init(&childw_out);
+    LOG(DEBUG, "Calling netbuf script: %s %s", script, op);
+
+    /* Fork and exec netbuf script */
+    pid = libxl__ev_child_fork(gc, &childw_out, netbuf_script_child_death_cb);
+    if (pid == -1) {
+        LOG(ERROR, "unable to fork netbuf script %s", script);
+        return ERROR_FAIL;
+    }
+
+    if (!pid) {
+        /* child: Launch netbuf script */
+        libxl__exec(gc, -1, -1, -1, args[0], args, env);
+        /* notreached */
+        abort();
+    }
+
+    assert(libxl__ev_child_inuse(&childw_out));
+
+    return 0;
+}
+
+static int script_done_cb(libxl__gc *gc, uint32_t domid,
+                          const char *state, void *userdata)
+{
+    return 0; /* No-op callback */
+}
+
+static int libxl__netbuf_script_setup(libxl__gc *gc, uint32_t domid,
+                                      int devid, char *vif, char *script,
+                                      char **ifb)
+{
+    int rc;
+    char *out_path_base, *hotplug_error;
+
+    rc = libxl__exec_netbuf_script(gc, domid, devid, vif,
+                                   script, "setup");
+    if (rc) return rc;
+
+    out_path_base = GCSPRINTF("%s/remus/netbuf/%d",
+                              libxl__xs_libxl_path(gc, domid), devid);
+
+    /* Now wait for the result (XENBUS_PATH/hotplug-status).
+     * It doesnt matter what the result is. If the hotplug-status path
+     * appears, then we are good to go.
+     */
+    rc = libxl__wait_for_offspring(gc, domid, LIBXL_HOTPLUG_TIMEOUT,
+                                   script,
+                                   /* path */
+                                   GCSPRINTF("%s/hotplug-status",
+                                             out_path_base),
+                                   NULL /* state */,
+                                   NULL, script_done_cb, NULL);
+    if (rc) {
+        LOG(ERROR, "unable to wait for %s setup to complete", script);
+        return ERROR_FAIL;
+    }
+
+    hotplug_error = libxl__xs_read(gc, XBT_NULL,
+                                   GCSPRINTF("%s/hotplug-error",
+                                             out_path_base));
+    if (hotplug_error) {
+        LOG(ERROR, "netbuf script %s setup failed: %s",
+            script, hotplug_error);
+        return ERROR_FAIL;
+    }
+
+    *ifb = libxl__xs_read(gc, XBT_NULL,
+                          GCSPRINTF("%s/remus/netbuf/%d/ifb",
+                                    libxl__xs_libxl_path(gc, domid),
+                                    devid));
+    if (!(*ifb)) {
+        LOG(ERROR, "Cannot get ifb dev name for domain %u dev %s",
+            domid, vif);
+        return ERROR_FAIL;
+    }
+
+    return 0;
+}
+
+static int libxl__netbuf_script_teardown(libxl__gc *gc, uint32_t domid,
+                                         int devid, char *vif,
+                                         char *script)
+{
+    /* Nothing to wait for during tear down */
+    return libxl__exec_netbuf_script(gc, domid, devid, vif,
+                                     script, "teardown");
+}
+
+/* Scan through the list of vifs belonging to domid and
+ * invoke the netbufscript to setup the IFB device & plug qdisc
+ * for each vif. Then scan through the list of IFB devices to obtain
+ * a handle on the plug qdisc installed on these IFB devices.
+ * Network output buffering is controlled via these qdiscs.
+ */
+int libxl__remus_netbuf_setup(libxl__gc *gc, uint32_t domid,
+                             libxl__remus_ctx *remus_ctx)
+{
+    int i, ret, ifindex, num_netbufs = 0;
+    struct rtnl_link *ifb = NULL;
+    struct rtnl_qdisc *qdisc = NULL;
+    libxl__remus_netbuf_ctx *netbuf_ctx = NULL;
+
+    /* If the domain backend is a stubdom, do nothing. We dont
+     * support stubdom network buffering yet.
+     */
+    if (libxl_get_stubdom_id(CTX, domid)) {
+        LOG(ERROR, "Network buffering is not supported with stubdoms");
+        return ERROR_FAIL;
+    }
+
+    netbuf_ctx = libxl__zalloc(gc, sizeof(libxl__remus_netbuf_ctx));
+    netbuf_ctx->vif_list = get_guest_vif_list(gc, domid, &num_netbufs);
+    if (!num_netbufs) return 0;
+
+    netbuf_ctx->ifb_list = libxl__calloc(gc, num_netbufs,
+                                         sizeof(char *));
+
+    /* convenience vars */
+    char **vif_list = netbuf_ctx->vif_list;
+    char **ifb_list = netbuf_ctx->ifb_list;
+
+    for (i = 0; i < num_netbufs; ++i) {
+
+        /* The setup script does the following
+         * find a free IFB to act as buffer for the vif.
+         * set up the plug qdisc on the IFB.
+         */
+        ret = libxl__netbuf_script_setup(gc, domid, i, vif_list[i],
+                                         (char *) remus_ctx->netbufscript,
+                                         &ifb_list[i]);
+        if (ret) {
+            LOG(ERROR, "Failed to setup ifb device for dev %s",
+                vif_list[i]);
+            return ERROR_FAIL;
+        }
+
+        LOG(DEBUG, "dev %s will be buffered at ifb %s", vif_list[i],
+            ifb_list[i]);
+    }
+
+    /* Now that we have brought up IFB devices with plug qdisc for
+     * each vif, lets get a netlink handle on the plug qdisc for use
+     * during checkpointing.
+     */
+    netbuf_ctx->nlsock = nl_socket_alloc();
+    if (!netbuf_ctx->nlsock) {
+        LOG(ERROR, "cannot allocate nl socket");
+        return ERROR_FAIL;
+    }
+
+    ret = nl_connect(netbuf_ctx->nlsock, NETLINK_ROUTE);
+    if (ret) {
+        LOG(ERROR, "failed to open netlink socket: %s",
+            nl_geterror(ret));
+        return ERROR_FAIL;
+    }
+
+    /* get list of all qdiscs installed on network devs. */
+    ret = rtnl_qdisc_alloc_cache(netbuf_ctx->nlsock,
+                                 &netbuf_ctx->qdisc_cache);
+    if (ret) {
+        LOG(ERROR, "failed to allocate qdisc cache: %s",
+            nl_geterror(ret));
+        goto end;
+    }
+
+    /* list of handles to plug qdiscs */
+    netbuf_ctx->netbuf_qdisc_list =
+        libxl__calloc(gc, num_netbufs,
+                      sizeof(struct rtnl_qdisc *));
+
+    ifb = rtnl_link_alloc();
+
+    for (i = 0; i < num_netbufs; ++i) {
+
+        /* get a handle to the IFB interface */
+        ret = rtnl_link_get_kernel(netbuf_ctx->nlsock, 0,
+                                   ifb_list[i], &ifb);
+        if (ret) {
+            LOG(ERROR, "cannot obtain handle for %s: %s", ifb_list[i],
+                nl_geterror(ret));
+            goto end;
+        }
+
+        ifindex = rtnl_link_get_ifindex(ifb);
+        if (!ifindex) {
+            LOG(ERROR, "interface %s has no index", ifb_list[i]);
+            goto end;
+        }
+
+        /* Get a reference to the root qdisc installed on the IFB, by
+         * querying the qdisc list we obtained earlier. The netbufscript
+         * sets up the plug qdisc as the root qdisc, so we dont have to
+         * search the entire qdisc tree on the IFB dev.
+
+         * There is no need to explicitly free this qdisc as its just a
+         * reference from the qdisc cache we allocated earlier.
+         */
+        qdisc = rtnl_qdisc_get_by_parent(netbuf_ctx->qdisc_cache, ifindex,
+                                         TC_H_ROOT);
+
+        if (qdisc) {
+            const char *tc_kind = rtnl_tc_get_kind(TC_CAST(qdisc));
+            /* Sanity check: Ensure that the root qdisc is a plug qdisc. */
+            if (!tc_kind || strcmp(tc_kind, "plug")) {
+                LOG(ERROR, "plug qdisc is not installed on %s", ifb_list[i]);
+                goto end;
+            }
+            netbuf_ctx->netbuf_qdisc_list[i] = qdisc;
+        } else {
+            LOG(ERROR, "Cannot get qdisc handle from ifb %s", ifb_list[i]);
+            goto end;
+        }
+    }
+
+    rtnl_link_put(ifb);
+
+    netbuf_ctx->num_netbufs = num_netbufs;
+
+    /* Update remus_ctx to point to the newly setup netbuffer context */
+    remus_ctx->netbuf_ctx = netbuf_ctx;
+    return 0;
+
+ end:
+    if (ifb) rtnl_link_put(ifb);
+    if (netbuf_ctx->qdisc_cache) nl_cache_free(netbuf_ctx->qdisc_cache);
+    if (netbuf_ctx->nlsock) nl_close(netbuf_ctx->nlsock);
+    return ERROR_FAIL;
+}
+
+/* Note: This function will be called in the same gc context as
+ * libxl__remus_netbuf_setup, created during the libxl_domain_remus_start
+ * API call.
+ */
+int libxl__remus_netbuf_teardown(libxl__gc *gc, uint32_t domid,
+                                libxl__remus_ctx *remus_ctx)
+{
+    libxl__remus_netbuf_ctx *netbuf_ctx = remus_ctx->netbuf_ctx;
+    char **vif_list = NULL, **ifb_list = NULL;
+    int i;
+
+    if (!(remus_ctx && netbuf_ctx && netbuf_ctx->num_netbufs))
+        return 0;
+
+    nl_cache_free(netbuf_ctx->qdisc_cache);
+    nl_close(netbuf_ctx->nlsock);
+
+    vif_list = netbuf_ctx->vif_list;
+    ifb_list = netbuf_ctx->ifb_list;
+
+    for (i = 0; i < netbuf_ctx->num_netbufs; ++i)
+        libxl__netbuf_script_teardown(gc, domid, i, vif_list[i],
+                                      (char *) remus_ctx->netbufscript);
+
+    return 0;
+}
+
+#define TC_BUFFER_START 1
+#define TC_BUFFER_RELEASE 2
+static int remus_netbuf_op(libxl__gc *gc, uint32_t domid,
+                          libxl__remus_ctx *remus_ctx,
+                          int buffer_op)
+{
+    int i, ret;
+    libxl__remus_netbuf_ctx *netbuf_ctx = remus_ctx->netbuf_ctx;
+
+    for (i = 0; i < netbuf_ctx->num_netbufs; ++i) {
+        if (buffer_op == TC_BUFFER_START)
+            ret = rtnl_qdisc_plug_buffer(netbuf_ctx->netbuf_qdisc_list[i]);
+        else
+            ret = 
rtnl_qdisc_plug_release_one(netbuf_ctx->netbuf_qdisc_list[i]);
+
+        if (!ret)
+            ret = rtnl_qdisc_add(netbuf_ctx->nlsock,
+                                 netbuf_ctx->netbuf_qdisc_list[i],
+                                 NLM_F_REQUEST);
+        if (ret) {
+            LOG(ERROR, "Remus: cannot do netbuf op %s on %s:%s",
+                ((buffer_op == TC_BUFFER_START) ?
+                 "start_new_epoch" : "release_prev_epoch"),
+                netbuf_ctx->ifb_list[i], nl_geterror(ret));
+            return ERROR_FAIL;
+        }
+    }
+
+    return 0;
+}
+
+int libxl__remus_netbuf_start_new_epoch(libxl__gc *gc, uint32_t domid,
+                                       libxl__remus_ctx *remus_ctx)
+{
+    return remus_netbuf_op(gc, domid, remus_ctx, TC_BUFFER_START);
+}
+
+int libxl__remus_netbuf_release_prev_epoch(libxl__gc *gc, uint32_t domid,
+                                          libxl__remus_ctx *remus_ctx)
+{
+    return remus_netbuf_op(gc, domid, remus_ctx, TC_BUFFER_RELEASE);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 4d24d36d30c3 -r 4b23104828c0 tools/libxl/libxl_nonetbuffer.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_nonetbuffer.c   Sun Aug 25 16:33:29 2013 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2013
+ * Author Shriram Rajagopalan <rshriram@xxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h" /* must come before any other headers */
+
+#include "libxl_internal.h"
+
+/* Remus network buffer related stubs */
+int libxl__remus_netbuf_setup(libxl__gc *gc, uint32_t domid,
+                             libxl__remus_ctx *remus_ctx)
+{
+    LOG(ERROR, "Remus: No support for network buffering");
+    return ERROR_FAIL;
+}
+
+int libxl__remus_netbuf_teardown(libxl__gc *gc, uint32_t domid,
+                                libxl__remus_ctx *remus_ctx)
+{
+    return 0; /* No point complaining in a teardown call. */
+}
+
+int libxl__remus_netbuf_start_new_epoch(libxl__gc *gc, uint32_t domid,
+                                       libxl__remus_ctx *remus_ctx)
+{
+    LOG(ERROR, "Remus: No support for network buffering");
+    return ERROR_FAIL;
+}
+
+int libxl__remus_netbuf_release_prev_epoch(libxl__gc *gc, uint32_t domid,
+                                          libxl__remus_ctx *remus_ctx)
+{
+    LOG(ERROR, "Remus: No support for network buffering");
+    return ERROR_FAIL;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 4d24d36d30c3 -r 4b23104828c0 tools/libxl/libxl_types.idl
--- a/tools/libxl/libxl_types.idl       Sun Aug 25 16:33:27 2013 -0700
+++ b/tools/libxl/libxl_types.idl       Sun Aug 25 16:33:29 2013 -0700
@@ -526,6 +526,8 @@ libxl_domain_remus_info = Struct("domain
     ("interval",     integer),
     ("blackhole",    bool),
     ("compression",  bool),
+    ("netbuf",  bool),
+    ("netbufscript", string),
     ])
 
 libxl_event_type = Enumeration("event_type", [

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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