backer->need_revalidate = 0;
HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
- struct facet *facet;
+ struct facet *facet, *next;
if (ofproto->backer != backer) {
continue;
}
- HMAP_FOR_EACH (facet, hmap_node, &ofproto->facets) {
+ HMAP_FOR_EACH_SAFE (facet, next, hmap_node, &ofproto->facets) {
if (need_revalidate
|| tag_set_intersects(&revalidate_set, facet->tags)) {
facet_revalidate(facet);
struct flow_miss_op {
struct dpif_op dpif_op;
- struct subfacet *subfacet; /* Subfacet */
void *garbage; /* Pointer to pass to free(), NULL if none. */
uint64_t stub[1024 / 8]; /* Temporary buffer. */
};
eth_pop_vlan(packet);
}
- op->subfacet = NULL;
op->garbage = NULL;
op->dpif_op.type = DPIF_OP_EXECUTE;
op->dpif_op.u.execute.key = miss->key;
struct dpif_execute *execute = &op->dpif_op.u.execute;
init_flow_miss_execute_op(miss, packet, op);
- op->subfacet = subfacet;
if (!subfacet->slow) {
execute->actions = subfacet->actions;
execute->actions_len = subfacet->actions_len;
struct flow_miss_op *op = &ops[(*n_ops)++];
struct dpif_flow_put *put = &op->dpif_op.u.flow_put;
- op->subfacet = subfacet;
+ subfacet->path = want_path;
+
op->garbage = NULL;
op->dpif_op.type = DPIF_OP_FLOW_PUT;
put->flags = DPIF_FP_CREATE | DPIF_FP_MODIFY;
}
dpif_operate(backer->dpif, dpif_ops, n_ops);
- /* Free memory and update facets. */
+ /* Free memory. */
for (i = 0; i < n_ops; i++) {
- struct flow_miss_op *op = &flow_miss_ops[i];
-
- switch (op->dpif_op.type) {
- case DPIF_OP_EXECUTE:
- break;
-
- case DPIF_OP_FLOW_PUT:
- if (!op->dpif_op.error) {
- op->subfacet->path = subfacet_want_path(op->subfacet->slow);
- }
- break;
-
- case DPIF_OP_FLOW_DEL:
- NOT_REACHED();
- }
-
- free(op->garbage);
+ free(flow_miss_ops[i].garbage);
}
hmap_destroy(&todo);
}
|| tag_set_intersects(&ofproto->backer->revalidate_set,
facet->tags))) {
facet_revalidate(facet);
+
+ /* facet_revalidate() may have destroyed 'facet'. */
+ facet = facet_find(ofproto, flow, hash);
}
return facet;
* 'facet' to the new rule and recompiles its actions.
*
* - If the rule found is the same as 'facet''s current rule, leaves 'facet'
- * where it is and recompiles its actions anyway. */
+ * where it is and recompiles its actions anyway.
+ *
+ * - If any of 'facet''s subfacets correspond to a new flow according to
+ * ofproto_receive(), 'facet' is removed. */
static void
facet_revalidate(struct facet *facet)
{
COVERAGE_INC(facet_revalidate);
+ /* Check that child subfacets still correspond to this facet. Tunnel
+ * configuration changes could cause a subfacet's OpenFlow in_port to
+ * change. */
+ LIST_FOR_EACH (subfacet, list_node, &facet->subfacets) {
+ struct ofproto_dpif *recv_ofproto;
+ struct flow recv_flow;
+ int error;
+
+ error = ofproto_receive(ofproto->backer, NULL, subfacet->key,
+ subfacet->key_len, &recv_flow, NULL,
+ &recv_ofproto, NULL, NULL);
+ if (error
+ || recv_ofproto != ofproto
+ || memcmp(&recv_flow, &facet->flow, sizeof recv_flow)) {
+ facet_remove(facet);
+ return;
+ }
+ }
+
new_rule = rule_dpif_lookup(ofproto, &facet->flow);
/* Calculate new datapath actions.