Add stats message that allows querying description of components in OpenFlow.
authorJustin Pettit <jpettit@nicira.com>
Sat, 16 Aug 2008 16:43:05 +0000 (09:43 -0700)
committerJustin Pettit <jpettit@nicira.com>
Sat, 16 Aug 2008 16:43:05 +0000 (09:43 -0700)
datapath/datapath.c
include/openflow.h
lib/ofp-print.c
switch/datapath.c
switch/switch.c
utilities/dpctl.c

index 5b59676..7c26493 100644 (file)
 #include "compat.h"
 
 
+/* Strings to describe the manufacturer, hardware, and software.  This data 
+ * is queriable through the version stats message. */
+static char mfr_desc[VERSION_STR_LEN] = "Nicira Networks";
+static char hw_desc[VERSION_STR_LEN] = "Reference Linux Kernel Module";
+static char sw_desc[VERSION_STR_LEN] = VERSION;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+module_param_string(mfr_desc, mfr_desc, sizeof mfr_desc, 0444);
+module_param_string(hw_desc, hw_desc, sizeof hw_desc, 0444);
+module_param_string(sw_desc, sw_desc, sizeof sw_desc, 0444);
+#else
+MODULE_PARM(mfr_desc, "s");
+MODULE_PARM(hw_desc, "s");
+MODULE_PARM(sw_desc, "s");
+#endif
+
+
 /* Number of milliseconds between runs of the maintenance thread. */
 #define MAINT_SLEEP_MSECS 1000
 
@@ -1079,6 +1096,24 @@ static struct nla_policy dp_genl_openflow_policy[DP_GENL_A_MAX + 1] = {
        [DP_GENL_A_DP_IDX] = { .type = NLA_U32 },
 };
 
+static int version_stats_dump(struct datapath *dp, void *state,
+                           void *body, int *body_len)
+{
+       struct ofp_version_stats *ovs = body;
+       int n_bytes = sizeof *ovs;
+
+       if (n_bytes > *body_len) {
+               return -ENOBUFS;
+       }
+       *body_len = n_bytes;
+
+       strncpy(ovs->mfr_desc, mfr_desc, sizeof ovs->mfr_desc);
+       strncpy(ovs->hw_desc, hw_desc, sizeof ovs->hw_desc);
+       strncpy(ovs->sw_desc, sw_desc, sizeof ovs->sw_desc);
+
+       return 0;
+}
+
 struct flow_stats_state {
        int table_idx;
        struct sw_table_position position;
@@ -1350,6 +1385,13 @@ struct stats_type {
 };
 
 static const struct stats_type stats[] = {
+       [OFPST_VERSION] = {
+               0,
+               0,
+               NULL,
+               version_stats_dump,
+               NULL
+       },
        [OFPST_FLOW] = {
                sizeof(struct ofp_flow_stats_request),
                sizeof(struct ofp_flow_stats_request),
index ba25687..cd21673 100644 (file)
@@ -424,6 +424,11 @@ struct ofp_error_msg {
 OFP_ASSERT(sizeof(struct ofp_error_msg) == 12);
 
 enum ofp_stats_types {
+    /* Description of this OpenFlow switch. 
+     * The request body is empty.
+     * The reply body is struct ofp_version_stats. */
+    OFPST_VERSION,
+
     /* Individual flow statistics.
      * The request body is struct ofp_flow_stats_request.
      * The reply body is an array of struct ofp_flow_stats. */
@@ -465,6 +470,16 @@ struct ofp_stats_reply {
 };
 OFP_ASSERT(sizeof(struct ofp_stats_reply) == 12);
 
+#define VERSION_STR_LEN 256
+/* Body of reply to OFPST_VERSION request.  Each entry is a NULL-terminated 
+ * ASCII string. */
+struct ofp_version_stats {
+    char mfr_desc[VERSION_STR_LEN];  /* Manufacturer description. */
+    char hw_desc[VERSION_STR_LEN];   /* Hardware description. */
+    char sw_desc[VERSION_STR_LEN];   /* Software description. */
+};
+OFP_ASSERT(sizeof(struct ofp_version_stats) == 768);
+
 /* Body for ofp_stats_request of type OFPST_FLOW. */
 struct ofp_flow_stats_request {
     struct ofp_match match;   /* Fields to match */
@@ -522,7 +537,7 @@ struct ofp_table_stats {
 };
 OFP_ASSERT(sizeof(struct ofp_table_stats) == 56);
 
-/* Statistics about a particular port.  If a counter is unsupported, set
+/* Body of reply to OFPST_PORT request. If a counter is unsupported, set
  * the field to all ones. */
 struct ofp_port_stats {
     uint16_t port_no;
index 01e49b7..1f05675 100644 (file)
@@ -557,6 +557,17 @@ ofp_print_port_status(struct ds *string, const void *oh, size_t len,
     ofp_print_phy_port(string, &ops->desc);
 }
 
+static void
+ofp_version_stats_reply(struct ds *string, const void *body, size_t len,
+                     int verbosity)
+{
+    const struct ofp_version_stats *vs = body;
+
+    ds_put_format(string, "Manufacturer: %s\n", vs->mfr_desc);
+    ds_put_format(string, "Hardware: %s\n", vs->hw_desc);
+    ds_put_format(string, "Software: %s\n", vs->sw_desc);
+}
+
 static void
 ofp_flow_stats_request(struct ds *string, const void *oh, size_t len,
                       int verbosity) 
@@ -750,6 +761,11 @@ print_stats(struct ds *string, int type, const void *body, size_t body_len,
     };
 
     static const struct stats_type stats_types[] = {
+        [OFPST_VERSION] = {
+            "version",
+            { 0, 0, NULL },
+            { 0, SIZE_MAX, ofp_version_stats_reply },
+        },
         [OFPST_FLOW] = {
             "flow",
             { sizeof(struct ofp_flow_stats_request),
index 4e7b625..f9f4a8d 100644 (file)
 
 #define BRIDGE_PORT_NO_FLOOD    0x00000001
 
+extern char mfr_desc;
+extern char hw_desc;
+extern char sw_desc;
+
 /* Capabilities supported by this implementation. */
 #define OFP_SUPPORTED_CAPABILITIES ( OFPC_FLOW_STATS \
         | OFPC_TABLE_STATS \
@@ -1155,6 +1159,18 @@ recv_flow(struct datapath *dp, const struct sender *sender UNUSED,
     }
 }
 
+static int version_stats_dump(struct datapath *dp, void *state,
+                              struct buffer *buffer)
+{
+    struct ofp_version_stats *ovs = buffer_put_uninit(buffer, sizeof *ovs);
+
+    strncpy(ovs->mfr_desc, &mfr_desc, sizeof ovs->mfr_desc);
+    strncpy(ovs->hw_desc, &hw_desc, sizeof ovs->hw_desc);
+    strncpy(ovs->sw_desc, &sw_desc, sizeof ovs->sw_desc);
+
+    return 0;
+}
+
 struct flow_stats_state {
     int table_idx;
     struct sw_table_position position;
@@ -1374,6 +1390,13 @@ struct stats_type {
 };
 
 static const struct stats_type stats[] = {
+    [OFPST_VERSION] = {
+        0,
+        0,
+        NULL,
+        version_stats_dump,
+        NULL
+    },
     [OFPST_FLOW] = {
         sizeof(struct ofp_flow_stats_request),
         sizeof(struct ofp_flow_stats_request),
index 3a9c604..61fbfb9 100644 (file)
 #define THIS_MODULE VLM_switch
 #include "vlog.h"
 
+
+/* Strings to describe the manufacturer, hardware, and software.  This data 
+ * is queriable through the version stats message. */
+char mfr_desc[VERSION_STR_LEN] = "Nicira Networks";
+char hw_desc[VERSION_STR_LEN] = "Reference User-Space Switch";
+char sw_desc[VERSION_STR_LEN] = VERSION;
+
 static void parse_options(int argc, char *argv[]);
 static void usage(void) NO_RETURN;
 
@@ -152,7 +159,10 @@ static void
 parse_options(int argc, char *argv[])
 {
     enum {
-        OPT_MAX_BACKOFF = UCHAR_MAX + 1
+        OPT_MAX_BACKOFF = UCHAR_MAX + 1,
+        OPT_MFR_DESC,
+        OPT_HW_DESC,
+        OPT_SW_DESC
     };
 
     static struct option long_options[] = {
@@ -165,6 +175,9 @@ parse_options(int argc, char *argv[])
         {"verbose",     optional_argument, 0, 'v'},
         {"help",        no_argument, 0, 'h'},
         {"version",     no_argument, 0, 'V'},
+        {"mfr-desc",    required_argument, 0, OPT_MFR_DESC},
+        {"hw-desc",     required_argument, 0, OPT_HW_DESC},
+        {"sw-desc",     required_argument, 0, OPT_SW_DESC},
         VCONN_SSL_LONG_OPTIONS
         {0, 0, 0, 0},
     };
@@ -228,6 +241,18 @@ parse_options(int argc, char *argv[])
             }
             break;
 
+        case OPT_MFR_DESC:
+            strncpy(mfr_desc, optarg, sizeof mfr_desc);
+            break;
+
+        case OPT_HW_DESC:
+            strncpy(hw_desc, optarg, sizeof hw_desc);
+            break;
+
+        case OPT_SW_DESC:
+            strncpy(sw_desc, optarg, sizeof sw_desc);
+            break;
+
         case 'l':
             if (listen_vconn_name) {
                 fatal(0, "-l or --listen may be only specified once");
index b074edd..f969412 100644 (file)
@@ -186,6 +186,7 @@ usage(void)
 #endif
            "\nFor local datapaths and remote switches:\n"
            "  show SWITCH                 show information\n"
+           "  dump-version SWITCH         print version information\n"
            "  dump-tables SWITCH          print table stats\n"
            "  dump-ports SWITCH           print port statistics\n"
            "  dump-flows SWITCH           print all flow entries\n"
@@ -388,6 +389,12 @@ do_show(int argc UNUSED, char *argv[])
 }
 
 
+static void
+do_dump_version(int argc, char *argv[])
+{
+    dump_trivial_stats_transaction(argv[1], OFPST_VERSION);
+}
+
 static void
 do_dump_tables(int argc, char *argv[])
 {
@@ -890,6 +897,7 @@ static struct command all_commands[] = {
 
     { "help", 0, INT_MAX, do_help },
     { "monitor", 1, 1, do_monitor },
+    { "dump-version", 1, 1, do_dump_version },
     { "dump-tables", 1, 1, do_dump_tables },
     { "dump-flows", 1, 2, do_dump_flows },
     { "dump-aggregate", 1, 2, do_dump_aggregate },