X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto-dpif.c;h=7b3e1eb649c13ad4eb36ee3b9df138b3b0778038;hb=bdd534291ff72077390f7b1745c4443ad3833d99;hp=62c1e4ca52f7c2d6ec8f2af5b76df7d3014c92b5;hpb=41a91a0b9f08753764c5dbfa1027c061d84d4179;p=sliver-openvswitch.git diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 62c1e4ca5..7b3e1eb64 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc. + * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -256,6 +256,10 @@ struct dpif_backer { * OVS_USERSPACE_ATTR_USERDATA in OVS_ACTION_ATTR_USERSPACE actions. * False if the datapath supports only 8-byte (or shorter) userdata. */ bool variable_length_userdata; + + /* Maximum number of MPLS label stack entries that the datapath supports + * in a match */ + size_t max_mpls_depth; }; /* All existing ofproto_backer instances, indexed by ofproto->up.type. */ @@ -319,6 +323,12 @@ ofproto_dpif_cast(const struct ofproto *ofproto) return CONTAINER_OF(ofproto, struct ofproto_dpif, up); } +size_t +ofproto_dpif_get_max_mpls_depth(const struct ofproto_dpif *ofproto) +{ + return ofproto->backer->max_mpls_depth; +} + static struct ofport_dpif *get_ofp_port(const struct ofproto_dpif *ofproto, ofp_port_t ofp_port); static void ofproto_trace(struct ofproto_dpif *, const struct flow *, @@ -558,7 +568,8 @@ type_run(const char *type) ofproto->netflow, ofproto->up.frag_handling, ofproto->up.forward_bpdu, connmgr_has_in_band(ofproto->up.connmgr), - ofproto->backer->variable_length_userdata); + ofproto->backer->variable_length_userdata, + ofproto->backer->max_mpls_depth); HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) { xlate_bundle_set(ofproto, bundle, bundle->name, @@ -781,6 +792,7 @@ struct odp_garbage { }; static bool check_variable_length_userdata(struct dpif_backer *backer); +static size_t check_max_mpls_depth(struct dpif_backer *backer); static int open_dpif_backer(const char *type, struct dpif_backer **backerp) @@ -881,6 +893,7 @@ open_dpif_backer(const char *type, struct dpif_backer **backerp) return error; } backer->variable_length_userdata = check_variable_length_userdata(backer); + backer->max_mpls_depth = check_max_mpls_depth(backer); if (backer->recv_set_enable) { udpif_set_threads(backer->udpif, n_handlers, n_revalidators); @@ -965,6 +978,53 @@ check_variable_length_userdata(struct dpif_backer *backer) } } +/* Tests the MPLS label stack depth supported by 'backer''s datapath. + * + * Returns the number of elements in a struct flow's mpls_lse field + * if the datapath supports at least that many entries in an + * MPLS label stack. + * Otherwise returns the number of MPLS push actions supported by + * the datapath. */ +static size_t +check_max_mpls_depth(struct dpif_backer *backer) +{ + struct flow flow; + int n; + + for (n = 0; n < FLOW_MAX_MPLS_LABELS; n++) { + struct odputil_keybuf keybuf; + struct ofpbuf key; + int error; + + memset(&flow, 0, sizeof flow); + flow.dl_type = htons(ETH_TYPE_MPLS); + flow_set_mpls_bos(&flow, n, 1); + + ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); + odp_flow_key_from_flow(&key, &flow, 0); + + error = dpif_flow_put(backer->dpif, DPIF_FP_CREATE | DPIF_FP_MODIFY, + key.data, key.size, NULL, 0, NULL, 0, NULL); + if (error && error != EEXIST) { + if (error != EINVAL) { + VLOG_WARN("%s: MPLS stack length feature probe failed (%s)", + dpif_name(backer->dpif), ovs_strerror(error)); + } + break; + } + + error = dpif_flow_del(backer->dpif, key.data, key.size, NULL); + if (error) { + VLOG_WARN("%s: failed to delete MPLS feature probe flow", + dpif_name(backer->dpif)); + } + } + + VLOG_INFO("%s: MPLS label stack length probed as %d", + dpif_name(backer->dpif), n); + return n; +} + static int construct(struct ofproto *ofproto_) { @@ -1129,9 +1189,9 @@ destruct(struct ofproto *ofproto_) OFPROTO_FOR_EACH_TABLE (table, &ofproto->up) { struct cls_cursor cursor; - ovs_rwlock_rdlock(&table->cls.rwlock); + fat_rwlock_rdlock(&table->cls.rwlock); cls_cursor_init(&cursor, &table->cls, NULL); - ovs_rwlock_unlock(&table->cls.rwlock); + fat_rwlock_unlock(&table->cls.rwlock); CLS_CURSOR_FOR_EACH_SAFE (rule, next_rule, up.cr, &cursor) { ofproto_rule_delete(&ofproto->up, &rule->up); } @@ -3008,11 +3068,13 @@ rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto, if (wc) { memset(&wc->masks.dl_type, 0xff, sizeof wc->masks.dl_type); - wc->masks.nw_frag |= FLOW_NW_FRAG_MASK; + if (is_ip_any(flow)) { + wc->masks.nw_frag |= FLOW_NW_FRAG_MASK; + } } cls = &ofproto->up.tables[table_id].cls; - ovs_rwlock_rdlock(&cls->rwlock); + fat_rwlock_rdlock(&cls->rwlock); frag = (flow->nw_frag & FLOW_NW_FRAG_ANY) != 0; if (frag && ofproto->up.frag_handling == OFPC_FRAG_NORMAL) { /* We must pretend that transport ports are unavailable. */ @@ -3029,7 +3091,7 @@ rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto, *rule = rule_dpif_cast(rule_from_cls_rule(cls_rule)); rule_dpif_ref(*rule); - ovs_rwlock_unlock(&cls->rwlock); + fat_rwlock_unlock(&cls->rwlock); return *rule != NULL; } @@ -3653,7 +3715,7 @@ parse_flow_and_packet(int argc, const char *argv[], } if (xlate_receive(backer, NULL, odp_key.data, odp_key.size, flow, - NULL, ofprotop, NULL, NULL, NULL, NULL)) { + ofprotop, NULL, NULL, NULL, NULL)) { error = "Invalid datapath flow"; goto exit; } @@ -4038,11 +4100,10 @@ static bool ofproto_dpif_contains_flow(const struct ofproto_dpif *ofproto, const struct nlattr *key, size_t key_len) { - enum odp_key_fitness fitness; struct ofproto_dpif *ofp; struct flow flow; - xlate_receive(ofproto->backer, NULL, key, key_len, &flow, &fitness, &ofp, + xlate_receive(ofproto->backer, NULL, key, key_len, &flow, &ofp, NULL, NULL, NULL, NULL); return ofp == ofproto; }