enum ofoperation_type);
static void ofoperation_destroy(struct ofoperation *);
-static void ofport_destroy__(struct ofport *);
-static void ofport_destroy(struct ofport *);
+/* oftable. */
+static void oftable_init(struct oftable *);
+static void oftable_destroy(struct oftable *);
-static uint64_t pick_datapath_id(const struct ofproto *);
-static uint64_t pick_fallback_dpid(void);
-
-static void ofproto_destroy__(struct ofproto *);
+static void oftable_remove_rule(struct rule *);
+static struct rule *oftable_replace_rule(struct rule *);
+static void oftable_substitute_rule(struct rule *old, struct rule *new);
+/* rule. */
static void ofproto_rule_destroy__(struct rule *);
static void ofproto_rule_send_removed(struct rule *, uint8_t reason);
-static void ofopgroup_destroy(struct ofopgroup *);
+/* ofport. */
+static void ofport_destroy__(struct ofport *);
+static void ofport_destroy(struct ofport *);
+
+static void update_port(struct ofproto *, const char *devname);
+static int init_ports(struct ofproto *);
+static void reinit_ports(struct ofproto *);
+/* OpenFlow. */
static enum ofperr add_flow(struct ofproto *, struct ofconn *,
const struct ofputil_flow_mod *,
const struct ofp_header *);
static bool handle_openflow(struct ofconn *, struct ofpbuf *);
static enum ofperr handle_flow_mod__(struct ofproto *, struct ofconn *,
const struct ofputil_flow_mod *,
- const struct ofp_header *);
+ const struct ofp_header *);
-static void update_port(struct ofproto *, const char *devname);
-static int init_ports(struct ofproto *);
-static void reinit_ports(struct ofproto *);
+/* ofproto. */
+static uint64_t pick_datapath_id(const struct ofproto *);
+static uint64_t pick_fallback_dpid(void);
+static void ofproto_destroy__(struct ofproto *);
static void set_internal_devs_mtu(struct ofproto *);
+/* unixctl. */
static void ofproto_unixctl_init(void);
/* All registered ofproto classes, in probe order. */
struct ofproto **ofprotop)
{
const struct ofproto_class *class;
- struct classifier *table;
struct ofproto *ofproto;
+ struct oftable *table;
int n_tables;
int error;
ofproto->n_tables = n_tables;
ofproto->tables = xmalloc(n_tables * sizeof *ofproto->tables);
OFPROTO_FOR_EACH_TABLE (table, ofproto) {
- classifier_init(table);
+ oftable_init(table);
}
ofproto->datapath_id = pick_datapath_id(ofproto);
static void
ofproto_flush__(struct ofproto *ofproto)
{
- struct classifier *table;
struct ofopgroup *group;
+ struct oftable *table;
if (ofproto->ofproto_class->flush) {
ofproto->ofproto_class->flush(ofproto);
struct rule *rule, *next_rule;
struct cls_cursor cursor;
- cls_cursor_init(&cursor, table, NULL);
+ cls_cursor_init(&cursor, &table->cls, NULL);
CLS_CURSOR_FOR_EACH_SAFE (rule, next_rule, cr, &cursor) {
if (!rule->pending) {
ofoperation_create(group, rule, OFOPERATION_DELETE);
- classifier_remove(table, &rule->cr);
+ oftable_remove_rule(rule);
ofproto->ofproto_class->rule_destruct(rule);
}
}
static void
ofproto_destroy__(struct ofproto *ofproto)
{
- struct classifier *table;
+ struct oftable *table;
assert(list_is_empty(&ofproto->pending));
assert(!ofproto->n_pending);
shash_destroy(&ofproto->port_by_name);
OFPROTO_FOR_EACH_TABLE (table, ofproto) {
- assert(classifier_is_empty(table));
- classifier_destroy(table);
+ oftable_destroy(table);
}
free(ofproto->tables);
const struct rule *rule;
rule = rule_from_cls_rule(classifier_find_rule_exactly(
- &ofproto->tables[0], cls_rule));
+ &ofproto->tables[0].cls, cls_rule));
if (!rule || !ofputil_actions_equal(rule->actions, rule->n_actions,
actions, n_actions)) {
struct ofputil_flow_mod fm;
struct rule *rule;
rule = rule_from_cls_rule(classifier_find_rule_exactly(
- &ofproto->tables[0], target));
+ &ofproto->tables[0].cls, target));
if (!rule) {
/* No such rule -> success. */
return true;
/* Initiate deletion -> success. */
struct ofopgroup *group = ofopgroup_create_unattached(ofproto);
ofoperation_create(group, rule, OFOPERATION_DELETE);
- classifier_remove(&ofproto->tables[rule->table_id], &rule->cr);
+ oftable_remove_rule(rule);
rule->ofproto->ofproto_class->rule_destruct(rule);
ofopgroup_submit(group);
return true;
ofproto_rule_destroy(struct rule *rule)
{
assert(!rule->pending);
- classifier_remove(&rule->ofproto->tables[rule->table_id], &rule->cr);
+ oftable_remove_rule(rule);
ofproto_rule_destroy__(rule);
}
sprintf(ots[i].name, "table%zu", i);
ots[i].wildcards = htonl(OFPFW_ALL);
ots[i].max_entries = htonl(1000000); /* An arbitrary big number. */
- ots[i].active_count = htonl(classifier_count(&p->tables[i]));
+ ots[i].active_count = htonl(classifier_count(&p->tables[i].cls));
}
p->ofproto_class->get_tables(p, ots);
}
-static struct classifier *
+static struct oftable *
first_matching_table(struct ofproto *ofproto, uint8_t table_id)
{
if (table_id == 0xff) {
}
}
-static struct classifier *
+static struct oftable *
next_matching_table(struct ofproto *ofproto,
- struct classifier *cls, uint8_t table_id)
+ struct oftable *table, uint8_t table_id)
{
- return (table_id == 0xff && cls != &ofproto->tables[ofproto->n_tables - 1]
- ? cls + 1
+ return (table_id == 0xff && table < &ofproto->tables[ofproto->n_tables - 1]
+ ? table + 1
: NULL);
}
-/* Assigns CLS to each classifier table, in turn, that matches TABLE_ID in
- * OFPROTO:
+/* Assigns TABLE to each oftable, in turn, that matches TABLE_ID in OFPROTO:
*
* - If TABLE_ID is 0xff, this iterates over every classifier table in
* OFPROTO.
*
* All parameters are evaluated multiple times.
*/
-#define FOR_EACH_MATCHING_TABLE(CLS, TABLE_ID, OFPROTO) \
- for ((CLS) = first_matching_table(OFPROTO, TABLE_ID); \
- (CLS) != NULL; \
- (CLS) = next_matching_table(OFPROTO, CLS, TABLE_ID))
+#define FOR_EACH_MATCHING_TABLE(TABLE, TABLE_ID, OFPROTO) \
+ for ((TABLE) = first_matching_table(OFPROTO, TABLE_ID); \
+ (TABLE) != NULL; \
+ (TABLE) = next_matching_table(OFPROTO, TABLE, TABLE_ID))
/* Searches 'ofproto' for rules in table 'table_id' (or in all tables, if
* 'table_id' is 0xff) that match 'match' in the "loose" way required for
ovs_be64 cookie, ovs_be64 cookie_mask,
uint16_t out_port, struct list *rules)
{
- struct classifier *cls;
+ struct oftable *table;
enum ofperr error;
error = check_table_id(ofproto, table_id);
}
list_init(rules);
- FOR_EACH_MATCHING_TABLE (cls, table_id, ofproto) {
+ FOR_EACH_MATCHING_TABLE (table, table_id, ofproto) {
struct cls_cursor cursor;
struct rule *rule;
- cls_cursor_init(&cursor, cls, match);
+ cls_cursor_init(&cursor, &table->cls, match);
CLS_CURSOR_FOR_EACH (rule, cr, &cursor) {
if (rule->pending) {
return OFPROTO_POSTPONE;
ovs_be64 cookie, ovs_be64 cookie_mask,
uint16_t out_port, struct list *rules)
{
- struct classifier *cls;
+ struct oftable *table;
int error;
error = check_table_id(ofproto, table_id);
}
list_init(rules);
- FOR_EACH_MATCHING_TABLE (cls, table_id, ofproto) {
+ FOR_EACH_MATCHING_TABLE (table, table_id, ofproto) {
struct rule *rule;
- rule = rule_from_cls_rule(classifier_find_rule_exactly(cls, match));
+ rule = rule_from_cls_rule(classifier_find_rule_exactly(&table->cls,
+ match));
if (rule) {
if (rule->pending) {
return OFPROTO_POSTPONE;
void
ofproto_get_all_flows(struct ofproto *p, struct ds *results)
{
- struct classifier *cls;
+ struct oftable *table;
- OFPROTO_FOR_EACH_TABLE (cls, p) {
+ OFPROTO_FOR_EACH_TABLE (table, p) {
struct cls_cursor cursor;
struct rule *rule;
- cls_cursor_init(&cursor, cls, NULL);
+ cls_cursor_init(&cursor, &table->cls, NULL);
CLS_CURSOR_FOR_EACH (rule, cr, &cursor) {
flow_stats_ds(rule, results);
}
add_flow(struct ofproto *ofproto, struct ofconn *ofconn,
const struct ofputil_flow_mod *fm, const struct ofp_header *request)
{
- struct classifier *table;
+ struct oftable *table;
struct ofopgroup *group;
struct rule *victim;
struct rule *rule;
/* Check for overlap, if requested. */
if (fm->flags & OFPFF_CHECK_OVERLAP
- && classifier_rule_overlaps(table, &fm->cr)) {
+ && classifier_rule_overlaps(&table->cls, &fm->cr)) {
return OFPERR_OFPFMFC_OVERLAP;
}
rule->n_actions = fm->n_actions;
/* Insert new rule. */
- victim = rule_from_cls_rule(classifier_replace(table, &rule->cr));
+ victim = oftable_replace_rule(rule);
if (victim && victim->pending) {
error = OFPROTO_POSTPONE;
} else {
/* Back out if an error occurred. */
if (error) {
- if (victim) {
- classifier_replace(table, &victim->cr);
- } else {
- classifier_remove(table, &rule->cr);
- }
+ oftable_substitute_rule(rule, victim);
ofproto_rule_destroy__(rule);
}
return error;
ofproto_rule_send_removed(rule, OFPRR_DELETE);
ofoperation_create(group, rule, OFOPERATION_DELETE);
- classifier_remove(&ofproto->tables[rule->table_id], &rule->cr);
+ oftable_remove_rule(rule);
rule->ofproto->ofproto_class->rule_destruct(rule);
}
ofopgroup_submit(group);
group = ofopgroup_create_unattached(ofproto);
ofoperation_create(group, rule, OFOPERATION_DELETE);
- classifier_remove(&ofproto->tables[rule->table_id], &rule->cr);
+ oftable_remove_rule(rule);
rule->ofproto->ofproto_class->rule_destruct(rule);
ofopgroup_submit(group);
}
struct ofopgroup *group = op->group;
struct rule *rule = op->rule;
struct ofproto *ofproto = rule->ofproto;
- struct classifier *table = &ofproto->tables[rule->table_id];
assert(rule->pending == op);
assert(op->status < 0);
}
}
} else {
- if (op->victim) {
- classifier_replace(table, &op->victim->cr);
- op->victim = NULL;
- } else {
- classifier_remove(table, &rule->cr);
- }
+ oftable_substitute_rule(rule, op->victim);
ofproto_rule_destroy__(rule);
}
op->victim = NULL;
return eth_addr_to_uint64(ea);
}
\f
+/* oftables. */
+
+/* Initializes 'table'. */
+static void
+oftable_init(struct oftable *table)
+{
+ classifier_init(&table->cls);
+}
+
+/* Destroys 'table'.
+ *
+ * The caller is responsible for freeing 'table' itself. */
+static void
+oftable_destroy(struct oftable *table)
+{
+ assert(classifier_is_empty(&table->cls));
+ classifier_destroy(&table->cls);
+}
+
+/* Removes 'rule' from the oftable that contains it. */
+static void
+oftable_remove_rule(struct rule *rule)
+{
+ struct ofproto *ofproto = rule->ofproto;
+ struct oftable *table = &ofproto->tables[rule->table_id];
+
+ classifier_remove(&table->cls, &rule->cr);
+}
+
+/* Inserts 'rule' into its oftable. Removes any existing rule from 'rule''s
+ * oftable that has an identical cls_rule. Returns the rule that was removed,
+ * if any, and otherwise NULL. */
+static struct rule *
+oftable_replace_rule(struct rule *rule)
+{
+ struct ofproto *ofproto = rule->ofproto;
+ struct oftable *table = &ofproto->tables[rule->table_id];
+
+ return rule_from_cls_rule(classifier_replace(&table->cls, &rule->cr));
+}
+
+/* Removes 'old' from its oftable then, if 'new' is nonnull, inserts 'new'. */
+static void
+oftable_substitute_rule(struct rule *old, struct rule *new)
+{
+ if (new) {
+ oftable_replace_rule(new);
+ } else {
+ oftable_remove_rule(old);
+ }
+}
+\f
/* unixctl commands. */
struct ofproto *
void
ofproto_get_vlan_usage(struct ofproto *ofproto, unsigned long int *vlan_bitmap)
{
- const struct classifier *cls;
+ const struct oftable *oftable;
free(ofproto->vlan_bitmap);
ofproto->vlan_bitmap = bitmap_allocate(4096);
ofproto->vlans_changed = false;
- OFPROTO_FOR_EACH_TABLE (cls, ofproto) {
+ OFPROTO_FOR_EACH_TABLE (oftable, ofproto) {
const struct cls_table *table;
- HMAP_FOR_EACH (table, hmap_node, &cls->tables) {
+ HMAP_FOR_EACH (table, hmap_node, &oftable->cls.tables) {
if ((table->wc.vlan_tci_mask & htons(VLAN_VID_MASK))
== htons(VLAN_VID_MASK)) {
const struct cls_rule *rule;