Многопоточность DPDK rte_hash

#multithreading #concurrency #atomic #dpdk

#многопоточность #параллелизм #атомарный #dpdk

Вопрос:

все! Я пишу приложение на основе DPDK. Я считываю пакеты из сетевой карты, отправляя их в кольцо. Затем у меня есть несколько рабочих потоков, которые выводят пакеты из очереди из rx ring, анализируют их заголовки, чтобы получить IP-адрес назначения и порт назначения протокола уровня 4. Эти данные упакованы в структуру:

 struct session_key {
    rte_be32_t ip_dst;
    rte_be16_t port_dst;
};
  

Эта структура используется в качестве ключа в таблице rte_hash. В качестве данных в этой хэш-таблице я использую счетчик uint32_t, который увеличивается, когда пакет соответствует ключу. Я создаю rte_hash с флагом RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY, чтобы сделать его потокобезопасным для многопоточного чтения и записи.
Каждый рабочий поток получает dst_ip и dst_port из пакета и ищет хэш-таблицу для такого ключа. Если ключ существует, его значение увеличивается, если ключ не существует, он добавляется в таблицу с данными = 1.

 uint32_t *found;
int ret = rte_hash_lookup_data(sessions_hash_table, (void *)amp;key, (void **)amp;found);
if (ret < 0) {
   uint32_t *data = rte_zmalloc("session_key", sizeof(uint32_t), 0);
   *data = 1;
   rte_hash_add_key_data(sessions_hash_table, amp;key, data);
} else {
   (*found)  ;
}
  

Итак, у меня есть несколько читателей, записи в хеш-таблицу. После того, как все рабочие завершены, общая статистика вычисляется в основном потоке. Количество пакетов, соответствующих каждой паре ip и портов, выводится на экран.
Проблема в том, что когда я использую только одного работника, проблем нет, количество полученных пакетов равно пакетам, сохраненным в хеш-таблице.

Но когда я использую несколько рабочих потоков, я получаю неравные числа. Я понимаю, что существует вероятность чтения таблицы, пока другой поток записывает в нее. Но я думал, что флаги конфигурации, такие как RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY, помогут мне справиться с многопоточностью.

Итак, мне нужен совет о том, как заставить rte_hash работать в многопоточном приложении, где несколько потоков записывают и считывают одну и ту же хэш-таблицу.

Комментарии:

1. Вместо того, чтобы использовать мьютекс и атомарность, почему бы просто не сохранить индекс идентификатора счетчика, как value в rte_hash . Таким образом, всякий раз, когда у вас есть совпадение, вы можете получить индекс счетчика. Рабочие потоки могут поддерживать локальную копию, которая увеличивается до таблицы счетчиков отдельно или в конце добавляется для каждого рабочего счетчика вместе. Этот метод значительно сокращает количество обновляемых хэш-таблиц.

2. Флаг RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY в службе хэширования DPDK разрешает одновременный доступ к хэш-таблице для нескольких операций чтения/записи. Это означает, что параллельные потоки могут добавлять / удалять записи в хеш-таблице. Но поскольку вы сохраняете адрес счетчика как данные в записях, DPDK не защищает обновления счетчика по этому адресу.

3. @pingvincible есть ли какие-либо обновления с вашей стороны?