OVS userspace are backword compatible with older Linux kernel modules. However, not having the most up-to-date datapath kernel modules can some times lead to user confusion. Storing the datapath version in OVSDB allows management software to check and optionally provide notifications to users.
Signed-off-by: Andy Zhou <az...@nicira.com> --- vswitchd/bridge.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++ vswitchd/vswitch.ovsschema | 6 ++-- vswitchd/vswitch.xml | 5 +++ 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 5f6000e..4371dbe 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -69,6 +69,12 @@ VLOG_DEFINE_THIS_MODULE(bridge); COVERAGE_DEFINE(bridge_reconfigure); +#define MAX_VERSION_STR_SIZE 80 +#define DATAPATH_VERSION_FILE "/sys/module/openvswitch/version" +/* A copy ovs_version from OVSDB. This is a default datapath version for + * all non-kernel datapathes. */ +static char *ovs_version = NULL; + struct iface { /* These members are always valid. * @@ -134,6 +140,10 @@ struct bridge { struct ovsrec_port synth_local_port; struct ovsrec_interface synth_local_iface; struct ovsrec_interface *synth_local_ifacep; + + /* Set true when created. Reset to false after the datpath + * information has been stored into ovsdb. */ + bool embryonic; }; /* All bridges, indexed by name. */ @@ -315,6 +325,23 @@ static void add_vlan_splinter_ports(struct bridge *, const unsigned long int *splinter_vlans, struct shash *ports); + +static void +free_ovs_version(void) +{ + free(ovs_version); +} + +static void +init_ovs_version(const char *version) +{ + if (ovs_version) { + free_ovs_version(); + } + + ovs_version = xstrdup(version ? version : VERSION); +} + static void bridge_init_ofproto(const struct ovsrec_open_vswitch *cfg) { @@ -381,6 +408,7 @@ bridge_init(const char *remote) ovsdb_idl_omit(idl, &ovsrec_open_vswitch_col_system_version); ovsdb_idl_omit_alert(idl, &ovsrec_bridge_col_datapath_id); + ovsdb_idl_omit_alert(idl, &ovsrec_bridge_col_datapath_version); ovsdb_idl_omit_alert(idl, &ovsrec_bridge_col_status); ovsdb_idl_omit_alert(idl, &ovsrec_bridge_col_rstp_status); ovsdb_idl_omit_alert(idl, &ovsrec_bridge_col_stp_enable); @@ -465,6 +493,7 @@ bridge_exit(void) bridge_destroy(br); } ovsdb_idl_destroy(idl); + free_ovs_version(); } /* Looks at the list of managers in 'ovs_cfg' and extracts their remote IP @@ -595,6 +624,9 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) ovs_strerror(error)); shash_destroy(&br->wanted_ports); bridge_destroy(br); + } else { + br->embryonic = true; + seq_change(connectivity_seq_get()); } } } @@ -2320,6 +2352,46 @@ iface_refresh_stats(struct iface *iface) } static void +br_refresh_datapath_info(struct bridge *br) +{ + char version[MAX_VERSION_STR_SIZE]; + + if (!br->ofproto) { + return; + } + + if (!br->embryonic) { + return; + } + + /* Only store the datapath version once. */ + br->embryonic = false; + + /* For "system" type datapath, record the Linux kenrel modules' + * verions number. Other datapath types are assumed to be supplied + * by openvswitch itself, thus inherit the same version string. */ + + if (!strcmp("system", ofproto_normalize_type(br->cfg->datapath_type))) { + FILE *f; + + f = fopen(DATAPATH_VERSION_FILE, "r"); + if (f) { + char *newline; + + fgets(version, MAX_VERSION_STR_SIZE, f); + newline = strchr(version, '\n'); + if (newline) { + *newline = '\0'; + } + ovsrec_bridge_set_datapath_version(br->cfg, version); + fclose(f); + } + } else { + ovsrec_bridge_set_datapath_version(br->cfg, ovs_version); + } +} + +static void br_refresh_stp_status(struct bridge *br) { struct smap smap = SMAP_INITIALIZER(&smap); @@ -2695,6 +2767,7 @@ run_status_update(void) br_refresh_stp_status(br); br_refresh_rstp_status(br); + br_refresh_datapath_info(br); HMAP_FOR_EACH (port, hmap_node, &br->ports) { struct iface *iface; @@ -2808,6 +2881,8 @@ bridge_run(void) } cfg = ovsrec_open_vswitch_first(idl); + init_ovs_version(cfg->ovs_version); + /* Initialize the ofproto library. This only needs to run once, but * it must be done after the configuration is set. If the * initialization has already occurred, bridge_init_ofproto() @@ -3054,6 +3129,7 @@ bridge_create(const struct ovsrec_bridge *br_cfg) br->name = xstrdup(br_cfg->name); br->type = xstrdup(ofproto_normalize_type(br_cfg->datapath_type)); br->cfg = br_cfg; + br->embryonic = true; /* Derive the default Ethernet address from the bridge's UUID. This should * be unique and it will be stable between ovs-vswitchd runs. */ diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema index 1817766..196c33c 100644 --- a/vswitchd/vswitch.ovsschema +++ b/vswitchd/vswitch.ovsschema @@ -1,6 +1,6 @@ {"name": "Open_vSwitch", - "version": "7.10.1", - "cksum": "2340049037 21461", + "version": "7.11.1", + "cksum": "1038213587 21518", "tables": { "Open_vSwitch": { "columns": { @@ -49,6 +49,8 @@ "mutable": false}, "datapath_type": { "type": "string"}, + "datapath_version": { + "type": "string"}, "datapath_id": { "type": {"key": "string", "min": 0, "max": 1}, "ephemeral": true}, diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index d90f221..0af0637 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -582,6 +582,11 @@ column="other-config" key="datapath-id"/> instead.) </column> + <column name="datapath_version"> + Reports the OpenFlow datapath version in use. Can be empty if + datapath version can not be determined. + </column> + <column name="other_config" key="datapath-id"> Exactly 16 hex digits to set the OpenFlow datapath ID to a specific value. May not be all-zero. -- 1.9.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev