goto exit_free_ofpacts;
}
if (po.in_port >= p->max_ports && po.in_port < OFPP_MAX) {
- error = OFPERR_NXBRC_BAD_IN_PORT;
+ error = OFPERR_OFPBRC_BAD_PORT;
goto exit_free_ofpacts;
}
const struct ofp_header *request)
{
struct ofproto *p = ofconn_get_ofproto(ofconn);
- struct ofp10_table_stats *ots;
+ struct ofp12_table_stats *ots;
struct ofpbuf *msg;
size_t i;
- msg = ofpraw_alloc_stats_reply(request, sizeof *ots * p->n_tables);
- ots = ofpbuf_put_zeros(msg, sizeof *ots * p->n_tables);
+ /* Set up default values.
+ *
+ * ofp12_table_stats is used as a generic structure as
+ * it is able to hold all the fields for ofp10_table_stats
+ * and ofp11_table_stats (and of course itself).
+ */
+ ots = xcalloc(p->n_tables, sizeof *ots);
for (i = 0; i < p->n_tables; i++) {
ots[i].table_id = i;
sprintf(ots[i].name, "table%zu", i);
- ots[i].wildcards = htonl(OFPFW10_ALL);
+ ots[i].match = htonll(OFPXMT12_MASK);
+ ots[i].wildcards = htonll(OFPXMT12_MASK);
+ ots[i].write_actions = htonl(OFPAT11_OUTPUT);
+ ots[i].apply_actions = htonl(OFPAT11_OUTPUT);
+ ots[i].write_setfields = htonll(OFPXMT12_MASK);
+ ots[i].apply_setfields = htonll(OFPXMT12_MASK);
+ ots[i].metadata_match = htonll(UINT64_MAX);
+ ots[i].metadata_write = htonll(UINT64_MAX);
+ ots[i].instructions = htonl(OFPIT11_ALL);
+ ots[i].config = htonl(OFPTC11_TABLE_MISS_MASK);
ots[i].max_entries = htonl(1000000); /* An arbitrary big number. */
ots[i].active_count = htonl(classifier_count(&p->tables[i].cls));
}
}
}
+ msg = ofputil_encode_table_stats_reply(ots, p->n_tables, request);
ofconn_send_reply(ofconn, msg);
+
+ free(ots);
+
return 0;
}
{
return (table_id == 0xff || table_id < ofproto->n_tables
? 0
- : OFPERR_NXBRC_BAD_TABLE_ID);
+ : OFPERR_OFPBRC_BAD_TABLE_ID);
}
} else if (fm->table_id < ofproto->n_tables) {
table = &ofproto->tables[fm->table_id];
} else {
- return OFPERR_NXFMFC_BAD_TABLE_ID;
+ return OFPERR_OFPBRC_BAD_TABLE_ID;
}
if (table->flags & OFTABLE_READONLY) {
fr.priority = rule->cr.priority;
fr.cookie = rule->flow_cookie;
fr.reason = reason;
+ fr.table_id = rule->table_id;
calc_flow_duration__(rule->created, time_msec(),
&fr.duration_sec, &fr.duration_nsec);
fr.idle_timeout = rule->idle_timeout;
}
if (fm.flags & OFPFF10_EMERG) {
- /* We do not support the OpenFlow 1.0 emergency flow cache, which is not
- * required in OpenFlow 1.0.1 and removed from OpenFlow 1.1. */
- /* We do not support the emergency flow cache. It will hopefully get
- * dropped from OpenFlow in the near future. There is no good error
- * code, so just state that the flow table is full. */
+ /* We do not support the OpenFlow 1.0 emergency flow cache, which
+ * is not required in OpenFlow 1.0.1 and removed from OpenFlow 1.1.
+ * There is no good error code, so just state that the flow table
+ * is full. */
error = OFPERR_OFPFMFC_ALL_TABLES_FULL;
}
if (!error) {
fu.cookie = rule->flow_cookie;
minimatch_expand(&rule->cr.match, &match);
fu.match = &match;
+ fu.priority = rule->cr.priority;
if (!(flags & NXFMF_ACTIONS)) {
fu.ofpacts = NULL;
fu.ofpacts_len = 0;