问题描述

对于五元组随机变化的 QinQ 报文,需要实现如下需求:

  1. dpdk 程序 rx 时网卡自动剥掉外层 vlan 头
  2. dpdk 程序 tx 时网卡在外层添加一个指定的 vlan 头
  3. 报文能够 hash 到不同的队列上
  4. 基于 dpdk-19.11 版本与 x710 网卡

QinQ 报文的格式

如下图所示,QinQ 其实可以简单的理解为 vlan 里面套了 vlan 的形式,QinQ 写成 802.1Q in 802.1 Q 可能更形象一点。

上图摘自:

https://www.cnblogs.com/sddai/p/6204496.html

对 QinQ 报文有基础的认识后,继续研究相关需求如何实现。

dpdk 程序 rx 时如何实现网卡自动剥掉外层 vlan?

dpdk 支持如下网卡 rx mode 配置:

#define DEV_RX_OFFLOAD_VLAN_STRIP  0x00000001
#define DEV_RX_OFFLOAD_IPV4_CKSUM  0x00000002
#define DEV_RX_OFFLOAD_UDP_CKSUM   0x00000004
#define DEV_RX_OFFLOAD_TCP_CKSUM   0x00000008
#define DEV_RX_OFFLOAD_TCP_LRO     0x00000010
#define DEV_RX_OFFLOAD_QINQ_STRIP  0x00000020
#define DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM 0x00000040
#define DEV_RX_OFFLOAD_MACSEC_STRIP     0x00000080
#define DEV_RX_OFFLOAD_HEADER_SPLIT 0x00000100
#define DEV_RX_OFFLOAD_VLAN_FILTER  0x00000200
#define DEV_RX_OFFLOAD_VLAN_EXTEND  0x00000400
#define DEV_RX_OFFLOAD_JUMBO_FRAME  0x00000800
#define DEV_RX_OFFLOAD_SCATTER      0x00002000
#define DEV_RX_OFFLOAD_TIMESTAMP    0x00004000
#define DEV_RX_OFFLOAD_SECURITY         0x00008000
#define DEV_RX_OFFLOAD_KEEP_CRC     0x00010000
#define DEV_RX_OFFLOAD_SCTP_CKSUM   0x00020000
#define DEV_RX_OFFLOAD_OUTER_UDP_CKSUM  0x00040000
#define DEV_RX_OFFLOAD_RSS_HASH     0x00080000

DEV_RX_OFFLOAD_VLAN_STRIP 这个 offload 使能后网卡会自动剥掉最外层的 vlan,同时 vlan 信息 会保存到收包描述符的特定字段上。

dpdk 驱动收包函数中会将描述符上的 vlan 信息转化并保存到 mbuf 中的 vlan_tci 字段中,上层程序通过访问 mbuf 的这个字段就能够获取到报文的 vlan 了。

这些 rx offloads 通过 rxmode 配置。dpdk 程序调用 rte_eth_dev_configure 函数时驱动层判段 rxmode 并执行相关的硬件初始化,示例代码如下:

local_port_conf.rxmode.offloads |=DEV_RX_OFFLOAD_VLAN_STRIP;
ret = rte_eth_dev_configure(portid, 1, 1, &local_port_conf);

dpdk i40e 普通收包函数中有如下关键代码:

 116 i40e_rxd_to_vlan_tci(struct rte_mbuf *mb, volatile union i40e_rx_desc *rxdp)117 {118     if (rte_le_to_cpu_64(rxdp->wb.qword1.status_error_len) &119         (1 << I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)) {120         mb->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;121         mb->vlan_tci =122             rte_le_to_cpu_16(rxdp->wb.qword0.lo_dword.l2tag1);123         PMD_RX_LOG(DEBUG, "Descriptor l2tag1: %u",124                rte_le_to_cpu_16(rxdp->wb.qword0.lo_dword.l2tag1));125     } else {126         mb->vlan_tci = 0;127     }

描述符中的字段由网卡硬件填充,在驱动收包函数中被转化存储到 mbuf 的 vlan_tci 字段中,这就是剥离 vlan 头 offload 的关键过程。

dpdk 程序如何在发包时让网卡自动添加一个指定的 vlan 头?

与 rx 类似,发包时添加 vlan 头也可以通过配置 tx offload 来使能。需要注意的是添加的 vlan 头需要的信息上层要在发包前填充到 dpdk mbuf 的指定字段上,这一点与收包过程刚好相反。

dpdk 支持的 tx offload 部分摘录:

#define DEV_TX_OFFLOAD_VLAN_INSERT 0x00000001
#define DEV_TX_OFFLOAD_IPV4_CKSUM  0x00000002
#define DEV_TX_OFFLOAD_UDP_CKSUM   0x00000004
#define DEV_TX_OFFLOAD_TCP_CKSUM   0x00000008
#define DEV_TX_OFFLOAD_SCTP_CKSUM  0x00000010
#define DEV_TX_OFFLOAD_TCP_TSO     0x00000020
#define DEV_TX_OFFLOAD_UDP_TSO     0x00000040
#define DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM 0x00000080 /**< Used for tunneling packet. */
#define DEV_TX_OFFLOAD_QINQ_INSERT 0x00000100

这些 offloads 通过 txmode 配置,在 dpdk 程序调用 rte_eth_dev_configure 函数时被使用,示例代码如:

local_port_conf.txmode.offloads |=DEV_TX_OFFLOAD_VLAN_INSERT;
ret = rte_eth_dev_configure(portid, 1, 1, &local_port_conf);

发包前上层应用对 mbuf vlan 相关字段填充信息示例:

mbufs[idx]->vlan_tci = 0xef00;
mbufs[idx]->ol_flags |= PKT_TX_VLAN_PKT;

这里存在的一个问题是,i40e 驱动的向量发包函数不支持 DEV_TX_OFFLOAD_VLAN_INSERT offload,配置了 DEV_TX_OFFLOAD_VLAN_INSERT offload 时只能使用普通的发包函数,不能使用向量发包函数。

报文 hash 到不同的队列上

要让报文 hash 到不同的队列上,可以通过配置网卡的 rss hash 功能来实现。测试对 QinQ 报文的 hash 时却发现存在如下问题:

x710 网卡必须同时配置 rss hash 与 rx vlan extend offload 才能 hash 到不同的队列上,rx vlan strip offload 是否配置不影响 hash 结果。

同时观测到如下现象:

  1. x710 网卡同时配置了 rx vlan strip offload 与 rx vlan extend offload 时,QinQ 报文的两层 vlan 都被剥掉。
  2. 配置了 rx vlan extend offload 后,tx VLAN_INSERT offload 异常。
  3. 单独使能 rx vlan extend offload 与 rx vlan strip offload 效果相同

经过其它的尝试,没有找到可用的方案。为了保证 rss hash 功能可用只能开启 rx vlan extend offload 同时上层在发包时软件添加 vlan 头。

一个改进方案

进一步的研究发现,x710 网卡 rxmode 进行如下配置时:

rxmode.hw_vlan_strip = 0
rxmode.hw_vlan_extend = 1;

网卡自动添加 vlan 错误的问题是:对于配置了 PKT_TX_VLAN_PKT 标志的带 vlan 报文,x710 网卡添加 vlan 头时会将 vlan 头添加到了内层 vlan 中,这样就覆盖了报文原有的 vlan。

这里可以将两个 vlan 头交换一下来软件规避,这样就不用进行内存拷贝,示例代码如下:

eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
if (eth_hdr->ether_type == ETHER_TYPE_VLAN_X86) {vh = (struct vlan_hdr *)(ether_hdr + 1);m->vlan_tci = rte_cpu_to_be_16(vh->vlan_tci);vh->vlan_tci = rte_cpu_to_be_16(send_card_id);
}m->ol_flags = PKT_TX_VLAN_PKT;

提问环节

  1. vlan extend 是什么?
    代码里面有注释表明 vlan extend 是 double vlan,网上搜索不到相关的信息。
  2. 通过配置 DEV_RX_OFFLOAD_QINQ_STRIP 是否能够 hash 开?
    环境限制,无法测试,只能暂且放弃了。

参考链接

https://dev.dpdk.narkive.com/XcHzHsvq/dpdk-rss-for-double-vlan-tagged-packets

https://doc.dpdk.org/api-2.2/structrte__eth__rxmode.html

https://linkthedevil.gitbook.io/little-things-about-dataplane/3

https://dev.dpdk.narkive.com/lCYIb96o/dpdk-vlan-header-insertion-and-removal

x710 offload QinQ 报文 vlan 并支持 rss hash 到多队列相关推荐

  1. VLAN网络支持ipv6的交换机和虚机配置

    VLAN支持ipv6的交换机和虚机配置 前言 一.创建VLAN网络并配置交换机 1.规划并在OpenStack上创建 VLAN网络 2.在交换机上配置VLAN 二.Ubuntu虚机配置 1.创建虚机 ...

  2. VLAN技术详解(VLAN、QinQ、VLAN Aggregation、MUX VLAN、Voice VLAN)

    一.VLAN基本概念 什么是VLAN 逻辑划分.不受地理位置限制 VLAN的作用 VLAN=LAN=局域网=IP子网=广播域 所以VLAN能够隔离广播域 VLAN帧格式 TPID:标签协议标识符,字段 ...

  3. PHP RSS/Feed 生成类库(支持RSS 1.0/2.0和ATOM)

    通用PHP RSS/Feed 生成类库(支持RSS 1.0/2.0和ATOM) PHP Universal Feed Generator (supports RSS 1.0, RSS 2.0 and ...

  4. QinQ与Vlan Mapping讲解与实验配置

    目录 QinQ Vlan扩展 QinQ实现方式 QinQ实验配置 Vlan Mapping Vlan映射 映射方式 配置命令 QinQ Vlan扩展 QinQ全称为802.1Q-in-802.1Q,为 ...

  5. 【HCIP 05】QinQ (vlan叠vlan)

    本实验模拟企业 A 和企业 B 跨越 ISP 网络实现二层互联的场景.实现以下需求: 1.企业内部的 vlan 跨 ISP 二层通信 2.企业 A/B 之间 vlan 相同,但不会发生冲突,保持隔离. ...

  6. linux 网卡rss hash,使用RSS提升DPDK应用的性能

    本文描述了RSS以及在DPDK中如何配置RSS达到性能提升和统一分发. DPDK 1.8.0 什么是RSS RSS(Receive Side Scaling)是一种能够在多处理器系统下使接收报文在多个 ...

  7. fabric.js 不同类型 不同控件_策略模式支持不同类型的消息队列

    需求来源 现有采集数据平台:主要是通过snmp协议等各种协议从不同的系统中获取数据,并将数据发送到kafka中. 最近在和项目经理聊天的过程中发现现有一个客户数据量不大,数万级别,这样的客户还不少,使 ...

  8. VPP调试trace显示

    注册如下的命令show trace,显示记录的报文信息,默认每个线程最大显示50条,可使用参数max进行更改. VLIB_CLI_COMMAND (show_trace_cli,static) = { ...

  9. vpp之浅谈插件和使用

    vpp版本 笔者这里使用的vpp版本是最新git下来的,show version信息如下 DBGvpp# show version vpp v19.04-rc0~531-g537e85d built ...

最新文章

  1. R.java文件介绍
  2. 云栖第一天:解密两个100%背后的云原生
  3. linux haproxy 脚本,haproxy部署脚本
  4. java 多线程的使用_Java的多线程1:线程的使用
  5. Any problem in computer science can be solved with another layer of indirection
  6. cad lisp 二次抛物线_学习CAD的五个段位,你是青铜还是王者?
  7. 步骤1:JMeter 录制脚本接口测试
  8. c+pow函数的头文件_pow()函数以及C ++中的示例
  9. HuggingFace学习1:tokenizer学习与将文本编码为固定长度(pytorch)
  10. R学习-小白笔记08
  11. 魅族系统怎么无需root激活Xposed框架的经验
  12. 关于H5请求数据报跨域问题记录
  13. 维特比算法(Viterbi algorithm) 的理解
  14. 记一次IOS与H5-SPA页面的交互经验
  15. 首汇农业北京油鸡专业养殖基地合作签约仪式在北京房山大石窝镇辛庄村顺利举行
  16. 图像审核产品“侦图” —— Milvus 在翼支付风控场景中的应用
  17. 视频教程-OpenGLES萌谷手册(iOS2018版)-其他
  18. 部署C#服务到win7/Windows server 2008 R2服务器上
  19. Bottle模板引擎分析
  20. 贝岭ADC(BL1063/BLAD16J125)使用和配置问题

热门文章

  1. 【软考系统规划与管理师笔记】第3篇 信息技术知识2
  2. 3d建模自学能学会吗?要学什么?需要学习多久?
  3. 权限控制最常见的五种方法
  4. Uniapp引用阿里图库
  5. SpringBoot使用WebSocket实现多屏联动(方案+实现)
  6. 图像旋转c代码实现(90度, -90度, 180度)
  7. 《中国企业数字化转型案例纪实》即将开启
  8. flyme os 插桩红米2 教程
  9. git-gitblit的搭建
  10. Android蓝牙与BLE通信相关的读、写、通知、指示操作