Signed-off-by: Jarno Rajahalme <jrajaha...@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 f737877..d5d9a9f 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -172,6 +172,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; @@ -2801,6 +2804,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)]; @@ -2816,6 +2820,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) { @@ -2862,6 +2870,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; @@ -3082,6 +3093,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, @@ -4848,9 +4860,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 1ec5def..745fd66 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -306,6 +306,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. */ @@ -1243,6 +1245,7 @@ construct(struct ofproto *ofproto_) return error; } + atomic_init(&ofproto->tables_version, CLS_NO_VERSION); ofproto->netflow = NULL; ofproto->sflow = NULL; ofproto->ipfix = NULL; @@ -1621,6 +1624,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) { @@ -3717,6 +3729,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. @@ -3724,16 +3745,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_NO_VERSION, flow, wc); + cls_rule = classifier_lookup(cls, version, flow, wc); rule = rule_dpif_cast(rule_from_cls_rule(cls_rule)); @@ -3770,9 +3791,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) { @@ -3823,7 +3844,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; @@ -5452,7 +5474,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; @@ -5507,6 +5531,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 9566924..4699f27 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. @@ -77,7 +77,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 9222fe4..8cbbb9f 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 5ce9331..e27bb7e 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -520,6 +520,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_NO_VERSION; hindex_init(&ofproto->cookies); hmap_init(&ofproto->learned_cookies); list_init(&ofproto->expirable); @@ -570,6 +571,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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev