名詞解釋

簡稱

全稱

備註

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__));