【lwip】09-IPv4协议&超全源码实现分析( 四 )

9.3.12 源IP字段占用32 bit 。
为源主机的IP地址 。
9.3.13 目标IP字段占用32 bit 。
为目标主机的IP地址 。
9.3.14 选项字段0到40字节 。
对于IP数据报首部来说,其大小必须为4字节的整数倍 。
如果选项字段长度不为4的倍数,则需要用0进行填充 。
在 LwIP 中只识别选项字段,不会处理选项字段的内容 。
该字段在IPv6报文中已经被移除了 。
9.3.15 数据区字段IP 数据报的最后的一个字段,装载着当前IP数据报的数据,是上层协议的数据报 。
9.3.16 对应wireshark包分析

【lwip】09-IPv4协议&超全源码实现分析

文章插图
9.4 IP首部数据结构注意:网络字节序是大端的 。
ipv4的IP首部数据结构:对应IP首部报文图 。
/* The IPv4 header */struct ip_hdr {/* version / header length */PACK_STRUCT_FLD_8(u8_t _v_hl); /* 版本号字段(4)+首部长度字段(4)单位字 *//* type of service */PACK_STRUCT_FLD_8(u8_t _tos); /* 服务类型TOS字段(8) *//* total length */PACK_STRUCT_FIELD(u16_t _len); /* 总长度字段(16)单位字节 *//* identification */PACK_STRUCT_FIELD(u16_t _id); /* 标识字段字段(16) *//* fragment offset field */PACK_STRUCT_FIELD(u16_t _offset); /* 标志字段(3)+分片偏移量字段(13)单位两字 */#define IP_RF 0x8000U/* 标志字段第一位:字段保留 */#define IP_DF 0x4000U/* 标志字段第二位:不发片掩码 */#define IP_MF 0x2000U/* 标志字段第三位:更多分片掩码 */#define IP_OFFMASK 0x1fffU/* 分片偏移量字段的掩码 *//* time to live */PACK_STRUCT_FLD_8(u8_t _ttl); /* TTL字段(8) *//* protocol*/PACK_STRUCT_FLD_8(u8_t _proto); /* 上层协议类型字段(8) *//* checksum */PACK_STRUCT_FIELD(u16_t _chksum); /* 首部校验和字段(16) *//* source and destination IP addresses */PACK_STRUCT_FLD_S(ip4_addr_p_t src); /* 源IP字段(32) */PACK_STRUCT_FLD_S(ip4_addr_p_t dest); /* 目的IP字段(32) */} PACK_STRUCT_STRUCT;由于IP首部部分字段的操作涉及到bit,所以lwip也封装出对应的宏操作 。
/* 均为网络字节序 *//* Macros to get struct ip_hdr fields: */#define IPH_V(hdr)((hdr)->_v_hl >> 4) /* 获取版本号 */#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f) /* 获取首部长度字段值 */#define IPH_HL_BYTES(hdr) ((u8_t)(IPH_HL(hdr) * 4)) /* 获取首部长度,单位字节 */#define IPH_TOS(hdr) ((hdr)->_tos) /* 获取服务类型TOS */#define IPH_LEN(hdr) ((hdr)->_len) /* 获取IP数据报总长度 */#define IPH_ID(hdr) ((hdr)->_id) /* 获取标识字段 */#define IPH_OFFSET(hdr) ((hdr)->_offset) /* 获取标志字段+分片偏移量字段 */#define IPH_OFFSET_BYTES(hdr) ((u16_t)((lwip_ntohs(IPH_OFFSET(hdr)) & IP_OFFMASK) * 8U)) /* 获取分片偏移量,单位字节 */#define IPH_TTL(hdr) ((hdr)->_ttl) /* 获取TTL */#define IPH_PROTO(hdr) ((hdr)->_proto) /* 获取协议类型 */#define IPH_CHKSUM(hdr) ((hdr)->_chksum) /* 获取首部校验和字段 *//* Macros to set struct ip_hdr fields: */#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (u8_t)((((v) << 4) | (hl))) /* 设置版本号 */#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos) /* 设置服务类型TOS */#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) /* 设置总长度字段值 */#define IPH_ID_SET(hdr, id) (hdr)->_id = (id) /* 设置标识 */#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) /* 设置标志字段+分片偏移量字段 */#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl) /* 设置TTL */#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto) /* 设置协议类型 */#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) /* 设置首部校验和 */9.5 网卡路由9.5.1 路由网卡匹配从官方源码看 , 匹配网卡的流程:
ip4_route_src()
  • 先函数LWIP_HOOK_IP4_ROUTE_SRC()匹配 。
  • 然后到ip4_route()基函数匹配 。
9.5.2 路由网卡匹配基函数ip4_route()