X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=bd31b7605f4786e4bb7376178cef719fca49c2be;hb=f9bfea1402fb4776e505eba7bb712c8355e01e70;hp=cd1bc8a2bf1e590ac47fc5249616080b3717f686;hpb=8054fc48f9a620aa07714a70f6ec301e0d8ec4ee;p=openvswitch diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index cd1bc8a2..bd31b760 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -64,12 +64,6 @@ VLOG_DEFINE_THIS_MODULE(ofproto); #include "sflow_api.h" -enum { - TABLEID_HASH = 0, - TABLEID_CLASSIFIER = 1 -}; - - struct ofport { struct hmap_node hmap_node; /* In struct ofproto's "ports" hmap. */ struct netdev *netdev; @@ -296,7 +290,7 @@ struct ofproto { bool need_revalidate; long long int next_expiration; struct tag_set revalidate_set; - bool tun_id_from_cookie; + int flow_format; /* One of NXFF_*. */ /* OpenFlow connections. */ struct hmap controllers; /* Controller "struct ofconn"s. */ @@ -404,6 +398,7 @@ ofproto_create(const char *datapath, const char *datapath_type, p->need_revalidate = false; p->next_expiration = time_msec() + 1000; tag_set_init(&p->revalidate_set); + p->flow_format = NXFF_OPENFLOW10; /* Initialize OpenFlow connections. */ list_init(&p->all_conns); @@ -1323,11 +1318,12 @@ void ofproto_delete_flow(struct ofproto *ofproto, const struct flow *flow, uint32_t wildcards, unsigned int priority) { + struct cls_rule target; struct rule *rule; + cls_rule_from_flow(flow, wildcards, priority, &target); rule = rule_from_cls_rule(classifier_find_rule_exactly(&ofproto->cls, - flow, wildcards, - priority)); + &target)); if (rule) { rule_remove(ofproto, rule); } @@ -2064,7 +2060,11 @@ rule_create_subrule(struct ofproto *ofproto, struct rule *rule, COVERAGE_INC(ofproto_subrule_create); cls_rule_from_flow(flow, 0, (rule->cr.priority <= UINT16_MAX ? UINT16_MAX : rule->cr.priority), &subrule->cr); - classifier_insert_exact(&ofproto->cls, &subrule->cr); + + if (classifier_insert(&ofproto->cls, &subrule->cr)) { + /* Can't happen, */ + NOT_REACHED(); + } return subrule; } @@ -2298,34 +2298,15 @@ queue_tx(struct ofpbuf *msg, const struct ofconn *ofconn, } } -static void -send_error(const struct ofconn *ofconn, const struct ofp_header *oh, - int error, const void *data, size_t len) -{ - struct ofpbuf *buf; - struct ofp_error_msg *oem; - - if (!(error >> 16)) { - VLOG_WARN_RL(&rl, "not sending bad error code %d to controller", - error); - return; - } - - COVERAGE_INC(ofproto_error); - oem = make_openflow_xid(len + sizeof *oem, OFPT_ERROR, - oh ? oh->xid : 0, &buf); - oem->type = htons((unsigned int) error >> 16); - oem->code = htons(error & 0xffff); - memcpy(oem->data, data, len); - queue_tx(buf, ofconn, ofconn->reply_counter); -} - static void send_error_oh(const struct ofconn *ofconn, const struct ofp_header *oh, int error) { - size_t oh_length = ntohs(oh->length); - send_error(ofconn, oh, error, oh, MIN(oh_length, 64)); + struct ofpbuf *buf = make_ofp_error_msg(error, oh); + if (buf) { + COVERAGE_INC(ofproto_error); + queue_tx(buf, ofconn, ofconn->reply_counter); + } } static void @@ -2495,7 +2476,8 @@ static struct rule * lookup_valid_rule(struct ofproto *ofproto, const struct flow *flow) { struct rule *rule; - rule = rule_from_cls_rule(classifier_lookup(&ofproto->cls, flow)); + rule = rule_from_cls_rule(classifier_lookup(&ofproto->cls, flow, + CLS_INC_ALL)); /* The rule we found might not be valid, since we could be in need of * revalidation. If it is not valid, don't return it. */ @@ -3068,44 +3050,27 @@ handle_table_stats_request(struct ofproto *p, struct ofconn *ofconn, { struct ofp_table_stats *ots; struct ofpbuf *msg; - struct odp_stats dpstats; - int n_exact, n_subrules, n_wild; struct rule *rule; + int n_rules; msg = start_stats_reply(request, sizeof *ots * 2); - /* Count rules of various kinds. */ - n_subrules = 0; + /* Count rules other than subrules. */ + n_rules = classifier_count(&p->cls); CLASSIFIER_FOR_EACH_EXACT_RULE (rule, cr, &p->cls) { if (rule->super) { - n_subrules++; + n_rules--; } } - n_exact = classifier_count_exact(&p->cls) - n_subrules; - n_wild = classifier_count(&p->cls) - classifier_count_exact(&p->cls); - - /* Hash table. */ - dpif_get_dp_stats(p->dpif, &dpstats); - ots = append_stats_reply(sizeof *ots, ofconn, &msg); - memset(ots, 0, sizeof *ots); - ots->table_id = TABLEID_HASH; - strcpy(ots->name, "hash"); - ots->wildcards = htonl(0); - ots->max_entries = htonl(dpstats.max_capacity); - ots->active_count = htonl(n_exact); - ots->lookup_count = htonll(dpstats.n_frags + dpstats.n_hit + - dpstats.n_missed); - ots->matched_count = htonll(dpstats.n_hit); /* XXX */ /* Classifier table. */ ots = append_stats_reply(sizeof *ots, ofconn, &msg); memset(ots, 0, sizeof *ots); - ots->table_id = TABLEID_CLASSIFIER; strcpy(ots->name, "classifier"); - ots->wildcards = p->tun_id_from_cookie ? htonl(OVSFW_ALL) - : htonl(OFPFW_ALL); - ots->max_entries = htonl(65536); - ots->active_count = htonl(n_wild); + ots->wildcards = (p->flow_format == NXFF_OPENFLOW10 + ? htonl(OFPFW_ALL) : htonl(OVSFW_ALL)); + ots->max_entries = htonl(1024 * 1024); /* An arbitrary big number. */ + ots->active_count = htonl(n_rules); ots->lookup_count = htonll(0); /* XXX */ ots->matched_count = htonll(0); /* XXX */ @@ -3257,10 +3222,10 @@ flow_stats_cb(struct cls_rule *rule_, void *cbdata_) ofs = append_stats_reply(len, cbdata->ofconn, &cbdata->msg); ofs->length = htons(len); - ofs->table_id = rule->cr.wc.wildcards ? TABLEID_CLASSIFIER : TABLEID_HASH; + ofs->table_id = 0; ofs->pad = 0; flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, - cbdata->ofproto->tun_id_from_cookie, &ofs->match); + cbdata->ofproto->flow_format, &ofs->match); ofs->duration_sec = htonl(sec); ofs->duration_nsec = htonl(msec * 1000000); ofs->cookie = rule->flow_cookie; @@ -3278,10 +3243,7 @@ flow_stats_cb(struct cls_rule *rule_, void *cbdata_) static int table_id_to_include(uint8_t table_id) { - return (table_id == TABLEID_HASH ? CLS_INC_EXACT - : table_id == TABLEID_CLASSIFIER ? CLS_INC_WILD - : table_id == 0xff ? CLS_INC_ALL - : 0); + return table_id == 0 || table_id == 0xff ? CLS_INC_ALL : 0; } static int @@ -3303,7 +3265,7 @@ handle_flow_stats_request(struct ofproto *p, struct ofconn *ofconn, cbdata.ofconn = ofconn; cbdata.out_port = fsr->out_port; cbdata.msg = start_stats_reply(osr, 1024); - cls_rule_from_match(&fsr->match, 0, false, 0, &target); + cls_rule_from_match(&fsr->match, 0, NXFF_OPENFLOW10, 0, &target); classifier_for_each_match(&p->cls, &target, table_id_to_include(fsr->table_id), flow_stats_cb, &cbdata); @@ -3333,7 +3295,7 @@ flow_stats_ds_cb(struct cls_rule *rule_, void *cbdata_) query_stats(cbdata->ofproto, rule, &packet_count, &byte_count); flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, - cbdata->ofproto->tun_id_from_cookie, &match); + cbdata->ofproto->flow_format, &match); ds_put_format(results, "duration=%llds, ", (time_msec() - rule->created) / 1000); @@ -3364,7 +3326,7 @@ ofproto_get_all_flows(struct ofproto *p, struct ds *results) cbdata.ofproto = p; cbdata.results = results; - cls_rule_from_match(&match, 0, false, 0, &target); + cls_rule_from_match(&match, 0, NXFF_OPENFLOW10, 0, &target); classifier_for_each_match(&p->cls, &target, CLS_INC_ALL, flow_stats_ds_cb, &cbdata); } @@ -3417,7 +3379,7 @@ handle_aggregate_stats_request(struct ofproto *p, struct ofconn *ofconn, cbdata.packet_count = 0; cbdata.byte_count = 0; cbdata.n_flows = 0; - cls_rule_from_match(&asr->match, 0, false, 0, &target); + cls_rule_from_match(&asr->match, 0, NXFF_OPENFLOW10, 0, &target); classifier_for_each_match(&p->cls, &target, table_id_to_include(asr->table_id), aggregate_stats_cb, &cbdata); @@ -3613,13 +3575,11 @@ add_flow(struct ofproto *p, struct ofconn *ofconn, int error; if (ofm->flags & htons(OFPFF_CHECK_OVERLAP)) { - struct flow flow; - uint32_t wildcards; + struct cls_rule cr; - flow_from_match(&ofm->match, p->tun_id_from_cookie, ofm->cookie, - &flow, &wildcards); - if (classifier_rule_overlaps(&p->cls, &flow, wildcards, - ntohs(ofm->priority))) { + cls_rule_from_match(&ofm->match, ntohs(ofm->priority), + p->flow_format, ofm->cookie, &cr); + if (classifier_rule_overlaps(&p->cls, &cr)) { return ofp_mkerr(OFPET_FLOW_MOD_FAILED, OFPFMFC_OVERLAP); } } @@ -3629,7 +3589,7 @@ add_flow(struct ofproto *p, struct ofconn *ofconn, ntohs(ofm->hard_timeout), ofm->cookie, ofm->flags & htons(OFPFF_SEND_FLOW_REM)); cls_rule_from_match(&ofm->match, ntohs(ofm->priority), - p->tun_id_from_cookie, ofm->cookie, &rule->cr); + p->flow_format, ofm->cookie, &rule->cr); error = 0; if (ofm->buffer_id != htonl(UINT32_MAX)) { @@ -3647,14 +3607,11 @@ add_flow(struct ofproto *p, struct ofconn *ofconn, static struct rule * find_flow_strict(struct ofproto *p, const struct ofp_flow_mod *ofm) { - uint32_t wildcards; - struct flow flow; + struct cls_rule target; - flow_from_match(&ofm->match, p->tun_id_from_cookie, ofm->cookie, - &flow, &wildcards); - return rule_from_cls_rule(classifier_find_rule_exactly( - &p->cls, &flow, wildcards, - ntohs(ofm->priority))); + cls_rule_from_match(&ofm->match, ntohs(ofm->priority), + p->flow_format, ofm->cookie, &target); + return rule_from_cls_rule(classifier_find_rule_exactly(&p->cls, &target)); } static int @@ -3712,8 +3669,7 @@ modify_flows_loose(struct ofproto *p, struct ofconn *ofconn, cbdata.n_actions = n_actions; cbdata.match = NULL; - cls_rule_from_match(&ofm->match, 0, p->tun_id_from_cookie, ofm->cookie, - &target); + cls_rule_from_match(&ofm->match, 0, p->flow_format, ofm->cookie, &target); classifier_for_each_match(&p->cls, &target, CLS_INC_ALL, modify_flows_cb, &cbdata); @@ -3814,8 +3770,7 @@ delete_flows_loose(struct ofproto *p, const struct ofp_flow_mod *ofm) cbdata.ofproto = p; cbdata.out_port = ofm->out_port; - cls_rule_from_match(&ofm->match, 0, p->tun_id_from_cookie, ofm->cookie, - &target); + cls_rule_from_match(&ofm->match, 0, p->flow_format, ofm->cookie, &target); classifier_for_each_match(&p->cls, &target, CLS_INC_ALL, delete_flows_cb, &cbdata); @@ -3952,7 +3907,7 @@ handle_tun_id_from_cookie(struct ofproto *p, struct nxt_tun_id_cookie *msg) return error; } - p->tun_id_from_cookie = !!msg->set; + p->flow_format = msg->set ? NXFF_TUN_ID_FROM_COOKIE : NXFF_OPENFLOW10; return 0; } @@ -3998,10 +3953,8 @@ handle_role_request(struct ofproto *ofproto, } ofconn->role = role; - reply = make_openflow_xid(sizeof *reply, OFPT_VENDOR, msg->header.xid, - &buf); - reply->nxh.vendor = htonl(NX_VENDOR_ID); - reply->nxh.subtype = htonl(NXT_ROLE_REPLY); + reply = make_nxmsg_xid(sizeof *reply, NXT_ROLE_REPLY, msg->header.xid, + &buf); reply->role = htonl(role); queue_tx(buf, ofconn, ofconn->reply_counter); @@ -4294,13 +4247,15 @@ ofproto_update_used(struct ofproto *p) for (i = 0; i < n_flows; i++) { struct odp_flow *f = &flows[i]; + struct cls_rule target; struct rule *rule; struct flow flow; odp_flow_key_to_flow(&f->key, &flow); + cls_rule_from_flow(&flow, 0, UINT16_MAX, &target); - rule = rule_from_cls_rule( - classifier_find_rule_exactly(&p->cls, &flow, 0, UINT16_MAX)); + rule = rule_from_cls_rule(classifier_find_rule_exactly(&p->cls, + &target)); if (rule && rule->installed) { update_time(p, rule, &f->stats); @@ -4536,7 +4491,8 @@ revalidate_rule(struct ofproto *p, struct rule *rule) COVERAGE_INC(ofproto_revalidate_rule); if (rule->super) { struct rule *super; - super = rule_from_cls_rule(classifier_lookup_wild(&p->cls, flow)); + super = rule_from_cls_rule(classifier_lookup(&p->cls, flow, + CLS_INC_WILD)); if (!super) { rule_remove(p, rule); return false; @@ -4567,7 +4523,7 @@ compose_flow_removed(struct ofproto *p, const struct rule *rule, uint32_t msec = tdiff - (sec * 1000); ofr = make_openflow(sizeof *ofr, OFPT_FLOW_REMOVED, &buf); - flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, p->tun_id_from_cookie, + flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, p->flow_format, &ofr->match); ofr->cookie = rule->flow_cookie; ofr->priority = htons(rule->cr.priority); @@ -4586,33 +4542,27 @@ send_flow_removed(struct ofproto *p, struct rule *rule, long long int now, uint8_t reason) { struct ofconn *ofconn; - struct ofconn *prev; - struct ofpbuf *buf = NULL; if (!rule->send_flow_removed) { return; } - /* We limit the maximum number of queued flow expirations it by accounting - * them under the counter for replies. That works because preventing - * OpenFlow requests from being processed also prevents new flows from - * being added (and expiring). (It also prevents processing OpenFlow - * requests that would not add new flows, so it is imperfect.) */ - - prev = NULL; LIST_FOR_EACH (ofconn, node, &p->all_conns) { - if (rconn_is_connected(ofconn->rconn) - && ofconn_receives_async_msgs(ofconn)) { - if (prev) { - queue_tx(ofpbuf_clone(buf), prev, prev->reply_counter); - } else { - buf = compose_flow_removed(p, rule, now, reason); - } - prev = ofconn; + struct ofpbuf *msg; + + if (!rconn_is_connected(ofconn->rconn) + || !ofconn_receives_async_msgs(ofconn)) { + continue; } - } - if (prev) { - queue_tx(buf, prev, prev->reply_counter); + + msg = compose_flow_removed(p, rule, now, reason); + + /* Account flow expirations under ofconn->reply_counter, the counter + * for replies to OpenFlow requests. That works because preventing + * OpenFlow requests from being processed also prevents new flows from + * being added (and expiring). (It also prevents processing OpenFlow + * requests that would not add new flows, so it is imperfect.) */ + queue_tx(msg, ofconn, ofconn->reply_counter); } }