DPDK学习(基础知识)

名词解释

简称 全称 备注
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 lcorehtml

对于多个线程运行在一个logical CPU上的情形,有两种处理办法:web

  • 使用–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的大小tcp

一个rte_mbuf一般存储一个L2报文,比较大的L2报文可能须要多个rte_mbuf存储ide

调用rte_eth_rx_burst()收包后,网卡读上来的L2报文存储在rte_mbuf后面,经过宏rte_pktmbuf_mtod(m, struct ether_hdr*)能够获得L2报文的以太网头指针svg

rte_ring

http://dpdk-docs.readthedocs.io/en/latest/prog_guide/ring_lib.htmlui

一、修改r->prod.head指向本地变量prod_next(CAS操做)spa

  • 若是r->prod.head等于本地变量prod_head,修改ring->prod.head指向本地变量prod_next,CAS操做成功
  • 若是r->prod.head不等于本地变量prod_head,CAS操做失败

二、修改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为一、TCP为六、UDP为1七、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__));