1 IP协议的输出处理
1.1 原理介绍
IP数据包的封装:
IP包头部数据格式(RFC791):
1.2 代码实现
代码组织如下:
xnet_tiny.h中添加如下代码:
#define XNET_VERSION_IPV4 4 // IPV4
#define XNET_IP_DEFAULT_TTL 64 // 缺省的IP包TTL值
xnet_err_t xip_out(xnet_protocol_t protocol, xipaddr_t* dest_ip, xnet_packet_t * packet);
xnet_tiny.c中添加如下代码:
/**
* 解析指定的IP地址,如果不在ARP表项中,则发送ARP请求
* @param ipaddr 查找的ip地址
* @param mac_addr 返回的mac地址存储区
* @return XNET_ERR_OK 查找成功,XNET_ERR_NONE 查找失败
*/
xnet_err_t xarp_resolve(const xipaddr_t * ipaddr, uint8_t ** mac_addr) {
if ((arp_entry.state == XARP_ENTRY_OK) && xipaddr_is_equal(ipaddr, &arp_entry.ipaddr)) {
*mac_addr = arp_entry.macaddr;
return XNET_ERR_OK;
}
xarp_make_request(ipaddr);
return XNET_ERR_NONE;
}
/**
* 将IP数据包通过以太网发送出去
* @param dest_ip 目标IP地址
* @param packet 待发送IP数据包
* @return 发送结果
*/
static xnet_err_t ethernet_out (xipaddr_t * dest_ip, xnet_packet_t * packet) {
xnet_err_t err;
uint8_t * mac_addr;
if ((err = xarp_resolve(dest_ip, &mac_addr) == XNET_ERR_OK)) {
return ethernet_out_to(XNET_PROTOCOL_IP, mac_addr, packet);
}
return err;
}
/**
* IP包的输出
* @param protocol 上层协议,ICMP、UDP或TCP
* @param dest_ip
* @param packet
* @return
*/
xnet_err_t xip_out(xnet_protocol_t protocol, xipaddr_t* dest_ip, xnet_packet_t * packet) {
static uint32_t ip_packet_id = 0;
xip_hdr_t * iphdr;
add_header(packet, sizeof(xip_hdr_t));
iphdr = (xip_hdr_t*)packet->data;
iphdr->version = XNET_VERSION_IPV4;
iphdr->hdr_len = sizeof(xip_hdr_t) / 4;
iphdr->tos = 0;
iphdr->total_len = swap_order16(packet->size);
iphdr->id = swap_order16(ip_packet_id);
iphdr->flags_fragment = 0;
iphdr->ttl = XNET_IP_DEFAULT_TTL;
iphdr->protocol = protocol;
memcpy(iphdr->dest_ip, dest_ip->array, XNET_IPV4_ADDR_SIZE);
memcpy(iphdr->src_ip, netif_ipaddr.array, XNET_IPV4_ADDR_SIZE);
iphdr->hdr_checksum = 0;
iphdr->hdr_checksum = checksum16((uint16_t *)iphdr, sizeof(xip_hdr_t), 0, 1);;
ip_packet_id++;
return ethernet_out(dest_ip, packet);
}