DIY TCP/IP Payload Buffer模块0

上一篇:DIY TCP/IP 网络设备模块6
6. pdbuf模块的实现
pdbuf是payload buffer的简称,该模块为DIY TCP/IP提供buffer管理功能,与Linux Kernel的struct sk_buff类似。pdbuf模块提供buffer的动态分配和释放,为有效载荷分配内存时预留协议头部所需内存空间,同时保证有效载荷加上协议头部(不包括14个字节的以太网头部)的大小不超过以太网的最大协议传输单元1500字节。pdbuf模块还提供buffer的push,pop,insert,rewind等函数接口,方便buffer流经DIY TCP/IP上层模块时添加协议头部。pdbuf操作buffer的函数接口也考虑了IP数据帧的分片和重组。
pdbuf模块为有效载荷分配内存时预留协议头部所需内存空间,例如TCP模块向pdbuf模块申请32个字节存放待发送的TCP数据,pbbuf模块申请32字节的内存同时,还会申请TCP头部,IP头部以及以太网头部所需内存空间。所以在实现pdbuf数据结构之前,先来添加ARP, ICMP, IP, TCP 和UDP层的头文件,在这些头文件中定义各层协议头部的数据结构,以便pdbuf模块使用。
6.1 协议头部数据结构
本节为pdbuf模块提供各层协议头部数据结构的定义,协议头部的详细解释在介绍DIY TCP各模块的协议实现时引入。本节只是根据wireshark抓包的结果来定义协议头部数据结构。相对物理媒介来说,第5章实现的网络设备模块是layer2,下面就按照layer3和layer4的顺序,介绍各层协议头部的数据结构。Layer3包括ARP,IP, layer4包括ICMP, TCP和UDP。
ARP
DIY TCP/IP Payload Buffer模块0_第1张图片
wireshark抓包结果可以看出,ARP数据在以太网头部的后面。上图右半边的raw byte显示,ARP数据一共是28个字节,添加arp.h,定义arphdr_t数据结构。

  #ifndef _ARP_H_
  #define _ARP_H_
  
  #define ARP_HW_TYPE  1   /* Ethernet */
  #define ARP_PROTO_TYPE   0x0800  /* IPv4 */
  #define ARP_HW_SZ    6   /* Hardware Address Length */
  #define ARP_PROTO_SZ 4   /* Protocol Address Length */
  
  /* ARP operation code */
  enum {
  		ARP_REQUEST = 1,
		ARP_REPLY = 2,
  } arp_op_code;
 
  /* ARP Packet */
  typedef struct _arphdr {
	unsigned short hw_type;
	unsigned short proto_type;
	unsigned char hw_sz;
	unsigned char proto_sz;
	unsigned short op_code;
	unsigned char sender_mac[ARP_HW_SZ];
	unsigned char sender_ip[ARP_PROTO_SZ];
	unsigned char target_mac[ARP_HW_SZ];
	unsigned char target_ip[ARP_PROTO_SZ];
  } __attribute__ ((packed)) arphdr_t;
  #endif

ARP头部各个字段的详细解释,在介绍DIY TCP/IP ARP模块的实现时引入。
IP
DIY TCP/IP Payload Buffer模块0_第2张图片
IP是网络层协议,紧跟在以太网头部后面,可以认为ARP和IP是同处于layer3的协议。从IP头部的protocol字段可以看出IP头部后面是UDP头部和UDP的有效载荷,raw byte显示IP头部一共是20个字节。添加ip.h,定义iphdr_t数据结构。

#ifndef _IP_H_
#define _IP_H_
 
#define IP_VERSION			4
#define IP_HDR_LEN			5
#define IP_FRAG_OFFSET		0x1FFF
#define REASSEMBLE_BUF_SZ	((1 << 16) - 1 - 20)

#define IP_PROTO_ICMP		0x01
#define IP_PROTO_TCP		0x06
#define IP_PROTO_UDP		0x11

/* ipv4 header, 20 bytes */
typedef struct _iphdr {
	 /* version and header length */
	 unsigned char hdr_len:4;
	 unsigned char ver:4;
	 /* type of service */
	 unsigned char tos;
	 /* total length: hdr_len + payload len */
	 unsigned short total_len;
	 /* identification */
	 unsigned short id;
	 /* flags and fragment offset */
	 unsigned short flags_offset;
	 /* time to live */
	 unsigned char ttl;
	 /* payload protocol */
	 unsigned char proto;
	 /* header checksum */
	 unsigned short hdr_cksum;
	 /* source ip address */
	 unsigned char src_ip[4];
	 /* destination ip address */
	 unsigned char dst_ip[4];
} __attribute__((packed)) iphdr_t;

#endif

IP头部各个字段的详细解释,在介绍DIY TCP/IP IP模块的实现时引入。
ICMP
DIY TCP/IP Payload Buffer模块0_第3张图片
ICMP跟在IP头部的后面,raw byte显示一共是40字节,减去32个字节的数据,2个字节的identifier,2个字节的sequence number,icmp头部一共是4个字节,添加icmp.h,定义icmphdr_t数据结构。

#ifndef _ICMP_H_
#define _ICMP_H_

#define ICMP_TYPE_ECHO			0x8
#define ICMP_TYPE_ECHO_REPLY	0x0
#define ICMP_CODE				0x0
  
/* icmp header, 4 bytes */
typedef struct _icmphdr {
	 /* icmp type */
	 unsigned char type;
	 /* code */
	 unsigned char code;
	 /* checksum */
	 unsigned short cksum;
} __attribute__ ((packed)) icmphdr_t;

#endif

ICMP头部各个字段的详细解释,在介绍DIY TCP/IP ICMP模块的实现时引入。
TCP
DIY TCP/IP Payload Buffer模块0_第4张图片
上图是一个TCP ACK数据帧,TCP头部紧跟在IP头部后面,从TCP头部的flags和tcp samgent len的长度可以看出,该TCP数据帧是一个不包含任何数据的TCP ACK,raw byte显示该TCP帧一共20个字节,全部都是tcp头部,添加tcp.h,定义tcphdr_t数据结构。

#ifndef _TCP_H_
#define _TCP_H_

typedef union _tcp_hdr_flags {
        struct _bitmap {
                unsigned short flags:12;
                unsigned short hdr_len:4;
        } bitmap;
        unsigned short word_val;
} tcp_hdr_flags_t;
 
/* tcp header, 20 bytes, options, 12 bytes */
typedef struct _tcphdr {
	 /* source port */
	 unsigned short src_port;
	 /* destination port */
	 unsigned short dst_port;
	 /* sequence number */
	 unsigned int seq_num;
	 /* acknowledge number */
	 unsigned int ack_num;
	 /* tcp header length and flags */
	 tcp_hdr_flags_t hdr_flags;
	 /* window size */
	 unsigned short wnd_sz;
	 /* checksum */
	 unsigned short cksum;
	 /* urgent point */
	 unsigned short ugtp;
	 /* options
	 * variable in length, may occupy space at the end
	 * of TCP header and are a multiple of 8 bits in
	 * length. All options are included in the checksum
	 */
	 unsigned char options[0];
} __attribute__ ((packed)) tcphdr_t;

#endif

TCP头部各个字段的详细解释,在介绍DIY TCP/IP TCP模块的实现时引入。
UDP
DIY TCP/IP Payload Buffer模块0_第5张图片
与TCP头部相比,UDP头部相对简单,UDP头部中的Length 97字节是UDP头部和89个字节的UDP数据的和。97减去89字节的UDP数据,与raw byte显示一致,UDP头部一共是8个字节,添加udp.h,定义udphdr_t数据结构。

 #ifndef _UDP_H_
 #define _UDP_H_
 /* udp header, 8 bytes */
 typedef struct _udphdr {
	  /* source port */
	  unsigned short src_port;
	  /* destination port */
	  unsigned short dst_port;
	  /* length: udp header length + payload length */
	  unsigned short len;
	  /* checksum */
	  unsigned short cksum;
 } __attribute__ ((packed)) udphdr_t;
 #endif

UDP头部各个字段的详细解释,在介绍DIY TCP/IP UDP模块的实现时引入。下节介绍pdbuf数据结构的定义时,将会用到本节的ARP,IP,ICMP,TCP,UDP头部数据结构的定义。
下一篇:DIY TCP/IP Payload Buffer模块1

你可能感兴趣的:(DIY,TCP/IP)