const struct ofproto_class *class;
struct ofproto *ofproto;
int error;
+ int i;
*ofprotop = NULL;
ofproto->ofp_port_ids = bitmap_allocate(ofproto->max_ports);
bitmap_set1(ofproto->ofp_port_ids, 0);
+ /* Check that hidden tables, if any, are at the end. */
assert(ofproto->n_tables);
+ for (i = 0; i + 1 < ofproto->n_tables; i++) {
+ enum oftable_flags flags = ofproto->tables[i].flags;
+ enum oftable_flags next_flags = ofproto->tables[i + 1].flags;
+
+ assert(!(flags & OFTABLE_HIDDEN) || next_flags & OFTABLE_HIDDEN);
+ }
ofproto->datapath_id = pick_datapath_id(ofproto);
init_ports(ofproto);
void
ofproto_set_controllers(struct ofproto *p,
const struct ofproto_controller *controllers,
- size_t n_controllers)
+ size_t n_controllers, uint32_t allowed_versions)
{
- connmgr_set_controllers(p->connmgr, controllers, n_controllers);
+ connmgr_set_controllers(p->connmgr, controllers, n_controllers,
+ allowed_versions);
}
void
return dump->error == EOF ? 0 : dump->error;
}
+/* Returns the type to pass to netdev_open() when a datapath of type
+ * 'datapath_type' has a port of type 'port_type', for a few special
+ * cases when a netdev type differs from a port type. For example, when
+ * using the userspace datapath, a port of type "internal" needs to be
+ * opened as "tap".
+ *
+ * Returns either 'type' itself or a string literal, which must not be
+ * freed. */
+const char *
+ofproto_port_open_type(const char *datapath_type, const char *port_type)
+{
+ const struct ofproto_class *class;
+
+ datapath_type = ofproto_normalize_type(datapath_type);
+ class = ofproto_class_find__(datapath_type);
+ if (!class) {
+ return port_type;
+ }
+
+ return (class->port_open_type
+ ? class->port_open_type(datapath_type, port_type)
+ : port_type);
+}
+
/* Attempts to add 'netdev' as a port on 'ofproto'. If 'ofp_portp' is
* non-null and '*ofp_portp' is not OFPP_NONE, attempts to use that as
* the port's OpenFlow port number.
* flows. */
while (ofp_port >= ofproto->max_ports) {
for (ofproto->alloc_port_no++;
- ofproto->alloc_port_no < ofproto->max_ports; ) {
+ ofproto->alloc_port_no < ofproto->max_ports;
+ ofproto->alloc_port_no++) {
if (!bitmap_is_set(ofproto->ofp_port_ids,
ofproto->alloc_port_no)) {
ofp_port = ofproto->alloc_port_no;
pp->state = netdev_get_carrier(netdev) ? 0 : OFPUTIL_PS_LINK_DOWN;
netdev_get_features(netdev, &pp->curr, &pp->advertised,
&pp->supported, &pp->peer);
- pp->curr_speed = netdev_features_to_bps(pp->curr);
- pp->max_speed = netdev_features_to_bps(pp->supported);
+ pp->curr_speed = netdev_features_to_bps(pp->curr, 0);
+ pp->max_speed = netdev_features_to_bps(pp->supported, 0);
return netdev;
}
bool
ofproto_rule_has_out_port(const struct rule *rule, uint16_t port)
{
- return (port == OFPP_NONE
+ return (port == OFPP_ANY
|| ofpacts_output_to_port(rule->ofpacts, rule->ofpacts_len, port));
}
assert(ofpbuf_headroom(packet) >= sizeof(struct ofp_packet_in));
- flow_extract(packet, 0, NULL, in_port, &flow);
+ flow_extract(packet, 0, 0, NULL, in_port, &flow);
return rule->ofproto->ofproto_class->rule_execute(rule, &flow, packet);
}
struct ofport *port;
bool arp_match_ip;
struct ofpbuf *b;
+ int n_tables;
+ int i;
ofproto->ofproto_class->get_features(ofproto, &arp_match_ip,
&features.actions);
assert(features.actions & OFPUTIL_A_OUTPUT); /* sanity check */
+ /* Count only non-hidden tables in the number of tables. (Hidden tables,
+ * if present, are always at the end.) */
+ n_tables = ofproto->n_tables;
+ for (i = 0; i < ofproto->n_tables; i++) {
+ if (ofproto->tables[i].flags & OFTABLE_HIDDEN) {
+ n_tables = i;
+ break;
+ }
+ }
+
features.datapath_id = ofproto->datapath_id;
features.n_buffers = pktbuf_capacity();
- features.n_tables = ofproto->n_tables;
+ features.n_tables = n_tables;
features.capabilities = (OFPUTIL_C_FLOW_STATS | OFPUTIL_C_TABLE_STATS |
OFPUTIL_C_PORT_STATS | OFPUTIL_C_QUEUE_STATS);
if (arp_match_ip) {
}
/* Verify actions against packet, then send packet if successful. */
- flow_extract(payload, 0, NULL, po.in_port, &flow);
+ flow_extract(payload, 0, 0, NULL, po.in_port, &flow);
error = ofpacts_check(po.ofpacts, po.ofpacts_len, &flow, p->max_ports);
if (!error) {
error = p->ofproto_class->packet_out(p, payload, &flow,
struct ofproto *p = ofconn_get_ofproto(ofconn);
struct ofp12_table_stats *ots;
struct ofpbuf *msg;
+ int n_tables;
size_t i;
/* Set up default values.
p->ofproto_class->get_tables(p, ots);
+ /* Post-process the tables, dropping hidden tables. */
+ n_tables = p->n_tables;
for (i = 0; i < p->n_tables; i++) {
const struct oftable *table = &p->tables[i];
+ if (table->flags & OFTABLE_HIDDEN) {
+ n_tables = i;
+ break;
+ }
+
if (table->name) {
ovs_strzcpy(ots[i].name, table->name, sizeof ots[i].name);
}
}
}
- msg = ofputil_encode_table_stats_reply(ots, p->n_tables, request);
+ msg = ofputil_encode_table_stats_reply(ots, n_tables, request);
ofconn_send_reply(ofconn, msg);
free(ots);
}
ofpmp_init(&replies, request);
- if (port_no != OFPP_NONE) {
+ if (port_no != OFPP_ANY) {
port = ofproto_get_port(p, port_no);
if (port) {
append_port_stat(port, &replies);
* OpenFlow OFPFC_MODIFY and OFPFC_DELETE requests and puts them on list
* 'rules'.
*
- * If 'out_port' is anything other than OFPP_NONE, then only rules that output
+ * If 'out_port' is anything other than OFPP_ANY, then only rules that output
* to 'out_port' are included.
*
* Hidden rules are always omitted.
* OpenFlow OFPFC_MODIFY_STRICT and OFPFC_DELETE_STRICT requests and puts them
* on list 'rules'.
*
- * If 'out_port' is anything other than OFPP_NONE, then only rules that output
+ * If 'out_port' is anything other than OFPP_ANY, then only rules that output
* to 'out_port' are included.
*
* Hidden rules are always omitted.
return error;
}
- if (oqsr.port_no == OFPP_ALL) {
+ if (oqsr.port_no == OFPP_ANY) {
error = OFPERR_OFPQOFC_BAD_QUEUE;
HMAP_FOR_EACH (port, hmap_node, &ofproto->ports) {
if (!handle_queue_stats_for_port(port, oqsr.queue_id, &cbdata)) {
error = collect_rules_loose(ofproto, fm->table_id, &fm->match,
fm->cookie, fm->cookie_mask,
- OFPP_NONE, &rules);
+ OFPP_ANY, &rules);
if (error) {
return error;
} else if (list_is_empty(&rules)) {
error = collect_rules_strict(ofproto, fm->table_id, &fm->match,
fm->priority, fm->cookie, fm->cookie_mask,
- OFPP_NONE, &rules);
+ OFPP_ANY, &rules);
if (error) {
return error;