Skip to content

Commit

Permalink
dpif: Allow adding ukeys for same flow by different pmds.
Browse files Browse the repository at this point in the history
In multiqueue mode several pmd threads may process one port, but
different queues. Flow may not depend on queue. It's true at least for
vhost-user ports.

When multiple pmd threads attempt to process upcalls for a particular
flow key, only the first will succeed. Any subsequent threads will
receive error = ENOSPC when attempting to insert a new udpif_key into
the umaps. This causes the latter threads to never insert a flow into
the datapath to handle the traffic, and as a result they will
consistently execute those flows through the slow path.

Fix that by mixing pmd_id with the bits from the ufid for ukey->hash
calculation. So, for a given flow key/UFID, each pmd thread will create
an independent udpif_key.

This also opens the possibility to reassign queues among pmd threads
without restarting them and deleting the megaflow cache.

Signed-off-by: Ilya Maximets <[email protected]>
Signed-off-by: Joe Stringer <[email protected]>
  • Loading branch information
igsilya authored and joestringer committed Feb 3, 2016
1 parent 45863ce commit 5f2ccb1
Showing 1 changed file with 13 additions and 10 deletions.
23 changes: 13 additions & 10 deletions ofproto/ofproto-dpif-upcall.c
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,8 @@ static bool ukey_install_start(struct udpif *, struct udpif_key *ukey);
static bool ukey_install_finish(struct udpif_key *ukey, int error);
static bool ukey_install(struct udpif *udpif, struct udpif_key *ukey);
static struct udpif_key *ukey_lookup(struct udpif *udpif,
const ovs_u128 *ufid);
const ovs_u128 *ufid,
const unsigned pmd_id);
static int ukey_acquire(struct udpif *, const struct dpif_flow *,
struct udpif_key **result, int *error);
static void ukey_delete__(struct udpif_key *);
Expand Down Expand Up @@ -1223,7 +1224,8 @@ process_upcall(struct udpif *udpif, struct upcall *upcall,
}
if (actions_len == 0) {
/* Lookup actions in userspace cache. */
struct udpif_key *ukey = ukey_lookup(udpif, upcall->ufid);
struct udpif_key *ukey = ukey_lookup(udpif, upcall->ufid,
upcall->pmd_id);
if (ukey) {
ukey_get_actions(ukey, &actions, &actions_len);
dpif_sflow_read_actions(flow, actions, actions_len,
Expand Down Expand Up @@ -1398,19 +1400,20 @@ handle_upcalls(struct udpif *udpif, struct upcall *upcalls,
}

static uint32_t
get_ufid_hash(const ovs_u128 *ufid)
get_ukey_hash(const ovs_u128 *ufid, const unsigned pmd_id)
{
return ufid->u32[0];
return hash_2words(ufid->u32[0], pmd_id);
}

static struct udpif_key *
ukey_lookup(struct udpif *udpif, const ovs_u128 *ufid)
ukey_lookup(struct udpif *udpif, const ovs_u128 *ufid, const unsigned pmd_id)
{
struct udpif_key *ukey;
int idx = get_ufid_hash(ufid) % N_UMAPS;
int idx = get_ukey_hash(ufid, pmd_id) % N_UMAPS;
struct cmap *cmap = &udpif->ukeys[idx].cmap;

CMAP_FOR_EACH_WITH_HASH (ukey, cmap_node, get_ufid_hash(ufid), cmap) {
CMAP_FOR_EACH_WITH_HASH (ukey, cmap_node,
get_ukey_hash(ufid, pmd_id), cmap) {
if (ovs_u128_equals(&ukey->ufid, ufid)) {
return ukey;
}
Expand Down Expand Up @@ -1456,7 +1459,7 @@ ukey_create__(const struct nlattr *key, size_t key_len,
ukey->ufid_present = ufid_present;
ukey->ufid = *ufid;
ukey->pmd_id = pmd_id;
ukey->hash = get_ufid_hash(&ukey->ufid);
ukey->hash = get_ukey_hash(&ukey->ufid, pmd_id);

ovsrcu_init(&ukey->actions, NULL);
ukey_set_actions(ukey, actions);
Expand Down Expand Up @@ -1589,7 +1592,7 @@ ukey_install_start(struct udpif *udpif, struct udpif_key *new_ukey)
idx = new_ukey->hash % N_UMAPS;
umap = &udpif->ukeys[idx];
ovs_mutex_lock(&umap->mutex);
old_ukey = ukey_lookup(udpif, &new_ukey->ufid);
old_ukey = ukey_lookup(udpif, &new_ukey->ufid, new_ukey->pmd_id);
if (old_ukey) {
/* Uncommon case: A ukey is already installed with the same UFID. */
if (old_ukey->key_len == new_ukey->key_len
Expand Down Expand Up @@ -1671,7 +1674,7 @@ ukey_acquire(struct udpif *udpif, const struct dpif_flow *flow,
struct udpif_key *ukey;
int retval;

ukey = ukey_lookup(udpif, &flow->ufid);
ukey = ukey_lookup(udpif, &flow->ufid, flow->pmd_id);
if (ukey) {
retval = ovs_mutex_trylock(&ukey->mutex);
} else {
Expand Down

0 comments on commit 5f2ccb1

Please sign in to comment.