Skip to content

Commit

Permalink
ofproto-dpif: Expose datapath capability to ovsdb.
Browse files Browse the repository at this point in the history
The patch adds support for fetching the datapath's capabilities
from the result of 'check_support()', and write the supported capability
to a new database column, called 'capabilities' under Datapath table.

To see how it works, run:
 # ovs-vsctl -- add-br br0 -- set Bridge br0 datapath_type=netdev
 # ovs-vsctl -- --id=@m create Datapath datapath_version=0 \
     'ct_zones={}' 'capabilities={}' \
     -- set Open_vSwitch . datapaths:"netdev"=@m

 # ovs-vsctl list-dp-cap netdev
 ufid=true sample_nesting=true clone=true tnl_push_pop=true \
 ct_orig_tuple=true ct_eventmask=true ct_state=true \
 ct_clear=true max_vlan_headers=1 recirc=true ct_label=true \
 max_hash_alg=1 ct_state_nat=true ct_timeout=true \
 ct_mark=true ct_orig_tuple6=true check_pkt_len=true \
 masked_set_action=true max_mpls_depth=3 trunc=true ct_zone=true

Signed-off-by: William Tu <u9012063@gmail.com>
Tested-by: Greg Rose <gvrose8192@gmail.com>
Reviewed-by: Greg Rose <gvrose8192@gmail.com>
---
v5:
    Add improved documentation from Ben and
    fix checkpatch error (tab and line 79 char)
v4:
    rebase to master
v3:
    fix 32-bit build, reported by Greg
    travis: https://travis-ci.org/williamtu/ovs-travis/builds/599276267
v2:
	rebase to master
  • Loading branch information
williamtu committed Nov 21, 2019
1 parent acb691e commit 2750180
Show file tree
Hide file tree
Showing 11 changed files with 379 additions and 4 deletions.
14 changes: 11 additions & 3 deletions lib/meta-flow.xml
Expand Up @@ -2488,7 +2488,7 @@ actions=clone(load:0->NXM_OF_IN_PORT[],output:123)

<group title="Connection Tracking">
<p>
Open vSwitch 2.5 and later support ``connection tracking,'' which allows
Open vSwitch supports ``connection tracking,'' which allows
bidirectional streams of packets to be statefully grouped into
connections. Open vSwitch connection tracking, for example, identifies
the patterns of TCP packets that indicates a successfully initiated
Expand Down Expand Up @@ -2524,7 +2524,14 @@ actions=clone(load:0->NXM_OF_IN_PORT[],output:123)
</p>

<p>
Connection tracking is an Open vSwitch extension to OpenFlow.
Connection tracking is an Open vSwitch extension to OpenFlow. Open
vSwitch 2.5 added the initial support for connection tracking.
Subsequent versions of Open vSwitch added many refinements and extensions
to the initial support. Many of these capabilities depend on the Open
vSwitch datapath rather than simply the userspace version. The
<code>capabilities</code> column in the <code>Datapath</code> table (see
<code>ovs-vswitchd.conf.db</code>(5)) reports the detailed capabilities
of a particular Open vSwitch datapath.
</p>

<field id="MFF_CT_STATE" title="Connection Tracking State">
Expand Down Expand Up @@ -2713,7 +2720,8 @@ actions=clone(load:0->NXM_OF_IN_PORT[],output:123)
</p>

<p>
The following fields are populated by the ct action, and require a
The following fields are populated by the <code>ct</code>
action, and require a
match to a valid connection tracking state as a prerequisite, in
addition to the IP or IPv6 ethertype match. Examples of valid
connection tracking state matches include <code>ct_state=+new</code>,
Expand Down
51 changes: 51 additions & 0 deletions ofproto/ofproto-dpif.c
Expand Up @@ -5444,6 +5444,56 @@ ct_del_zone_timeout_policy(const char *datapath_type, uint16_t zone_id)
}
}

static void
get_datapath_cap(const char *datapath_type, struct smap *cap)
{
char *str_value;
struct odp_support odp;
struct dpif_backer_support s;
struct dpif_backer *backer = shash_find_data(&all_dpif_backers,
datapath_type);
if (!backer) {
return;
}
s = backer->rt_support;
odp = s.odp;

/* ODP_SUPPORT_FIELDS */
str_value = xasprintf("%"PRIuSIZE, odp.max_vlan_headers);
smap_add(cap, "max_vlan_headers", str_value);
free(str_value);

str_value = xasprintf("%"PRIuSIZE, odp.max_mpls_depth);
smap_add(cap, "max_mpls_depth", str_value);
free(str_value);

smap_add(cap, "recirc", odp.recirc ? "true" : "false");
smap_add(cap, "ct_state", odp.ct_state ? "true" : "false");
smap_add(cap, "ct_zone", odp.ct_zone ? "true" : "false");
smap_add(cap, "ct_mark", odp.ct_mark ? "true" : "false");
smap_add(cap, "ct_label", odp.ct_label ? "true" : "false");
smap_add(cap, "ct_state_nat", odp.ct_state_nat ? "true" : "false");
smap_add(cap, "ct_orig_tuple", odp.ct_orig_tuple ? "true" : "false");
smap_add(cap, "ct_orig_tuple6", odp.ct_orig_tuple6 ? "true" : "false");

/* DPIF_SUPPORT_FIELDS */
smap_add(cap, "masked_set_action", s.masked_set_action ? "true" : "false");
smap_add(cap, "tnl_push_pop", s.tnl_push_pop ? "true" : "false");
smap_add(cap, "ufid", s.ufid ? "true" : "false");
smap_add(cap, "trunc", s.trunc ? "true" : "false");
smap_add(cap, "clone", s.clone ? "true" : "false");
smap_add(cap, "sample_nesting", s.sample_nesting ? "true" : "false");
smap_add(cap, "ct_eventmask", s.ct_eventmask ? "true" : "false");
smap_add(cap, "ct_clear", s.ct_clear ? "true" : "false");

str_value = xasprintf("%"PRIuSIZE, s.max_hash_alg);
smap_add(cap, "max_hash_alg", str_value);
free(str_value);

smap_add(cap, "check_pkt_len", s.check_pkt_len ? "true" : "false");
smap_add(cap, "ct_timeout", s.ct_timeout ? "true" : "false");
}

/* Gets timeout policy name in 'backer' based on 'zone', 'dl_type' and
* 'nw_proto'. Returns true if the zone-based timeout policy is configured.
* On success, stores the timeout policy name in 'tp_name', and sets
Expand Down Expand Up @@ -6585,4 +6635,5 @@ const struct ofproto_class ofproto_dpif_class = {
ct_flush, /* ct_flush */
ct_set_zone_timeout_policy,
ct_del_zone_timeout_policy,
get_datapath_cap,
};
2 changes: 2 additions & 0 deletions ofproto/ofproto-provider.h
Expand Up @@ -1889,6 +1889,8 @@ struct ofproto_class {
/* Deletes the timeout policy associated with 'zone' in datapath type
* 'dp_type'. */
void (*ct_del_zone_timeout_policy)(const char *dp_type, uint16_t zone);
/* Get the datapath's capabilities. */
void (*get_datapath_cap)(const char *dp_type, struct smap *caps);
};

extern const struct ofproto_class ofproto_dpif_class;
Expand Down
12 changes: 12 additions & 0 deletions ofproto/ofproto.c
Expand Up @@ -954,6 +954,18 @@ ofproto_get_flow_restore_wait(void)
return flow_restore_wait;
}

/* Retrieve datapath capabilities. */
void
ofproto_get_datapath_cap(const char *datapath_type, struct smap *dp_cap)
{
datapath_type = ofproto_normalize_type(datapath_type);
const struct ofproto_class *class = ofproto_class_find__(datapath_type);

if (class->get_datapath_cap) {
class->get_datapath_cap(datapath_type, dp_cap);
}
}

/* Connection tracking configuration. */
void
ofproto_ct_set_zone_timeout_policy(const char *datapath_type, uint16_t zone_id,
Expand Down
2 changes: 2 additions & 0 deletions ofproto/ofproto.h
Expand Up @@ -372,6 +372,8 @@ void ofproto_ct_set_zone_timeout_policy(const char *datapath_type,
struct simap *timeout_policy);
void ofproto_ct_del_zone_timeout_policy(const char *datapath_type,
uint16_t zone);
void ofproto_get_datapath_cap(const char *datapath_type,
struct smap *dp_cap);

/* Configuration of ports. */
void ofproto_port_unregister(struct ofproto *, ofp_port_t ofp_port);
Expand Down
10 changes: 10 additions & 0 deletions tests/ovs-vsctl.at
Expand Up @@ -819,6 +819,10 @@ AT_CHECK([RUN_OVS_VSCTL([del-zone-tp netdev zone=1])])
AT_CHECK([RUN_OVS_VSCTL([--if-exists del-zone-tp netdev zone=1])])
AT_CHECK([RUN_OVS_VSCTL([list-zone-tp netdev])], [0], [Zone:2, Timeout Policies: icmp_first=2 icmp_reply=3
])

AT_CHECK([RUN_OVS_VSCTL([-- --id=@m create Datapath datapath_version=0 'capabilities={recirc=true}' -- set Open_vSwitch . datapaths:"system"=@m])], [0], [stdout])
AT_CHECK([RUN_OVS_VSCTL([list-dp-cap system])], [0], [recirc=true
])
OVS_VSCTL_CLEANUP
AT_CLEANUP

Expand Down Expand Up @@ -962,6 +966,12 @@ AT_CHECK([RUN_OVS_VSCTL([del-zone-tp netdev zone=11])],
])
AT_CHECK([RUN_OVS_VSCTL([list-zone-tp netdev])], [0], [Zone:2, Timeout Policies: icmp_first=2 icmp_reply=3
])

AT_CHECK([RUN_OVS_VSCTL([-- --id=@m create Datapath datapath_version=0 'capabilities={recirc=true}' -- set Open_vSwitch . datapaths:"system"=@m])], [0], [stdout])
AT_CHECK([RUN_OVS_VSCTL([list-dp-cap nosystem])],
[1], [], [ovs-vsctl: datapath "nosystem" record not found
])

OVS_VSCTL_CLEANUP
AT_CLEANUP

Expand Down
6 changes: 6 additions & 0 deletions utilities/ovs-vsctl.8.in
Expand Up @@ -379,6 +379,12 @@ delete a zone that does not exist has no effect.
.IP "\fBlist\-zone\-tp \fIdatapath\fR"
Prints the timeout policies of all zones in \fIdatapath\fR.
.
.SS "Datapath Capabilities Command"
The command query datapath capabilities.
.
.IP "\fBlist\-dp\-cap \fIdatapath\fR"
Prints the datapath's capabilities.
.
.SS "OpenFlow Controller Connectivity"
.
\fBovs\-vswitchd\fR can perform all configured bridging and switching
Expand Down
28 changes: 28 additions & 0 deletions utilities/ovs-vsctl.c
Expand Up @@ -1362,6 +1362,31 @@ pre_get_zone(struct ctl_context *ctx)
ovsdb_idl_add_column(ctx->idl, &ovsrec_ct_timeout_policy_col_timeouts);
}

static void
pre_get_dp_cap(struct ctl_context *ctx)
{
ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_datapaths);
ovsdb_idl_add_column(ctx->idl, &ovsrec_datapath_col_capabilities);
}

static void
cmd_list_dp_cap(struct ctl_context *ctx)
{
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
struct smap_node *node;

struct ovsrec_datapath *dp = find_datapath(vsctl_ctx, ctx->argv[1]);
if (!dp) {
ctl_fatal("datapath \"%s\" record not found", ctx->argv[1]);
}

SMAP_FOR_EACH (node, &dp->capabilities) {
ds_put_format(&ctx->output, "%s=%s ",node->key, node->value);
}
ds_chomp(&ctx->output, ' ');
ds_put_char(&ctx->output, '\n');
}

static void
cmd_add_br(struct ctl_context *ctx)
{
Expand Down Expand Up @@ -3112,6 +3137,9 @@ static const struct ctl_command_syntax vsctl_commands[] = {
"--if-exists", RW},
{"list-zone-tp", 1, 1, "", pre_get_zone, cmd_list_zone_tp, NULL, "", RO},

/* Datapath capabilities. */
{"list-dp-cap", 1, 1, "", pre_get_dp_cap, cmd_list_dp_cap, NULL, "", RO},

{NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, RO},
};

Expand Down
21 changes: 21 additions & 0 deletions vswitchd/bridge.c
Expand Up @@ -171,6 +171,7 @@ struct datapath {
struct hmap ct_zones; /* Map of 'struct ct_zone' elements, indexed
* by 'zone'. */
struct hmap_node node; /* Node in 'all_datapaths' hmap. */
struct smap caps; /* Capabilities. */
unsigned int last_used; /* The last idl_seqno that this 'datapath'
* used in OVSDB. This number is used for
* garbage collection. */
Expand Down Expand Up @@ -700,6 +701,7 @@ datapath_create(const char *type)
dp->type = xstrdup(type);
hmap_init(&dp->ct_zones);
hmap_insert(&all_datapaths, &dp->node, hash_string(type, 0));
smap_init(&dp->caps);
return dp;
}

Expand All @@ -716,6 +718,7 @@ datapath_destroy(struct datapath *dp)
hmap_remove(&all_datapaths, &dp->node);
hmap_destroy(&dp->ct_zones);
free(dp->type);
smap_destroy(&dp->caps);
free(dp);
}
}
Expand Down Expand Up @@ -758,6 +761,23 @@ ct_zones_reconfigure(struct datapath *dp, struct ovsrec_datapath *dp_cfg)
}
}

static void
dp_capability_reconfigure(struct datapath *dp,
struct ovsrec_datapath *dp_cfg)
{
struct smap_node *node;
struct smap cap;

smap_init(&cap);
ofproto_get_datapath_cap(dp->type, &cap);

SMAP_FOR_EACH (node, &cap) {
ovsrec_datapath_update_capabilities_setkey(dp_cfg, node->key,
node->value);
}
smap_destroy(&cap);
}

static void
datapath_reconfigure(const struct ovsrec_open_vswitch *cfg)
{
Expand All @@ -771,6 +791,7 @@ datapath_reconfigure(const struct ovsrec_open_vswitch *cfg)
dp = datapath_lookup(dp_name);
if (!dp) {
dp = datapath_create(dp_name);
dp_capability_reconfigure(dp, dp_cfg);
}
dp->last_used = idl_seqno;
ct_zones_reconfigure(dp, dp_cfg);
Expand Down
5 changes: 4 additions & 1 deletion vswitchd/vswitch.ovsschema
@@ -1,6 +1,6 @@
{"name": "Open_vSwitch",
"version": "8.2.0",
"cksum": "4076590391 26298",
"cksum": "1076640191 26427",
"tables": {
"Open_vSwitch": {
"columns": {
Expand Down Expand Up @@ -650,6 +650,9 @@
"value": {"type": "uuid",
"refTable": "CT_Zone"},
"min": 0, "max": "unlimited"}},
"capabilities": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}}},
Expand Down

0 comments on commit 2750180

Please sign in to comment.