X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=3da2a7444d0af08ac07e58a764a95b5bd6e17df4;hb=a23aab1fc2f66b63ba9b7e4b9c9a8f6d58c367d0;hp=5e99fcab188390d276a5e9a80407118b20609aa6;hpb=9628cd42d45f47b17c5273a75db79826f1672c82;p=openvswitch diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 5e99fcab..3da2a744 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -24,6 +24,7 @@ #include #include #include +#include "byte-order.h" #include "classifier.h" #include "coverage.h" #include "discovery.h" @@ -58,18 +59,11 @@ #include "unixctl.h" #include "vconn.h" #include "vlog.h" -#include "xtoxll.h" -VLOG_DEFINE_THIS_MODULE(ofproto) +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; @@ -89,8 +83,7 @@ static int xlate_actions(const union ofp_action *in, size_t n_in, struct rule { struct cls_rule cr; - uint64_t flow_cookie; /* Controller-issued identifier. - (Kept in network-byte order.) */ + ovs_be64 flow_cookie; /* Controller-issued identifier. */ uint16_t idle_timeout; /* In seconds from time of last use. */ uint16_t hard_timeout; /* In seconds from time of creation. */ bool send_flow_removed; /* Send a flow removed message? */ @@ -155,7 +148,7 @@ rule_is_hidden(const struct rule *rule) static struct rule *rule_create(struct ofproto *, struct rule *super, const union ofp_action *, size_t n_actions, uint16_t idle_timeout, uint16_t hard_timeout, - uint64_t flow_cookie, bool send_flow_removed); + ovs_be64 flow_cookie, bool send_flow_removed); static void rule_free(struct rule *); static void rule_destroy(struct ofproto *, struct rule *); static struct rule *rule_from_cls_rule(const struct cls_rule *); @@ -1277,6 +1270,15 @@ ofproto_port_del(struct ofproto *ofproto, uint16_t odp_port) return error; } +/* Checks if 'ofproto' thinks 'odp_port' should be included in floods. Returns + * true if 'odp_port' exists and should be included, false otherwise. */ +bool +ofproto_port_is_floodable(struct ofproto *ofproto, uint16_t odp_port) +{ + struct ofport *ofport = get_port(ofproto, odp_port); + return ofport && !(ofport->opp.config & OFPPC_NO_FLOOD); +} + int ofproto_send_packet(struct ofproto *p, const struct flow *flow, const union ofp_action *actions, size_t n_actions, @@ -1315,11 +1317,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); } @@ -1363,6 +1366,8 @@ reinit_ports(struct ofproto *p) size_t n_odp_ports; size_t i; + COVERAGE_INC(ofproto_reinit_ports); + svec_init(&devnames); HMAP_FOR_EACH (ofport, hmap_node, &p->ports) { svec_add (&devnames, (char *) ofport->opp.name); @@ -1387,7 +1392,6 @@ make_ofport(const struct odp_port *odp_port) enum netdev_flags flags; struct ofport *ofport; struct netdev *netdev; - bool carrier; int error; memset(&netdev_options, 0, sizeof netdev_options); @@ -1415,8 +1419,7 @@ make_ofport(const struct odp_port *odp_port) netdev_get_flags(netdev, &flags); ofport->opp.config = flags & NETDEV_UP ? 0 : OFPPC_PORT_DOWN; - netdev_get_carrier(netdev, &carrier); - ofport->opp.state = carrier ? 0 : OFPPS_LINK_DOWN; + ofport->opp.state = netdev_get_carrier(netdev) ? 0 : OFPPS_LINK_DOWN; netdev_get_features(netdev, &ofport->opp.curr, &ofport->opp.advertised, @@ -1836,7 +1839,7 @@ static struct rule * rule_create(struct ofproto *ofproto, struct rule *super, const union ofp_action *actions, size_t n_actions, uint16_t idle_timeout, uint16_t hard_timeout, - uint64_t flow_cookie, bool send_flow_removed) + ovs_be64 flow_cookie, bool send_flow_removed) { struct rule *rule = xzalloc(sizeof *rule); rule->idle_timeout = idle_timeout; @@ -1897,7 +1900,7 @@ rule_destroy(struct ofproto *ofproto, struct rule *rule) } static bool -rule_has_out_port(const struct rule *rule, uint16_t out_port) +rule_has_out_port(const struct rule *rule, ovs_be16 out_port) { const union ofp_action *oa; struct actions_iterator i; @@ -2056,7 +2059,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; } @@ -2290,34 +2297,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 @@ -2487,7 +2475,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. */ @@ -2759,16 +2748,15 @@ do_xlate_actions(const union ofp_action *in, size_t n_in, case OFPAT_SET_VLAN_VID: oa = odp_actions_add(ctx->out, ODPAT_SET_DL_TCI); - oa->dl_tci.tci = ia->vlan_vid.vlan_vid & htons(VLAN_VID_MASK); - oa->dl_tci.mask = htons(VLAN_VID_MASK); + oa->dl_tci.tci = ia->vlan_vid.vlan_vid; + oa->dl_tci.tci |= htons(ctx->flow.dl_vlan_pcp << VLAN_PCP_SHIFT); ctx->flow.dl_vlan = ia->vlan_vid.vlan_vid; break; case OFPAT_SET_VLAN_PCP: oa = odp_actions_add(ctx->out, ODPAT_SET_DL_TCI); - oa->dl_tci.tci = htons((ia->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT) - & VLAN_PCP_MASK); - oa->dl_tci.mask = htons(VLAN_PCP_MASK); + oa->dl_tci.tci = htons(ia->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT); + oa->dl_tci.tci |= ctx->flow.dl_vlan; ctx->flow.dl_vlan_pcp = ia->vlan_pcp.vlan_pcp; break; @@ -2937,14 +2925,12 @@ handle_packet_out(struct ofproto *p, struct ofconn *ofconn, flow_extract(&payload, 0, ofp_port_to_odp_port(ntohs(opo->in_port)), &flow); error = xlate_actions((const union ofp_action *) opo->actions, n_actions, &flow, p, &payload, &actions, NULL, NULL, NULL); - if (error) { - return error; + if (!error) { + dpif_execute(p->dpif, actions.actions, actions.n_actions, &payload); } - - dpif_execute(p->dpif, actions.actions, actions.n_actions, &payload); ofpbuf_delete(buffer); - return 0; + return error; } static void @@ -3005,7 +2991,7 @@ handle_port_mod(struct ofproto *p, struct ofconn *ofconn, } static struct ofpbuf * -make_stats_reply(uint32_t xid, uint16_t type, size_t body_len) +make_stats_reply(ovs_be32 xid, ovs_be16 type, size_t body_len) { struct ofp_stats_reply *osr; struct ofpbuf *msg; @@ -3063,44 +3049,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->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 */ @@ -3171,7 +3140,7 @@ handle_port_stats_request(struct ofproto *p, struct ofconn *ofconn, struct flow_stats_cbdata { struct ofproto *ofproto; struct ofconn *ofconn; - uint16_t out_port; + ovs_be16 out_port; struct ofpbuf *msg; }; @@ -3252,7 +3221,7 @@ 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); @@ -3273,10 +3242,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 @@ -3338,6 +3304,8 @@ flow_stats_ds_cb(struct cls_rule *rule_, void *cbdata_) ofp_print_match(results, &match, true); if (act_len > 0) { ofp_print_actions(results, &rule->actions->header, act_len); + } else { + ds_put_cstr(results, "drop"); } ds_put_cstr(results, "\n"); } @@ -3364,7 +3332,7 @@ ofproto_get_all_flows(struct ofproto *p, struct ds *results) struct aggregate_stats_cbdata { struct ofproto *ofproto; - uint16_t out_port; + ovs_be16 out_port; uint64_t packet_count; uint64_t byte_count; uint32_t n_flows; @@ -3606,13 +3574,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->tun_id_from_cookie, ofm->cookie, &cr); + if (classifier_rule_overlaps(&p->cls, &cr)) { return ofp_mkerr(OFPET_FLOW_MOD_FAILED, OFPFMFC_OVERLAP); } } @@ -3640,14 +3606,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->tun_id_from_cookie, ofm->cookie, &target); + return rule_from_cls_rule(classifier_find_rule_exactly(&p->cls, &target)); } static int @@ -3791,11 +3754,11 @@ modify_flow(struct ofproto *p, const struct ofp_flow_mod *ofm, struct delete_flows_cbdata { struct ofproto *ofproto; - uint16_t out_port; + ovs_be16 out_port; }; static void delete_flows_cb(struct cls_rule *, void *cbdata_); -static void delete_flow(struct ofproto *, struct rule *, uint16_t out_port); +static void delete_flow(struct ofproto *, struct rule *, ovs_be16 out_port); /* Implements OFPFC_DELETE. */ static void @@ -3843,7 +3806,7 @@ delete_flows_cb(struct cls_rule *rule_, void *cbdata_) * 'out_port' is htons(OFPP_NONE) or if 'rule' actually outputs to the * specified 'out_port'. */ static void -delete_flow(struct ofproto *p, struct rule *rule, uint16_t out_port) +delete_flow(struct ofproto *p, struct rule *rule, ovs_be16 out_port) { if (rule_is_hidden(rule)) { return; @@ -4287,13 +4250,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); @@ -4529,7 +4494,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;