X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto-dpif.c;h=e5767169c7988ab08360c46d93a70313bc840279;hb=e1b1d06afdee407ccfa3c4c257b8dcfbcdd004ff;hp=beb12f0ac2daa40bd240a53db692a705987973c9;hpb=9185896026dc384f39e9bce79a05b736e4cc4ba4;p=openvswitch diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index beb12f0a..e5767169 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -118,8 +118,7 @@ static void rule_credit_stats(struct rule_dpif *, static void flow_push_stats(struct rule_dpif *, const struct flow *, const struct dpif_flow_stats *); static tag_type rule_calculate_tag(const struct flow *, - const struct flow_wildcards *, - uint32_t basis); + const struct minimask *, uint32_t basis); static void rule_invalidate(const struct rule_dpif *); #define MAX_MIRRORS 32 @@ -278,7 +277,7 @@ struct action_xlate_ctx { uint32_t orig_skb_priority; /* Priority when packet arrived. */ uint8_t table_id; /* OpenFlow table ID where flow was found. */ uint32_t sflow_n_outputs; /* Number of output ports. */ - uint16_t sflow_odp_port; /* Output port for composing sFlow action. */ + uint32_t sflow_odp_port; /* Output port for composing sFlow action. */ uint16_t user_cookie_offset;/* Used for user_action_cookie fixup. */ bool exit; /* No further actions should be processed. */ struct flow orig_flow; /* Copy of original flow. */ @@ -486,6 +485,7 @@ static void facet_account(struct facet *); static bool facet_is_controller_flow(struct facet *); struct ofport_dpif { + struct hmap_node odp_port_node; /* In ofproto-dpif's "odp_to_ofport_map". */ struct ofport up; uint32_t odp_port; @@ -544,6 +544,11 @@ static bool vsp_adjust_flow(const struct ofproto_dpif *, struct flow *); static void vsp_remove(struct ofport_dpif *); static void vsp_add(struct ofport_dpif *, uint16_t realdev_ofp_port, int vid); +static uint32_t ofp_port_to_odp_port(const struct ofproto_dpif *, + uint16_t ofp_port); +static uint16_t odp_port_to_ofp_port(const struct ofproto_dpif *, + uint32_t odp_port); + static struct ofport_dpif * ofport_dpif_cast(const struct ofport *ofport) { @@ -642,6 +647,9 @@ struct ofproto_dpif { /* VLAN splinters. */ struct hmap realdev_vid_map; /* (realdev,vid) -> vlandev. */ struct hmap vlandev_map; /* vlandev -> (realdev,vid). */ + + /* ODP port to ofp_port mapping. */ + struct hmap odp_to_ofport_map; }; /* Defer flow mod completion until "ovs-appctl ofproto/unclog"? (Useful only @@ -694,6 +702,11 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); /* Factory functions. */ +static void +init(const struct shash *iface_hints OVS_UNUSED) +{ +} + static void enumerate_types(struct sset *types) { @@ -804,6 +817,8 @@ construct(struct ofproto *ofproto_) hmap_init(&ofproto->vlandev_map); hmap_init(&ofproto->realdev_vid_map); + hmap_init(&ofproto->odp_to_ofport_map); + hmap_insert(&all_ofproto_dpifs, &ofproto->all_ofproto_dpifs_node, hash_string(ofproto->up.name, 0)); memset(&ofproto->stats, 0, sizeof ofproto->stats); @@ -822,8 +837,9 @@ add_internal_flow(struct ofproto_dpif *ofproto, int id, struct ofputil_flow_mod fm; int error; - cls_rule_init_catchall(&fm.cr, 0); - cls_rule_set_reg(&fm.cr, 0, id); + match_init_catchall(&fm.match); + fm.priority = 0; + match_set_reg(&fm.match, 0, id); fm.new_cookie = htonll(0); fm.cookie = htonll(0); fm.cookie_mask = htonll(0); @@ -844,7 +860,7 @@ add_internal_flow(struct ofproto_dpif *ofproto, int id, return error; } - *rulep = rule_dpif_lookup__(ofproto, &fm.cr.flow, TBL_INTERNAL); + *rulep = rule_dpif_lookup__(ofproto, &fm.match.flow, TBL_INTERNAL); assert(*rulep != NULL); return 0; @@ -927,6 +943,8 @@ destruct(struct ofproto *ofproto_) hmap_destroy(&ofproto->vlandev_map); hmap_destroy(&ofproto->realdev_vid_map); + hmap_destroy(&ofproto->odp_to_ofport_map); + dpif_close(ofproto->dpif); } @@ -1158,7 +1176,7 @@ get_features(struct ofproto *ofproto_ OVS_UNUSED, } static void -get_tables(struct ofproto *ofproto_, struct ofp10_table_stats *ots) +get_tables(struct ofproto *ofproto_, struct ofp12_table_stats *ots) { struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); struct dpif_dp_stats s; @@ -1166,9 +1184,8 @@ get_tables(struct ofproto *ofproto_, struct ofp10_table_stats *ots) strcpy(ots->name, "classifier"); dpif_get_dp_stats(ofproto->dpif, &s); - put_32aligned_be64(&ots->lookup_count, htonll(s.n_hit + s.n_missed)); - put_32aligned_be64(&ots->matched_count, - htonll(s.n_hit + ofproto->n_matches)); + ots->lookup_count = htonll(s.n_hit + s.n_missed); + ots->matched_count = htonll(s.n_hit + ofproto->n_matches); } static struct ofport * @@ -1190,9 +1207,10 @@ port_construct(struct ofport *port_) { struct ofport_dpif *port = ofport_dpif_cast(port_); struct ofproto_dpif *ofproto = ofproto_dpif_cast(port->up.ofproto); + struct dpif_port dpif_port; + int error; ofproto->need_revalidate = REV_RECONFIGURE; - port->odp_port = ofp_port_to_odp_port(port->up.ofp_port); port->bundle = NULL; port->cfm = NULL; port->tag = tag_create_random(); @@ -1204,8 +1222,28 @@ port_construct(struct ofport *port_) port->vlandev_vid = 0; port->carrier_seq = netdev_get_carrier_resets(port->up.netdev); + error = dpif_port_query_by_name(ofproto->dpif, + netdev_get_name(port->up.netdev), + &dpif_port); + if (error) { + return error; + } + + port->odp_port = dpif_port.port_no; + + /* Sanity-check that a mapping doesn't already exist. This + * shouldn't happen. */ + if (odp_port_to_ofp_port(ofproto, port->odp_port) != OFPP_NONE) { + VLOG_ERR("port %s already has an OpenFlow port number\n", + dpif_port.name); + return EBUSY; + } + + hmap_insert(&ofproto->odp_to_ofport_map, &port->odp_port_node, + hash_int(port->odp_port, 0)); + if (ofproto->sflow) { - dpif_sflow_add_port(ofproto->sflow, port_); + dpif_sflow_add_port(ofproto->sflow, port_, port->odp_port); } return 0; @@ -1217,6 +1255,7 @@ port_destruct(struct ofport *port_) struct ofport_dpif *port = ofport_dpif_cast(port_); struct ofproto_dpif *ofproto = ofproto_dpif_cast(port->up.ofproto); + hmap_remove(&ofproto->odp_to_ofport_map, &port->odp_port_node); ofproto->need_revalidate = REV_RECONFIGURE; bundle_remove(port_); set_cfm(port_, NULL); @@ -1269,7 +1308,7 @@ set_sflow(struct ofproto *ofproto_, ds = ofproto->sflow = dpif_sflow_create(ofproto->dpif); HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) { - dpif_sflow_add_port(ds, &ofport->up); + dpif_sflow_add_port(ds, &ofport->up, ofport->odp_port); } ofproto->need_revalidate = REV_RECONFIGURE; } @@ -2441,16 +2480,17 @@ get_ofp_port(const struct ofproto_dpif *ofproto, uint16_t ofp_port) static struct ofport_dpif * get_odp_port(const struct ofproto_dpif *ofproto, uint32_t odp_port) { - return get_ofp_port(ofproto, odp_port_to_ofp_port(odp_port)); + return get_ofp_port(ofproto, odp_port_to_ofp_port(ofproto, odp_port)); } static void -ofproto_port_from_dpif_port(struct ofproto_port *ofproto_port, +ofproto_port_from_dpif_port(struct ofproto_dpif *ofproto, + struct ofproto_port *ofproto_port, struct dpif_port *dpif_port) { ofproto_port->name = dpif_port->name; ofproto_port->type = dpif_port->type; - ofproto_port->ofp_port = odp_port_to_ofp_port(dpif_port->port_no); + ofproto_port->ofp_port = odp_port_to_ofp_port(ofproto, dpif_port->port_no); } static void @@ -2523,32 +2563,30 @@ port_query_by_name(const struct ofproto *ofproto_, const char *devname, error = dpif_port_query_by_name(ofproto->dpif, devname, &dpif_port); if (!error) { - ofproto_port_from_dpif_port(ofproto_port, &dpif_port); + ofproto_port_from_dpif_port(ofproto, ofproto_port, &dpif_port); } return error; } static int -port_add(struct ofproto *ofproto_, struct netdev *netdev, uint16_t *ofp_portp) +port_add(struct ofproto *ofproto_, struct netdev *netdev) { struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); - uint16_t odp_port = UINT16_MAX; - int error; + uint32_t odp_port = UINT32_MAX; - error = dpif_port_add(ofproto->dpif, netdev, &odp_port); - if (!error) { - *ofp_portp = odp_port_to_ofp_port(odp_port); - } - return error; + return dpif_port_add(ofproto->dpif, netdev, &odp_port); } static int port_del(struct ofproto *ofproto_, uint16_t ofp_port) { struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); - int error; + uint32_t odp_port = ofp_port_to_odp_port(ofproto, ofp_port); + int error = 0; - error = dpif_port_del(ofproto->dpif, ofp_port_to_odp_port(ofp_port)); + if (odp_port != OFPP_NONE) { + error = dpif_port_del(ofproto->dpif, odp_port); + } if (!error) { struct ofport_dpif *ofport = get_ofp_port(ofproto, ofp_port); if (ofport) { @@ -2640,11 +2678,12 @@ static int port_dump_next(const struct ofproto *ofproto_ OVS_UNUSED, void *state_, struct ofproto_port *port) { + struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); struct port_dump_state *state = state_; struct dpif_port dpif_port; if (dpif_port_dump_next(&state->dump, &dpif_port)) { - ofproto_port_from_dpif_port(port, &dpif_port); + ofproto_port_from_dpif_port(ofproto, port, &dpif_port); return 0; } else { int error = dpif_port_dump_done(&state->dump); @@ -3046,6 +3085,7 @@ ofproto_dpif_extract_flow_key(const struct ofproto_dpif *ofproto, enum odp_key_fitness fitness; fitness = odp_flow_key_to_flow(key, key_len, flow); + flow->in_port = odp_port_to_ofp_port(ofproto, flow->in_port); if (fitness == ODP_FIT_ERROR) { return fitness; } @@ -3107,18 +3147,19 @@ handle_miss_upcalls(struct ofproto_dpif *ofproto, struct dpif_upcall *upcalls, for (upcall = upcalls; upcall < &upcalls[n_upcalls]; upcall++) { struct flow_miss *miss = &misses[n_misses]; struct flow_miss *existing_miss; + struct flow flow; uint32_t hash; /* Obtain metadata and check userspace/kernel agreement on flow match, * then set 'flow''s header pointers. */ miss->key_fitness = ofproto_dpif_extract_flow_key( ofproto, upcall->key, upcall->key_len, - &miss->flow, &miss->initial_tci, upcall->packet); + &flow, &miss->initial_tci, upcall->packet); if (miss->key_fitness == ODP_FIT_ERROR) { continue; } - flow_extract(upcall->packet, miss->flow.skb_priority, - miss->flow.tun_id, miss->flow.in_port, &miss->flow); + flow_extract(upcall->packet, flow.skb_priority, + &flow.tunnel, flow.in_port, &miss->flow); /* Add other packets to a to-do list. */ hash = flow_hash(&miss->flow, 0); @@ -3217,6 +3258,7 @@ handle_sflow_upcall(struct ofproto_dpif *ofproto, enum odp_key_fitness fitness; ovs_be16 initial_tci; struct flow flow; + uint32_t odp_in_port; fitness = ofproto_dpif_extract_flow_key(ofproto, upcall->key, upcall->key_len, &flow, @@ -3226,7 +3268,9 @@ handle_sflow_upcall(struct ofproto_dpif *ofproto, } memcpy(&cookie, &upcall->userdata, sizeof(cookie)); - dpif_sflow_received(ofproto->sflow, upcall->packet, &flow, &cookie); + odp_in_port = ofp_port_to_odp_port(ofproto, flow.in_port); + dpif_sflow_received(ofproto->sflow, upcall->packet, &flow, + odp_in_port, &cookie); } static int @@ -3677,7 +3721,8 @@ execute_odp_actions(struct ofproto_dpif *ofproto, const struct flow *flow, int error; ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); - odp_flow_key_from_flow(&key, flow); + odp_flow_key_from_flow(&key, flow, + ofp_port_to_odp_port(ofproto, flow->in_port)); error = dpif_execute(ofproto->dpif, key.data, key.size, odp_actions, actions_len, packet); @@ -4326,6 +4371,7 @@ subfacet_find(struct ofproto_dpif *ofproto, struct flow flow; fitness = odp_flow_key_to_flow(key, key_len, &flow); + flow.in_port = odp_port_to_ofp_port(ofproto, flow.in_port); if (fitness == ODP_FIT_ERROR) { return NULL; } @@ -4373,9 +4419,15 @@ static void subfacet_get_key(struct subfacet *subfacet, struct odputil_keybuf *keybuf, struct ofpbuf *key) { + if (!subfacet->key) { + struct ofproto_dpif *ofproto; + struct flow *flow = &subfacet->facet->flow; + ofpbuf_use_stack(key, keybuf, sizeof *keybuf); - odp_flow_key_from_flow(key, &subfacet->facet->flow); + ofproto = ofproto_dpif_cast(subfacet->facet->rule->up.ofproto); + odp_flow_key_from_flow(key, flow, + ofp_port_to_odp_port(ofproto, flow->in_port)); } else { ofpbuf_use_const(key, subfacet->key, subfacet->key_len); } @@ -4638,13 +4690,6 @@ rule_construct(struct rule *rule_) struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto); struct rule_dpif *victim; uint8_t table_id; - enum ofperr error; - - error = ofpacts_check(rule->up.ofpacts, rule->up.ofpacts_len, - &rule->up.cr.flow, ofproto->up.max_ports); - if (error) { - return error; - } rule->packet_count = 0; rule->byte_count = 0; @@ -4671,10 +4716,17 @@ rule_construct(struct rule *rule_) } table_id = rule->up.table_id; - rule->tag = (victim ? victim->tag - : table_id == 0 ? 0 - : rule_calculate_tag(&rule->up.cr.flow, &rule->up.cr.wc, - ofproto->tables[table_id].basis)); + if (victim) { + rule->tag = victim->tag; + } else if (table_id == 0) { + rule->tag = 0; + } else { + struct flow flow; + + miniflow_expand(&rule->up.cr.match.flow, &flow); + rule->tag = rule_calculate_tag(&flow, &rule->up.cr.match.mask, + ofproto->tables[table_id].basis); + } complete_operation(rule); return 0; @@ -4747,15 +4799,6 @@ static void rule_modify_actions(struct rule *rule_) { struct rule_dpif *rule = rule_dpif_cast(rule_); - struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto); - enum ofperr error; - - error = ofpacts_check(rule->up.ofpacts, rule->up.ofpacts_len, - &rule->up.cr.flow, ofproto->up.max_ports); - if (error) { - ofoperation_complete(rule->up.pending, error); - return; - } complete_operation(rule); } @@ -4769,11 +4812,11 @@ send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet) const struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto); struct ofpbuf key, odp_actions; struct odputil_keybuf keybuf; - uint16_t odp_port; + uint32_t odp_port; struct flow flow; int error; - flow_extract(packet, 0, 0, 0, &flow); + flow_extract(packet, 0, NULL, 0, &flow); odp_port = vsp_realdev_to_vlandev(ofproto, ofport->odp_port, flow.vlan_tci); if (odp_port != ofport->odp_port) { @@ -4782,7 +4825,8 @@ send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet) } ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); - odp_flow_key_from_flow(&key, &flow); + odp_flow_key_from_flow(&key, &flow, + ofp_port_to_odp_port(ofproto, flow.in_port)); ofpbuf_init(&odp_actions, 32); compose_sflow_action(ofproto, &odp_actions, &flow, odp_port); @@ -4851,7 +4895,7 @@ put_userspace_action(const struct ofproto_dpif *ofproto, uint32_t pid; pid = dpif_port_get_pid(ofproto->dpif, - ofp_port_to_odp_port(flow->in_port)); + ofp_port_to_odp_port(ofproto, flow->in_port)); return odp_put_userspace_action(pid, cookie, odp_actions); } @@ -4959,7 +5003,7 @@ compose_output_action__(struct action_xlate_ctx *ctx, uint16_t ofp_port, bool check_stp) { const struct ofport_dpif *ofport = get_ofp_port(ctx->ofproto, ofp_port); - uint16_t odp_port = ofp_port_to_odp_port(ofp_port); + uint32_t odp_port = ofp_port_to_odp_port(ctx->ofproto, ofp_port); ovs_be16 flow_vlan_tci = ctx->flow.vlan_tci; uint8_t flow_nw_tos = ctx->flow.nw_tos; uint16_t out_port; @@ -4967,8 +5011,11 @@ compose_output_action__(struct action_xlate_ctx *ctx, uint16_t ofp_port, if (ofport) { struct priority_to_dscp *pdscp; - if (ofport->up.pp.config & OFPUTIL_PC_NO_FWD - || (check_stp && !stp_forward_in_state(ofport->stp_state))) { + if (ofport->up.pp.config & OFPUTIL_PC_NO_FWD) { + xlate_report(ctx, "OFPPC_NO_FWD set, skipping output"); + return; + } else if (check_stp && !stp_forward_in_state(ofport->stp_state)) { + xlate_report(ctx, "STP not in forwarding state, skipping output"); return; } @@ -5029,7 +5076,7 @@ xlate_table_action(struct action_xlate_ctx *ctx, ctx->tags |= (rule && rule->tag ? rule->tag : rule_calculate_tag(&ctx->flow, - &table->other_table->wc, + &table->other_table->mask, table->basis)); } } @@ -5242,6 +5289,8 @@ xlate_output_action(struct action_xlate_ctx *ctx, default: if (port != ctx->flow.in_port) { compose_output_action(ctx, port); + } else { + xlate_report(ctx, "skipping output to input port"); } break; } @@ -5464,6 +5513,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, } OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) { struct ofpact_controller *controller; + const struct ofpact_metadata *metadata; if (ctx->exit) { break; @@ -5503,6 +5553,11 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, ctx->flow.vlan_tci = htons(0); break; + case OFPACT_PUSH_VLAN: + /* TODO:XXX 802.1AD(QinQ) */ + ctx->flow.vlan_tci = htons(VLAN_CFI); + break; + case OFPACT_SET_ETH_SRC: memcpy(ctx->flow.dl_src, ofpact_get_SET_ETH_SRC(a)->mac, ETH_ADDR_LEN); @@ -5542,7 +5597,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; case OFPACT_SET_TUNNEL: - ctx->flow.tun_id = htonll(ofpact_get_SET_TUNNEL(a)->tun_id); + ctx->flow.tunnel.tun_id = htonll(ofpact_get_SET_TUNNEL(a)->tun_id); break; case OFPACT_SET_QUEUE: @@ -5603,6 +5658,29 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, ctx->has_fin_timeout = true; xlate_fin_timeout(ctx, ofpact_get_FIN_TIMEOUT(a)); break; + + case OFPACT_CLEAR_ACTIONS: + /* TODO:XXX + * Nothing to do because writa-actions is not supported for now. + * When writa-actions is supported, clear-actions also must + * be supported at the same time. + */ + break; + + case OFPACT_WRITE_METADATA: + metadata = ofpact_get_WRITE_METADATA(a); + ctx->flow.metadata &= ~metadata->mask; + ctx->flow.metadata |= metadata->metadata & metadata->mask; + break; + + case OFPACT_GOTO_TABLE: { + /* TODO:XXX remove recursion */ + /* It is assumed that goto-table is last action */ + struct ofpact_goto_table *ogt = ofpact_get_GOTO_TABLE(a); + assert(ctx->table_id < ogt->table_id); + xlate_table_action(ctx, ctx->flow.in_port, ogt->table_id, true); + break; + } } } @@ -5627,7 +5705,7 @@ action_xlate_ctx_init(struct action_xlate_ctx *ctx, ctx->ofproto = ofproto; ctx->flow = *flow; ctx->base_flow = ctx->flow; - ctx->base_flow.tun_id = 0; + memset(&ctx->base_flow.tunnel, 0, sizeof ctx->base_flow.tunnel); ctx->base_flow.vlan_tci = initial_tci; ctx->rule = rule; ctx->packet = packet; @@ -6017,7 +6095,7 @@ add_mirror_actions(struct action_xlate_ctx *ctx, const struct flow *orig_flow) m = ofproto->mirrors[mirror_mask_ffs(mirrors) - 1]; if (!vlan_is_mirrored(m, vlan)) { - mirrors &= mirrors - 1; + mirrors = zero_rightmost_1bit(mirrors); continue; } @@ -6047,7 +6125,7 @@ update_mirror_stats(struct ofproto_dpif *ofproto, mirror_mask_t mirrors, return; } - for (; mirrors; mirrors &= mirrors - 1) { + for (; mirrors; mirrors = zero_rightmost_1bit(mirrors)) { struct ofmirror *m; m = ofproto->mirrors[mirror_mask_ffs(mirrors) - 1]; @@ -6330,18 +6408,17 @@ xlate_normal(struct action_xlate_ctx *ctx) * a few more, but not all of the facets or even all of the facets that * resubmit to the table modified by MAC learning). */ -/* Calculates the tag to use for 'flow' and wildcards 'wc' when it is inserted +/* Calculates the tag to use for 'flow' and mask 'mask' when it is inserted * into an OpenFlow table with the given 'basis'. */ static tag_type -rule_calculate_tag(const struct flow *flow, const struct flow_wildcards *wc, +rule_calculate_tag(const struct flow *flow, const struct minimask *mask, uint32_t secret) { - if (flow_wildcards_is_catchall(wc)) { + if (minimask_is_catchall(mask)) { return 0; } else { - struct flow tag_flow = *flow; - flow_zero_wildcards(&tag_flow, wc); - return tag_create_deterministic(flow_hash(&tag_flow, secret)); + uint32_t hash = flow_hash_in_minimask(flow, mask, secret); + return tag_create_deterministic(hash); } } @@ -6443,36 +6520,33 @@ packet_out(struct ofproto *ofproto_, struct ofpbuf *packet, const struct ofpact *ofpacts, size_t ofpacts_len) { struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); - enum ofperr error; + struct odputil_keybuf keybuf; + struct dpif_flow_stats stats; - error = ofpacts_check(ofpacts, ofpacts_len, flow, ofproto->up.max_ports); - if (!error) { - struct odputil_keybuf keybuf; - struct dpif_flow_stats stats; + struct ofpbuf key; - struct ofpbuf key; + struct action_xlate_ctx ctx; + uint64_t odp_actions_stub[1024 / 8]; + struct ofpbuf odp_actions; - struct action_xlate_ctx ctx; - uint64_t odp_actions_stub[1024 / 8]; - struct ofpbuf odp_actions; + ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); + odp_flow_key_from_flow(&key, flow, + ofp_port_to_odp_port(ofproto, flow->in_port)); - ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); - odp_flow_key_from_flow(&key, flow); + dpif_flow_stats_extract(flow, packet, time_msec(), &stats); - dpif_flow_stats_extract(flow, packet, time_msec(), &stats); + action_xlate_ctx_init(&ctx, ofproto, flow, flow->vlan_tci, NULL, + packet_get_tcp_flags(packet, flow), packet); + ctx.resubmit_stats = &stats; - action_xlate_ctx_init(&ctx, ofproto, flow, flow->vlan_tci, NULL, - packet_get_tcp_flags(packet, flow), packet); - ctx.resubmit_stats = &stats; + ofpbuf_use_stub(&odp_actions, + odp_actions_stub, sizeof odp_actions_stub); + xlate_actions(&ctx, ofpacts, ofpacts_len, &odp_actions); + dpif_execute(ofproto->dpif, key.data, key.size, + odp_actions.data, odp_actions.size, packet); + ofpbuf_uninit(&odp_actions); - ofpbuf_use_stub(&odp_actions, - odp_actions_stub, sizeof odp_actions_stub); - xlate_actions(&ctx, ofpacts, ofpacts_len, &odp_actions); - dpif_execute(ofproto->dpif, key.data, key.size, - odp_actions.data, odp_actions.size, packet); - ofpbuf_uninit(&odp_actions); - } - return error; + return 0; } /* NetFlow. */ @@ -6775,7 +6849,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[], const char *tun_id_s = argv[3]; const char *in_port_s = argv[4]; const char *packet_s = argv[5]; - uint16_t in_port = ofp_port_to_odp_port(atoi(in_port_s)); + uint32_t in_port = atoi(in_port_s); ovs_be64 tun_id = htonll(strtoull(tun_id_s, NULL, 0)); uint32_t priority = atoi(priority_s); const char *msg; @@ -6791,7 +6865,8 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[], ds_put_cstr(&result, s); free(s); - flow_extract(packet, priority, tun_id, in_port, &flow); + flow_extract(packet, priority, NULL, in_port, &flow); + flow.tunnel.tun_id = tun_id; initial_tci = flow.vlan_tci; } else { unixctl_command_reply_error(conn, "Bad command syntax"); @@ -7050,16 +7125,17 @@ vsp_realdev_to_vlandev(const struct ofproto_dpif *ofproto, uint32_t realdev_odp_port, ovs_be16 vlan_tci) { if (!hmap_is_empty(&ofproto->realdev_vid_map)) { - uint16_t realdev_ofp_port = odp_port_to_ofp_port(realdev_odp_port); + uint16_t realdev_ofp_port; int vid = vlan_tci_to_vid(vlan_tci); const struct vlan_splinter *vsp; + realdev_ofp_port = odp_port_to_ofp_port(ofproto, realdev_odp_port); HMAP_FOR_EACH_WITH_HASH (vsp, realdev_vid_node, hash_realdev_vid(realdev_ofp_port, vid), &ofproto->realdev_vid_map) { if (vsp->realdev_ofp_port == realdev_ofp_port && vsp->vid == vid) { - return ofp_port_to_odp_port(vsp->vlandev_ofp_port); + return ofp_port_to_odp_port(ofproto, vsp->vlandev_ofp_port); } } } @@ -7174,8 +7250,32 @@ vsp_add(struct ofport_dpif *port, uint16_t realdev_ofp_port, int vid) VLOG_ERR("duplicate vlan device record"); } } - + +static uint32_t +ofp_port_to_odp_port(const struct ofproto_dpif *ofproto, uint16_t ofp_port) +{ + const struct ofport_dpif *ofport = get_ofp_port(ofproto, ofp_port); + return ofport ? ofport->odp_port : OVSP_NONE; +} + +static uint16_t +odp_port_to_ofp_port(const struct ofproto_dpif *ofproto, uint32_t odp_port) +{ + struct ofport_dpif *port; + + HMAP_FOR_EACH_IN_BUCKET (port, odp_port_node, + hash_int(odp_port, 0), + &ofproto->odp_to_ofport_map) { + if (port->odp_port == odp_port) { + return port->up.ofp_port; + } + } + + return OFPP_NONE; +} + const struct ofproto_class ofproto_dpif_class = { + init, enumerate_types, enumerate_names, del,