Skip to content

Commit

Permalink
bridge: Store datapath version into ovsdb
Browse files Browse the repository at this point in the history
OVS userspace are backward 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 <[email protected]>
Acked-by: Ben Pfaff <[email protected]>
  • Loading branch information
azhou-nicira committed Nov 5, 2014
1 parent f8f417d commit b5cbbcf
Show file tree
Hide file tree
Showing 11 changed files with 163 additions and 2 deletions.
7 changes: 7 additions & 0 deletions lib/dpif-netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2520,6 +2520,12 @@ dp_netdev_reset_pmd_threads(struct dp_netdev *dp)
}
}

static char *
dpif_netdev_get_datapath_version(void)
{
return xstrdup("<built-in>");
}

static void
dp_netdev_flow_used(struct dp_netdev_flow *netdev_flow,
int cnt, int size,
Expand Down Expand Up @@ -3100,6 +3106,7 @@ const struct dpif_class dpif_netdev_class = {
dpif_netdev_register_upcall_cb,
dpif_netdev_enable_upcall,
dpif_netdev_disable_upcall,
dpif_netdev_get_datapath_version,
};

static void
Expand Down
31 changes: 31 additions & 0 deletions lib/dpif-netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -2141,6 +2141,36 @@ dpif_netlink_recv_purge(struct dpif *dpif_)
fat_rwlock_unlock(&dpif->upcall_lock);
}

static char *
dpif_netlink_get_datapath_version(void)
{
char *version_str = NULL;

#ifdef __linux__

#define MAX_VERSION_STR_SIZE 80
#define LINUX_DATAPATH_VERSION_FILE "/sys/module/openvswitch/version"
FILE *f;

f = fopen(LINUX_DATAPATH_VERSION_FILE, "r");
if (f) {
char *newline;
char version[MAX_VERSION_STR_SIZE];

if (fgets(version, MAX_VERSION_STR_SIZE, f)) {
newline = strchr(version, '\n');
if (newline) {
*newline = '\0';
}
version_str = xstrdup(version);
}
fclose(f);
}
#endif

return version_str;
}

const struct dpif_class dpif_netlink_class = {
"system",
dpif_netlink_enumerate,
Expand Down Expand Up @@ -2178,6 +2208,7 @@ const struct dpif_class dpif_netlink_class = {
NULL, /* register_upcall_cb */
NULL, /* enable_upcall */
NULL, /* disable_upcall */
dpif_netlink_get_datapath_version, /* get_datapath_version */
};

static int
Expand Down
4 changes: 4 additions & 0 deletions lib/dpif-provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,10 @@ struct dpif_class {

/* Disables upcalls if 'dpif' directly executes upcall functions. */
void (*disable_upcall)(struct dpif *);

/* Get datapath version. Caller is responsible for freeing the string
* returned. */
char *(*get_datapath_version)(void);
};

extern const struct dpif_class dpif_netlink_class;
Expand Down
16 changes: 16 additions & 0 deletions lib/dpif.c
Original file line number Diff line number Diff line change
Expand Up @@ -1379,6 +1379,22 @@ dpif_recv_wait(struct dpif *dpif, uint32_t handler_id)
}
}

/*
* Return the datapath version. Caller is responsible for freeing
* the string.
*/
char *
dpif_get_dp_version(const struct dpif *dpif)
{
char *version = NULL;

if (dpif->dpif_class->get_datapath_version) {
version = dpif->dpif_class->get_datapath_version();
}

return version;
}

/* Obtains the NetFlow engine type and engine ID for 'dpif' into '*engine_type'
* and '*engine_id', respectively. */
void
Expand Down
1 change: 1 addition & 0 deletions lib/dpif.h
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,7 @@ void dpif_get_netflow_ids(const struct dpif *,
int dpif_queue_to_priority(const struct dpif *, uint32_t queue_id,
uint32_t *priority);

char *dpif_get_dp_version(const struct dpif *);
#ifdef __cplusplus
}
#endif
Expand Down
17 changes: 17 additions & 0 deletions ofproto/ofproto-dpif.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,9 @@ struct dpif_backer {
/* Maximum number of MPLS label stack entries that the datapath supports
* in a match */
size_t max_mpls_depth;

/* Version string of the datapath stored in OVSDB. */
char *dp_version_string;
};

/* All existing ofproto_backer instances, indexed by ofproto->up.type. */
Expand Down Expand Up @@ -839,6 +842,7 @@ close_dpif_backer(struct dpif_backer *backer)
shash_find_and_delete(&all_dpif_backers, backer->type);
recirc_id_pool_destroy(backer->rid_pool);
free(backer->type);
free(backer->dp_version_string);
dpif_close(backer->dpif);
free(backer);
}
Expand Down Expand Up @@ -967,6 +971,7 @@ open_dpif_backer(const char *type, struct dpif_backer **backerp)
* as the kernel module checks that the 'pid' in userspace action
* is non-zero. */
backer->variable_length_userdata = check_variable_length_userdata(backer);
backer->dp_version_string = dpif_get_dp_version(backer->dpif);

return error;
}
Expand Down Expand Up @@ -4087,6 +4092,17 @@ ofproto_dpif_send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet
return error;
}

/* Return the version string of the datapath that backs up
* this 'ofproto'.
*/
static const char *
get_datapath_version(const struct ofproto *ofproto_)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);

return ofproto->backer->dp_version_string;
}

static bool
set_frag_handling(struct ofproto *ofproto_,
enum ofp_config_flags frag_handling)
Expand Down Expand Up @@ -5436,4 +5452,5 @@ const struct ofproto_class ofproto_dpif_class = {
group_dealloc, /* group_dealloc */
group_modify, /* group_modify */
group_get_stats, /* group_get_stats */
get_datapath_version, /* get_datapath_version */
};
13 changes: 13 additions & 0 deletions ofproto/ofproto-provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -1659,6 +1659,19 @@ struct ofproto_class {

enum ofperr (*group_get_stats)(const struct ofgroup *,
struct ofputil_group_stats *);

/* ## --------------------- ## */
/* ## Datapath information ## */
/* ## --------------------- ## */
/* Retrieve the version string of the datapath. The version
* string can be NULL if it can not be determined.
*
* The version retuned is read only. The caller should not
* free it.
*
* This function should be NULL if an implementation does not support it.
*/
const char *(*get_datapath_version)(const struct ofproto *);
};

extern const struct ofproto_class ofproto_dpif_class;
Expand Down
2 changes: 2 additions & 0 deletions tests/ovs-vsctl.at
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,7 @@ _uuid : <0>
controller : []
datapath_id : []
datapath_type : ""
datapath_version : ""
external_ids : {}
fail_mode : []
flood_vlans : []
Expand Down Expand Up @@ -1146,6 +1147,7 @@ _uuid : <1>
controller : []
datapath_id : []
datapath_type : ""
datapath_version : ""
external_ids : {}
fail_mode : []
flood_vlans : []
Expand Down
18 changes: 18 additions & 0 deletions vswitchd/bridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,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);
Expand Down Expand Up @@ -595,6 +596,9 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
ovs_strerror(error));
shash_destroy(&br->wanted_ports);
bridge_destroy(br);
} else {
/* Trigger storing datapath version. */
seq_change(connectivity_seq_get());
}
}
}
Expand Down Expand Up @@ -2319,6 +2323,19 @@ iface_refresh_stats(struct iface *iface)
#undef IFACE_STATS
}

static void
br_refresh_datapath_info(struct bridge *br)
{
const char *version;

version = (br->ofproto && br->ofproto->ofproto_class->get_datapath_version
? br->ofproto->ofproto_class->get_datapath_version(br->ofproto)
: NULL);

ovsrec_bridge_set_datapath_version(br->cfg,
version ? version : "<unknown>");
}

static void
br_refresh_stp_status(struct bridge *br)
{
Expand Down Expand Up @@ -2695,6 +2712,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;

Expand Down
6 changes: 4 additions & 2 deletions vswitchd/vswitch.ovsschema
Original file line number Diff line number Diff line change
@@ -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": {
Expand Down Expand Up @@ -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},
Expand Down
50 changes: 50 additions & 0 deletions vswitchd/vswitch.xml
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,56 @@
column="other-config" key="datapath-id"/> instead.)
</column>

<column name="datapath_version">
<p>
Reports the version number of the Open vSwitch datapath in use.
This allows management software to detect and report discrepancies
between Open vSwitch userspace and datapath versions. (The <ref
column="ovs_version" table="Open_vSwitch"/> column in the <ref
table="Open_vSwitch"/> reports the Open vSwitch userspace version.)
The version reported depends on the datapath in use:
</p>

<ul>
<li>
When the kernel module included in the Open vSwitch source tree is
used, this column reports the Open vSwitch version from which the
module was taken.
</li>

<li>
When the kernel module that is part of the upstream Linux kernel is
used, this column reports <code>&lt;unknown&gt;</code>.
</li>

<li>
When the datapath is built into the <code>ovs-vswitchd</code>
binary, this column reports <code>&lt;built-in&gt;</code>. A
built-in datapath is by definition the same version as the rest of
the Open VSwitch userspace.
</li>

<li>
Other datapaths (such as the Hyper-V kernel datapath) currently
report <code>&lt;unknown&gt;</code>.
</li>
</ul>

<p>
A version discrepancy between <code>ovs-vswitchd</code> and the
datapath in use is not normally cause for alarm. The Open vSwitch
kernel datapaths for Linux and Hyper-V, in particular, are designed
for maximum inter-version compatibility: any userspace version works
with with any kernel version. Some reasons do exist to insist on
particular user/kernel pairings. First, newer kernel versions add
new features, that can only be used by new-enough userspace, e.g.
VXLAN tunneling requires certain minimal userspace and kernel
versions. Second, as an extension to the first reason, some newer
kernel versions add new features for enhancing performance that only
new-enough userspace versions can take advantage of.
</p>
</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.
Expand Down

0 comments on commit b5cbbcf

Please sign in to comment.