网络数据在传输过程中,在传输层,会在数据前加上 源端口,目的端口,即TCP头(UDP头)
在网络层,会加上源IP、目的IP以及传输方式(TCP/UDP),即IP头
在数据链路层,会加上源MAC、目的MAC ,即Eth头
一个数据包由以上部分组成
我们接收到数据包,运用的DPDK为例,提取出Eth头,IP头,端口
Linux中有定义好的存储 Eth头,IP头这种结构体,直接复制过来用
#include <linux/byteorder/little_endian.h>
#include <rte_mbuf_h> // dpdk
#define __bitwise
typedef unsigned char __u8;
typedef unsigned short __u16;
typedef unsigned int __u32;
typedef unsigned char u8;
typedef __u16 __bitwise __be16;
typedef __u16 __bitwise __sum16;
typedef __u32 __bitwise __be32;
//Eth头
struct ethhdr {
unsigned char h_dest[ETH_ALEN];
unsigned char h_source[ETH_ALEN];
__be16 h_proto;
} __attribute__((packed));
//ipv4 IP头结构体
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8 version:4,
ihl:4;
#else
#error "Please fix <asm/byteorder.h>"
#endif
__u8 tos;
__be16 tot_len;
__be16 id;
__be16 frag_off;
__u8 ttl;
__u8 protocol;
__sum16 check;
__be32 saddr;
__be32 daddr;
/*The options start here. */
};
//IPV6 IP头结构体
struct ipv6hdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 priority:4,
version:4;
#else
__u8 version:4,
priority:4;
#endif
__u8 flow_lbl[3];
__be16 payload_len;
__u8 nexthdr;
__u8 hop_limit;
//struct in6_addr saddr;
//struct in6_addr daddr;
u8 saddr[16];
u8 daddr[16];
};
//TCP/UDP port
struct tcp_udp_port
{
__be16 source;
__be16 dest;
};
//写给作者自己看的 rte_mbuf 为DPDK结构体
int 5tuples_parse(int count, struct rte_mbuf **m)
{
struct ethhdr* eth = NULL;
struct iphdr* iph = NULL;
struct ipv6hdr* iph6 = NULL;
struct tcp_udp_port* tup = NULL;
eth = (struct ethhdr*)(m[0]->buf_addr+RTE_PKTMBUF_HEADROOM);
switch(eth->h_proto = htons(eth->h_proto)) //网络序转成主机序
{
//ipv4
case 0x0800:
iph = (struct iphdr*)(m[0]->buf_addr+RTE_PKTMBUF_HEADROOM + sizeof(struct ethhdr));
if(iph->protocol == 17 || iph->protocol == 6) //17表示UDP 6表示TCP
{
//iph->ihl*4 表示iphdr结构体大小
tup = (tcp_udp_port*)(m[0]->buf_addr+RTE_PKTMBUF_HEADROOM + sizeof(struct ethhdr) + iph->ihl*4);
}
break;
//ipv6
case 0x86dd:
iph6 = (struct ipv6hdr*)(m[0]->buf_addr+RTE_PKTMBUF_HEADROOM + sizeof(struct ethhdr));
if(iph6->nexthdr == 17 || iph6->nexthdr == 6) //17表示UDP 6表示TCP
{
//iph->ihl*4 表示iphdr结构体大小
tup = (tcp_udp_port*)(m[0]->buf_addr+RTE_PKTMBUF_HEADROOM + sizeof(struct ethhdr)
+ sizeof(struct ipv6hdr));
}
break;
}
return 0;
}