Merge snmp stuff into mirror.git
authorMichael Spang <mspang@csclub.uwaterloo.ca>
Mon, 8 Mar 2010 00:29:49 +0000 (19:29 -0500)
committerMichael Spang <mspang@csclub.uwaterloo.ca>
Mon, 8 Mar 2010 00:30:25 +0000 (19:30 -0500)
1  2 
snmp/.gitignore
snmp/CSC-MIB.txt
snmp/Makefile
snmp/csc-snmp-subagent.c
snmp/mirror-mib.c
snmp/mirror-mib.h
snmp/mirror-nl-glue.c
snmp/mirror-nl-glue.h
snmp/mirror-stats.c

diff --cc snmp/.gitignore
index 0000000,0000000..1792b04
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,3 @@@
++/csc-snmp-subagent
++/mirror-stats
++*.o
index 0000000,0000000..97a314d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,46 @@@
++CSC-MIB DEFINITIONS ::= BEGIN
++
++IMPORTS
++    MODULE-IDENTITY, OBJECT-TYPE, Counter32, Gauge32, Counter64,
++    Integer32, TimeTicks, mib-2, enterprises,
++    NOTIFICATION-TYPE                        FROM SNMPv2-SMI
++    TEXTUAL-CONVENTION, DisplayString,
++    PhysAddress, TruthValue, RowStatus,
++    TimeStamp, AutonomousType, TestAndIncr   FROM SNMPv2-TC
++    MODULE-COMPLIANCE, OBJECT-GROUP,
++    NOTIFICATION-GROUP                       FROM SNMPv2-CONF
++    snmpTraps                                FROM SNMPv2-MIB
++    IANAifType                               FROM IANAifType-MIB;
++
++csclub OBJECT IDENTIFIER ::= { enterprises 27934 }
++
++cscMIB MODULE-IDENTITY
++    LAST-UPDATED "200905080000Z"
++    ORGANIZATION "University of Waterloo Computer Science Club"
++    CONTACT-INFO "systems-committee@csclub.uwaterloo.ca"
++    DESCRIPTION  "Computer Science Club Local MIBs"
++    REVISION     "200905080000Z"
++    DESCRIPTION  "Initial revision"
++    ::= { csclub 2 }
++
++mirror OBJECT IDENTIFIER ::= { cscMIB 2 }
++
++cogentBytes OBJECT-TYPE
++    SYNTAX      Counter64
++    MAX-ACCESS  read-only
++    STATUS      current
++    ::= { mirror 1 }
++
++orionBytes OBJECT-TYPE
++    SYNTAX      Counter64
++    MAX-ACCESS  read-only
++    STATUS      current
++    ::= { mirror 2 }
++
++campusBytes OBJECT-TYPE
++    SYNTAX      Counter64
++    MAX-ACCESS  read-only
++    STATUS      current
++    ::= { mirror 3 }
++
++END
diff --cc snmp/Makefile
index 0000000,0000000..ae0ec1d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,11 @@@
++LDFLAGS := -lnl $(shell net-snmp-config --base-agent-libs)
++CFLAGS := -g3 -O2 -Wall
++
++all: mirror-stats csc-snmp-subagent
++
++mirror-stats: mirror-stats.o mirror-nl-glue.o
++
++csc-snmp-subagent: csc-snmp-subagent.o mirror-mib.o mirror-nl-glue.o
++
++clean:
++      rm -f *.o mirror-stats csc-snmp-subagent
index 0000000,0000000..103760b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,221 @@@
++/* generated from net-snmp-config */
++#include <net-snmp/net-snmp-config.h>
++#ifdef HAVE_SIGNAL
++#include <signal.h>
++#endif /* HAVE_SIGNAL */
++#include <net-snmp/net-snmp-includes.h>
++#include <net-snmp/agent/net-snmp-agent-includes.h>
++  #include "mirror-mib.h"
++const char *app_name = "cscMIB";
++
++extern int netsnmp_running;
++
++#ifdef __GNUC__
++#define UNUSED __attribute__((unused))
++#else
++#define UNUSED
++#endif
++
++RETSIGTYPE
++stop_server(UNUSED int a) {
++    netsnmp_running = 0;
++}
++
++static void
++usage(const char *prog)
++{
++    fprintf(stderr,
++            "USAGE: %s [OPTIONS]\n"
++            "\n"
++            "OPTIONS:\n", prog);
++
++    fprintf(stderr,
++            "  -d\t\t\tdump all traffic\n"
++            "  -D TOKEN[,...]\tturn on debugging output for the specified "
++            "TOKENs\n"
++            "\t\t\t   (ALL gives extremely verbose debugging output)\n"
++            "  -f\t\t\tDo not fork() from the calling shell.\n"
++            "  -h\t\t\tdisplay this help message\n"
++            "  -H\t\t\tdisplay a list of configuration file directives\n"
++            "  -L LOGOPTS\t\tToggle various defaults controlling logging:\n");
++    snmp_log_options_usage("\t\t\t  ", stderr);
++#ifndef DISABLE_MIB_LOADING
++    fprintf(stderr,
++            "  -m MIB[:...]\t\tload given list of MIBs (ALL loads "
++            "everything)\n"
++            "  -M DIR[:...]\t\tlook in given list of directories for MIBs\n");
++#endif /* DISABLE_MIB_LOADING */
++#ifndef DISABLE_MIB_LOADING
++    fprintf(stderr,
++            "  -P MIBOPTS\t\tToggle various defaults controlling mib "
++            "parsing:\n");
++    snmp_mib_toggle_options_usage("\t\t\t  ", stderr);
++#endif /* DISABLE_MIB_LOADING */
++    fprintf(stderr,
++            "  -v\t\t\tdisplay package version number\n"
++            "  -x TRANSPORT\tconnect to master agent using TRANSPORT\n");
++    exit(1);
++}
++
++static void
++version(void)
++{
++    fprintf(stderr, "NET-SNMP version: %s\n", netsnmp_get_version());
++    exit(0);
++}
++
++int
++main (int argc, char **argv)
++{
++  int arg;
++  char* cp = NULL;
++  int dont_fork = 0, do_help = 0;
++
++  while ((arg = getopt(argc, argv, "dD:fhHL:"
++#ifndef DISABLE_MIB_LOADING
++                       "m:M:"
++#endif /* DISABLE_MIB_LOADING */
++                       "n:"
++#ifndef DISABLE_MIB_LOADING
++                       "P:"
++#endif /* DISABLE_MIB_LOADING */
++                       "vx:")) != EOF) {
++    switch (arg) {
++    case 'd':
++      netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
++                             NETSNMP_DS_LIB_DUMP_PACKET, 1);
++      break;
++
++    case 'D':
++      debug_register_tokens(optarg);
++      snmp_set_do_debugging(1);
++      break;
++
++    case 'f':
++      dont_fork = 1;
++      break;
++
++    case 'h':
++      usage(argv[0]);
++      break;
++
++    case 'H':
++      do_help = 1;
++      break;
++
++    case 'L':
++      if (snmp_log_options(optarg, argc, argv) < 0) {
++        exit(1);
++      }
++      break;
++
++#ifndef DISABLE_MIB_LOADING
++    case 'm':
++      if (optarg != NULL) {
++        setenv("MIBS", optarg, 1);
++      } else {
++        usage(argv[0]);
++      }
++      break;
++
++    case 'M':
++      if (optarg != NULL) {
++        setenv("MIBDIRS", optarg, 1);
++      } else {
++        usage(argv[0]);
++      }
++      break;
++#endif /* DISABLE_MIB_LOADING */
++
++    case 'n':
++      if (optarg != NULL) {
++        app_name = optarg;
++        netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
++                              NETSNMP_DS_LIB_APPTYPE, app_name);
++      } else {
++        usage(argv[0]);
++      }
++      break;
++
++#ifndef DISABLE_MIB_LOADING
++    case 'P':
++      cp = snmp_mib_toggle_options(optarg);
++      if (cp != NULL) {
++        fprintf(stderr, "Unknown parser option to -P: %c.\n", *cp);
++        usage(argv[0]);
++      }
++      break;
++#endif /* DISABLE_MIB_LOADING */
++
++    case 'v':
++      version();
++      break;
++
++    case 'x':
++      if (optarg != NULL) {
++        netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
++                              NETSNMP_DS_AGENT_X_SOCKET, optarg);
++      } else {
++        usage(argv[0]);
++      }
++      break;
++
++    default:
++      fprintf(stderr, "invalid option: -%c\n", arg);
++      usage(argv[0]);
++      break;
++    }
++  }
++
++  if (do_help) {
++    netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
++                           NETSNMP_DS_AGENT_NO_ROOT_ACCESS, 1);
++  } else {
++    /* we are a subagent */
++    netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
++                           NETSNMP_DS_AGENT_ROLE, 1);
++
++    if (!dont_fork) {
++      if (netsnmp_daemonize(1, snmp_stderrlog_status()) != 0)
++        exit(1);
++    }
++
++    /* initialize tcpip, if necessary */
++    SOCK_STARTUP;
++  }
++
++  /* initialize the agent library */
++  init_agent(app_name);
++
++  /* initialize your mib code here */
++  init_mirror_mib();
++
++  /* cscMIB will be used to read cscMIB.conf files. */
++  init_snmp("cscMIB");
++
++  if (do_help) {
++    fprintf(stderr, "Configuration directives understood:\n");
++    read_config_print_usage("  ");
++    exit(0);
++  }
++
++  /* In case we received a request to stop (kill -TERM or kill -INT) */
++  netsnmp_running = 1;
++#ifdef SIGTERM
++  signal(SIGTERM, stop_server);
++#endif
++#ifdef SIGINT
++  signal(SIGINT, stop_server);
++#endif
++
++  /* main loop here... */
++  while(netsnmp_running) {
++    agent_check_and_process(1);
++  }
++
++  /* at shutdown time */
++  snmp_shutdown(app_name);
++  SOCK_CLEANUP;
++  exit(0);
++}
++
index 0000000,0000000..4cd7e87
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,109 @@@
++/*
++ * Note: this file originally auto-generated by mib2c using
++ *        : mib2c.scalar.conf 11805 2005-01-07 09:37:18Z dts12 $
++ */
++
++#include <net-snmp/net-snmp-config.h>
++#include <net-snmp/net-snmp-includes.h>
++#include <net-snmp/agent/net-snmp-agent-includes.h>
++#include "mirror-mib.h"
++#include "mirror-nl-glue.h"
++
++void
++init_mirror_mib(void)
++{
++    static oid      cogentBytes_oid[] =
++        { 1, 3, 6, 1, 4, 1, 27934, 2, 2, 1 };
++    static oid      orionBytes_oid[] =
++        { 1, 3, 6, 1, 4, 1, 27934, 2, 2, 2 };
++    static oid      campusBytes_oid[] =
++        { 1, 3, 6, 1, 4, 1, 27934, 2, 2, 3 };
++
++    DEBUGMSGTL(("mirror_mib", "Initializing\n"));
++
++    mirror_stats_initialize();
++
++    netsnmp_register_scalar(netsnmp_create_handler_registration
++                            ("cogentBytes", handle_cogentBytes,
++                             cogentBytes_oid, OID_LENGTH(cogentBytes_oid),
++                             HANDLER_CAN_RONLY));
++    netsnmp_register_scalar(netsnmp_create_handler_registration
++                            ("orionBytes", handle_orionBytes,
++                             orionBytes_oid, OID_LENGTH(orionBytes_oid),
++                             HANDLER_CAN_RONLY));
++    netsnmp_register_scalar(netsnmp_create_handler_registration
++                            ("campusBytes", handle_campusBytes,
++                             campusBytes_oid, OID_LENGTH(campusBytes_oid),
++                             HANDLER_CAN_RONLY));
++}
++
++void explode_counter64(uint64_t num, struct counter64 *counter) {
++    counter->low = num & 0xFFFFFFFF;
++    counter->high = (num >> 32) & 0xFFFFFFFF;
++}
++
++int
++handle_cogentBytes(netsnmp_mib_handler *handler,
++                   netsnmp_handler_registration *reginfo,
++                   netsnmp_agent_request_info *reqinfo,
++                   netsnmp_request_info *requests)
++{
++    struct counter64 counter;
++    mirror_stats_refresh();
++    explode_counter64(get_class_byte_count(&cogent_class), &counter);
++
++    switch (reqinfo->mode) {
++        case MODE_GET:
++            snmp_set_var_typed_value(requests->requestvb, ASN_COUNTER64,
++                    (u_char *)&counter, sizeof(counter));
++            break;
++        default:
++            die("unknown mode");
++    }
++
++    return SNMP_ERR_NOERROR;
++}
++
++int
++handle_orionBytes(netsnmp_mib_handler *handler,
++                  netsnmp_handler_registration *reginfo,
++                  netsnmp_agent_request_info *reqinfo,
++                  netsnmp_request_info *requests)
++{
++    struct counter64 counter;
++    mirror_stats_refresh();
++    explode_counter64(get_class_byte_count(&orion_class), &counter);
++
++    switch (reqinfo->mode) {
++        case MODE_GET:
++            snmp_set_var_typed_value(requests->requestvb, ASN_COUNTER64,
++                    (u_char *)&counter, sizeof(counter));
++            break;
++        default:
++            die("unknown mode");
++    }
++
++    return SNMP_ERR_NOERROR;
++}
++
++int
++handle_campusBytes(netsnmp_mib_handler *handler,
++                   netsnmp_handler_registration *reginfo,
++                   netsnmp_agent_request_info *reqinfo,
++                   netsnmp_request_info *requests)
++{
++    struct counter64 counter;
++    mirror_stats_refresh();
++    explode_counter64(get_class_byte_count(&campus_class), &counter);
++
++    switch (reqinfo->mode) {
++        case MODE_GET:
++            snmp_set_var_typed_value(requests->requestvb, ASN_COUNTER64,
++                    (u_char *)&counter, sizeof(counter));
++            break;
++        default:
++            die("unknown mode");
++    }
++
++    return SNMP_ERR_NOERROR;
++}
index 0000000,0000000..f707f97
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,9 @@@
++#ifndef MIRRORMIB_H
++#define MIRRORMIB_H
++
++void            init_mirror_mib(void);
++Netsnmp_Node_Handler handle_cogentBytes;
++Netsnmp_Node_Handler handle_orionBytes;
++Netsnmp_Node_Handler handle_campusBytes;
++
++#endif
index 0000000,0000000..720ac6a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,102 @@@
++#include <unistd.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <inttypes.h>
++#include <libgen.h>
++#include <netlink/route/class.h>
++#include <netlink/route/link.h>
++#include <netlink/cache-api.h>
++#include <netlink/object.h>
++#include "mirror-nl-glue.h"
++
++static struct nl_cache *link_cache, *class_cache;
++static struct rtnl_link *eth;
++static int ifindex;
++
++struct class_info cogent_class = { "cogent", "01:02", };
++struct class_info orion_class  = { "orion",  "01:03", };
++struct class_info campus_class = { "campus", "01:04", };
++
++static struct nl_handle *nl_handle;
++
++void die(const char *message) {
++    fprintf(stderr, "fatal: %s\n", message);
++    exit(1);
++}
++
++static void match_obj(struct nl_object *obj, void *arg) {
++    struct nl_object *needle = *(struct nl_object **)arg;
++    struct nl_object **ret = (struct nl_object **)arg + 1;
++
++    if (!*ret && nl_object_identical(obj, needle)) {
++        nl_object_get(obj);
++        *ret = obj;
++    }
++}
++
++static struct rtnl_class *get_class_by_id(char *id, int ifindex) {
++    uint32_t handle;
++    struct rtnl_class *needle;
++    struct nl_object *magic[2];
++
++    if (rtnl_tc_str2handle(id, &handle))
++        die("invalid id");
++
++    needle = rtnl_class_alloc();
++    rtnl_class_set_ifindex(needle, ifindex);
++    rtnl_class_set_handle(needle, handle);
++
++    magic[0] = (struct nl_object *)needle;
++    magic[1] = (struct nl_object *)NULL;
++
++    nl_cache_foreach(class_cache, match_obj, magic);
++
++    rtnl_class_put(needle);
++    return (struct rtnl_class *)magic[1];
++}
++
++uint64_t get_class_byte_count(struct class_info *info) {
++    struct rtnl_class *class = get_class_by_id(info->id, ifindex);
++    uint64_t bytes;
++    if (!class)
++        die("class not found");
++    bytes = rtnl_class_get_stat(class, RTNL_TC_BYTES);
++    rtnl_class_put(class);
++    return bytes;
++}
++
++void mirror_stats_refresh(void) {
++    nl_cache_refill(nl_handle, class_cache);
++}
++
++void mirror_stats_initialize(void) {
++    nl_handle = nl_handle_alloc();
++    if (!nl_handle)
++        die("unable to allocate handle");
++
++    if (nl_connect(nl_handle, NETLINK_ROUTE) < 0)
++        die("unable to connect to netlink");
++
++    link_cache = rtnl_link_alloc_cache(nl_handle);
++    if (!link_cache)
++        die("unable to allocate link cache");
++
++    eth = rtnl_link_get_by_name(link_cache, "eth0");
++    if (!eth)
++        die("unable to acquire eth0");
++    ifindex = rtnl_link_get_ifindex(eth);
++
++    class_cache = rtnl_class_alloc_cache(nl_handle, ifindex);
++    if (!class_cache)
++        die("unable to allocate class cache");
++}
++
++void mirror_stats_cleanup(void) {
++    rtnl_link_put(eth);
++    nl_cache_free(class_cache);
++    nl_cache_free(link_cache);
++    nl_close(nl_handle);
++    nl_handle_destroy(nl_handle);
++}
++
index 0000000,0000000..53add1a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,25 @@@
++#include <unistd.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <inttypes.h>
++#include <libgen.h>
++#include <netlink/route/class.h>
++#include <netlink/route/link.h>
++#include <netlink/cache-api.h>
++#include <netlink/object.h>
++
++struct class_info {
++    char *name;
++    char *id;
++};
++
++extern struct class_info cogent_class;
++extern struct class_info orion_class;
++extern struct class_info campus_class;
++
++void mirror_stats_refresh(void);
++void mirror_stats_initialize(void);
++void mirror_stats_cleanup(void);
++void die(const char *);
++uint64_t get_class_byte_count(struct class_info *);
index 0000000,0000000..44bade4
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,12 @@@
++#include "mirror-nl-glue.h"
++
++int main(int argc, char *argv[]) {
++    mirror_stats_initialize();
++    for (;;) {
++        printf("%s %"PRIu64"\n", cogent_class.id, get_class_byte_count(&cogent_class));
++        printf("%s %"PRIu64"\n", orion_class.id, get_class_byte_count(&orion_class));
++        printf("%s %"PRIu64"\n", campus_class.id, get_class_byte_count(&campus_class));
++        sleep(1);
++        mirror_stats_refresh();
++    }
++}