dpif_netdev_execute may be called while doing upcall processing. Since the context of the input port is not tracked upto this point, we used the chared dp->emc_cache for packet execution. Execution needs to be able to pass the cache to recirculation code.
Typically the pmd threads use their own emc_cache, so there is little value in using the shared emc_cache while processing recirculation during packet execution. Also, whenever the shared emc_cache was already used while doing the upcall, the emc_mutex is already held, and would be locked recursively in dpif_netdev_execute(). Rather than changing the mutex to a recursive type, it seems more proper to not use any emc_cache in dpif_netdev_execute. Forthcoming new unit tests will fail with the current lock recursion. Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com> --- lib/dpif-netdev.c | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 869fb55..846c329 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -380,10 +380,9 @@ static void dp_netdev_execute_actions(struct dp_netdev *dp, struct emc_cache *flow_cache, const struct nlattr *actions, size_t actions_len); -static void dp_netdev_port_input(struct dp_netdev *dp, - struct emc_cache *flow_cache, - struct dpif_packet **packets, int cnt, - odp_port_t port_no); +static void dp_netdev_input(struct dp_netdev *, struct emc_cache *, + struct dpif_packet **, int cnt, + struct pkt_metadata *); static void dp_netdev_set_pmd_threads(struct dp_netdev *, int n); static void dp_netdev_disable_upcall(struct dp_netdev *); @@ -1176,6 +1175,10 @@ emc_insert(struct emc_cache *cache, const struct miniflow *mf, uint32_t hash, struct emc_entry *to_be_replaced = NULL; struct emc_entry *current_entry; + if (OVS_UNLIKELY(!cache)) { + return; + } + EMC_FOR_EACH_POS_WITH_HASH(cache, current_entry, hash) { if (current_entry->hash == hash && miniflow_equal(¤t_entry->mf.flow, mf)) { @@ -1708,11 +1711,9 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute) packet.ofpbuf = *execute->packet; pp = &packet; - ovs_mutex_lock(&dp->emc_mutex); dp_netdev_execute_actions(dp, &pp, 1, false, md, - &dp->flow_cache, execute->actions, + NULL, execute->actions, execute->actions_len); - ovs_mutex_unlock(&dp->emc_mutex); /* Even though may_steal is set to false, some actions could modify or * reallocate the ofpbuf memory. We need to pass those changes to the @@ -1799,14 +1800,15 @@ dp_netdev_process_rxq_port(struct dp_netdev *dp, error = netdev_rxq_recv(rxq, packets, &cnt); if (!error) { - dp_netdev_port_input(dp, flow_cache, packets, cnt, port->port_no); + struct pkt_metadata md = PKT_METADATA_INITIALIZER(port->port_no); + + *recirc_depth_get() = 0; + dp_netdev_input(dp, flow_cache, packets, cnt, &md); } else if (error != EAGAIN && error != EOPNOTSUPP) { - static struct vlog_rate_limit rl - = VLOG_RATE_LIMIT_INIT(1, 5); + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); VLOG_ERR_RL(&rl, "error receiving data from %s: %s", - netdev_get_name(port->netdev), - ovs_strerror(error)); + netdev_get_name(port->netdev), ovs_strerror(error)); } } @@ -2240,6 +2242,10 @@ emc_processing(struct dp_netdev *dp, struct emc_cache *flow_cache, size_t n_batches, i; size_t notfound_cnt = 0; + if (OVS_UNLIKELY(!flow_cache)) { + return cnt; + } + n_batches = 0; miniflow_initialize(&key.flow, key.buf); for (i = 0; i < cnt; i++) { @@ -2404,18 +2410,6 @@ dp_netdev_input(struct dp_netdev *dp, struct emc_cache *flow_cache, } } - -static void -dp_netdev_port_input(struct dp_netdev *dp, struct emc_cache *flow_cache, - struct dpif_packet **packets, int cnt, odp_port_t port_no) -{ - uint32_t *recirc_depth = recirc_depth_get(); - struct pkt_metadata md = PKT_METADATA_INITIALIZER(port_no); - - *recirc_depth = 0; - dp_netdev_input(dp, flow_cache, packets, cnt, &md); -} - struct dp_netdev_execute_aux { struct dp_netdev *dp; struct emc_cache *flow_cache; -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev