[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