summaryrefslogtreecommitdiffstats
path: root/src/in_dummy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/in_dummy.c')
-rw-r--r--src/in_dummy.c243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/in_dummy.c b/src/in_dummy.c
new file mode 100644
index 0000000..00eca82
--- /dev/null
+++ b/src/in_dummy.c
@@ -0,0 +1,243 @@
+/*
+ * in_dummy.c Dummy Input Method
+ *
+ * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2013 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <bmon/bmon.h>
+#include <bmon/input.h>
+#include <bmon/group.h>
+#include <bmon/element.h>
+#include <bmon/attr.h>
+#include <bmon/utils.h>
+
+#define MAXDEVS 32
+
+static uint64_t c_rx_b_inc = 1000000000;
+static uint64_t c_tx_b_inc = 80000000;
+static uint64_t c_rx_p_inc = 1000;
+static uint64_t c_tx_p_inc = 800;
+static int c_numdev = 5;
+static int c_randomize = 0;
+static int c_mtu = 1540;
+static int c_maxpps = 100000;
+static int c_numgroups = 2;
+
+static uint64_t *cnts;
+
+enum {
+ DUMMY_BYTES,
+ DUMMY_PACKETS,
+ NUM_DUMMY_VALUE,
+};
+
+static struct attr_map link_attrs[NUM_DUMMY_VALUE] = {
+{
+ .name = "bytes",
+ .type = ATTR_TYPE_COUNTER,
+ .unit = UNIT_BYTE,
+ .description = "Bytes",
+},
+{
+ .name = "packets",
+ .type = ATTR_TYPE_COUNTER,
+ .unit = UNIT_NUMBER,
+ .description = "Packtes",
+}
+};
+
+/* cnts[ngroups][ndevs][2][2] */
+
+static inline int cnt_size(void)
+{
+ return c_numgroups * c_numdev * 2 * 2;
+}
+
+static inline uint64_t *cnt(int group, int dev, int unit,
+ int direction)
+{
+ return cnts + (group * c_numdev * 2 * 2) +
+ (dev * 2 * 2) +
+ (unit * 2) +
+ direction;
+}
+
+static void dummy_read(void)
+{
+ int gidx, n;
+
+ for (gidx = 0; gidx < c_numgroups; gidx++) {
+ char gname[32];
+ struct element_group *group;
+
+ snprintf(gname, sizeof(gname), "group%02d", gidx);
+ group = group_lookup(gname, GROUP_CREATE);
+
+ for (n = 0; n < c_numdev; n++) {
+ char ifname[IFNAMSIZ];
+ struct element *e;
+ int i;
+
+ snprintf(ifname, sizeof(ifname), "dummy%d", n);
+
+ if (!(e = element_lookup(group, ifname, 0, NULL, ELEMENT_CREAT)))
+ return;
+
+ if (e->e_flags & ELEMENT_FLAG_CREATED) {
+ if (element_set_key_attr(e, "bytes", "packets") ||
+ element_set_usage_attr(e, "bytes"))
+ BUG();
+ e->e_flags &= ~ELEMENT_FLAG_CREATED;
+ }
+
+ if (e->e_flags & ELEMENT_FLAG_UPDATED)
+ continue;
+
+ if (c_randomize) {
+ uint64_t rx = rand() % c_maxpps;
+ uint64_t tx = rand() % c_maxpps;
+
+ *cnt(gidx, n, 0, 0) += rx;
+ *cnt(gidx, n, 0, 1) += tx;
+ *cnt(gidx, n, 1, 0) += rx * (rand() % c_mtu);
+ *cnt(gidx, n, 1, 1) += tx * (rand() % c_mtu);
+ } else {
+ *cnt(gidx, n, 0, 0) += c_rx_p_inc;
+ *cnt(gidx, n, 0, 1) += c_tx_p_inc;
+ *cnt(gidx, n, 1, 0) += c_rx_b_inc;
+ *cnt(gidx, n, 1, 1) += c_tx_b_inc;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(link_attrs); i++) {
+ struct attr_map *m = &link_attrs[i];
+
+ attr_update(e, m->attrid,
+ *cnt(gidx, n, i, 0),
+ *cnt(gidx, n, i, 1),
+ UPDATE_FLAG_RX | UPDATE_FLAG_TX |
+ UPDATE_FLAG_64BIT);
+ }
+
+ element_notify_update(e, NULL);
+ element_lifesign(e, 1);
+ }
+ }
+}
+
+static void print_help(void)
+{
+ printf(
+ "dummy - Statistic generator module (dummy)\n" \
+ "\n" \
+ " Basic statistic generator for testing purposes. Can produce a\n" \
+ " constant or random statistic flow with configurable parameters.\n" \
+ " Author: Thomas Graf <tgraf@suug.ch>\n" \
+ "\n" \
+ " Options:\n" \
+ " rxb=NUM RX bytes increment amount (default: 10^9)\n" \
+ " txb=NUM TX bytes increment amount (default: 8*10^7)\n" \
+ " rxp=NUM RX packets increment amount (default: 1K)\n" \
+ " txp=NUM TX packets increment amount (default: 800)\n" \
+ " num=NUM Number of devices (default: 5)\n" \
+ " numgroups=NUM Number of groups (default: 2)\n" \
+ " randomize Randomize counters (default: off)\n" \
+ " seed=NUM Seed for randomizer (default: time(0))\n" \
+ " mtu=NUM Maximal Transmission Unit (default: 1540)\n" \
+ " maxpps=NUM Upper limit for packets per second (default: 100K)\n" \
+ "\n" \
+ " Randomizer:\n" \
+ " RX-packets := Rand() %% maxpps\n" \
+ " TX-packets := Rand() %% maxpps\n" \
+ " RX-bytes := RX-packets * (Rand() %% mtu)\n" \
+ " TX-bytes := TX-packets * (Rand() %% mtu)\n");
+}
+
+static void dummy_parse_opt(const char *value, const char *type)
+{
+ if (!strcasecmp(type, "rxb") && value)
+ c_rx_b_inc = strtol(value, NULL, 0);
+ else if (!strcasecmp(type, "txb") && value)
+ c_tx_b_inc = strtol(value, NULL, 0);
+ else if (!strcasecmp(type, "rxp") && value)
+ c_rx_p_inc = strtol(value, NULL, 0);
+ else if (!strcasecmp(type, "txp") && value)
+ c_tx_p_inc = strtol(value, NULL, 0);
+ else if (!strcasecmp(type, "num") && value)
+ c_numdev = strtol(value, NULL, 0);
+ else if (!strcasecmp(type, "randomize")) {
+ c_randomize = 1;
+ srand(time(0));
+ } else if (!strcasecmp(type, "seed") && value)
+ srand(strtol(value, NULL, 0));
+ else if (!strcasecmp(type, "mtu") && value)
+ c_mtu = strtol(value, NULL, 0);
+ else if (!strcasecmp(type, "maxpps") && value)
+ c_maxpps = strtol(value, NULL, 0);
+ else if (!strcasecmp(type, "numgroups") && value)
+ c_numgroups = strtol(value, NULL, 0);
+ else if (!strcasecmp(type, "help")) {
+ print_help();
+ exit(0);
+ }
+}
+
+static int dummy_do_init(void)
+{
+ if (attr_map_load(link_attrs, ARRAY_SIZE(link_attrs)))
+ BUG();
+
+ return 0;
+}
+
+static int dummy_probe(void)
+{
+ int i;
+
+ if (c_numdev >= MAXDEVS) {
+ fprintf(stderr, "numdev must be in range 0..%d\n", MAXDEVS);
+ return 0;
+ }
+
+ cnts = xcalloc(cnt_size(), sizeof(uint64_t));
+
+ for (i = 0; i < c_numgroups; i++) {
+ char groupname[32];
+ snprintf(groupname, sizeof(groupname), "group%02d", i);
+
+ group_new_derived_hdr(groupname, groupname, DEFAULT_GROUP);
+ }
+
+ return 1;
+}
+
+static struct bmon_module dummy_ops = {
+ .m_name = "dummy",
+ .m_do = dummy_read,
+ .m_parse_opt = dummy_parse_opt,
+ .m_probe = dummy_probe,
+ .m_init = dummy_do_init,
+};
+
+static void __init dummy_init(void)
+{
+ input_register(&dummy_ops);
+}