|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 3 of 5] tools/libxl: setup/teardown Remus network buffering
On 26/08/2013 00:45, rshriram@xxxxxxxxx wrote:
> # 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)
This can be reduced to:
if (dss->remus_ctx && dss->remus_ctx->compression)
~Andrew
> 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
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |