X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=ba9ef1903db12d59260fbd2a170010e6bfaca885;hb=f7de2cdffcadaca5f62003f9c115052aa295aa70;hp=fd1256fc7ac6343b78772c9d9993c7bcb6fbdd25;hpb=79eee1eb33caa89ced4a03c2f486d94cd1b6930f;p=openvswitch diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index fd1256fc..ba9ef190 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -219,6 +219,7 @@ struct ofproto { bool need_revalidate; long long int next_expiration; struct tag_set revalidate_set; + bool tun_id_from_cookie; /* OpenFlow connections. */ struct list all_conns; @@ -717,8 +718,9 @@ ofproto_destroy(struct ofproto *p) return; } - /* Destroy fail-open early, because it touches the classifier. */ + /* Destroy fail-open and in-band early, since they touch the classifier. */ ofproto_set_failure(p, false); + ofproto_set_in_band(p, false); ofproto_flush_flows(p); classifier_destroy(&p->cls); @@ -736,7 +738,6 @@ ofproto_destroy(struct ofproto *p) shash_destroy(&p->port_by_name); switch_status_destroy(p->switch_status); - in_band_destroy(p->in_band); discovery_destroy(p->discovery); pinsched_destroy(p->miss_sched); pinsched_destroy(p->action_sched); @@ -1029,7 +1030,7 @@ ofproto_add_flow(struct ofproto *p, rule = rule_create(p, NULL, actions, n_actions, idle_timeout >= 0 ? idle_timeout : 5 /* XXX */, 0, 0, false); - cls_rule_from_flow(&rule->cr, flow, wildcards, priority); + cls_rule_from_flow(flow, wildcards, priority, &rule->cr); rule_insert(p, rule, NULL, 0); } @@ -1583,7 +1584,7 @@ rule_insert(struct ofproto *p, struct rule *rule, struct ofpbuf *packet, /* Send the packet and credit it to the rule. */ if (packet) { flow_t flow; - flow_extract(packet, in_port, &flow); + flow_extract(packet, 0, in_port, &flow); rule_execute(p, rule, packet, &flow); } @@ -1610,9 +1611,8 @@ rule_create_subrule(struct ofproto *ofproto, struct rule *rule, rule->idle_timeout, rule->hard_timeout, 0, false); COVERAGE_INC(ofproto_subrule_create); - cls_rule_from_flow(&subrule->cr, flow, 0, - (rule->cr.priority <= UINT16_MAX ? UINT16_MAX - : rule->cr.priority)); + 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); return subrule; @@ -1669,6 +1669,7 @@ do_put_flow(struct ofproto *ofproto, struct rule *rule, int flags, put->flow.key = rule->cr.flow; put->flow.actions = rule->odp_actions; put->flow.n_actions = rule->n_odp_actions; + put->flow.flags = 0; put->flags = flags; return dpif_flow_put(ofproto->dpif, put); } @@ -1764,6 +1765,7 @@ rule_uninstall(struct ofproto *p, struct rule *rule) odp_flow.key = rule->cr.flow; odp_flow.actions = NULL; odp_flow.n_actions = 0; + odp_flow.flags = 0; if (!dpif_flow_del(p->dpif, &odp_flow)) { update_stats(p, rule, &odp_flow.stats); } @@ -1999,7 +2001,7 @@ add_controller_action(struct odp_actions *actions, struct action_xlate_ctx { /* Input. */ - const flow_t *flow; /* Flow to which these actions correspond. */ + flow_t flow; /* Flow to which these actions correspond. */ int recurse; /* Recursion level, via xlate_table_action. */ struct ofproto *ofproto; const struct ofpbuf *packet; /* The packet corresponding to 'flow', or a @@ -2062,13 +2064,17 @@ static void xlate_table_action(struct action_xlate_ctx *ctx, uint16_t in_port) { if (!ctx->recurse) { + uint16_t old_in_port; struct rule *rule; - flow_t flow; - flow = *ctx->flow; - flow.in_port = in_port; + /* Look up a flow with 'in_port' as the input port. Then restore the + * original input port (otherwise OFPP_NORMAL and OFPP_IN_PORT will + * have surprising behavior). */ + old_in_port = ctx->flow.in_port; + ctx->flow.in_port = in_port; + rule = lookup_valid_rule(ctx->ofproto, &ctx->flow); + ctx->flow.in_port = old_in_port; - rule = lookup_valid_rule(ctx->ofproto, &flow); if (rule) { if (rule->super) { rule = rule->super; @@ -2092,13 +2098,13 @@ xlate_output_action(struct action_xlate_ctx *ctx, switch (ntohs(oao->port)) { case OFPP_IN_PORT: - add_output_action(ctx, ctx->flow->in_port); + add_output_action(ctx, ctx->flow.in_port); break; case OFPP_TABLE: - xlate_table_action(ctx, ctx->flow->in_port); + xlate_table_action(ctx, ctx->flow.in_port); break; case OFPP_NORMAL: - if (!ctx->ofproto->ofhooks->normal_cb(ctx->flow, ctx->packet, + if (!ctx->ofproto->ofhooks->normal_cb(&ctx->flow, ctx->packet, ctx->out, ctx->tags, &ctx->nf_output_iface, ctx->ofproto->aux)) { @@ -2121,7 +2127,7 @@ xlate_output_action(struct action_xlate_ctx *ctx, break; default: odp_port = ofp_port_to_odp_port(ntohs(oao->port)); - if (odp_port != ctx->flow->in_port) { + if (odp_port != ctx->flow.in_port) { add_output_action(ctx, odp_port); } break; @@ -2142,6 +2148,8 @@ xlate_nicira_action(struct action_xlate_ctx *ctx, const struct nx_action_header *nah) { const struct nx_action_resubmit *nar; + const struct nx_action_set_tunnel *nast; + union odp_action *oa; int subtype = ntohs(nah->subtype); assert(nah->vendor == htonl(NX_VENDOR_ID)); @@ -2151,6 +2159,15 @@ xlate_nicira_action(struct action_xlate_ctx *ctx, xlate_table_action(ctx, ofp_port_to_odp_port(ntohs(nar->in_port))); break; + case NXAST_SET_TUNNEL: + nast = (const struct nx_action_set_tunnel *) nah; + oa = odp_actions_add(ctx->out, ODPAT_SET_TUNNEL); + ctx->flow.tun_id = oa->tunnel.tun_id = nast->tun_id; + break; + + /* If you add a new action here that modifies flow data, don't forget to + * update the flow key in ctx->flow in the same key. */ + default: VLOG_DBG_RL(&rl, "unknown Nicira action type %"PRIu16, subtype); break; @@ -2165,9 +2182,9 @@ do_xlate_actions(const union ofp_action *in, size_t n_in, const union ofp_action *ia; const struct ofport *port; - port = port_array_get(&ctx->ofproto->ports, ctx->flow->in_port); + port = port_array_get(&ctx->ofproto->ports, ctx->flow.in_port); if (port && port->opp.config & (OFPPC_NO_RECV | OFPPC_NO_RECV_STP) && - port->opp.config & (eth_addr_equals(ctx->flow->dl_dst, stp_eth_addr) + port->opp.config & (eth_addr_equals(ctx->flow.dl_dst, stp_eth_addr) ? OFPPC_NO_RECV_STP : OFPPC_NO_RECV)) { /* Drop this flow. */ return; @@ -2184,53 +2201,59 @@ 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_VLAN_VID); - oa->vlan_vid.vlan_vid = ia->vlan_vid.vlan_vid; + ctx->flow.dl_vlan = oa->vlan_vid.vlan_vid = ia->vlan_vid.vlan_vid; break; case OFPAT_SET_VLAN_PCP: oa = odp_actions_add(ctx->out, ODPAT_SET_VLAN_PCP); - oa->vlan_pcp.vlan_pcp = ia->vlan_pcp.vlan_pcp; + ctx->flow.dl_vlan_pcp = oa->vlan_pcp.vlan_pcp = ia->vlan_pcp.vlan_pcp; break; case OFPAT_STRIP_VLAN: odp_actions_add(ctx->out, ODPAT_STRIP_VLAN); + ctx->flow.dl_vlan = OFP_VLAN_NONE; + ctx->flow.dl_vlan_pcp = 0; break; case OFPAT_SET_DL_SRC: oa = odp_actions_add(ctx->out, ODPAT_SET_DL_SRC); memcpy(oa->dl_addr.dl_addr, ((struct ofp_action_dl_addr *) ia)->dl_addr, ETH_ADDR_LEN); + memcpy(ctx->flow.dl_src, + ((struct ofp_action_dl_addr *) ia)->dl_addr, ETH_ADDR_LEN); break; case OFPAT_SET_DL_DST: oa = odp_actions_add(ctx->out, ODPAT_SET_DL_DST); memcpy(oa->dl_addr.dl_addr, ((struct ofp_action_dl_addr *) ia)->dl_addr, ETH_ADDR_LEN); + memcpy(ctx->flow.dl_dst, + ((struct ofp_action_dl_addr *) ia)->dl_addr, ETH_ADDR_LEN); break; case OFPAT_SET_NW_SRC: oa = odp_actions_add(ctx->out, ODPAT_SET_NW_SRC); - oa->nw_addr.nw_addr = ia->nw_addr.nw_addr; + ctx->flow.nw_src = oa->nw_addr.nw_addr = ia->nw_addr.nw_addr; break; case OFPAT_SET_NW_DST: oa = odp_actions_add(ctx->out, ODPAT_SET_NW_DST); - oa->nw_addr.nw_addr = ia->nw_addr.nw_addr; + ctx->flow.nw_dst = oa->nw_addr.nw_addr = ia->nw_addr.nw_addr; break; case OFPAT_SET_NW_TOS: oa = odp_actions_add(ctx->out, ODPAT_SET_NW_TOS); - oa->nw_tos.nw_tos = ia->nw_tos.nw_tos; + ctx->flow.nw_tos = oa->nw_tos.nw_tos = ia->nw_tos.nw_tos; break; case OFPAT_SET_TP_SRC: oa = odp_actions_add(ctx->out, ODPAT_SET_TP_SRC); - oa->tp_port.tp_port = ia->tp_port.tp_port; + ctx->flow.tp_src = oa->tp_port.tp_port = ia->tp_port.tp_port; break; case OFPAT_SET_TP_DST: oa = odp_actions_add(ctx->out, ODPAT_SET_TP_DST); - oa->tp_port.tp_port = ia->tp_port.tp_port; + ctx->flow.tp_dst = oa->tp_port.tp_port = ia->tp_port.tp_port; break; case OFPAT_VENDOR: @@ -2255,7 +2278,7 @@ xlate_actions(const union ofp_action *in, size_t n_in, struct action_xlate_ctx ctx; COVERAGE_INC(ofproto_ofp2odp); odp_actions_init(out); - ctx.flow = flow; + ctx.flow = *flow; ctx.recurse = 0; ctx.ofproto = ofproto; ctx.packet = packet; @@ -2314,7 +2337,7 @@ handle_packet_out(struct ofproto *p, struct ofconn *ofconn, buffer = NULL; } - flow_extract(&payload, ofp_port_to_odp_port(ntohs(opo->in_port)), &flow); + 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) { @@ -2483,7 +2506,8 @@ handle_table_stats_request(struct ofproto *p, struct ofconn *ofconn, memset(ots, 0, sizeof *ots); ots->table_id = TABLEID_CLASSIFIER; strcpy(ots->name, "classifier"); - ots->wildcards = htonl(OFPFW_ALL); + 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->lookup_count = htonll(0); /* XXX */ @@ -2641,7 +2665,8 @@ flow_stats_cb(struct cls_rule *rule_, void *cbdata_) ofs->length = htons(len); ofs->table_id = rule->cr.wc.wildcards ? TABLEID_CLASSIFIER : TABLEID_HASH; ofs->pad = 0; - flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, &ofs->match); + flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, + cbdata->ofproto->tun_id_from_cookie, &ofs->match); ofs->duration_sec = htonl(sec); ofs->duration_nsec = htonl(msec * 1000000); ofs->cookie = rule->flow_cookie; @@ -2682,7 +2707,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(&target, &fsr->match, 0); + cls_rule_from_match(&fsr->match, 0, false, 0, &target); classifier_for_each_match(&p->cls, &target, table_id_to_include(fsr->table_id), flow_stats_cb, &cbdata); @@ -2711,7 +2736,8 @@ 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, &match); + flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, + cbdata->ofproto->tun_id_from_cookie, &match); ds_put_format(results, "duration=%llds, ", (time_msec() - rule->created) / 1000); @@ -2733,12 +2759,12 @@ ofproto_get_all_flows(struct ofproto *p, struct ds *results) struct flow_stats_ds_cbdata cbdata; memset(&match, 0, sizeof match); - match.wildcards = htonl(OFPFW_ALL); + match.wildcards = htonl(OVSFW_ALL); cbdata.ofproto = p; cbdata.results = results; - cls_rule_from_match(&target, &match, 0); + cls_rule_from_match(&match, 0, false, 0, &target); classifier_for_each_match(&p->cls, &target, CLS_INC_ALL, flow_stats_ds_cb, &cbdata); } @@ -2791,7 +2817,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(&target, &asr->match, 0); + cls_rule_from_match(&asr->match, 0, false, 0, &target); classifier_for_each_match(&p->cls, &target, table_id_to_include(asr->table_id), aggregate_stats_cb, &cbdata); @@ -2899,7 +2925,8 @@ add_flow(struct ofproto *p, struct ofconn *ofconn, flow_t flow; uint32_t wildcards; - flow_from_match(&flow, &wildcards, &ofm->match); + 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))) { return ofp_mkerr(OFPET_FLOW_MOD_FAILED, OFPFMFC_OVERLAP); @@ -2910,7 +2937,8 @@ add_flow(struct ofproto *p, struct ofconn *ofconn, n_actions, ntohs(ofm->idle_timeout), ntohs(ofm->hard_timeout), ofm->cookie, ofm->flags & htons(OFPFF_SEND_FLOW_REM)); - cls_rule_from_match(&rule->cr, &ofm->match, ntohs(ofm->priority)); + cls_rule_from_match(&ofm->match, ntohs(ofm->priority), + p->tun_id_from_cookie, ofm->cookie, &rule->cr); error = 0; if (ofm->buffer_id != htonl(UINT32_MAX)) { @@ -2932,7 +2960,8 @@ find_flow_strict(struct ofproto *p, const struct ofp_flow_mod *ofm) uint32_t wildcards; flow_t flow; - flow_from_match(&flow, &wildcards, &ofm->match); + 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))); @@ -2957,7 +2986,7 @@ send_buffered_packet(struct ofproto *ofproto, struct ofconn *ofconn, return error; } - flow_extract(packet, in_port, &flow); + flow_extract(packet, 0, in_port, &flow); rule_execute(ofproto, rule, packet, &flow); ofpbuf_delete(packet); @@ -2994,7 +3023,8 @@ modify_flows_loose(struct ofproto *p, struct ofconn *ofconn, cbdata.n_actions = n_actions; cbdata.match = NULL; - cls_rule_from_match(&target, &ofm->match, 0); + cls_rule_from_match(&ofm->match, 0, p->tun_id_from_cookie, ofm->cookie, + &target); classifier_for_each_match(&p->cls, &target, CLS_INC_ALL, modify_flows_cb, &cbdata); @@ -3095,7 +3125,8 @@ 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(&target, &ofm->match, 0); + cls_rule_from_match(&ofm->match, 0, p->tun_id_from_cookie, ofm->cookie, + &target); classifier_for_each_match(&p->cls, &target, CLS_INC_ALL, delete_flows_cb, &cbdata); @@ -3199,6 +3230,20 @@ handle_flow_mod(struct ofproto *p, struct ofconn *ofconn, } } +static int +handle_tun_id_from_cookie(struct ofproto *p, struct nxt_tun_id_cookie *msg) +{ + int error; + + error = check_ofp_message(&msg->header, OFPT_VENDOR, sizeof *msg); + if (error) { + return error; + } + + p->tun_id_from_cookie = !!msg->set; + return 0; +} + static int handle_vendor(struct ofproto *p, struct ofconn *ofconn, void *msg) { @@ -3206,12 +3251,18 @@ handle_vendor(struct ofproto *p, struct ofconn *ofconn, void *msg) struct nicira_header *nh; if (ntohs(ovh->header.length) < sizeof(struct ofp_vendor_header)) { + VLOG_WARN_RL(&rl, "received vendor message of length %zu " + "(expected at least %zu)", + ntohs(ovh->header.length), sizeof(struct ofp_vendor_header)); return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } if (ovh->vendor != htonl(NX_VENDOR_ID)) { return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_VENDOR); } if (ntohs(ovh->header.length) < sizeof(struct nicira_header)) { + VLOG_WARN_RL(&rl, "received Nicira vendor message of length %zu " + "(expected at least %zu)", + ntohs(ovh->header.length), sizeof(struct nicira_header)); return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } @@ -3220,6 +3271,9 @@ handle_vendor(struct ofproto *p, struct ofconn *ofconn, void *msg) case NXT_STATUS_REQUEST: return switch_status_handle_request(p->switch_status, ofconn->rconn, msg); + + case NXT_TUN_ID_FROM_COOKIE: + return handle_tun_id_from_cookie(p, msg); } return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE); @@ -3317,7 +3371,7 @@ handle_odp_miss_msg(struct ofproto *p, struct ofpbuf *packet) payload.data = msg + 1; payload.size = msg->length - sizeof *msg; - flow_extract(&payload, msg->port, &flow); + flow_extract(&payload, msg->arg, msg->port, &flow); /* Check with in-band control to see if this packet should be sent * to the local port regardless of the flow table. */ @@ -3457,7 +3511,8 @@ revalidate_rule(struct ofproto *p, struct rule *rule) } static struct ofpbuf * -compose_flow_removed(const struct rule *rule, long long int now, uint8_t reason) +compose_flow_removed(struct ofproto *p, const struct rule *rule, + long long int now, uint8_t reason) { struct ofp_flow_removed *ofr; struct ofpbuf *buf; @@ -3466,7 +3521,8 @@ compose_flow_removed(const struct rule *rule, long long int now, uint8_t reason) 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, &ofr->match); + flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, p->tun_id_from_cookie, + &ofr->match); ofr->cookie = rule->flow_cookie; ofr->priority = htons(rule->cr.priority); ofr->reason = reason; @@ -3511,7 +3567,7 @@ send_flow_removed(struct ofproto *p, struct rule *rule, if (prev) { queue_tx(ofpbuf_clone(buf), prev, prev->reply_counter); } else { - buf = compose_flow_removed(rule, now, reason); + buf = compose_flow_removed(p, rule, now, reason); } prev = ofconn; } @@ -3694,7 +3750,7 @@ send_packet_in_miss(struct ofpbuf *packet, void *p_) ? pktbuf_get_null() : pktbuf_save(pb, &payload, msg->port)); int send_len = (buffer_id != UINT32_MAX ? ofconn->miss_send_len - : UINT32_MAX); + : INT_MAX); do_send_packet_in(ofconn, buffer_id, packet, send_len); } }