[ovs-dev] [PATCH v4 06/12] ofproto: Infra for table versioning.
Jarno Rajahalme
jrajahalme at nicira.com
Wed Jun 10 00:24:13 UTC 2015
Signed-off-by: Jarno Rajahalme <jrajahalme at nicira.com>
---
ofproto/ofproto-dpif-xlate.c | 17 ++++++++++++++++-
ofproto/ofproto-dpif.c | 43 +++++++++++++++++++++++++++++++++---------
ofproto/ofproto-dpif.h | 5 ++++-
ofproto/ofproto-provider.h | 6 ++++++
ofproto/ofproto.c | 5 +++++
5 files changed, 65 insertions(+), 11 deletions(-)
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 59cd088..ac3b99e 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -159,6 +159,9 @@ struct xlate_ctx {
const struct xbridge *xbridge;
+ /* Flow tables version at the beginning of the translation. */
+ long long tables_version;
+
/* Flow at the last commit. */
struct flow base_flow;
@@ -2774,6 +2777,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
const struct xport *peer = xport->peer;
struct flow old_flow = ctx->xin->flow;
bool old_was_mpls = ctx->was_mpls;
+ long long old_version = ctx->tables_version;
enum slow_path_reason special;
struct ofpbuf old_stack = ctx->stack;
union mf_subvalue new_stack[1024 / sizeof(union mf_subvalue)];
@@ -2789,6 +2793,10 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
memset(flow->regs, 0, sizeof flow->regs);
flow->actset_output = OFPP_UNSET;
+ /* Set tables version after the bridge has been fixed. */
+ ctx->tables_version
+ = ofproto_dpif_get_tables_version(ctx->xbridge->ofproto);
+
special = process_special(ctx, &ctx->xin->flow, peer,
ctx->xin->packet);
if (special) {
@@ -2835,6 +2843,9 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
ofpbuf_uninit(&ctx->stack);
ctx->stack = old_stack;
+ /* Restore calling bridge's lookup version. */
+ ctx->tables_version = old_version;
+
/* The peer bridge popping MPLS should have no effect on the original
* bridge. */
ctx->was_mpls = old_was_mpls;
@@ -3056,6 +3067,7 @@ xlate_table_action(struct xlate_ctx *ctx, ofp_port_t in_port, uint8_t table_id,
wc = (ctx->xin->skip_wildcards) ? NULL : &ctx->xout->wc;
rule = rule_dpif_lookup_from_table(ctx->xbridge->ofproto,
+ ctx->tables_version,
&ctx->xin->flow, wc,
ctx->xin->xcache != NULL,
ctx->xin->resubmit_stats,
@@ -4826,9 +4838,12 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
flow->recirc_id);
return;
}
+ /* Set tables version after the bridge has been fixed. */
+ ctx.tables_version = ofproto_dpif_get_tables_version(ctx.xbridge->ofproto);
if (!xin->ofpacts && !ctx.rule) {
- rule = rule_dpif_lookup_from_table(ctx.xbridge->ofproto, flow, wc,
+ rule = rule_dpif_lookup_from_table(ctx.xbridge->ofproto,
+ ctx.tables_version, flow, wc,
ctx.xin->xcache != NULL,
ctx.xin->resubmit_stats,
&ctx.table_id,
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 81beca0..cc5d9d4 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -287,6 +287,8 @@ struct ofproto_dpif {
struct ofproto up;
struct dpif_backer *backer;
+ atomic_llong tables_version; /* Version # to use in classifier lookups. */
+
uint64_t dump_seq; /* Last read of udpif_dump_seq(). */
/* Special OpenFlow rules. */
@@ -1227,6 +1229,7 @@ construct(struct ofproto *ofproto_)
return error;
}
+ atomic_init(&ofproto->tables_version, CLS_MIN_VERSION);
ofproto->netflow = NULL;
ofproto->sflow = NULL;
ofproto->ipfix = NULL;
@@ -1605,6 +1608,15 @@ query_tables(struct ofproto *ofproto,
}
}
+static void
+set_tables_version(struct ofproto *ofproto_, long long version)
+{
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
+
+ atomic_store_relaxed(&ofproto->tables_version, version);
+}
+
+
static struct ofport *
port_alloc(void)
{
@@ -3709,6 +3721,15 @@ rule_set_recirc_id(struct rule *rule_, uint32_t id)
ovs_mutex_unlock(&rule->up.mutex);
}
+long long
+ofproto_dpif_get_tables_version(struct ofproto_dpif *ofproto)
+{
+ long long version;
+
+ atomic_read_relaxed(&ofproto->tables_version, &version);
+ return version;
+}
+
/* The returned rule (if any) is valid at least until the next RCU quiescent
* period. If the rule needs to stay around longer, a non-zero 'take_ref'
* must be passed in to cause a reference to be taken on it.
@@ -3716,16 +3737,16 @@ rule_set_recirc_id(struct rule *rule_, uint32_t id)
* 'flow' is non-const to allow for temporary modifications during the lookup.
* Any changes are restored before returning. */
static struct rule_dpif *
-rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto, uint8_t table_id,
- struct flow *flow, struct flow_wildcards *wc,
- bool take_ref)
+rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto, long long version,
+ uint8_t table_id, struct flow *flow,
+ struct flow_wildcards *wc, bool take_ref)
{
struct classifier *cls = &ofproto->up.tables[table_id].cls;
const struct cls_rule *cls_rule;
struct rule_dpif *rule;
do {
- cls_rule = classifier_lookup(cls, CLS_MAX_VERSION, flow, wc);
+ cls_rule = classifier_lookup(cls, version, flow, wc);
rule = rule_dpif_cast(rule_from_cls_rule(cls_rule));
@@ -3762,9 +3783,9 @@ rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto, uint8_t table_id,
* 'flow' is non-const to allow for temporary modifications during the lookup.
* Any changes are restored before returning. */
struct rule_dpif *
-rule_dpif_lookup_from_table(struct ofproto_dpif *ofproto, struct flow *flow,
- struct flow_wildcards *wc, bool take_ref,
- const struct dpif_flow_stats *stats,
+rule_dpif_lookup_from_table(struct ofproto_dpif *ofproto, long long version,
+ struct flow *flow, struct flow_wildcards *wc,
+ bool take_ref, const struct dpif_flow_stats *stats,
uint8_t *table_id, ofp_port_t in_port,
bool may_packet_in, bool honor_table_miss)
{
@@ -3815,7 +3836,8 @@ rule_dpif_lookup_from_table(struct ofproto_dpif *ofproto, struct flow *flow,
next_id++, next_id += (next_id == TBL_INTERNAL))
{
*table_id = next_id;
- rule = rule_dpif_lookup_in_table(ofproto, next_id, flow, wc, take_ref);
+ rule = rule_dpif_lookup_in_table(ofproto, version, next_id, flow, wc,
+ take_ref);
if (stats) {
struct oftable *tbl = &ofproto->up.tables[next_id];
unsigned long orig;
@@ -5444,7 +5466,9 @@ ofproto_dpif_add_internal_flow(struct ofproto_dpif *ofproto,
return error;
}
- rule = rule_dpif_lookup_in_table(ofproto, TBL_INTERNAL, &fm.match.flow,
+ rule = rule_dpif_lookup_in_table(ofproto,
+ ofproto_dpif_get_tables_version(ofproto),
+ TBL_INTERNAL, &fm.match.flow,
&fm.match.wc, false);
if (rule) {
*rulep = &rule->up;
@@ -5499,6 +5523,7 @@ const struct ofproto_class ofproto_dpif_class = {
type_get_memory_usage,
flush,
query_tables,
+ set_tables_version,
port_alloc,
port_construct,
port_destruct,
diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h
index 9d625a1..aaaf671 100644
--- a/ofproto/ofproto-dpif.h
+++ b/ofproto/ofproto-dpif.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
+/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -102,7 +102,10 @@ size_t ofproto_dpif_get_max_mpls_depth(const struct ofproto_dpif *);
bool ofproto_dpif_get_enable_recirc(const struct ofproto_dpif *);
bool ofproto_dpif_get_enable_ufid(struct dpif_backer *backer);
+long long ofproto_dpif_get_tables_version(struct ofproto_dpif *);
+
struct rule_dpif *rule_dpif_lookup_from_table(struct ofproto_dpif *,
+ long long version,
struct flow *,
struct flow_wildcards *,
bool take_ref,
diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
index 2e4d333..46ffe7f 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -93,6 +93,8 @@ struct ofproto {
long long int eviction_group_timer; /* For rate limited reheapification. */
struct oftable *tables;
int n_tables;
+ long long tables_version; /* Controls which rules are visible to
+ * table lookups. */
/* Rules indexed on their cookie values, in all flow tables. */
struct hindex cookies OVS_GUARDED_BY(ofproto_mutex);
@@ -834,6 +836,10 @@ struct ofproto_class {
struct ofputil_table_features *features,
struct ofputil_table_stats *stats);
+ /* Sets the current tables version the provider should use for classifier
+ * lookups. */
+ void (*set_tables_version)(struct ofproto *ofproto,
+ long long version);
/* ## ---------------- ## */
/* ## ofport Functions ## */
/* ## ---------------- ## */
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index b5424b9..716fbfa 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -527,6 +527,7 @@ ofproto_create(const char *datapath_name, const char *datapath_type,
ofproto->eviction_group_timer = LLONG_MIN;
ofproto->tables = NULL;
ofproto->n_tables = 0;
+ ofproto->tables_version = CLS_MIN_VERSION;
hindex_init(&ofproto->cookies);
hmap_init(&ofproto->learned_cookies);
list_init(&ofproto->expirable);
@@ -577,6 +578,10 @@ ofproto_create(const char *datapath_name, const char *datapath_type,
ofproto->meters = xzalloc((ofproto->meter_features.max_meters + 1)
* sizeof(struct meter *));
+ /* Set the initial tables version. */
+ ofproto->ofproto_class->set_tables_version(ofproto,
+ ofproto->tables_version);
+
*ofprotop = ofproto;
return 0;
}
--
1.7.10.4
More information about the dev
mailing list