X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=7ccff438c44f1a7afd2139687df3c3582fad7413;hb=HEAD;hp=49444c19328d853bea938aa62afcd6af0541150a;hpb=5c09b672114fab2357c8ce71d608d486eb5ae1ae;p=sliver-openvswitch.git diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 49444c193..7ccff438c 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -58,6 +58,7 @@ #include "unaligned.h" #include "unixctl.h" #include "vlog.h" +#include "bundles.h" VLOG_DEFINE_THIS_MODULE(ofproto); @@ -125,7 +126,7 @@ struct ofoperation { /* OFOPERATION_MODIFY, OFOPERATION_REPLACE: The old actions, if the actions * are changing. */ - struct rule_actions *actions; + const struct rule_actions *actions; /* OFOPERATION_DELETE. */ enum ofp_flow_removed_reason reason; /* Reason flow was removed. */ @@ -1941,7 +1942,7 @@ ofproto_add_flow(struct ofproto *ofproto, const struct match *match, rule = rule_from_cls_rule(classifier_find_match_exactly( &ofproto->tables[0].cls, match, priority)); if (rule) { - struct rule_actions *actions = rule_get_actions(rule); + const struct rule_actions *actions = rule_get_actions(rule); must_add = !ofpacts_equal(actions->ofpacts, actions->ofpacts_len, ofpacts, ofpacts_len); } else { @@ -1975,14 +1976,13 @@ ofproto_flow_mod(struct ofproto *ofproto, struct ofputil_flow_mod *fm) if (fm->command == OFPFC_MODIFY_STRICT && fm->table_id != OFPTT_ALL && !(fm->flags & OFPUTIL_FF_RESET_COUNTS)) { struct oftable *table = &ofproto->tables[fm->table_id]; - struct cls_rule match_rule; struct rule *rule; bool done = false; - cls_rule_init(&match_rule, &fm->match, fm->priority); fat_rwlock_rdlock(&table->cls.rwlock); - rule = rule_from_cls_rule(classifier_find_rule_exactly(&table->cls, - &match_rule)); + rule = rule_from_cls_rule(classifier_find_match_exactly(&table->cls, + &fm->match, + fm->priority)); if (rule) { /* Reading many of the rule fields and writing on 'modified' * requires the rule->mutex. Also, rule->actions may change @@ -2686,38 +2686,30 @@ ofproto_rule_unref(struct rule *rule) static uint32_t get_provider_meter_id(const struct ofproto *, uint32_t of_meter_id); -/* Creates and returns a new 'struct rule_actions', with a ref_count of 1, - * whose actions are a copy of from the 'ofpacts_len' bytes of 'ofpacts'. */ -struct rule_actions * +/* Creates and returns a new 'struct rule_actions', whose actions are a copy + * of from the 'ofpacts_len' bytes of 'ofpacts'. */ +const struct rule_actions * rule_actions_create(const struct ofproto *ofproto, const struct ofpact *ofpacts, size_t ofpacts_len) { struct rule_actions *actions; - actions = xmalloc(sizeof *actions); - actions->ofpacts = xmemdup(ofpacts, ofpacts_len); + actions = xmalloc(sizeof *actions + ofpacts_len); actions->ofpacts_len = ofpacts_len; actions->provider_meter_id = get_provider_meter_id(ofproto, ofpacts_get_meter(ofpacts, ofpacts_len)); + memcpy(actions->ofpacts, ofpacts, ofpacts_len); return actions; } -static void -rule_actions_destroy_cb(struct rule_actions *actions) -{ - free(actions->ofpacts); - free(actions); -} - -/* Decrements 'actions''s ref_count and frees 'actions' if the ref_count - * reaches 0. */ +/* Free the actions after the RCU quiescent period is reached. */ void -rule_actions_destroy(struct rule_actions *actions) +rule_actions_destroy(const struct rule_actions *actions) { if (actions) { - ovsrcu_postpone(rule_actions_destroy_cb, actions); + ovsrcu_postpone(free, CONST_CAST(struct rule_actions *, actions)); } } @@ -3661,7 +3653,7 @@ handle_flow_stats_request(struct ofconn *ofconn, long long int now = time_msec(); struct ofputil_flow_stats fs; long long int created, used, modified; - struct rule_actions *actions; + const struct rule_actions *actions; enum ofputil_flow_mod_flags flags; ovs_mutex_lock(&rule->mutex); @@ -3702,7 +3694,7 @@ static void flow_stats_ds(struct rule *rule, struct ds *results) { uint64_t packet_count, byte_count; - struct rule_actions *actions; + const struct rule_actions *actions; long long int created, used; rule->ofproto->ofproto_class->rule_get_stats(rule, &packet_count, @@ -3962,7 +3954,8 @@ is_flow_deletion_pending(const struct ofproto *ofproto, HMAP_FOR_EACH_WITH_HASH (op, hmap_node, cls_rule_hash(cls_rule, table_id), &ofproto->deletions) { - if (cls_rule_equal(cls_rule, &op->rule->cr)) { + if (op->rule->table_id == table_id + && cls_rule_equal(cls_rule, &op->rule->cr)) { return true; } } @@ -4244,7 +4237,7 @@ modify_flows__(struct ofproto *ofproto, struct ofconn *ofconn, reset_counters = (fm->flags & OFPUTIL_FF_RESET_COUNTS) != 0; if (actions_changed || reset_counters) { - struct rule_actions *new_actions; + const struct rule_actions *new_actions; op->actions = rule_get_actions(rule); new_actions = rule_actions_create(ofproto, @@ -5939,6 +5932,69 @@ handle_table_mod(struct ofconn *ofconn, const struct ofp_header *oh) return table_mod(ofproto, &tm); } +static enum ofperr +handle_bundle_control(struct ofconn *ofconn, const struct ofp_header *oh) +{ + enum ofperr error; + struct ofputil_bundle_ctrl_msg bctrl; + struct ofpbuf *buf; + struct ofputil_bundle_ctrl_msg reply; + + error = ofputil_decode_bundle_ctrl(oh, &bctrl); + if (error) { + return error; + } + reply.flags = 0; + reply.bundle_id = bctrl.bundle_id; + + switch (bctrl.type) { + case OFPBCT_OPEN_REQUEST: + error = ofp_bundle_open(ofconn, bctrl.bundle_id, bctrl.flags); + reply.type = OFPBCT_OPEN_REPLY; + break; + case OFPBCT_CLOSE_REQUEST: + error = ofp_bundle_close(ofconn, bctrl.bundle_id, bctrl.flags); + reply.type = OFPBCT_CLOSE_REPLY;; + break; + case OFPBCT_COMMIT_REQUEST: + error = ofp_bundle_commit(ofconn, bctrl.bundle_id, bctrl.flags); + reply.type = OFPBCT_COMMIT_REPLY; + break; + case OFPBCT_DISCARD_REQUEST: + error = ofp_bundle_discard(ofconn, bctrl.bundle_id); + reply.type = OFPBCT_DISCARD_REPLY; + break; + + case OFPBCT_OPEN_REPLY: + case OFPBCT_CLOSE_REPLY: + case OFPBCT_COMMIT_REPLY: + case OFPBCT_DISCARD_REPLY: + return OFPERR_OFPBFC_BAD_TYPE; + break; + } + + if (!error) { + buf = ofputil_encode_bundle_ctrl_reply(oh, &reply); + ofconn_send_reply(ofconn, buf); + } + return error; +} + + +static enum ofperr +handle_bundle_add(struct ofconn *ofconn, const struct ofp_header *oh) +{ + enum ofperr error; + struct ofputil_bundle_add_msg badd; + + error = ofputil_decode_bundle_add(oh, &badd); + if (error) { + return error; + } + + return ofp_bundle_add_message(ofconn, &badd); +} + static enum ofperr handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg) OVS_EXCLUDED(ofproto_mutex) @@ -6071,6 +6127,12 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg) case OFPTYPE_QUEUE_GET_CONFIG_REQUEST: return handle_queue_get_config_request(ofconn, oh); + case OFPTYPE_BUNDLE_CONTROL: + return handle_bundle_control(ofconn, oh); + + case OFPTYPE_BUNDLE_ADD_MESSAGE: + return handle_bundle_add(ofconn, oh); + case OFPTYPE_HELLO: case OFPTYPE_ERROR: case OFPTYPE_FEATURES_REPLY: @@ -6342,7 +6404,7 @@ ofopgroup_complete(struct ofopgroup *group) rule->hard_timeout = op->hard_timeout; ovs_mutex_unlock(&rule->mutex); if (op->actions) { - struct rule_actions *old_actions; + const struct rule_actions *old_actions; ovs_mutex_lock(&rule->mutex); old_actions = rule_get_actions(rule); @@ -6918,7 +6980,7 @@ oftable_insert_rule(struct rule *rule) { struct ofproto *ofproto = rule->ofproto; struct oftable *table = &ofproto->tables[rule->table_id]; - struct rule_actions *actions; + const struct rule_actions *actions; bool may_expire; ovs_mutex_lock(&rule->mutex); @@ -7000,25 +7062,30 @@ ofproto_unixctl_init(void) void ofproto_get_vlan_usage(struct ofproto *ofproto, unsigned long int *vlan_bitmap) { + struct match match; + struct cls_rule target; const struct oftable *oftable; + match_init_catchall(&match); + match_set_vlan_vid_masked(&match, htons(VLAN_CFI), htons(VLAN_CFI)); + cls_rule_init(&target, &match, 0); + free(ofproto->vlan_bitmap); ofproto->vlan_bitmap = bitmap_allocate(4096); ofproto->vlans_changed = false; OFPROTO_FOR_EACH_TABLE (oftable, ofproto) { - const struct cls_subtable *table; + struct cls_cursor cursor; + struct rule *rule; fat_rwlock_rdlock(&oftable->cls.rwlock); - HMAP_FOR_EACH (table, hmap_node, &oftable->cls.subtables) { - if (minimask_get_vid_mask(&table->mask) == VLAN_VID_MASK) { - const struct cls_rule *rule; - - HMAP_FOR_EACH (rule, hmap_node, &table->rules) { - uint16_t vid = miniflow_get_vid(&rule->match.flow); - bitmap_set1(vlan_bitmap, vid); - bitmap_set1(ofproto->vlan_bitmap, vid); - } + cls_cursor_init(&cursor, &oftable->cls, &target); + CLS_CURSOR_FOR_EACH (rule, cr, &cursor) { + if (minimask_get_vid_mask(&rule->cr.match.mask) == VLAN_VID_MASK) { + uint16_t vid = miniflow_get_vid(&rule->cr.match.flow); + + bitmap_set1(vlan_bitmap, vid); + bitmap_set1(ofproto->vlan_bitmap, vid); } } fat_rwlock_unlock(&oftable->cls.rwlock);