[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 |