ofproto_rule_destroy__(struct rule *rule)
{
if (rule) {
+ cls_rule_destroy(&rule->cr);
free(rule->ofpacts);
rule->ofproto->ofproto_class->rule_dealloc(rule);
}
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;
}
+
/* Get payload. */
if (po.buffer_id != UINT32_MAX) {
error = ofconn_pktbuf_retrieve(ofconn, po.buffer_id, &payload, NULL);
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);
}
cls_cursor_init(&cursor, &table->cls, &cr);
CLS_CURSOR_FOR_EACH (rule, cr, &cursor) {
if (rule->pending) {
- return OFPROTO_POSTPONE;
+ error = OFPROTO_POSTPONE;
+ goto exit;
}
if (!ofproto_rule_is_hidden(rule)
&& ofproto_rule_has_out_port(rule, out_port)
}
}
}
- return 0;
+
+exit:
+ cls_rule_destroy(&cr);
+ return error;
}
/* Searches 'ofproto' for rules in table 'table_id' (or in all tables, if
&cr));
if (rule) {
if (rule->pending) {
- return OFPROTO_POSTPONE;
+ error = OFPROTO_POSTPONE;
+ goto exit;
}
if (!ofproto_rule_is_hidden(rule)
&& ofproto_rule_has_out_port(rule, out_port)
}
}
}
+
+exit:
+ cls_rule_destroy(&cr);
return 0;
}
long long int now = time_msec();
struct ofputil_flow_stats fs;
- fs.match = rule->cr.match;
+ minimatch_expand(&rule->cr.match, &fs.match);
fs.priority = rule->cr.priority;
fs.cookie = rule->flow_cookie;
fs.table_id = rule->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) {
/* Serialize against pending deletion. */
if (is_flow_deletion_pending(ofproto, &cr, table - ofproto->tables)) {
+ cls_rule_destroy(&rule->cr);
ofproto->ofproto_class->rule_dealloc(rule);
return OFPROTO_POSTPONE;
}
/* Check for overlap, if requested. */
if (fm->flags & OFPFF_CHECK_OVERLAP
&& classifier_rule_overlaps(&table->cls, &rule->cr)) {
+ cls_rule_destroy(&rule->cr);
ofproto->ofproto_class->rule_dealloc(rule);
return OFPERR_OFPFMFC_OVERLAP;
}
return;
}
- fr.match = rule->cr.match;
+ minimatch_expand(&rule->cr.match, &fr.match);
fr.priority = rule->cr.priority;
fr.cookie = rule->flow_cookie;
fr.reason = reason;
{
struct ofoperation *op = rule->pending;
struct ofputil_flow_update fu;
+ struct match match;
if (op && op->type == OFOPERATION_ADD && !op->victim) {
/* We'll report the final flow when the operation completes. Reporting
fu.hard_timeout = rule->hard_timeout;
fu.table_id = rule->table_id;
fu.cookie = rule->flow_cookie;
- fu.match = CONST_CAST(struct match *, &rule->cr.match);
+ 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;
const struct oftable *table;
struct cls_rule target;
- cls_rule_init(&target, &m->match, 0);
+ cls_rule_init_from_minimatch(&target, &m->match, 0);
FOR_EACH_MATCHING_TABLE (table, m->table_id, ofproto) {
struct cls_cursor cursor;
struct rule *rule;
ofproto_collect_ofmonitor_refresh_rule(m, rule, seqno, rules);
}
}
+ cls_rule_destroy(&target);
}
static void
switch (op->type) {
case OFOPERATION_ADD:
if (!op->error) {
+ uint16_t vid_mask;
+
ofproto_rule_destroy__(op->victim);
- if ((rule->cr.match.wc.masks.vlan_tci & htons(VLAN_VID_MASK))
- == htons(VLAN_VID_MASK)) {
+ vid_mask = minimask_get_vid_mask(&rule->cr.match.mask);
+ if (vid_mask == VLAN_VID_MASK) {
if (ofproto->vlan_bitmap) {
- uint16_t vid;
-
- vid = vlan_tci_to_vid(rule->cr.match.flow.vlan_tci);
+ uint16_t vid = miniflow_get_vid(&rule->cr.match.flow);
if (!bitmap_is_set(ofproto->vlan_bitmap, vid)) {
bitmap_set1(ofproto->vlan_bitmap, vid);
ofproto->vlans_changed = true;
{
struct oftable *table = &rule->ofproto->tables[rule->table_id];
const struct mf_subfield *sf;
+ struct flow flow;
uint32_t hash;
hash = table->eviction_group_id_basis;
+ miniflow_expand(&rule->cr.match.flow, &flow);
for (sf = table->eviction_fields;
sf < &table->eviction_fields[table->n_eviction_fields];
sf++)
{
- if (mf_are_prereqs_ok(sf->field, &rule->cr.match.flow)) {
+ if (mf_are_prereqs_ok(sf->field, &flow)) {
union mf_value value;
- mf_get_value(sf->field, &rule->cr.match.flow, &value);
+ mf_get_value(sf->field, &flow, &value);
if (sf->ofs) {
bitwise_zero(&value, sf->field->n_bytes, 0, sf->ofs);
}
const struct cls_table *table;
HMAP_FOR_EACH (table, hmap_node, &oftable->cls.tables) {
- if ((table->wc.masks.vlan_tci & htons(VLAN_VID_MASK))
- == htons(VLAN_VID_MASK)) {
+ if (minimask_get_vid_mask(&table->mask) == VLAN_VID_MASK) {
const struct cls_rule *rule;
HMAP_FOR_EACH (rule, hmap_node, &table->rules) {
- uint16_t vid = vlan_tci_to_vid(rule->match.flow.vlan_tci);
+ uint16_t vid = miniflow_get_vid(&rule->match.flow);
bitmap_set1(vlan_bitmap, vid);
bitmap_set1(ofproto->vlan_bitmap, vid);
}