名词解释
简称 | 全称 | 备注 |
---|---|---|
DPDK | Data Plane Development Kit | 数据平面开发套件 |
RTE | RunTime Environment | 运行时环境 |
EAL | Environment Abstraction Layer | 环境抽象层 |
lcore | logical core | EAL pthread |
TLS | Thread Local Storage | 线程本地存储 |
lcore
一个lcore就是一个基于pthread实现的线程,不同的lcore可以亲和到不同的logical CPU,它们之间是多对多的关系。在当前线程中调用rte_eal_init()后,当前线程会被设置成MASTER lcore,MASTER lcore会根据lcore的个数创建SLAVE lcore
对于多个线程运行在一个logical CPU上的情形,有两种处理办法:
- 使用–lcores参数指定lcore及亲和到的logical CPU,全部使用EAL pthread(个人推荐的方法)
- 第一个线程直接使用EAL pthread,其它线程使用通过pthread_create()创建的用户线程并绑核
rte_mbuf
http://dpdk.org/doc/guides/prog_guide/mbuf_lib.html
https://www.cnblogs.com/MerlinJ/p/4284706.html
一般在MASTER lcore中调用rte_pktmbuf_pool_create()创建一个rte_mempool,在创建rte_mempool时需要指定包含多少个rte_mbuf以及每个rte_mbuf的大小
一个rte_mbuf通常存储一个L2报文,比较大的L2报文可能需要多个rte_mbuf存储
调用rte_eth_rx_burst()收包后,网卡读上来的L2报文存储在rte_mbuf后面,通过宏rte_pktmbuf_mtod(m, struct ether_hdr *)可以得到L2报文的以太网头指针
rte_ring
http://dpdk-docs.readthedocs.io/en/latest/prog_guide/ring_lib.html
1、修改r->prod.head指向本地变量prod_next(CAS操作)
- 如果r->prod.head等于本地变量prod_head,修改ring->prod.head指向本地变量prod_next,CAS操作成功
- 如果r->prod.head不等于本地变量prod_head,CAS操作失败
2、修改r->prod.tail指向r->prod.head:只有r->prod.tail等于本地变量prod_head才能修改
struct rte_ring_headtail {
volatile uint32_t head; /**< Prod/consumer head. */
volatile uint32_t tail; /**< Prod/consumer tail. */
uint32_t single; /**< True if single prod/cons */
};
struct rte_ring {
char name[RTE_MEMZONE_NAMESIZE] __rte_cache_aligned; /**< Name of the ring. */
int flags; /**< Flags supplied at creation. */
const struct rte_memzone *memzone;
/**< Memzone, if any, containing the rte_ring */
uint32_t size; /**< Size of ring. */
uint32_t mask; /**< Mask (size-1) of ring. */
uint32_t capacity; /**< Usable size of ring */
/** Ring producer status. */
struct rte_ring_headtail prod __rte_aligned(PROD_ALIGN);
/** Ring consumer status. */
struct rte_ring_headtail cons __rte_aligned(CONS_ALIGN);
};
报文结构体
type | fomart |
---|---|
Ethernet | https://en.wikipedia.org/wiki/IEEE_802.1Q |
ARP | https://en.wikipedia.org/wiki/Address_Resolution_Protocol |
IPv4 | https://en.wikipedia.org/wiki/IPv4 |
ICMP | https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol |
TCP | https://en.wikipedia.org/wiki/Transmission_Control_Protocol |
UDP | https://en.wikipedia.org/wiki/User_Datagram_Protocol |
VXLAN | https://datatracker.ietf.org/doc/rfc7348/?include_text=1 |
以上各种报文在DPDK中的定义如下:
struct ether_addr {
uint8_t addr_bytes[ETHER_ADDR_LEN]; /**< Addr bytes in tx order */ // 包含6个uint8_t的数组表示MAC地址
} __attribute__((__packed__));
struct ether_hdr {
struct ether_addr d_addr; /**< Destination address. */ // 目的MAC地址
struct ether_addr s_addr; /**< Source address. */ // 源MAC地址
uint16_t ether_type; /**< Frame type. */ // 不带VLAN时:类型(IP为0x0800、ARP为0x0806)
// 带VLAN时:TPID(0x8100)
} __attribute__((__packed__));
struct vlan_hdr {
uint16_t vlan_tci; /**< Priority (3) + CFI (1) + Identifier Code (12) */ // 3位PCP + 1位DEI + 12位VID
uint16_t eth_proto;/**< Ethernet type of encapsulated frame. */ // 类型(IP为0x0800、ARP为0x0806)
} __attribute__((__packed__));
struct arp_ipv4 {
struct ether_addr arp_sha; /**< sender hardware address */ // 发送端以太网地址
uint32_t arp_sip; /**< sender IP address */ // 发送端IP地址
struct ether_addr arp_tha; /**< target hardware address */ // 目的以太网地址
uint32_t arp_tip; /**< target IP address */ // 目的IP地址
} __attribute__((__packed__));
struct arp_hdr {
uint16_t arp_hrd; /* format of hardware address */ // 硬件类型
#define ARP_HRD_ETHER 1 /* ARP Ethernet address format */
uint16_t arp_pro; /* format of protocol address */ // 协议类型
uint8_t arp_hln; /* length of hardware address */ // 硬件地址长度
uint8_t arp_pln; /* length of protocol address */ // 协议地址长度
uint16_t arp_op; /* ARP opcode (command) */
#define ARP_OP_REQUEST 1 /* request to resolve address */
#define ARP_OP_REPLY 2 /* response to previous request */
#define ARP_OP_REVREQUEST 3 /* request proto addr given hardware */
#define ARP_OP_REVREPLY 4 /* response giving protocol address */
#define ARP_OP_INVREQUEST 8 /* request to identify peer */
#define ARP_OP_INVREPLY 9 /* response identifying peer */
struct arp_ipv4 arp_data;
} __attribute__((__packed__));
struct ipv4_hdr {
uint8_t version_ihl; /**< version and header length */ // 4位版本 + 4位首部长度(word数)
uint8_t type_of_service; /**< type of service */
uint16_t total_length; /**< length of packet */ // 总长度
uint16_t packet_id; /**< packet ID */
uint16_t fragment_offset; /**< fragmentation offset */
uint8_t time_to_live; /**< time to live */
uint8_t next_proto_id; /**< protocol ID */ // 协议(ICMP为1、TCP为6、UDP为17、GRE为47)
uint16_t hdr_checksum; /**< header checksum */
uint32_t src_addr; /**< source address */ // 源IP地址
uint32_t dst_addr; /**< destination address */ // 目的IP地址
} __attribute__((__packed__));
struct icmp_hdr {
uint8_t icmp_type; /* ICMP packet type. */ // 类型
uint8_t icmp_code; /* ICMP packet code. */ // 代码
uint16_t icmp_cksum; /* ICMP packet checksum. */ // 检验和
uint16_t icmp_ident; /* ICMP packet identifier. */ // 标识符
uint16_t icmp_seq_nb; /* ICMP packet sequence number. */ // 序列号
} __attribute__((__packed__));
struct tcp_hdr {
uint16_t src_port; /**< TCP source port. */ // 源端口号
uint16_t dst_port; /**< TCP destination port. */ // 目的端口号
uint32_t sent_seq; /**< TX data sequence number. */ // 序列号
uint32_t recv_ack; /**< RX data acknowledgement sequence number. */ // 确认号
uint8_t data_off; /**< Data offset. */ // 4位首部长度(word数) + 4位保留
uint8_t tcp_flags; /**< TCP flags */ // 2位保留 + FIN/SYN/RST/PSH/ACK/URG
uint16_t rx_win; /**< RX flow control window. */
uint16_t cksum; /**< TCP checksum. */
uint16_t tcp_urp; /**< TCP urgent pointer, if any. */
} __attribute__((__packed__));
struct udp_hdr {
uint16_t src_port; /**< UDP source port. */ // 源端口号
uint16_t dst_port; /**< UDP destination port. */ // 目的端口号
uint16_t dgram_len; /**< UDP datagram length */ // 总长度
uint16_t dgram_cksum; /**< UDP datagram checksum */
} __attribute__((__packed__));
struct vxlan_hdr {
uint32_t vx_flags; /**< flag (8) + Reserved (24). */ // 8位Flags(0x08) + 24位保留
uint32_t vx_vni; /**< VNI (24) + Reserved (8). */ // 24位VNI + 8位保留
} __attribute__((__packed__));