名詞解釋
|
簡稱
|
全稱
|
備註
|
|
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
一般在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__));