X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=01b44e7f30c7028a17c9b897b1093ed2dbfe954c;hb=2ac6beddbf6a85299c449939a2086126f1f47dbc;hp=fb63606ad6d1ccb6aac121084ee278f914cee559;hpb=10b78e7d091b85a2808bac9dd24d7fd3cfeaa8b1;p=openvswitch diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index fb63606a..01b44e7f 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -54,6 +54,7 @@ #include "pinsched.h" #include "pktbuf.h" #include "poll-loop.h" +#include "private.h" #include "rconn.h" #include "shash.h" #include "sset.h" @@ -101,7 +102,7 @@ struct rule; struct ofport { struct hmap_node hmap_node; /* In struct ofproto's "ports" hmap. */ struct netdev *netdev; - struct ofp_phy_port opp; /* In host byte order. */ + struct ofp_phy_port opp; uint16_t odp_port; struct cfm *cfm; /* Connectivity Fault Management, if any. */ }; @@ -276,6 +277,9 @@ static void send_packet_in(struct ofproto *, struct dpif_upcall *, const struct flow *, bool clone); struct ofproto { + char *name; /* Datapath name. */ + struct hmap_node hmap_node; /* In global 'all_ofprotos' hmap. */ + /* Settings. */ uint64_t datapath_id; /* Datapath ID. */ uint64_t fallback_dpid; /* Datapath ID if no better choice found. */ @@ -317,7 +321,7 @@ struct ofproto { }; /* Map from dpif name to struct ofproto, for use by unixctl commands. */ -static struct shash all_ofprotos = SHASH_INITIALIZER(&all_ofprotos); +static struct hmap all_ofprotos = HMAP_INITIALIZER(&all_ofprotos); static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); @@ -358,7 +362,7 @@ ofproto_create(const char *datapath, const char *datapath_type, ofproto_unixctl_init(); /* Connect to datapath and start listening for messages. */ - error = dpif_open(datapath, datapath_type, &dpif); + error = dpif_create_and_open(datapath, datapath_type, &dpif); if (error) { VLOG_ERR("failed to open datapath %s: %s", datapath, strerror(error)); return error; @@ -386,6 +390,8 @@ ofproto_create(const char *datapath, const char *datapath_type, /* Initialize settings. */ p = xzalloc(sizeof *p); + p->name = xstrdup(dpif_name(dpif)); + hmap_insert(&all_ofprotos, &p->hmap_node, hash_string(p->name, 0)); p->fallback_dpid = pick_fallback_dpid(); p->datapath_id = p->fallback_dpid; p->mfr_desc = xstrdup(DEFAULT_MFR_DESC); @@ -429,8 +435,6 @@ ofproto_create(const char *datapath, const char *datapath_type, p->datapath_id = pick_datapath_id(p); VLOG_INFO("using datapath ID %016"PRIx64, p->datapath_id); - shash_add_once(&all_ofprotos, dpif_name(p->dpif), p); - /* Initialize OpenFlow connections. */ p->connmgr = connmgr_create(p, datapath, local_name); @@ -592,7 +596,7 @@ ofproto_set_sflow(struct ofproto *ofproto, /* Clears the CFM configuration from 'port_no' on 'ofproto'. */ void -ofproto_iface_clear_cfm(struct ofproto *ofproto, uint32_t port_no) +ofproto_port_clear_cfm(struct ofproto *ofproto, uint32_t port_no) { struct ofport *ofport = get_port(ofproto, port_no); if (ofport && ofport->cfm){ @@ -608,16 +612,16 @@ ofproto_iface_clear_cfm(struct ofproto *ofproto, uint32_t port_no) * * This function has no effect if 'ofproto' does not have a port 'port_no'. */ void -ofproto_iface_set_cfm(struct ofproto *ofproto, uint32_t port_no, - const struct cfm *cfm, - const uint16_t *remote_mps, size_t n_remote_mps) +ofproto_port_set_cfm(struct ofproto *ofproto, uint32_t port_no, + const struct cfm *cfm, + const uint16_t *remote_mps, size_t n_remote_mps) { struct ofport *ofport; ofport = get_port(ofproto, port_no); if (!ofport) { VLOG_WARN("%s: cannot configure CFM on nonexistent port %"PRIu32, - dpif_name(ofproto->dpif), port_no); + ofproto->name, port_no); return; } @@ -633,7 +637,7 @@ ofproto_iface_set_cfm(struct ofproto *ofproto, uint32_t port_no, if (!cfm_configure(ofport->cfm)) { VLOG_WARN("%s: CFM configuration on port %"PRIu32" (%s) failed", - dpif_name(ofproto->dpif), port_no, + ofproto->name, port_no, netdev_get_name(ofport->netdev)); cfm_destroy(ofport->cfm); ofport->cfm = NULL; @@ -645,7 +649,7 @@ ofproto_iface_set_cfm(struct ofproto *ofproto, uint32_t port_no, * 'port_no' or if that port does not have CFM configured. The caller must not * modify or destroy the returned object. */ const struct cfm * -ofproto_iface_get_cfm(struct ofproto *ofproto, uint32_t port_no) +ofproto_port_get_cfm(struct ofproto *ofproto, uint32_t port_no) { struct ofport *ofport = get_port(ofproto, port_no); return ofport ? ofport->cfm : NULL; @@ -657,12 +661,6 @@ ofproto_get_datapath_id(const struct ofproto *ofproto) return ofproto->datapath_id; } -bool -ofproto_has_primary_controller(const struct ofproto *ofproto) -{ - return connmgr_has_controllers(ofproto->connmgr); -} - enum ofproto_fail_mode ofproto_get_fail_mode(const struct ofproto *p) { @@ -681,8 +679,8 @@ ofproto_get_snoops(const struct ofproto *ofproto, struct sset *snoops) connmgr_get_snoops(ofproto->connmgr, snoops); } -void -ofproto_destroy(struct ofproto *p) +static void +ofproto_destroy__(struct ofproto *p, bool delete) { struct ofport *ofport, *next_ofport; @@ -690,14 +688,22 @@ ofproto_destroy(struct ofproto *p) return; } - shash_find_and_delete(&all_ofprotos, dpif_name(p->dpif)); + hmap_remove(&all_ofprotos, &p->hmap_node); ofproto_flush_flows__(p); connmgr_destroy(p->connmgr); classifier_destroy(&p->cls); hmap_destroy(&p->facets); + if (delete) { + int error = dpif_delete(p->dpif); + if (error && error != ENOENT) { + VLOG_ERR("bridge %s: failed to destroy (%s)", + p->name, strerror(error)); + } + } dpif_close(p->dpif); + netdev_monitor_destroy(p->netdev_monitor); HMAP_FOR_EACH_SAFE (ofport, next_ofport, hmap_node, &p->ports) { hmap_remove(&p->ports, &ofport->hmap_node); @@ -718,9 +724,22 @@ ofproto_destroy(struct ofproto *p) hmap_destroy(&p->ports); + free(p->name); free(p); } +void +ofproto_destroy(struct ofproto *p) +{ + ofproto_destroy__(p, false); +} + +void +ofproto_destroy_and_delete(struct ofproto *p) +{ + ofproto_destroy__(p, true); +} + int ofproto_run(struct ofproto *p) { @@ -765,7 +784,7 @@ ofproto_run1(struct ofproto *p) * spin from here on out. */ static struct vlog_rate_limit rl2 = VLOG_RATE_LIMIT_INIT(1, 5); VLOG_ERR_RL(&rl2, "%s: datapath was destroyed externally", - dpif_name(p->dpif)); + p->name); return ENODEV; } break; @@ -899,7 +918,134 @@ ofproto_free_ofproto_controller_info(struct shash *info) shash_destroy(info); } -/* Deletes port number 'odp_port' from the datapath for 'ofproto'. +/* Makes a deep copy of 'old' into 'port'. */ +void +ofproto_port_clone(struct ofproto_port *port, const struct ofproto_port *old) +{ + port->name = xstrdup(old->name); + port->type = xstrdup(old->type); + port->ofp_port = old->ofp_port; +} + +/* Frees memory allocated to members of 'ofproto_port'. + * + * Do not call this function on an ofproto_port obtained from + * ofproto_port_dump_next(): that function retains ownership of the data in the + * ofproto_port. */ +void +ofproto_port_destroy(struct ofproto_port *ofproto_port) +{ + free(ofproto_port->name); + free(ofproto_port->type); +} + +/* Converts a dpif_port into an ofproto_port. + * + * This only makes a shallow copy, so make sure that the dpif_port doesn't get + * freed while the ofproto_port is still in use. You can choose to free the + * ofproto_port instead of the dpif_port. */ +static void +ofproto_port_from_dpif_port(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); +} + +/* Initializes 'dump' to begin dumping the ports in an ofproto. + * + * This function provides no status indication. An error status for the entire + * dump operation is provided when it is completed by calling + * ofproto_port_dump_done(). + */ +void +ofproto_port_dump_start(struct ofproto_port_dump *dump, + const struct ofproto *ofproto) +{ + struct dpif_port_dump *dpif_dump; + + dump->state = dpif_dump = xmalloc(sizeof *dpif_dump); + dpif_port_dump_start(dpif_dump, ofproto->dpif); +} + +/* Attempts to retrieve another port from 'dump', which must have been created + * with ofproto_port_dump_start(). On success, stores a new ofproto_port into + * 'port' and returns true. On failure, returns false. + * + * Failure might indicate an actual error or merely that the last port has been + * dumped. An error status for the entire dump operation is provided when it + * is completed by calling ofproto_port_dump_done(). + * + * The ofproto owns the data stored in 'port'. It will remain valid until at + * least the next time 'dump' is passed to ofproto_port_dump_next() or + * ofproto_port_dump_done(). */ +bool +ofproto_port_dump_next(struct ofproto_port_dump *dump, + struct ofproto_port *port) +{ + struct dpif_port_dump *dpif_dump = dump->state; + struct dpif_port dpif_port; + bool ok; + + ok = dpif_port_dump_next(dpif_dump, &dpif_port); + if (ok) { + ofproto_port_from_dpif_port(port, &dpif_port); + } + return ok; +} + +/* Completes port table dump operation 'dump', which must have been created + * with ofproto_port_dump_start(). Returns 0 if the dump operation was + * error-free, otherwise a positive errno value describing the problem. */ +int +ofproto_port_dump_done(struct ofproto_port_dump *dump) +{ + struct dpif_port_dump *dpif_dump = dump->state; + int error = dpif_port_dump_done(dpif_dump); + free(dpif_dump); + return error; +} + +/* Attempts to add 'netdev' as a port on 'ofproto'. If successful, returns 0 + * and sets '*ofp_portp' to the new port's port OpenFlow number (if 'ofp_portp' + * is non-null). On failure, returns a positive errno value and sets + * '*ofp_portp' to OFPP_NONE (if 'ofp_portp' is non-null). */ +int +ofproto_port_add(struct ofproto *ofproto, struct netdev *netdev, + uint16_t *ofp_portp) +{ + uint16_t odp_port; + int error; + + error = dpif_port_add(ofproto->dpif, netdev, &odp_port); + if (ofp_portp) { + *ofp_portp = error ? OFPP_NONE : odp_port_to_ofp_port(odp_port); + } + return error; +} + +/* Looks up a port named 'devname' in 'ofproto'. On success, returns 0 and + * initializes '*port' appropriately; on failure, returns a positive errno + * value. + * + * The caller owns the data in 'port' and must free it with + * ofproto_port_destroy() when it is no longer needed. */ +int +ofproto_port_query_by_name(const struct ofproto *ofproto, const char *devname, + struct ofproto_port *port) +{ + struct dpif_port dpif_port; + int error; + + error = dpif_port_query_by_name(ofproto->dpif, devname, &dpif_port); + if (!error) { + ofproto_port_from_dpif_port(port, &dpif_port); + } + return error; +} + +/* Deletes port number 'ofp_port' from the datapath for 'ofproto'. * * This is almost the same as calling dpif_port_del() directly on the * datapath, but it also makes 'ofproto' close its open netdev for the port @@ -910,8 +1056,9 @@ ofproto_free_ofproto_controller_info(struct shash *info) * * Returns 0 if successful, otherwise a positive errno. */ int -ofproto_port_del(struct ofproto *ofproto, uint16_t odp_port) +ofproto_port_del(struct ofproto *ofproto, uint16_t ofp_port) { + uint32_t odp_port = ofp_port_to_odp_port(ofp_port); struct ofport *ofport = get_port(ofproto, odp_port); const char *name = ofport ? netdev_get_name(ofport->netdev) : ""; int error; @@ -919,7 +1066,7 @@ ofproto_port_del(struct ofproto *ofproto, uint16_t odp_port) error = dpif_port_del(ofproto->dpif, odp_port); if (error) { VLOG_ERR("%s: failed to remove port %"PRIu16" (%s) interface (%s)", - dpif_name(ofproto->dpif), odp_port, name, strerror(error)); + ofproto->name, odp_port, name, strerror(error)); } else if (ofport) { /* 'name' is the netdev's name and update_port() is going to close the * netdev. Just in case update_port() refers to 'name' after it @@ -938,7 +1085,7 @@ 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); + return ofport && !(ofport->opp.config & htonl(OFPPC_NO_FLOOD)); } /* Sends 'packet' out of port 'port_no' within 'p'. If 'vlan_tci' is zero the @@ -946,7 +1093,7 @@ ofproto_port_is_floodable(struct ofproto *ofproto, uint16_t odp_port) * will be sent with the VLAN TCI specified by 'vlan_tci & ~VLAN_CFI'. * * Returns 0 if successful, otherwise a positive errno value. */ -int +static int ofproto_send_packet(struct ofproto *ofproto, uint32_t port_no, uint16_t vlan_tci, const struct ofpbuf *packet) @@ -966,7 +1113,7 @@ ofproto_send_packet(struct ofproto *ofproto, if (error) { VLOG_WARN_RL(&rl, "%s: failed to send packet on port %"PRIu32" (%s)", - dpif_name(ofproto->dpif), port_no, strerror(error)); + ofproto->name, port_no, strerror(error)); } return error; } @@ -1062,10 +1209,11 @@ reinit_ports(struct ofproto *p) } /* Opens and returns a netdev for 'dpif_port', or a null pointer if the netdev - * cannot be opened. On success, also fills in 'opp', in *HOST* byte order. */ + * cannot be opened. On success, also fills in 'opp'. */ static struct netdev * ofport_open(const struct dpif_port *dpif_port, struct ofp_phy_port *opp) { + uint32_t curr, advertised, supported, peer; struct netdev_options netdev_options; enum netdev_flags flags; struct netdev *netdev; @@ -1086,14 +1234,18 @@ ofport_open(const struct dpif_port *dpif_port, struct ofp_phy_port *opp) } netdev_get_flags(netdev, &flags); + netdev_get_features(netdev, &curr, &advertised, &supported, &peer); - opp->port_no = odp_port_to_ofp_port(dpif_port->port_no); + opp->port_no = htons(odp_port_to_ofp_port(dpif_port->port_no)); netdev_get_etheraddr(netdev, opp->hw_addr); ovs_strzcpy(opp->name, dpif_port->name, sizeof opp->name); - opp->config = flags & NETDEV_UP ? 0 : OFPPC_PORT_DOWN; - opp->state = netdev_get_carrier(netdev) ? 0 : OFPPS_LINK_DOWN; - netdev_get_features(netdev, &opp->curr, &opp->advertised, - &opp->supported, &opp->peer); + opp->config = flags & NETDEV_UP ? 0 : htonl(OFPPC_PORT_DOWN); + opp->state = netdev_get_carrier(netdev) ? 0 : htonl(OFPPS_LINK_DOWN); + opp->curr = htonl(curr); + opp->advertised = htonl(advertised); + opp->supported = htonl(supported); + opp->peer = htonl(peer); + return netdev; } @@ -1122,7 +1274,7 @@ ofport_equal(const struct ofp_phy_port *a, const struct ofp_phy_port *b) BUILD_ASSERT_DECL(sizeof *a == 48); /* Detect ofp_phy_port changes. */ return (!memcmp(a->hw_addr, b->hw_addr, sizeof a->hw_addr) && a->state == b->state - && !((a->config ^ b->config) & OFPPC_PORT_DOWN) + && !((a->config ^ b->config) & htonl(OFPPC_PORT_DOWN)) && a->curr == b->curr && a->advertised == b->advertised && a->supported == b->supported @@ -1145,7 +1297,7 @@ ofport_install(struct ofproto *p, ofport = xmalloc(sizeof *ofport); ofport->netdev = netdev; ofport->opp = *opp; - ofport->odp_port = ofp_port_to_odp_port(opp->port_no); + ofport->odp_port = ofp_port_to_odp_port(ntohs(opp->port_no)); ofport->cfm = NULL; /* Add port to 'p'. */ @@ -1195,8 +1347,8 @@ ofport_modified(struct ofproto *ofproto, struct ofport *port, struct netdev *netdev, struct ofp_phy_port *opp) { memcpy(port->opp.hw_addr, opp->hw_addr, ETH_ADDR_LEN); - port->opp.config = ((port->opp.config & ~OFPPC_PORT_DOWN) - | (opp->config & OFPPC_PORT_DOWN)); + port->opp.config = ((port->opp.config & ~htonl(OFPPC_PORT_DOWN)) + | (opp->config & htonl(OFPPC_PORT_DOWN))); port->opp.state = opp->state; port->opp.curr = opp->curr; port->opp.advertised = opp->advertised; @@ -1928,7 +2080,7 @@ handle_features_request(struct ofconn *ofconn, const struct ofp_header *oh) (1u << OFPAT_ENQUEUE)); HMAP_FOR_EACH (port, hmap_node, &ofproto->ports) { - hton_ofp_phy_port(ofpbuf_put(buf, &port->opp, sizeof port->opp)); + ofpbuf_put(buf, &port->opp, sizeof port->opp); } ofconn_send_reply(ofconn, buf); @@ -1993,7 +2145,7 @@ add_output_action(struct action_xlate_ctx *ctx, uint16_t port) const struct ofport *ofport = get_port(ctx->ofproto, port); if (ofport) { - if (ofport->opp.config & OFPPC_NO_FWD) { + if (ofport->opp.config & htonl(OFPPC_NO_FWD)) { /* Forwarding disabled on port. */ return; } @@ -2048,7 +2200,7 @@ xlate_table_action(struct action_xlate_ctx *ctx, uint16_t in_port) } static void -flood_packets(struct ofproto *ofproto, uint16_t odp_in_port, uint32_t mask, +flood_packets(struct ofproto *ofproto, uint16_t odp_in_port, ovs_be32 mask, uint16_t *nf_output_iface, struct ofpbuf *odp_actions) { struct ofport *ofport; @@ -2088,11 +2240,11 @@ xlate_output_action__(struct action_xlate_ctx *ctx, } break; case OFPP_FLOOD: - flood_packets(ctx->ofproto, ctx->flow.in_port, OFPPC_NO_FLOOD, + flood_packets(ctx->ofproto, ctx->flow.in_port, htonl(OFPPC_NO_FLOOD), &ctx->nf_output_iface, ctx->odp_actions); break; case OFPP_ALL: - flood_packets(ctx->ofproto, ctx->flow.in_port, 0, + flood_packets(ctx->ofproto, ctx->flow.in_port, htonl(0), &ctx->nf_output_iface, ctx->odp_actions); break; case OFPP_CONTROLLER: @@ -2345,9 +2497,10 @@ do_xlate_actions(const union ofp_action *in, size_t n_in, const struct ofport *port; port = get_port(ctx->ofproto, ctx->flow.in_port); - if (port && port->opp.config & (OFPPC_NO_RECV | OFPPC_NO_RECV_STP) && + if (port && port->opp.config & htonl(OFPPC_NO_RECV | OFPPC_NO_RECV_STP) && port->opp.config & (eth_addr_equals(ctx->flow.dl_dst, eth_addr_stp) - ? OFPPC_NO_RECV_STP : OFPPC_NO_RECV)) { + ? htonl(OFPPC_NO_RECV_STP) + : htonl(OFPPC_NO_RECV))) { /* Drop this flow. */ return; } @@ -2589,11 +2742,11 @@ exit: static void update_port_config(struct ofproto *p, struct ofport *port, - uint32_t config, uint32_t mask) + ovs_be32 config, ovs_be32 mask) { mask &= config ^ port->opp.config; - if (mask & OFPPC_PORT_DOWN) { - if (config & OFPPC_PORT_DOWN) { + if (mask & htonl(OFPPC_PORT_DOWN)) { + if (config & htonl(OFPPC_PORT_DOWN)) { netdev_turn_flags_off(port->netdev, NETDEV_UP, true); } else { netdev_turn_flags_on(port->netdev, NETDEV_UP, true); @@ -2601,14 +2754,14 @@ update_port_config(struct ofproto *p, struct ofport *port, } #define REVALIDATE_BITS (OFPPC_NO_RECV | OFPPC_NO_RECV_STP | \ OFPPC_NO_FWD | OFPPC_NO_FLOOD) - if (mask & REVALIDATE_BITS) { + if (mask & htonl(REVALIDATE_BITS)) { COVERAGE_INC(ofproto_costly_flags); - port->opp.config ^= mask & REVALIDATE_BITS; + port->opp.config ^= mask & htonl(REVALIDATE_BITS); p->need_revalidate = true; } #undef REVALIDATE_BITS - if (mask & OFPPC_NO_PACKET_IN) { - port->opp.config ^= OFPPC_NO_PACKET_IN; + if (mask & htonl(OFPPC_NO_PACKET_IN)) { + port->opp.config ^= htonl(OFPPC_NO_PACKET_IN); } } @@ -2631,7 +2784,7 @@ handle_port_mod(struct ofconn *ofconn, const struct ofp_header *oh) } else if (memcmp(port->opp.hw_addr, opm->hw_addr, OFP_ETH_ALEN)) { return ofp_mkerr(OFPET_PORT_MOD_FAILED, OFPPMFC_BAD_HW_ADDR); } else { - update_port_config(p, port, ntohl(opm->config), ntohl(opm->mask)); + update_port_config(p, port, opm->config, opm->mask); if (opm->advertise) { netdev_set_advertisements(port->netdev, ntohl(opm->advertise)); } @@ -2770,7 +2923,7 @@ append_port_stat(struct ofport *port, struct ofconn *ofconn, netdev_get_stats(port->netdev, &stats); ops = append_ofp_stats_reply(sizeof *ops, ofconn, msgp); - ops->port_no = htons(port->opp.port_no); + ops->port_no = port->opp.port_no; memset(ops->pad, 0, sizeof ops->pad); put_32aligned_be64(&ops->rx_packets, htonll(stats.rx_packets)); put_32aligned_be64(&ops->tx_packets, htonll(stats.tx_packets)); @@ -3022,6 +3175,15 @@ ofproto_get_all_flows(struct ofproto *p, struct ds *results) } } +/* Obtains the NetFlow engine type and engine ID for 'ofproto' into + * '*engine_type' and '*engine_id', respectively. */ +void +ofproto_get_netflow_ids(const struct ofproto *ofproto, + uint8_t *engine_type, uint8_t *engine_id) +{ + dpif_get_netflow_ids(ofproto->dpif, engine_type, engine_id); +} + static void query_aggregate_stats(struct ofproto *ofproto, struct cls_rule *target, ovs_be16 out_port, uint8_t table_id, @@ -3126,7 +3288,7 @@ put_queue_stats(struct queue_stats_cbdata *cbdata, uint32_t queue_id, struct ofp_queue_stats *reply; reply = append_ofp_stats_reply(sizeof *reply, cbdata->ofconn, &cbdata->msg); - reply->port_no = htons(cbdata->ofport->opp.port_no); + reply->port_no = cbdata->ofport->opp.port_no; memset(reply->pad, 0, sizeof reply->pad); reply->queue_id = htonl(queue_id); put_32aligned_be64(&reply->tx_bytes, htonll(stats->tx_bytes)); @@ -3794,7 +3956,7 @@ handle_miss_upcall(struct ofproto *p, struct dpif_upcall *upcall) /* Don't send a packet-in if OFPPC_NO_PACKET_IN asserted. */ struct ofport *port = get_port(p, flow.in_port); if (port) { - if (port->opp.config & OFPPC_NO_PACKET_IN) { + if (port->opp.config & htonl(OFPPC_NO_PACKET_IN)) { COVERAGE_INC(ofproto_no_packet_in); /* XXX install 'drop' flow entry */ ofpbuf_delete(upcall->packet); @@ -4059,8 +4221,7 @@ ofproto_dp_max_idle(const struct ofproto *ofproto) ds_put_format(&s, " %d:%d", i * BUCKET_WIDTH, buckets[i]); } } - VLOG_INFO("%s: %s (msec:count)", - dpif_name(ofproto->dpif), ds_cstr(&s)); + VLOG_INFO("%s: %s (msec:count)", ofproto->name, ds_cstr(&s)); ds_destroy(&s); } @@ -4234,16 +4395,30 @@ pick_fallback_dpid(void) return eth_addr_to_uint64(ea); } +static struct ofproto * +ofproto_lookup(const char *name) +{ + struct ofproto *ofproto; + + HMAP_FOR_EACH_WITH_HASH (ofproto, hmap_node, hash_string(name, 0), + &all_ofprotos) { + if (!strcmp(ofproto->name, name)) { + return ofproto; + } + } + return NULL; +} + static void ofproto_unixctl_list(struct unixctl_conn *conn, const char *arg OVS_UNUSED, void *aux OVS_UNUSED) { - const struct shash_node *node; + struct ofproto *ofproto; struct ds results; ds_init(&results); - SHASH_FOR_EACH (node, &all_ofprotos) { - ds_put_format(&results, "%s\n", node->name); + HMAP_FOR_EACH (ofproto, hmap_node, &all_ofprotos) { + ds_put_format(&results, "%s\n", ofproto->name); } unixctl_command_reply(conn, 200, ds_cstr(&results)); ds_destroy(&results); @@ -4330,7 +4505,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, const char *args_, goto exit; } - ofproto = shash_find_data(&all_ofprotos, dpname); + ofproto = ofproto_lookup(dpname); if (!ofproto) { unixctl_command_reply(conn, 501, "Unknown ofproto (use ofproto/list " "for help)"); @@ -4437,7 +4612,7 @@ default_normal_ofhook_cb(const struct flow *flow, const struct ofpbuf *packet, /* Determine output port. */ dst_mac = mac_learning_lookup(ofproto->ml, flow->dl_dst, 0, tags); if (!dst_mac) { - flood_packets(ofproto, flow->in_port, OFPPC_NO_FLOOD, + flood_packets(ofproto, flow->in_port, htonl(OFPPC_NO_FLOOD), nf_output_iface, odp_actions); } else { int out_port = dst_mac->port.i;