X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=ba9ef1903db12d59260fbd2a170010e6bfaca885;hb=f7de2cdffcadaca5f62003f9c115052aa295aa70;hp=9ddf6b155a9670d61a88a5170af68b7b6a56eaf0;hpb=e18fe8a220f268624e5b670d6adcf2d4080866aa;p=openvswitch diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 9ddf6b15..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); } @@ -2062,11 +2064,17 @@ static void xlate_table_action(struct action_xlate_ctx *ctx, uint16_t in_port) { if (!ctx->recurse) { - uint16_t old_in_port = ctx->flow.in_port; + uint16_t old_in_port; struct rule *rule; + /* 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; + if (rule) { if (rule->super) { rule = rule->super; @@ -2076,7 +2084,6 @@ xlate_table_action(struct action_xlate_ctx *ctx, uint16_t in_port) do_xlate_actions(rule->actions, rule->n_actions, ctx); ctx->recurse--; } - ctx->flow.in_port = old_in_port; } } @@ -2141,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)); @@ -2150,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; @@ -2183,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: @@ -2313,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) { @@ -2482,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 */ @@ -2640,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; @@ -2681,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); @@ -2710,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); @@ -2732,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); } @@ -2790,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); @@ -2898,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); @@ -2909,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)) { @@ -2931,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))); @@ -2956,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); @@ -2993,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); @@ -3094,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); @@ -3198,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) { @@ -3205,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); } @@ -3219,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); @@ -3316,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. */ @@ -3456,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; @@ -3465,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; @@ -3510,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; } @@ -3693,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); } }