установка разгрузки контрольной суммы с использованием ol_flags в структуре rte_mbuf не эффективна - PullRequest
1 голос
/ 29 марта 2019

Флаги разгрузки, используемые для вычисления контрольной суммы на аппаратном уровне, не действуют в более новой версии DPDK 18.08. Контрольная сумма не вычисляется на аппаратном уровне после установки этих флагов. Значения контрольной суммы остаются такими же, как те, которые установлены прикладным программным обеспечением. Это приводит к ошибочным ошибочным контрольным суммам заголовков IPV4 и ошибочным контрольным суммам UDP и, в конечном итоге, к сбрасыванию пакетов на маршрутизаторе. Эти флаги разгрузки контрольной суммы работали со старой версией DPDK, и те же флаги, и тот же фрагмент кода теперь не работает.

ol_flags в структуре rte_mbuf использовался для установки разгрузки контрольной суммы для пакетов IPV4 и UDP на программном уровне. Есть ли какие-либо известные проблемы с DPDK 18.08 в отношении этих флагов разгрузки контрольной суммы для пакетов IPV4 и UDP? Код, используемый для установки разгрузки контрольной суммы с использованием ol_flags структуры rte_mbuf, показан ниже.

struct ipv4_hdr *ip = NULL;
struct udp_hdr* udphdr;
struct rte_mbuf *mbuf;

ip = (struct ipv4_hdr*)(rte_pktmbuf_mtod(m, unsigned char *) + l2_data_shift);
udphdr = (struct udp_hdr*)(rte_pktmbuf_mtod(m, unsigned char *) + l2_data_shift + sizeof(struct ipv4_hdr));


ip->hdr_checksum = 0;  
m->data_len = m->pkt_len = l2_data_shift +rte_be_to_cpu_16(ip->total_length);
mbuf->l3_len = sizeof(struct ipv4_hdr);
m->ol_flags |= PKT_TX_IP_CKSUM | PKT_TX_UDP_CKSUM;
udphdr->dgram_cksum =ipv4sum(ip);



uint16_t ipv4sum(struct ipv4_hdr * ip_hdr)
{
    uint16_t proto;
    uint32_t sum;

    proto = ip_hdr->next_proto_id;
    proto = rte_cpu_to_be_16(proto);
    sum = proto;

    sum += rte_cpu_to_be_16((uint16_t)(rte_be_to_cpu_16(ip_hdr->total_length) - sizeof(struct ipv4_hdr)));
    if (sum > UINT16_MAX) sum -= UINT16_MAX;

    sum += ip_hdr->src_addr & 0xFFFF;
    if (sum > UINT16_MAX) sum -= UINT16_MAX;
    sum += (ip_hdr->src_addr >> 16);
    if (sum > UINT16_MAX) sum -= UINT16_MAX;

    sum += ip_hdr->dst_addr & 0xFFFF;
    if (sum > UINT16_MAX) sum -= UINT16_MAX;
    sum += (ip_hdr->dst_addr >> 16);
    if (sum > UINT16_MAX) sum -= UINT16_MAX;

    sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff);
    sum &= 0x0ffff;

    return (uint16_t)sum;

}

Не могли бы вы предложить решение для обхода этих ошибок контрольной суммы и отбрасывания пакетов?

Ответы [ 2 ]

0 голосов
/ 30 марта 2019

1.) Я забыл упомянуть, что l2 len было установлено следующим образом.

if (ETHER_TYPE_VLAN == eth_type)
{
     mbuf->l2_len = sizeof(struct ether_hdr) + sizeof(struct vlan_hdr);
}

else {
    mbuf->ol_flags = PKT_TX_VLAN_PKT;
    mbuf->l2_len = sizeof(struct ether_hdr);       
}

2.) Я пытался использовать второй вариант как хорошо после установки l2_len и l3_len, но это не сработало.

ip->hdr_checksum = 0;   

mbuf->ol_flags |=  PKT_TX_IPV4 | PKT_TX_IP_CKSUM | PKT_TX_UDP_CKSUM;
udphdr->dgram_cksum = rte_ipv4_phdr_cksum(mbuf->l3_len, mbuf->ol_flags); 

3.) Как уже упоминалось, он поддерживается на аппаратной рекламе DEV_TX_OFFLOAD_IPV4_CKSUM, DEV_TX_OFFLOAD_UDP_CKSUM и DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM.

Так что в качестве другого варианта я попытался установить разгрузки txmode во время инициализации порта вместе с вариантом 2.)

struct rte_eth_conf port_conf;
port_conf.txmode.offloads |= DEV_TX_OFFLOAD_UDP_CKSUM |DEV_TX_OFFLOAD_IPV4_CKSUM;
ret = rte_eth_dev_configure(port, nbqueue, nbqueue, &port_conf);

Это тоже не сработало. Пожалуйста, предложите любые другие обходные пути, которые я могу попробовать.

0 голосов
/ 30 марта 2019

Есть две проблемы с кодом:

  1. l2_len должен быть правильно установлен (вероятно, на длину заголовка Ethernet?)
  2. Вместо пользовательской функцииipv4sum(), нам лучше использовать DPDK rte_ipv4_phdr_cksum().

Итак, чтобы вычислить внешние контрольные суммы IP и UDP:

mb->l2_len = len(out_eth)
mb->l3_len = len(out_ip)
mb->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CSUM | PKT_TX_UDP_CKSUM
set out_ip checksum to 0 in the packet
set out_udp checksum to pseudo header using rte_ipv4_phdr_cksum()

На всякий случай, чтобы вычислить внешнююКонтрольные суммы IP и TCP:

mb->l2_len = len(out_eth)
mb->l3_len = len(out_ip)
mb->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CSUM | PKT_TX_TCP_CKSUM
set out_ip checksum to 0 in the packet
set out_tcp checksum to pseudo header using rte_ipv4_phdr_cksum()

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...