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;
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)
{
/* 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
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);
hmap_destroy(&ofproto->vlandev_map);
hmap_destroy(&ofproto->realdev_vid_map);
+ hmap_destroy(&ofproto->odp_to_ofport_map);
+
dpif_close(ofproto->dpif);
}
{
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();
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;
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);
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;
}
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
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_);
- uint32_t odp_port = *ofp_portp != OFPP_NONE ? *ofp_portp : UINT32_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) {
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);
enum odp_key_fitness fitness;
fitness = odp_flow_key_to_flow(key, key_len, flow);
- flow->in_port = odp_port_to_ofp_port(flow->in_port);
+ flow->in_port = odp_port_to_ofp_port(ofproto, flow->in_port);
if (fitness == ODP_FIT_ERROR) {
return fitness;
}
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,
}
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
int error;
ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
- odp_flow_key_from_flow(&key, flow, ofp_port_to_odp_port(flow->in_port));
+ 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);
struct flow flow;
fitness = odp_flow_key_to_flow(key, key_len, &flow);
- flow.in_port = odp_port_to_ofp_port(flow.in_port);
+ flow.in_port = odp_port_to_ofp_port(ofproto, flow.in_port);
if (fitness == ODP_FIT_ERROR) {
return NULL;
}
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, flow, ofp_port_to_odp_port(flow->in_port));
+ 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);
}
}
ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
- odp_flow_key_from_flow(&key, &flow, ofp_port_to_odp_port(flow.in_port));
+ 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);
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);
}
bool check_stp)
{
const struct ofport_dpif *ofport = get_ofp_port(ctx->ofproto, ofp_port);
- uint32_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;
struct ofpbuf odp_actions;
ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
- odp_flow_key_from_flow(&key, flow, ofp_port_to_odp_port(flow->in_port));
+ odp_flow_key_from_flow(&key, flow,
+ ofp_port_to_odp_port(ofproto, flow->in_port));
dpif_flow_stats_extract(flow, packet, time_msec(), &stats);
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);
}
}
}
VLOG_ERR("duplicate vlan device record");
}
}
-\f
+
+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,