COVERAGE_DEFINE(facet_revalidate);
COVERAGE_DEFINE(facet_unexpected);
COVERAGE_DEFINE(facet_suppress);
+COVERAGE_DEFINE(subfacet_install_fail);
struct flow_miss;
struct facet;
uint64_t slow_stub[128 / 8]; /* Buffer for compose_slow_path() */
struct xlate_out xout;
bool xout_garbage; /* 'xout' needs to be uninitialized? */
+
+ struct ofpbuf mask; /* Flow mask for "put" ops. */
+ struct odputil_keybuf maskbuf;
+
+ /* If this is a "put" op, then a pointer to the subfacet that should
+ * be marked as uninstalled if the operation fails. */
+ struct subfacet *subfacet;
};
/* Sends an OFPT_PACKET_IN message for 'packet' of type OFPR_NO_MATCH to each
eth_pop_vlan(packet);
}
+ op->subfacet = NULL;
op->xout_garbage = false;
op->dpif_op.type = DPIF_OP_EXECUTE;
op->dpif_op.u.execute.key = miss->key;
op->dpif_op.u.execute.key_len = miss->key_len;
op->dpif_op.u.execute.packet = packet;
+ ofpbuf_use_stack(&op->mask, &op->maskbuf, sizeof op->maskbuf);
}
/* Helper for handle_flow_miss_without_facet() and
subfacet->path = want_path;
+ ofpbuf_use_stack(&op->mask, &op->maskbuf, sizeof op->maskbuf);
+ odp_flow_key_from_mask(&op->mask, &facet->xout.wc.masks,
+ &miss->flow, UINT32_MAX);
+
op->xout_garbage = false;
op->dpif_op.type = DPIF_OP_FLOW_PUT;
+ op->subfacet = subfacet;
put->flags = DPIF_FP_CREATE | DPIF_FP_MODIFY;
put->key = miss->key;
put->key_len = miss->key_len;
- put->mask = NULL;
- put->mask_len = 0;
+ put->mask = op->mask.data;
+ put->mask_len = op->mask.size;
+
if (want_path == SF_FAST_PATH) {
put->actions = facet->xout.odp_actions.data;
put->actions_len = facet->xout.odp_actions.size;
}
dpif_operate(backer->dpif, dpif_ops, n_ops);
- /* Free memory. */
for (i = 0; i < n_ops; i++) {
+ if (dpif_ops[i]->error != 0
+ && flow_miss_ops[i].dpif_op.type == DPIF_OP_FLOW_PUT
+ && flow_miss_ops[i].subfacet) {
+ struct subfacet *subfacet = flow_miss_ops[i].subfacet;
+
+ COVERAGE_INC(subfacet_install_fail);
+
+ subfacet->path = SF_NOT_INSTALLED;
+ }
+
+ /* Free memory. */
if (flow_miss_ops[i].xout_garbage) {
xlate_out_uninit(&flow_miss_ops[i].xout);
}
{
const struct dpif_flow_stats *stats;
struct dpif_flow_dump dump;
- const struct nlattr *key;
- size_t key_len;
+ const struct nlattr *key, *mask;
+ size_t key_len, mask_len;
dpif_flow_dump_start(&dump, backer->dpif);
while (dpif_flow_dump_next(&dump, &key, &key_len,
- NULL, NULL, NULL, NULL, &stats)) {
+ &mask, &mask_len, NULL, NULL, &stats)) {
struct subfacet *subfacet;
uint32_t key_hash;
enum subfacet_path path = facet->xout.slow ? SF_SLOW_PATH : SF_FAST_PATH;
const struct nlattr *actions = odp_actions->data;
size_t actions_len = odp_actions->size;
+ struct odputil_keybuf maskbuf;
+ struct ofpbuf mask;
uint64_t slow_path_stub[128 / 8];
enum dpif_flow_put_flags flags;
&actions, &actions_len);
}
- ret = dpif_flow_put(ofproto->backer->dpif, flags, subfacet->key,
- subfacet->key_len, NULL, 0,
+ ofpbuf_use_stack(&mask, &maskbuf, sizeof maskbuf);
+ odp_flow_key_from_mask(&mask, &facet->xout.wc.masks,
+ &facet->flow, UINT32_MAX);
+
+ ret = dpif_flow_put(subfacet->backer->dpif, flags, subfacet->key,
+ subfacet->key_len, mask.data, mask.size,
actions, actions_len, stats);
if (stats) {
subfacet_reset_dp_stats(subfacet, stats);
}
- if (!ret) {
+ if (ret) {
+ COVERAGE_INC(subfacet_install_fail);
+ } else {
subfacet->path = path;
}
return ret;