/*
- * Copyright (c) 2015 Nicira, Inc.
+ * Copyright (c) 2015, 2016 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
}
static bool
-constrain_match(const struct expr *expr, const struct simap *ports,
- struct match *m)
+constrain_match(const struct expr *expr,
+ bool (*lookup_port)(const void *aux, const char *port_name,
+ unsigned int *portp),
+ const void *aux, struct match *m)
{
ovs_assert(expr->type == EXPR_T_CMP);
if (expr->cmp.symbol->width) {
mf_mask_subfield(expr->cmp.symbol->field, &expr->cmp.value,
&expr->cmp.mask, m);
} else {
- const struct simap_node *node;
- node = ports ? simap_find(ports, expr->cmp.string) : NULL;
- if (!node) {
+ unsigned int port;
+ if (!lookup_port(aux, expr->cmp.string, &port)) {
return false;
}
union mf_subvalue x;
memset(&x, 0, sizeof x);
- x.integer = htonll(node->data);
+ x.integer = htonll(port);
mf_write_subfield(&sf, &x, m);
}
}
static bool
-add_disjunction(const struct expr *or, const struct simap *ports,
+add_disjunction(const struct expr *or,
+ bool (*lookup_port)(const void *aux, const char *port_name,
+ unsigned int *portp),
+ const void *aux,
struct match *m, uint8_t clause, uint8_t n_clauses,
uint32_t conj_id, struct hmap *matches)
{
LIST_FOR_EACH (sub, node, &or->andor) {
struct expr_match *match = expr_match_new(m, clause, n_clauses,
conj_id);
- if (constrain_match(sub, ports, &match->match)) {
+ if (constrain_match(sub, lookup_port, aux, &match->match)) {
expr_match_add(matches, match);
n++;
} else {
}
static void
-add_conjunction(const struct expr *and, const struct simap *ports,
- uint32_t *n_conjsp, struct hmap *matches)
+add_conjunction(const struct expr *and,
+ bool (*lookup_port)(const void *aux, const char *port_name,
+ unsigned int *portp),
+ const void *aux, uint32_t *n_conjsp, struct hmap *matches)
{
struct match match;
int n_clauses = 0;
LIST_FOR_EACH (sub, node, &and->andor) {
switch (sub->type) {
case EXPR_T_CMP:
- if (!constrain_match(sub, ports, &match)) {
+ if (!constrain_match(sub, lookup_port, aux, &match)) {
return;
}
break;
} else if (n_clauses == 1) {
LIST_FOR_EACH (sub, node, &and->andor) {
if (sub->type == EXPR_T_OR) {
- add_disjunction(sub, ports, &match, 0, 0, 0, matches);
+ add_disjunction(sub, lookup_port, aux, &match, 0, 0, 0,
+ matches);
}
}
} else {
(*n_conjsp)++;
LIST_FOR_EACH (sub, node, &and->andor) {
if (sub->type == EXPR_T_OR) {
- if (!add_disjunction(sub, ports, &match, clause++,
+ if (!add_disjunction(sub, lookup_port, aux, &match, clause++,
n_clauses, *n_conjsp, matches)) {
/* This clause can't ever match, so we might as well skip
* adding the other clauses--the overall disjunctive flow
}
static void
-add_cmp_flow(const struct expr *cmp, const struct simap *ports,
- struct hmap *matches)
+add_cmp_flow(const struct expr *cmp,
+ bool (*lookup_port)(const void *aux, const char *port_name,
+ unsigned int *portp),
+ const void *aux, struct hmap *matches)
{
struct expr_match *m = expr_match_new(NULL, 0, 0, 0);
- if (constrain_match(cmp, ports, &m->match)) {
+ if (constrain_match(cmp, lookup_port, aux, &m->match)) {
expr_match_add(matches, m);
} else {
free(m);
* caller should remap the conj_id and add the OpenFlow flow with its
* desired actions.
*
- * 'ports' must be a map from strings (presumably names of ports) to integers.
- * Any comparisons against string fields in 'expr' are translated into integers
- * through this map. A comparison against a string that is not in 'ports' acts
- * like a Boolean "false"; that is, it will always fail to match. For a simple
- * expression, this means that the overall expression always fails to match,
- * but an expression with a disjunction on the string field might still match
- * on other port names.
+ * 'lookup_port' must be a function to map from a port name to a port number.
+ * When successful, 'lookup_port' stores the port number into '*portp' and
+ * returns true; when there is no port by the given name, it returns false.
+ * 'aux' is passed to 'lookup_port' as auxiliary data. Any comparisons against
+ * string fields in 'expr' are translated into integers through this function.
+ * A comparison against a string that is not in 'ports' acts like a Boolean
+ * "false"; that is, it will always fail to match. For a simple expression,
+ * this means that the overall expression always fails to match, but an
+ * expression with a disjunction on the string field might still match on other
+ * port names.
*
* (This treatment of string fields might be too simplistic in general, but it
* seems reasonable for now when string fields are used only for ports.) */
uint32_t
-expr_to_matches(const struct expr *expr, const struct simap *ports,
- struct hmap *matches)
+expr_to_matches(const struct expr *expr,
+ bool (*lookup_port)(const void *aux, const char *port_name,
+ unsigned int *portp),
+ const void *aux, struct hmap *matches)
{
uint32_t n_conjs = 0;
hmap_init(matches);
switch (expr->type) {
case EXPR_T_CMP:
- add_cmp_flow(expr, ports, matches);
+ add_cmp_flow(expr, lookup_port, aux, matches);
break;
case EXPR_T_AND:
- add_conjunction(expr, ports, &n_conjs, matches);
+ add_conjunction(expr, lookup_port, aux, &n_conjs, matches);
break;
case EXPR_T_OR:
struct expr *sub;
LIST_FOR_EACH (sub, node, &expr->andor) {
- add_cmp_flow(sub, ports, matches);
+ add_cmp_flow(sub, lookup_port, aux, matches);
}
} else {
struct expr *sub;
LIST_FOR_EACH (sub, node, &expr->andor) {
if (sub->type == EXPR_T_AND) {
- add_conjunction(sub, ports, &n_conjs, matches);
+ add_conjunction(sub, lookup_port, aux, &n_conjs, matches);
} else {
- add_cmp_flow(sub, ports, matches);
+ add_cmp_flow(sub, lookup_port, aux, matches);
}
}
}
}
static struct expr *
-parse_assignment(struct expr_context *ctx, const struct simap *ports,
- struct ofpbuf *ofpacts)
+parse_assignment(struct expr_context *ctx,
+ bool (*lookup_port)(const void *aux, const char *port_name,
+ unsigned int *portp),
+ const void *aux, struct ofpbuf *ofpacts)
{
struct expr *prereqs = NULL;
&c->mask.u8[sizeof c->mask - sf->field->n_bytes],
sf->field->n_bytes);
} else {
- uint32_t port = simap_get(ports, c->string);
+ uint32_t port;
+ if (!lookup_port(aux, c->string, &port)) {
+ port = 0;
+ }
bitwise_put(port, &sf->value,
sf->field->n_bytes, 0, sf->field->n_bits);
bitwise_one(&sf->mask, sf->field->n_bytes, 0, sf->field->n_bits);
* those for actions_parse(). */
char *
expr_parse_assignment(struct lexer *lexer, const struct shash *symtab,
- const struct simap *ports,
+ bool (*lookup_port)(const void *aux,
+ const char *port_name,
+ unsigned int *portp),
+ const void *aux,
struct ofpbuf *ofpacts, struct expr **prereqsp)
{
struct expr_context ctx;
ctx.error = NULL;
ctx.not = false;
- struct expr *prereqs = parse_assignment(&ctx, ports, ofpacts);
+ struct expr *prereqs = parse_assignment(&ctx, lookup_port, aux, ofpacts);
if (ctx.error) {
expr_destroy(prereqs);
prereqs = NULL;