summaryrefslogtreecommitdiffstats
path: root/lib/cli
diff options
context:
space:
mode:
authorShriram Rajagopalan <rshriram@cs.ubc.ca>2012-02-12 22:53:10 (GMT)
committerThomas Graf <tgraf@redhat.com>2012-02-14 11:02:04 (GMT)
commita17970b974bb3896f253817f98a9fa6176fcd422 (patch)
tree030e758db546ae0539a810c8eda3ac3468e5afef /lib/cli
parenta39bb563ab8450d5463540384f4b8abca0d3755e (diff)
downloadlibnl-a17970b974bb3896f253817f98a9fa6176fcd422.zip
libnl-a17970b974bb3896f253817f98a9fa6176fcd422.tar.gz
libnl-a17970b974bb3896f253817f98a9fa6176fcd422.tar.bz2
Support plug qdisc - queue traffic until explicit release
The plug qdisc supports two operations - plug and unplug. When the qdisc receives a plug ("buffer") command via netlink request, packets arriving henceforth are buffered until a corresponding unplug command is received. Depending on the type of unplug ("release_one" or "release_indefinite"), the queue can be unplugged indefinitely or selectively. The plug qdisc allows a user to implement network output buffering (aka output commit), used commonly in checkpoint based fault tolerance systems. It also supports a general purpose queue plug/unplug functionality. The associated kernel module is available in David Miller's net-next tree, commit: c3059be16c9ef29c05f0876a9df5fea21f29724f This patch introduces userspace tools and API, to control the qdisc via netlink messages. Signed-off-by: Shriram Rajagopalan <rshriram@cs.ubc.ca> Signed-off-by: Thomas Graf <tgraf@redhat.com>
Diffstat (limited to 'lib/cli')
-rw-r--r--lib/cli/qdisc/plug.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/lib/cli/qdisc/plug.c b/lib/cli/qdisc/plug.c
new file mode 100644
index 0000000..2b8d5d6
--- /dev/null
+++ b/lib/cli/qdisc/plug.c
@@ -0,0 +1,113 @@
+
+/*
+ * src/lib/cli/qdisc/plug.c plug module for CLI lib
+ *
+ * This library 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
+ * of the License.
+ *
+ * Copyright (c) 2012 Shriram Rajagopalan <rshriram@cs.ubc.ca>
+ */
+
+#include <netlink/cli/utils.h>
+#include <netlink/cli/tc.h>
+#include <netlink/route/qdisc/plug.h>
+
+static void print_usage(void)
+{
+ printf(
+"Usage: nl-qdisc-add [...] plug [OPTIONS]...\n"
+"\n"
+"OPTIONS\n"
+" --help Show this help text.\n"
+" --limit Maximum queue length in bytes.\n"
+" --buffer create a new buffer(plug) and queue incoming traffic into it.\n"
+" --release-one release traffic from previous buffer.\n"
+" --release-indefinite stop buffering and release all (buffered and new) packets.\n"
+"\n"
+"EXAMPLE"
+" # Attach plug qdisc with 32KB queue size to ifb0\n"
+" nl-qdisc-add --dev=ifb0 --parent=root plug --limit=32768\n"
+" # Plug network traffic arriving at ifb0\n"
+" nl-qdisc-add --dev=ifb0 --parent=root --update plug --buffer\n"
+" # Unplug traffic arriving at ifb0 indefinitely\n"
+" nl-qdisc-add --dev=ifb0 --parent=root --update plug --release-indefinite\n\n"
+" # If operating in output buffering mode:\n"
+" # at time t=t0, create a new output buffer b0 to hold network output\n"
+" nl-qdisc-add --dev=ifb0 --parent=root --update plug --buffer\n\n"
+" # at time t=t1, take a checkpoint c0, create a new output buffer b1\n"
+" nl-qdisc-add --dev=ifb0 --parent=root --update plug --buffer\n"
+" # at time t=t1+r, after c0 is committed, release b0\n"
+" nl-qdisc-add --dev=ifb0 --parent=root --update plug --release-one\n\n"
+" # at time t=t2, take a checkpoint c1, create a new output buffer b2\n"
+" nl-qdisc-add --dev=ifb0 --parent=root --update plug --buffer\n"
+" # at time t=t2+r, after c1 is committed, release b1\n"
+" nl-qdisc-add --dev=ifb0 --parent=root --update plug --release-one\n");
+}
+
+static void plug_parse_argv(struct rtnl_tc *tc, int argc, char **argv)
+{
+ struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc;
+
+ for (;;) {
+ int c, optidx = 0;
+ enum {
+ ARG_LIMIT = 257,
+ ARG_BUFFER = 258,
+ ARG_RELEASE_ONE = 259,
+ ARG_RELEASE_INDEFINITE = 260,
+ };
+ static struct option long_opts[] = {
+ { "help", 0, 0, 'h' },
+ { "limit", 1, 0, ARG_LIMIT },
+ { "buffer", 0, 0, ARG_BUFFER },
+ { "release-one", 0, 0, ARG_RELEASE_ONE },
+ { "release-indefinite", 0, 0, ARG_RELEASE_INDEFINITE },
+ { 0, 0, 0, 0 }
+ };
+
+ c = getopt_long(argc, argv, "h", long_opts, &optidx);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_usage();
+ return;
+
+ case ARG_LIMIT:
+ rtnl_qdisc_plug_set_limit(qdisc, nl_cli_parse_u32(optarg));
+ break;
+
+ case ARG_BUFFER:
+ rtnl_qdisc_plug_buffer(qdisc);
+ break;
+
+ case ARG_RELEASE_ONE:
+ rtnl_qdisc_plug_release_one(qdisc);
+ break;
+
+ case ARG_RELEASE_INDEFINITE:
+ rtnl_qdisc_plug_release_indefinite(qdisc);
+ break;
+ }
+ }
+}
+
+static struct nl_cli_tc_module plug_module =
+{
+ .tm_name = "plug",
+ .tm_type = RTNL_TC_TYPE_QDISC,
+ .tm_parse_argv = plug_parse_argv,
+};
+
+static void __init plug_init(void)
+{
+ nl_cli_tc_register(&plug_module);
+}
+
+static void __exit plug_exit(void)
+{
+ nl_cli_tc_unregister(&plug_module);
+}