@@ -692,13 +692,23 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow,
}
}
}
+
+ struct addrset_info as_info = {
+ .name = m->as_name,
+ .ip = m->as_ip,
+ .mask = m->as_mask
+ };
if (!m->n) {
ofctrl_add_flow_metered(l_ctx_out->flow_table, ptable,
lflow->priority,
lflow->header_.uuid.parts[0], &m->match,
&ofpacts, &lflow->header_.uuid,
- ctrl_meter_id);
+ ctrl_meter_id,
+ as_info.name ? &as_info : NULL);
} else {
+ if (m->n > 1) {
+ ovs_assert(!as_info.name);
+ }
uint64_t conj_stubs[64 / 8];
struct ofpbuf conj;
@@ -716,7 +726,8 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow,
ofctrl_add_or_append_flow(l_ctx_out->flow_table, ptable,
lflow->priority, 0,
&m->match, &conj, &lflow->header_.uuid,
- ctrl_meter_id);
+ ctrl_meter_id,
+ as_info.name ? &as_info : NULL);
ofpbuf_uninit(&conj);
}
}
@@ -1524,7 +1535,7 @@ add_lb_ct_snat_hairpin_dp_flows(struct ovn_controller_lb *lb,
ofctrl_add_or_append_flow(flow_table, OFTABLE_CT_SNAT_HAIRPIN, 200,
lb->slb->header_.uuid.parts[0],
&dp_match, &dp_acts, &lb->slb->header_.uuid,
- NX_CTLR_NO_METER);
+ NX_CTLR_NO_METER, NULL);
}
ofpbuf_uninit(&dp_acts);
@@ -1698,7 +1709,7 @@ add_lb_ct_snat_hairpin_vip_flow(struct ovn_controller_lb *lb,
ofctrl_add_or_append_flow(flow_table, OFTABLE_CT_SNAT_HAIRPIN, priority,
lb->slb->header_.uuid.parts[0],
&match, &ofpacts, &lb->slb->header_.uuid,
- NX_CTLR_NO_METER);
+ NX_CTLR_NO_METER, NULL);
ofpbuf_uninit(&ofpacts);
}
@@ -165,15 +165,35 @@ struct sb_to_flow {
struct uuid sb_uuid;
struct ovs_list flows; /* A list of struct sb_flow_ref nodes that
are referenced by the sb_uuid. */
+ struct ovs_list addrsets; /* A list of struct sb_addrset_ref. */
};
struct sb_flow_ref {
struct ovs_list sb_list; /* List node in desired_flow.references. */
- struct ovs_list flow_list; /* List node in sb_to_flow.desired_flows. */
+ struct ovs_list flow_list; /* List node in sb_to_flow.flows. */
+ struct ovs_list as_ip_flow_list; /* List node in ip_to_flow_node.flows. */
struct desired_flow *flow;
struct uuid sb_uuid;
};
+struct sb_addrset_ref {
+ struct ovs_list list_node; /* List node in sb_to_flow.addrsets. */
+ char *name; /* Name of the address set. */
+ struct hmap ip_to_flow_map; /* map from IPs in the address set to flows.
+ Each node is struct ip_to_flow_node. */
+};
+
+struct ip_to_flow_node {
+ struct hmap_node hmap_node; /* Node in sb_addrset_ref.ip_to_flow_map. */
+ struct in6_addr as_ip;
+ struct in6_addr as_mask;
+
+ /* A list of struct sb_flow_ref. A single IP in an address set can be
+ * used by multiple flows. e.g., in match:
+ * ip.src == $as1 && ip.dst == $as1. */
+ struct ovs_list flows;
+};
+
/* An installed flow, in static variable installed_lflows/installed_pflows.
*
* Installed flows are updated in ofctrl_put for maintaining the flow
@@ -1030,9 +1050,26 @@ sb_to_flow_find(struct hmap *uuid_flow_table, const struct uuid *sb_uuid)
return NULL;
}
+static struct ip_to_flow_node *
+ip_to_flow_find(struct hmap *ip_to_flow_map, const struct in6_addr *as_ip,
+ const struct in6_addr *as_mask)
+{
+ uint32_t hash = hash_bytes(as_ip, sizeof *as_ip, 0);
+
+ struct ip_to_flow_node *itfn;
+ HMAP_FOR_EACH_WITH_HASH (itfn, hmap_node, hash, ip_to_flow_map) {
+ if (ipv6_addr_equals(&itfn->as_ip, as_ip)
+ && ipv6_addr_equals(&itfn->as_mask, as_mask)) {
+ return itfn;
+ }
+ }
+ return NULL;
+}
+
static void
link_flow_to_sb(struct ovn_desired_flow_table *flow_table,
- struct desired_flow *f, const struct uuid *sb_uuid)
+ struct desired_flow *f, const struct uuid *sb_uuid,
+ const struct addrset_info *as_info)
{
struct sb_flow_ref *sfr = xmalloc(sizeof *sfr);
mem_stats.sb_flow_ref_usage += sb_flow_ref_size(sfr);
@@ -1046,10 +1083,48 @@ link_flow_to_sb(struct ovn_desired_flow_table *flow_table,
mem_stats.sb_flow_ref_usage += sb_to_flow_size(stf);
stf->sb_uuid = *sb_uuid;
ovs_list_init(&stf->flows);
+ ovs_list_init(&stf->addrsets);
hmap_insert(&flow_table->uuid_flow_table, &stf->hmap_node,
uuid_hash(sb_uuid));
}
ovs_list_insert(&stf->flows, &sfr->flow_list);
+
+ if (!as_info) {
+ ovs_list_init(&sfr->as_ip_flow_list);
+ return;
+ }
+
+ /* link flow to address_set + ip */
+ struct sb_addrset_ref *sar;
+ bool found = false;
+ LIST_FOR_EACH (sar, list_node, &stf->addrsets) {
+ if (!strcmp(sar->name, as_info->name)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ sar = xmalloc(sizeof *sar);
+ mem_stats.sb_flow_ref_usage += sizeof *sar;
+ sar->name = xstrdup(as_info->name);
+ hmap_init(&sar->ip_to_flow_map);
+ ovs_list_insert(&stf->addrsets, &sar->list_node);
+ }
+
+ struct ip_to_flow_node * itfn = ip_to_flow_find(&sar->ip_to_flow_map,
+ &as_info->ip,
+ &as_info->mask);
+ if (!itfn) {
+ itfn = xmalloc(sizeof *itfn);
+ mem_stats.sb_flow_ref_usage += sizeof *itfn;
+ itfn->as_ip = as_info->ip;
+ itfn->as_mask = as_info->mask;
+ ovs_list_init(&itfn->flows);
+ uint32_t hash = hash_bytes(&as_info->ip, sizeof as_info->ip, 0);
+ hmap_insert(&sar->ip_to_flow_map, &itfn->hmap_node, hash);
+ }
+
+ ovs_list_insert(&itfn->flows, &sfr->as_ip_flow_list);
}
/* Flow table interfaces to the rest of ovn-controller. */
@@ -1068,13 +1143,17 @@ link_flow_to_sb(struct ovn_desired_flow_table *flow_table,
void
ofctrl_check_and_add_flow_metered(struct ovn_desired_flow_table *flow_table,
uint8_t table_id, uint16_t priority,
- uint64_t cookie, const struct match *match,
+ uint64_t cookie,
+ const struct match *match,
const struct ofpbuf *actions,
const struct uuid *sb_uuid,
- uint32_t meter_id, bool log_duplicate_flow)
+ uint32_t meter_id,
+ const struct addrset_info *as_info,
+ bool log_duplicate_flow)
{
struct desired_flow *f = desired_flow_alloc(table_id, priority, cookie,
- match, actions, meter_id);
+ match, actions,
+ meter_id);
if (desired_flow_lookup_check_uuid(flow_table, &f->flow, sb_uuid)) {
if (log_duplicate_flow) {
@@ -1091,7 +1170,7 @@ ofctrl_check_and_add_flow_metered(struct ovn_desired_flow_table *flow_table,
hmap_insert(&flow_table->match_flow_table, &f->match_hmap_node,
f->flow.hash);
- link_flow_to_sb(flow_table, f, sb_uuid);
+ link_flow_to_sb(flow_table, f, sb_uuid, as_info);
track_flow_add_or_modify(flow_table, f);
ovn_flow_log(&f->flow, "ofctrl_add_flow");
}
@@ -1103,7 +1182,7 @@ ofctrl_add_flow(struct ovn_desired_flow_table *desired_flows,
const struct uuid *sb_uuid)
{
ofctrl_add_flow_metered(desired_flows, table_id, priority, cookie,
- match, actions, sb_uuid, NX_CTLR_NO_METER);
+ match, actions, sb_uuid, NX_CTLR_NO_METER, NULL);
}
void
@@ -1111,11 +1190,12 @@ ofctrl_add_flow_metered(struct ovn_desired_flow_table *desired_flows,
uint8_t table_id, uint16_t priority, uint64_t cookie,
const struct match *match,
const struct ofpbuf *actions,
- const struct uuid *sb_uuid, uint32_t meter_id)
+ const struct uuid *sb_uuid, uint32_t meter_id,
+ const struct addrset_info *as_info)
{
ofctrl_check_and_add_flow_metered(desired_flows, table_id, priority,
cookie, match, actions, sb_uuid,
- meter_id, true);
+ meter_id, as_info, true);
}
/* Either add a new flow, or append actions on an existing flow. If the
@@ -1127,7 +1207,8 @@ ofctrl_add_or_append_flow(struct ovn_desired_flow_table *desired_flows,
const struct match *match,
const struct ofpbuf *actions,
const struct uuid *sb_uuid,
- uint32_t meter_id)
+ uint32_t meter_id,
+ const struct addrset_info *as_info)
{
struct desired_flow *existing;
struct desired_flow *f;
@@ -1156,11 +1237,20 @@ ofctrl_add_or_append_flow(struct ovn_desired_flow_table *desired_flows,
ofpbuf_uninit(&compound);
desired_flow_destroy(f);
f = existing;
+
+ /* Remove as_info tracking for the existing flow. */
+ struct sb_flow_ref *sfr;
+ LIST_FOR_EACH (sfr, sb_list, &f->references) {
+ ovs_list_remove(&sfr->as_ip_flow_list);
+ ovs_list_init(&sfr->as_ip_flow_list);
+ }
+ /* Link to sb but don't track the as_info. */
+ link_flow_to_sb(desired_flows, f, sb_uuid, NULL);
} else {
hmap_insert(&desired_flows->match_flow_table, &f->match_hmap_node,
f->flow.hash);
+ link_flow_to_sb(desired_flows, f, sb_uuid, as_info);
}
- link_flow_to_sb(desired_flows, f, sb_uuid);
track_flow_add_or_modify(desired_flows, f);
if (existing) {
@@ -1269,6 +1359,7 @@ remove_flows_from_sb_to_flow(struct ovn_desired_flow_table *flow_table,
LIST_FOR_EACH_SAFE (sfr, next, flow_list, &stf->flows) {
ovs_list_remove(&sfr->sb_list);
ovs_list_remove(&sfr->flow_list);
+ ovs_list_remove(&sfr->as_ip_flow_list);
struct desired_flow *f = sfr->flow;
mem_stats.sb_flow_ref_usage -= sb_flow_ref_size(sfr);
free(sfr);
@@ -1286,6 +1377,22 @@ remove_flows_from_sb_to_flow(struct ovn_desired_flow_table *flow_table,
}
}
+ struct sb_addrset_ref *sar, *next_sar;
+ LIST_FOR_EACH_SAFE (sar, next_sar, list_node, &stf->addrsets) {
+ ovs_list_remove(&sar->list_node);
+ struct ip_to_flow_node *itfn, *itfn_next;
+ HMAP_FOR_EACH_SAFE (itfn, itfn_next, hmap_node, &sar->ip_to_flow_map) {
+ hmap_remove(&sar->ip_to_flow_map, &itfn->hmap_node);
+ ovs_assert(ovs_list_is_empty(&itfn->flows));
+ mem_stats.sb_flow_ref_usage -= sizeof *itfn;
+ free(itfn);
+ }
+ hmap_destroy(&sar->ip_to_flow_map);
+ mem_stats.sb_flow_ref_usage -= (sizeof *sar + strlen(sar->name) + 1);
+ free(sar->name);
+ free(sar);
+ }
+
hmap_remove(&flow_table->uuid_flow_table, &stf->hmap_node);
mem_stats.sb_flow_ref_usage -= sb_to_flow_size(stf);
free(stf);
@@ -1300,6 +1407,7 @@ remove_flows_from_sb_to_flow(struct ovn_desired_flow_table *flow_table,
ovs_assert(!ovs_list_is_empty(&f->references));
LIST_FOR_EACH (sfr, sb_list, &f->references) {
ovs_list_remove(&sfr->flow_list);
+ ovs_list_remove(&sfr->as_ip_flow_list);
}
}
LIST_FOR_EACH_SAFE (f, f_next, list_node, &to_be_removed) {
@@ -71,24 +71,34 @@ char *ofctrl_inject_pkt(const struct ovsrec_bridge *br_int,
const struct shash *port_groups);
/* Flow table interfaces to the rest of ovn-controller. */
+
+/* Information of IP of an address set used to track a flow that is generated
+ * from a logical flow referencing address set(s). */
+struct addrset_info {
+ const char *name; /* The address set's name. */
+ struct in6_addr ip; /* An IP in the address set. */
+ struct in6_addr mask; /* The mask of the IP. */
+};
void ofctrl_add_flow(struct ovn_desired_flow_table *, uint8_t table_id,
uint16_t priority, uint64_t cookie,
const struct match *, const struct ofpbuf *ofpacts,
const struct uuid *);
-void ofctrl_add_or_append_flow(struct ovn_desired_flow_table *desired_flows,
+void ofctrl_add_or_append_flow(struct ovn_desired_flow_table *,
uint8_t table_id, uint16_t priority,
- uint64_t cookie, const struct match *match,
+ uint64_t cookie, const struct match *,
const struct ofpbuf *actions,
const struct uuid *sb_uuid,
- uint32_t meter_id);
+ uint32_t meter_id,
+ const struct addrset_info *);
void ofctrl_add_flow_metered(struct ovn_desired_flow_table *desired_flows,
uint8_t table_id, uint16_t priority,
uint64_t cookie, const struct match *match,
const struct ofpbuf *actions,
const struct uuid *sb_uuid,
- uint32_t meter_id);
+ uint32_t meter_id,
+ const struct addrset_info *);
/* Removes a bundles of flows from the flow table for a specific sb_uuid. The
* flows are removed only if they are not referenced by any other sb_uuid(s).
@@ -123,6 +133,7 @@ void ofctrl_check_and_add_flow_metered(struct ovn_desired_flow_table *,
uint64_t cookie, const struct match *,
const struct ofpbuf *ofpacts,
const struct uuid *, uint32_t meter_id,
+ const struct addrset_info *,
bool log_duplicate_flow);
@@ -835,7 +835,7 @@ put_local_common_flows(uint32_t dp_key,
put_stack(MFF_IN_PORT, ofpact_put_STACK_POP(ofpacts_p));
ofctrl_check_and_add_flow_metered(flow_table, OFTABLE_SAVE_INPORT, 100,
0, &match, ofpacts_p, hc_uuid,
- NX_CTLR_NO_METER, false);
+ NX_CTLR_NO_METER, NULL, false);
}
}
@@ -367,6 +367,8 @@ bool expr_relop_from_token(enum lex_type type, enum expr_relop *relop);
struct expr {
struct ovs_list node; /* In parent EXPR_T_AND or EXPR_T_OR if any. */
enum expr_type type; /* Expression type. */
+ char *as_name; /* Address set name. Null if it is not an
+ address set. */
union {
/* EXPR_T_CMP.
@@ -469,6 +471,11 @@ struct expr_match {
struct match match;
struct cls_conjunction *conjunctions;
size_t n, allocated;
+
+ /* Tracked address set information. */
+ char *as_name;
+ struct in6_addr as_ip;
+ struct in6_addr as_mask;
};
uint32_t expr_to_matches(const struct expr *,
@@ -526,6 +533,8 @@ struct expr_constant_set {
size_t n_values; /* Number of constants. */
enum expr_constant_type type; /* Type of the constants. */
bool in_curlies; /* Whether the constants were in {}. */
+ char *as_name; /* Name of an address set. It is NULL if not
+ an address set. */
};
bool expr_constant_set_parse(struct lexer *, struct expr_constant_set *);
@@ -160,7 +160,7 @@ expr_relop_test(enum expr_relop relop, int cmp)
struct expr *
expr_create_andor(enum expr_type type)
{
- struct expr *e = xmalloc(sizeof *e);
+ struct expr *e = xzalloc(sizeof *e);
e->type = type;
ovs_list_init(&e->andor);
return e;
@@ -190,9 +190,17 @@ expr_combine(enum expr_type type, struct expr *a, struct expr *b)
} else {
ovs_list_push_back(&a->andor, &b->node);
}
+ if (a->as_name) {
+ free(a->as_name);
+ a->as_name = NULL;
+ }
return a;
} else if (b->type == type) {
ovs_list_push_front(&b->andor, &a->node);
+ if (b->as_name) {
+ free(b->as_name);
+ b->as_name = NULL;
+ }
return b;
} else {
struct expr *e = expr_create_andor(type);
@@ -220,7 +228,7 @@ expr_insert_andor(struct expr *andor, struct expr *before, struct expr *new)
struct expr *
expr_create_boolean(bool b)
{
- struct expr *e = xmalloc(sizeof *e);
+ struct expr *e = xzalloc(sizeof *e);
e->type = EXPR_T_BOOLEAN;
e->boolean = b;
return e;
@@ -680,6 +688,10 @@ make_cmp(struct expr_context *ctx,
e = expr_combine(r == EXPR_R_EQ ? EXPR_T_OR : EXPR_T_AND,
e, make_cmp__(f, r, &cs->values[i]));
}
+ /* Track address set */
+ if (r == EXPR_R_EQ && e->type == EXPR_T_OR && cs->as_name) {
+ e->as_name = xstrdup(cs->as_name);
+ }
exit:
expr_constant_set_destroy(cs);
return e;
@@ -802,6 +814,10 @@ parse_addr_sets(struct expr_context *ctx, struct expr_constant_set *cs,
return false;
}
+ if (!cs->n_values) {
+ cs->as_name = xstrdup(ctx->lexer->token.s);
+ }
+
size_t n_values = cs->n_values + addr_sets->n_values;
if (n_values >= *allocated_values) {
cs->values = xrealloc(cs->values, n_values * sizeof *cs->values);
@@ -875,6 +891,13 @@ parse_constant(struct expr_context *ctx, struct expr_constant_set *cs,
sizeof *cs->values);
}
+ if (cs->as_name) {
+ /* Combining other values to the constant set that is tracking an
+ * address set, so untrack it. */
+ free(cs->as_name);
+ cs->as_name = NULL;
+ }
+
if (ctx->lexer->token.type == LEX_T_STRING) {
if (!assign_constant_set_type(ctx, cs, EXPR_C_STRING)) {
return false;
@@ -1057,6 +1080,7 @@ expr_constant_set_destroy(struct expr_constant_set *cs)
}
}
free(cs->values);
+ free(cs->as_name);
}
}
@@ -1244,6 +1268,7 @@ expr_parse_primary(struct expr_context *ctx, bool *atomic)
c.values = cst;
c.n_values = 1;
c.in_curlies = false;
+ c.as_name = NULL;
return make_cmp(ctx, &f, EXPR_R_NE, &c);
} else if (parse_relop(ctx, &r) && parse_constant_set(ctx, &c)) {
return make_cmp(ctx, &f, r, &c);
@@ -1709,6 +1734,7 @@ expr_symtab_destroy(struct shash *symtab)
static struct expr *
expr_clone_cmp(struct expr *expr)
{
+ ovs_assert(!expr->as_name);
struct expr *new = xmemdup(expr, sizeof *expr);
if (!new->cmp.symbol->width) {
new->cmp.string = xstrdup(new->cmp.string);
@@ -1732,6 +1758,7 @@ expr_clone_andor(struct expr *expr)
static struct expr *
expr_clone_condition(struct expr *expr)
{
+ ovs_assert(!expr->as_name);
struct expr *new = xmemdup(expr, sizeof *expr);
new->cond.string = xstrdup(new->cond.string);
return new;
@@ -1767,6 +1794,8 @@ expr_destroy(struct expr *expr)
return;
}
+ free(expr->as_name);
+
struct expr *sub, *next;
switch (expr->type) {
@@ -2373,7 +2402,7 @@ crush_and_string(struct expr *expr, const struct expr_symbol *symbol)
const char *string;
SSET_FOR_EACH (string, &result) {
- sub = xmalloc(sizeof *sub);
+ sub = xzalloc(sizeof *sub);
sub->type = EXPR_T_CMP;
sub->cmp.relop = EXPR_R_EQ;
sub->cmp.symbol = symbol;
@@ -2432,7 +2461,7 @@ crush_and_numeric(struct expr *expr, const struct expr_symbol *symbol)
return expr_create_boolean(true);
} else {
struct expr *cmp;
- cmp = xmalloc(sizeof *cmp);
+ cmp = xzalloc(sizeof *cmp);
cmp->type = EXPR_T_CMP;
cmp->cmp.symbol = symbol;
cmp->cmp.relop = EXPR_R_EQ;
@@ -2447,7 +2476,7 @@ crush_and_numeric(struct expr *expr, const struct expr_symbol *symbol)
struct expr *disjuncts = expr_from_node(ovs_list_pop_front(&expr->andor));
struct expr *or;
- or = xmalloc(sizeof *or);
+ or = xzalloc(sizeof *or);
or->type = EXPR_T_OR;
ovs_list_init(&or->andor);
@@ -2483,7 +2512,7 @@ crush_and_numeric(struct expr *expr, const struct expr_symbol *symbol)
struct expr *new = NULL;
struct expr *or;
- or = xmalloc(sizeof *or);
+ or = xzalloc(sizeof *or);
or->type = EXPR_T_OR;
ovs_list_init(&or->andor);
@@ -2502,7 +2531,7 @@ crush_and_numeric(struct expr *expr, const struct expr_symbol *symbol)
LIST_FOR_EACH (b, node, &bs->andor) {
ovs_assert(b->type == EXPR_T_CMP);
if (!new) {
- new = xmalloc(sizeof *new);
+ new = xzalloc(sizeof *new);
new->type = EXPR_T_CMP;
new->cmp.symbol = symbol;
new->cmp.relop = EXPR_R_EQ;
@@ -2608,6 +2637,9 @@ crush_or(struct expr *expr, const struct expr_symbol *symbol)
ovs_list_push_back(&expr->andor, &b->node);
} else {
expr_destroy(b);
+ /* Member modified, so untrack address set. */
+ free(expr->as_name);
+ expr->as_name = NULL;
}
}
free(subs);
@@ -2659,7 +2691,7 @@ expr_sort(struct expr *expr)
ovs_assert(expr->type == EXPR_T_AND);
size_t n = ovs_list_size(&expr->andor);
- struct expr_sort *subs = xmalloc(n * sizeof *subs);
+ struct expr_sort *subs = xzalloc(n * sizeof *subs);
struct expr *sub;
size_t i;
@@ -2884,7 +2916,7 @@ static struct expr_match *
expr_match_new(const struct match *m, uint8_t clause, uint8_t n_clauses,
uint32_t conj_id)
{
- struct expr_match *match = xmalloc(sizeof *match);
+ struct expr_match *match = xzalloc(sizeof *match);
if (m) {
match->match = *m;
} else {
@@ -2905,6 +2937,14 @@ expr_match_new(const struct match *m, uint8_t clause, uint8_t n_clauses,
return match;
}
+static void
+expr_match_destroy(struct expr_match *match)
+{
+ free(match->as_name);
+ free(match->conjunctions);
+ free(match);
+}
+
/* Adds 'match' to hash table 'matches', which becomes the new owner of
* 'match'.
*
@@ -2932,8 +2972,12 @@ expr_match_add(struct hmap *matches, struct expr_match *match)
}
m->conjunctions[m->n++] = match->conjunctions[0];
}
- free(match->conjunctions);
- free(match);
+ if (m->as_name) {
+ /* m is combined with match. so untracked the address set. */
+ free(m->as_name);
+ m->as_name = NULL;
+ }
+ expr_match_destroy(match);
return;
}
}
@@ -2994,12 +3038,18 @@ add_disjunction(const struct expr *or,
LIST_FOR_EACH (sub, node, &or->andor) {
struct expr_match *match = expr_match_new(m, clause, n_clauses,
conj_id);
+ if (or->as_name) {
+ ovs_assert(sub->type == EXPR_T_CMP);
+ ovs_assert(sub->cmp.symbol->width);
+ match->as_name = xstrdup(or->as_name);
+ match->as_ip = sub->cmp.value.ipv6;
+ match->as_mask = sub->cmp.mask.ipv6;
+ }
if (constrain_match(sub, lookup_port, aux, &match->match)) {
expr_match_add(matches, match);
n++;
} else {
- free(match->conjunctions);
- free(match);
+ expr_match_destroy(match);
}
}
@@ -3082,7 +3132,7 @@ add_cmp_flow(const struct expr *cmp,
if (constrain_match(cmp, lookup_port, aux, &m->match)) {
expr_match_add(matches, m);
} else {
- free(m);
+ expr_match_destroy(m);
}
}
@@ -3214,8 +3264,7 @@ expr_matches_destroy(struct hmap *matches)
}
HMAP_FOR_EACH_POP (m, hmap_node, matches) {
- free(m->conjunctions);
- free(m);
+ expr_match_destroy(m);
}
hmap_destroy(matches);
}
This patch tracks individual address information when parsing address sets from logical flows, and link to the corresponding desired flow resulted from the IP. Signed-off-by: Han Zhou <hzhou@ovn.org> --- controller/lflow.c | 19 ++++-- controller/ofctrl.c | 130 ++++++++++++++++++++++++++++++++++++++---- controller/ofctrl.h | 19 ++++-- controller/physical.c | 2 +- include/ovn/expr.h | 9 +++ lib/expr.c | 81 ++++++++++++++++++++------ 6 files changed, 224 insertions(+), 36 deletions(-)