From bffc058934d43fb5a2c8629ee914a949ddf80c8e Mon Sep 17 00:00:00 2001 From: Andrew Evans Date: Fri, 21 Jan 2011 11:01:45 -0800 Subject: [PATCH] bridge: Add controller status to Controller table. Get status information for controller(s) attached to each bridge and store in Controller table every 5 seconds. --- ofproto/ofproto.c | 54 ++++++++++++++++++++++++++++++++++++++ ofproto/ofproto.h | 14 ++++++++++ vswitchd/bridge.c | 37 ++++++++++++++++++++++++++ vswitchd/vswitch.ovsschema | 15 +++++++++-- vswitchd/vswitch.xml | 54 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 172 insertions(+), 2 deletions(-) diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 7df8600e..aae85680 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -1354,6 +1354,60 @@ ofproto_is_alive(const struct ofproto *p) return !hmap_is_empty(&p->controllers); } +void +ofproto_get_ofproto_controller_info(const struct ofproto * ofproto, + struct shash *info) +{ + const struct ofconn *ofconn; + + shash_init(info); + + HMAP_FOR_EACH (ofconn, hmap_node, &ofproto->controllers) { + const struct rconn *rconn = ofconn->rconn; + const int last_error = rconn_get_last_error(rconn); + struct ofproto_controller_info *cinfo = xmalloc(sizeof *cinfo); + + shash_add(info, rconn_get_target(rconn), cinfo); + + cinfo->is_connected = rconn_is_connected(rconn); + cinfo->role = ofconn->role; + + cinfo->pairs.n = 0; + + if (last_error == EOF) { + cinfo->pairs.keys[cinfo->pairs.n] = "last_error"; + cinfo->pairs.values[cinfo->pairs.n++] = xstrdup("End of file"); + } else if (last_error > 0) { + cinfo->pairs.keys[cinfo->pairs.n] = "last_error"; + cinfo->pairs.values[cinfo->pairs.n++] = + xstrdup(strerror(last_error)); + } + + cinfo->pairs.keys[cinfo->pairs.n] = "state"; + cinfo->pairs.values[cinfo->pairs.n++] = + xstrdup(rconn_get_state(rconn)); + + cinfo->pairs.keys[cinfo->pairs.n] = "time_in_state"; + cinfo->pairs.values[cinfo->pairs.n++] = + xasprintf("%u", rconn_get_state_elapsed(rconn)); + } +} + +void +ofproto_free_ofproto_controller_info(struct shash *info) +{ + struct shash_node *node; + + SHASH_FOR_EACH (node, info) { + struct ofproto_controller_info *cinfo = node->data; + while (cinfo->pairs.n) { + free((char *) cinfo->pairs.values[--cinfo->pairs.n]); + } + free(cinfo); + } + shash_destroy(info); +} + /* Deletes port number 'odp_port' from the datapath for 'ofproto'. * * This is almost the same as calling dpif_port_del() directly on the diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index eeaeb6f7..8e4e2a65 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -34,8 +34,19 @@ struct cls_rule; struct nlattr; struct ofhooks; struct ofproto; +struct shash; struct svec; +struct ofproto_controller_info { + bool is_connected; + enum nx_role role; + struct { + const char *keys[3]; + const char *values[3]; + size_t n; + } pairs; +}; + struct ofexpired { struct flow flow; uint64_t packet_count; /* Packets from subrules. */ @@ -147,6 +158,9 @@ struct ofhooks { void ofproto_revalidate(struct ofproto *, tag_type); struct tag_set *ofproto_get_revalidate_set(struct ofproto *); +void ofproto_get_ofproto_controller_info(const struct ofproto *, struct shash *); +void ofproto_free_ofproto_controller_info(struct shash *); + #ifdef __cplusplus } #endif diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 680c1adf..1065d6ea 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -1318,6 +1318,42 @@ refresh_system_stats(const struct ovsrec_open_vswitch *cfg) &datum); } +static inline const char * +nx_role_to_str(enum nx_role role) +{ + switch (role) { + case NX_ROLE_OTHER: + return "other"; + case NX_ROLE_MASTER: + return "master"; + case NX_ROLE_SLAVE: + return "slave"; + default: + return "*** INVALID ROLE ***"; + } +} + +static void +bridge_refresh_controller_status(const struct bridge *br) +{ + struct shash info; + const struct ovsrec_controller *cfg; + + ofproto_get_ofproto_controller_info(br->ofproto, &info); + + OVSREC_CONTROLLER_FOR_EACH(cfg, idl) { + struct ofproto_controller_info *cinfo = shash_find_data(&info, cfg->target); + + ovsrec_controller_set_is_connected(cfg, cinfo->is_connected); + ovsrec_controller_set_role(cfg, nx_role_to_str(cinfo->role)); + ovsrec_controller_set_status(cfg, (char **) cinfo->pairs.keys, + (char **) cinfo->pairs.values, + cinfo->pairs.n); + } + + ofproto_free_ofproto_controller_info(&info); +} + void bridge_run(void) { @@ -1393,6 +1429,7 @@ bridge_run(void) iface_refresh_status(iface); } } + bridge_refresh_controller_status(br); } refresh_system_stats(cfg); ovsdb_idl_txn_commit(txn); diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema index 75c4326e..c62353c5 100644 --- a/vswitchd/vswitch.ovsschema +++ b/vswitchd/vswitch.ovsschema @@ -1,5 +1,5 @@ {"name": "Open_vSwitch", - "version": "1.0.6", + "version": "99.99.99", "cksum": "2256400918 14940", "tables": { "Open_vSwitch": { @@ -384,7 +384,18 @@ "min": 0, "max": 1}}, "external_ids": { "type": {"key": "string", "value": "string", - "min": 0, "max": "unlimited"}}}}, + "min": 0, "max": "unlimited"}}, + "is_connected": { + "type": "boolean", + "ephemeral": true}, + "role": { + "type": {"key": {"type": "string", + "enum": ["set", ["other", "master", "slave"]]}, + "min": 0, "max": 1}, + "ephemeral": true}, + "status": { + "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}, + "ephemeral": true}}}, "Manager": { "columns": { "target": { diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index dfa3f20a..6565b958 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -1844,6 +1844,60 @@ unique. No common key-value pairs are currently defined. + + + + true if currently connected to this controller, + false otherwise. + + + +

The level of authority this controller has on the associated + bridge. Possible values are:

+
+
other
+
Allows the controller access to all OpenFlow features.
+
+
+
master
+
Equivalent to other, except that there may be at + most one master controller at a time. When a controller configures + itself as master, any existing master is demoted to + the slaverole.
+
+
+
slave
+
Allows the controller read-only access to OpenFlow features. + Attempts to modify the flow table will be rejected with an + error. Slave controllers do not receive OFPT_PACKET_IN or + OFPT_FLOW_REMOVED messages, but they do receive OFPT_PORT_STATUS + messages.
+
+
+ + +

Key-value pairs that report controller status.

+
+
last_error
+
A human-readable description of the last error on the connection + to the controller; i.e. strerror(errno). This key + will exist only if an error has occurred.
+
+
+
state
+
The state of the connection to the controller. Possible values + are: VOID, BACKOFF, + CONNECTING, ACTIVE, and + IDLE.
+
+
+
time_in_state
+
Seconds since connecting to (if currently connected) or + disconnecting from (if currently disconnected) this + controller.
+
+
+
-- 2.30.2