Правильный способ применения фрагментации ip в нескольких ядрах в DPDK - PullRequest
0 голосов
/ 05 ноября 2018

Привет эксперты Stackoverflow,

У меня проблемы с применением ip-фрагментации в нескольких ядрах.

Мой последний вопрос: возможно ли выделить несколько таблиц фрагментации ip для каждого отдельного прямого и косвенного пула.

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


Назначение

Я пытаюсь применить ip-фрагментацию в нескольких ядрах и максимизировать производительность с сообщениями, превышающими MTU.

  • для каждого локального и удаленного хоста (с использованием от 1 до 8 логических ядер)
  • 1 ~ 4 для передачи фрагментированного сообщения
  • 4 ~ 8 для получения и сборки сообщения
  • Отправка 4KB сообщения с локального
  • удаленный эхо-сообщение обратно на локальный.
  • рассчитать общую пропускную способность


Задача

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

for each coreid, coreid < allocated cores; coreid++
     fragmentation_table[coreid] = rte_ip_frag_table_create(...);
     direct_pool[coreid] = rte_pktmbuf_pool_create(...);
     indirect_pool[coreid] rte_pktmbuf_pool_create(...);

Таким образом, в качестве альтернативы я выделил несколько таблиц фрагментации для каждого lcore, но позволил разделить прямой и косвенный пулы вместе.

for each coreid, coreid < allocated cores; coreid++
     fragmentation_table[coreid] = rte_ip_frag_table_create(...);

direct_pool = rte_pktmbuf_pool_create(...);
indirect_pool = rte_pktmbuf_pool_create(...);


Положение

Теперь, когда я отправляю сообщения с использованием нескольких ядер с локального на удаленный хост, удаленный хост успешно получает сообщение только тогда, когда я отправляю сообщение с добавлением задержки, такой как (добавление sleep (1); для каждой отправки сообщения). Я был возможность получать сообщения с локального на удаленный. Но я не могу получить никаких данных, когда я пытаюсь отправить их без задержки.


Заключение

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

Я действительно хочу услышать от экспертов DPDK об этой проблеме, с которой я сталкиваюсь, и буду очень благодарен за любые советы по этому вопросу ...

static int
setup_queue_tbl(struct lcore_rx_queue *rxq, uint32_t lcore, uint32_t queue)
{
    int socket;
    uint32_t nb_mbuf;
    uint64_t frag_cycles;
    char buf[RTE_MEMPOOL_NAMESIZE];

    socket = rte_lcore_to_socket_id(lcore);
    if (socket == SOCKET_ID_ANY)
        socket = 0;

    frag_cycles = (rte_get_tsc_hz() + MS_PER_S - 1) / MS_PER_S * max_flow_ttl;
    if ((rxq->frag_tbl = rte_ip_frag_table_create(max_flow_num,
                                                  IP_FRAG_TBL_BUCKET_ENTRIES, max_flow_num, frag_cycles,
                                                  socket)) == NULL) {
        printf("rte_ip_frag_table_create failed!!!!\n");
        return -1;
    }

    nb_mbuf = RTE_MAX(max_flow_num, 2UL * MAX_PKT_BURST) * MAX_FRAG_NUM;
    nb_mbuf *= (port_conf.rxmode.max_rx_pkt_len + BUF_SIZE - 1) / BUF_SIZE;
    nb_mbuf *= 1;
    nb_mbuf += nb_rxd + nb_txd;

    if (transfer_pool[lcore] == NULL) {

        snprintf(buf, sizeof(buf), "pool_recieve_%d", socket);
        receive_pool[lcore] = rte_pktmbuf_pool_create(buf, nb_mbuf, MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, socket);

        snprintf(buf, sizeof(buf), "pool_transfer_%d", socket);
        transfer_pool[lcore] = rte_pktmbuf_pool_create(buf, nb_mbuf, MEMPOOL_CACHE_SIZE, 0, PKT_SIZE + 128, socket);

        snprintf(buf, sizeof(buf), "pool_direct_%d", socket);
        direct_pool[lcore] = rte_pktmbuf_pool_create(buf, nb_mbuf, MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, socket);

        snprintf(buf, sizeof(buf), "pool_indirect_%d", socket);
        indirect_pool[lcore] = rte_pktmbuf_pool_create(buf, nb_mbuf, MEMPOOL_CACHE_SIZE, 0, 0, socket);
    }

    snprintf(buf, sizeof(buf), "mbuf_rx_ring_%d", lcore);
    rx_ring[lcore] = rte_ring_create(buf, 512, socket, 0);
    snprintf(buf, sizeof(buf), "mbuf_tx_ring_%d", lcore);
    tx_ring[lcore] = rte_ring_create(buf, 512, socket, 0);

    // for packet assemble
    rxq->ar = (struct assembled_result *)malloc(sizeof(struct assembled_result));
    rxq->ar->length = 0;
    rxq->ar->assembled_pkt = (char *)malloc(sizeof(char)*PKT_SIZE);
    return 0;
}

Вот полный исходный код, код, который я хочу убедиться, что он правильный, находится в dpdk_init.h

https://github.com/SungHoHong2/DPDK-Experiment/blob/master/dpdk-server-multi/dpdk_init.h

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Ответ был очень простой .. Проблема была в конфигурации огромных страниц. Размер огромной страницы был разным для каждого кластера, который я тестировал.

Один кластер, который выделял фраг-таблицы, был ...

AnonHugePages:    208896 kB
HugePages_Total:       8
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:    1048576 kB

В то время как другой кластер, который продолжал возвращать ошибки сегментации, когда я пытался выделить фраг-таблицы, был ...

AnonHugePages:      6144 kB 
HugePages_Total:    1024    
HugePages_Free:        0    
HugePages_Rsvd:        0    
HugePages_Surp:        0    
Hugepagesize:       2048 kB 

Вот базовая производительность масштабирования rx и tx -queues для каждого логического ядра. Как вы можете видеть, можно использовать несколько очередей rx-tx, каждая из которых связана с frag-таблицей с логическими ядрами и требуемыми пулами.

enter image description here

0 голосов
/ 05 ноября 2018

1. Пожалуйста, предоставьте исходный код

Это поможет вам получить ответы, а не догадки;)

2. Таблица фрагментов против lcores

Руководство программиста DPDK четко гласит:

все операции обновления / поиска в таблице фрагментов не являются потокобезопасными.

Источник

Таким образом, у каждого lcore должна быть своя собственная таблица фрагментов, или должны использоваться блокировки.

3. Пулы памяти против lcores

По умолчанию пулы памяти в DPDK являются поточно-ориентированными, если только мы не передадим флаг типа MEMPOOL_F_SP_PUT. Итак, отвечая на ваш вопрос:

возможно ли выделение нескольких таблиц фрагментации ip для каждого отдельного прямого и косвенного пула.

По умолчанию несколько ядер могут совместно использовать пулы памяти.

4. Угадайте!

Поскольку исходный код отсутствует, я предполагаю, что основной причиной является то, что TTL для фрагментов составляет менее 1 секунды, поэтому при sleep(1) пакеты приходят слишком поздно, чтобы их можно было собрать.

5. Примечание

Повторная сборка занимает много времени и места и ее следует избегать любой ценой.

Рассмотрите некоторые способы размещения вашего сообщения в одном пакете, изменив протокол или используя гигантские кадры.

...