*
* This is a helper function for in-band control and fail-open. */
void
-ofproto_add_flow(struct ofproto *ofproto, const struct cls_rule *cls_rule,
+ofproto_add_flow(struct ofproto *ofproto, const struct match *match,
+ unsigned int priority,
const struct ofpact *ofpacts, size_t ofpacts_len)
{
const struct rule *rule;
- rule = rule_from_cls_rule(classifier_find_rule_exactly(
- &ofproto->tables[0].cls, cls_rule));
+ rule = rule_from_cls_rule(classifier_find_match_exactly(
+ &ofproto->tables[0].cls, match, priority));
if (!rule || !ofpacts_equal(rule->ofpacts, rule->ofpacts_len,
ofpacts, ofpacts_len)) {
struct ofputil_flow_mod fm;
memset(&fm, 0, sizeof fm);
- fm.cr = *cls_rule;
+ fm.match = *match;
+ fm.priority = priority;
fm.buffer_id = UINT32_MAX;
fm.ofpacts = xmemdup(ofpacts, ofpacts_len);
fm.ofpacts_len = ofpacts_len;
*
* This is a helper function for in-band control and fail-open. */
bool
-ofproto_delete_flow(struct ofproto *ofproto, const struct cls_rule *target)
+ofproto_delete_flow(struct ofproto *ofproto,
+ const struct match *target, unsigned int priority)
{
struct rule *rule;
- rule = rule_from_cls_rule(classifier_find_rule_exactly(
- &ofproto->tables[0].cls, target));
+ rule = rule_from_cls_rule(classifier_find_match_exactly(
+ &ofproto->tables[0].cls, target, priority));
if (!rule) {
/* No such rule -> success. */
return true;
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);
* Returns 0 on success, otherwise an OpenFlow error code. */
static enum ofperr
collect_rules_loose(struct ofproto *ofproto, uint8_t table_id,
- const struct cls_rule *match,
+ const struct match *match,
ovs_be64 cookie, ovs_be64 cookie_mask,
uint16_t out_port, struct list *rules)
{
struct oftable *table;
+ struct cls_rule cr;
enum ofperr error;
error = check_table_id(ofproto, table_id);
}
list_init(rules);
+ cls_rule_init(&cr, match, 0);
FOR_EACH_MATCHING_TABLE (table, table_id, ofproto) {
struct cls_cursor cursor;
struct rule *rule;
- cls_cursor_init(&cursor, &table->cls, match);
+ 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
* Returns 0 on success, otherwise an OpenFlow error code. */
static enum ofperr
collect_rules_strict(struct ofproto *ofproto, uint8_t table_id,
- const struct cls_rule *match,
+ const struct match *match, unsigned int priority,
ovs_be64 cookie, ovs_be64 cookie_mask,
uint16_t out_port, struct list *rules)
{
struct oftable *table;
+ struct cls_rule cr;
int error;
error = check_table_id(ofproto, table_id);
}
list_init(rules);
+ cls_rule_init(&cr, match, priority);
FOR_EACH_MATCHING_TABLE (table, table_id, ofproto) {
struct rule *rule;
rule = rule_from_cls_rule(classifier_find_rule_exactly(&table->cls,
- match));
+ &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.rule = rule->cr;
+ minimatch_expand(&rule->cr.match, &fs.match);
+ fs.priority = rule->cr.priority;
fs.cookie = rule->flow_cookie;
fs.table_id = rule->table_id;
calc_flow_duration__(rule->created, now, &fs.duration_sec,
struct oftable *table;
struct ofopgroup *group;
struct rule *victim;
+ struct cls_rule cr;
struct rule *rule;
int error;
if (fm->table_id == 0xff) {
uint8_t table_id;
if (ofproto->ofproto_class->rule_choose_table) {
- error = ofproto->ofproto_class->rule_choose_table(ofproto, &fm->cr,
+ error = ofproto->ofproto_class->rule_choose_table(ofproto,
+ &fm->match,
&table_id);
if (error) {
return error;
return OFPERR_OFPBRC_EPERM;
}
- /* Check for overlap, if requested. */
- if (fm->flags & OFPFF_CHECK_OVERLAP
- && classifier_rule_overlaps(&table->cls, &fm->cr)) {
- return OFPERR_OFPFMFC_OVERLAP;
+ /* Allocate new rule and initialize classifier rule. */
+ rule = ofproto->ofproto_class->rule_alloc();
+ if (!rule) {
+ VLOG_WARN_RL(&rl, "%s: failed to create rule (%s)",
+ ofproto->name, strerror(error));
+ return ENOMEM;
}
+ cls_rule_init(&rule->cr, &fm->match, fm->priority);
/* Serialize against pending deletion. */
- if (is_flow_deletion_pending(ofproto, &fm->cr, table - ofproto->tables)) {
+ if (is_flow_deletion_pending(ofproto, &cr, table - ofproto->tables)) {
+ cls_rule_destroy(&rule->cr);
+ ofproto->ofproto_class->rule_dealloc(rule);
return OFPROTO_POSTPONE;
}
- /* Allocate new rule. */
- rule = ofproto->ofproto_class->rule_alloc();
- if (!rule) {
- VLOG_WARN_RL(&rl, "%s: failed to create rule (%s)",
- ofproto->name, strerror(error));
- return ENOMEM;
+ /* 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;
}
+
rule->ofproto = ofproto;
- rule->cr = fm->cr;
rule->pending = NULL;
rule->flow_cookie = fm->new_cookie;
rule->created = rule->modified = rule->used = time_msec();
struct list rules;
int error;
- error = collect_rules_loose(ofproto, fm->table_id, &fm->cr,
+ error = collect_rules_loose(ofproto, fm->table_id, &fm->match,
fm->cookie, fm->cookie_mask,
OFPP_NONE, &rules);
if (error) {
struct list rules;
int error;
- error = collect_rules_strict(ofproto, fm->table_id, &fm->cr,
- fm->cookie, fm->cookie_mask,
+ error = collect_rules_strict(ofproto, fm->table_id, &fm->match,
+ fm->priority, fm->cookie, fm->cookie_mask,
OFPP_NONE, &rules);
if (error) {
struct list rules;
enum ofperr error;
- error = collect_rules_loose(ofproto, fm->table_id, &fm->cr,
+ error = collect_rules_loose(ofproto, fm->table_id, &fm->match,
fm->cookie, fm->cookie_mask,
fm->out_port, &rules);
return (error ? error
struct list rules;
enum ofperr error;
- error = collect_rules_strict(ofproto, fm->table_id, &fm->cr,
- fm->cookie, fm->cookie_mask,
+ error = collect_rules_strict(ofproto, fm->table_id, &fm->match,
+ fm->priority, fm->cookie, fm->cookie_mask,
fm->out_port, &rules);
return (error ? error
: list_is_singleton(&rules) ? delete_flows__(ofproto, ofconn,
return;
}
- fr.rule = rule->cr;
+ minimatch_expand(&rule->cr.match, &fr.match);
+ fr.priority = rule->cr.priority;
fr.cookie = rule->flow_cookie;
fr.reason = reason;
calc_flow_duration__(rule->created, time_msec(),
}
if (!error) {
error = ofpacts_check(fm.ofpacts, fm.ofpacts_len,
- &fm.cr.flow, ofproto->max_ports);
+ &fm.match.flow, ofproto->max_ports);
}
if (!error) {
error = handle_flow_mod__(ofconn_get_ofproto(ofconn), ofconn, &fm, oh);
{
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 cls_rule *, &rule->cr);
+ minimatch_expand(&rule->cr.match, &match);
+ fu.match = &match;
if (!(flags & NXFMF_ACTIONS)) {
fu.ofpacts = NULL;
fu.ofpacts_len = 0;
const struct ofproto *ofproto = ofconn_get_ofproto(m->ofconn);
const struct ofoperation *op;
const struct oftable *table;
+ struct cls_rule target;
+ 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;
- cls_cursor_init(&cursor, &table->cls, &m->match);
+ cls_cursor_init(&cursor, &table->cls, &target);
CLS_CURSOR_FOR_EACH (rule, cr, &cursor) {
assert(!rule->pending); /* XXX */
ofproto_collect_ofmonitor_refresh_rule(m, rule, seqno, rules);
if (((m->table_id == 0xff
? !(ofproto->tables[rule->table_id].flags & OFTABLE_HIDDEN)
: m->table_id == rule->table_id))
- && cls_rule_is_loose_match(&rule->cr, &m->match)) {
+ && cls_rule_is_loose_match(&rule->cr, &target.match)) {
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.wc.vlan_tci_mask & 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 = vlan_tci_to_vid(rule->cr.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.flow)) {
+ if (mf_are_prereqs_ok(sf->field, &flow)) {
union mf_value value;
- mf_get_value(sf->field, &rule->cr.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.vlan_tci_mask & 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->flow.vlan_tci);
+ uint16_t vid = miniflow_get_vid(&rule->match.flow);
bitmap_set1(vlan_bitmap, vid);
bitmap_set1(ofproto->vlan_bitmap, vid);
}