VLOG_DEFINE_THIS_MODULE(ofproto_dpif_upcall);
-COVERAGE_DEFINE(upcall_duplicate_flow);
+COVERAGE_DEFINE(dumped_duplicate_flow);
+COVERAGE_DEFINE(dumped_new_flow);
COVERAGE_DEFINE(revalidate_missed_dp_flow);
/* A thread that reads upcalls from dpif, forwards each upcall's packet,
struct ofpbuf recv_bufs[UPCALL_MAX_BATCH];
struct dpif_upcall dupcalls[UPCALL_MAX_BATCH];
struct upcall upcalls[UPCALL_MAX_BATCH];
+ struct flow flows[UPCALL_MAX_BATCH];
size_t n_upcalls, i;
n_upcalls = 0;
struct ofpbuf *recv_buf = &recv_bufs[n_upcalls];
struct dpif_upcall *dupcall = &dupcalls[n_upcalls];
struct upcall *upcall = &upcalls[n_upcalls];
+ struct flow *flow = &flows[n_upcalls];
struct pkt_metadata md;
- struct flow flow;
int error;
ofpbuf_use_stub(recv_buf, recv_stubs[n_upcalls],
break;
}
- if (odp_flow_key_to_flow(dupcall->key, dupcall->key_len, &flow)
+ if (odp_flow_key_to_flow(dupcall->key, dupcall->key_len, flow)
== ODP_FIT_ERROR) {
goto free_dupcall;
}
error = upcall_receive(upcall, udpif->backer, &dupcall->packet,
- dupcall->type, dupcall->userdata, &flow);
+ dupcall->type, dupcall->userdata, flow);
if (error) {
if (error == ENODEV) {
/* Received packet on datapath port for which we couldn't
dpif_flow_put(udpif->dpif, DPIF_FP_CREATE, dupcall->key,
dupcall->key_len, NULL, 0, NULL, 0, NULL);
VLOG_INFO_RL(&rl, "received packet on unassociated datapath "
- "port %"PRIu32, flow.in_port.odp_port);
+ "port %"PRIu32, flow->in_port.odp_port);
}
goto free_dupcall;
}
upcall->out_tun_key = dupcall->out_tun_key;
- if (vsp_adjust_flow(upcall->ofproto, &flow, &dupcall->packet)) {
+ if (vsp_adjust_flow(upcall->ofproto, flow, &dupcall->packet)) {
upcall->vsp_adjusted = true;
}
- md = pkt_metadata_from_flow(&flow);
- flow_extract(&dupcall->packet, &md, &flow);
+ md = pkt_metadata_from_flow(flow);
+ flow_extract(&dupcall->packet, &md, flow);
error = process_upcall(udpif, upcall, NULL);
if (error) {
buf);
}
-/* The upcall must be destroyed with upcall_uninit() before quiescing,
- * as the referred objects are guaranteed to exist only until the calling
- * thread quiesces. */
+/* If there is no error, the upcall must be destroyed with upcall_uninit()
+ * before quiescing, as the referred objects are guaranteed to exist only
+ * until the calling thread quiesces. Otherwise, do not call upcall_uninit()
+ * since the 'upcall->put_actions' remains uninitialized. */
static int
upcall_receive(struct upcall *upcall, const struct dpif_backer *backer,
const struct ofpbuf *packet, enum dpif_upcall_type type,
error = upcall_receive(&upcall, udpif->backer, packet, type, userdata,
flow);
if (error) {
- goto out;
+ return error;
}
error = process_upcall(udpif, &upcall, actions);
/* XXX: This could be avoided with sufficient API changes. */
*wc = upcall.xout.wc;
} else {
- memset(wc, 0xff, sizeof *wc);
- flow_wildcards_clear_non_packet_fields(wc);
+ flow_wildcards_init_for_packet(wc, flow);
}
}
op->u.execute.actions = ofpbuf_data(upcall->xout.odp_actions);
op->u.execute.actions_len = ofpbuf_size(upcall->xout.odp_actions);
op->u.execute.needs_help = (upcall->xout.slow & SLOW_ACTION) != 0;
+ op->u.execute.probe = false;
}
}
/* We couldn't acquire the ukey. This means that
* another revalidator is processing this flow
* concurrently, so don't bother processing it. */
- COVERAGE_INC(upcall_duplicate_flow);
+ COVERAGE_INC(dumped_duplicate_flow);
continue;
}
already_dumped = ukey->dump_seq == dump_seq;
if (already_dumped) {
- /* The flow has already been dumped and handled by another
- * revalidator during this flow dump operation. Skip it. */
- COVERAGE_INC(upcall_duplicate_flow);
+ /* The flow has already been handled during this flow dump
+ * operation. Skip it. */
+ if (ukey->xcache) {
+ COVERAGE_INC(dumped_duplicate_flow);
+ } else {
+ COVERAGE_INC(dumped_new_flow);
+ }
ovs_mutex_unlock(&ukey->mutex);
continue;
}
void *aux OVS_UNUSED)
{
if (list_is_singleton(&all_udpifs)) {
- struct udpif *udpif;
+ struct udpif *udpif = NULL;
size_t len;
udpif = OBJECT_CONTAINING(list_front(&all_udpifs), udpif, list_node);