在无人问津的渡口,总是开满鲜花。

本节课主要实现将IP数据包添加头部并通过以太网发包的全过程
xnet_tinny.h
声明函数xip_out:
cpp
#define XNET_VERSION_IPV4 4
xnet_err_t xip_out(xnet_protocol_t protocol, xipaddr_t* dest_ip, xnet_packet_t * packet);
xnet_tinny.c
cpp
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->dst_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);
}
由于以太网层面无法直接识别IP地址,还需要实现一下IP地址到MAC地址的转换函数ethernet_out
将IP地址转为MAC地址之后,再调用以太网底层发送函数ethernet_out_to来完成发包
cpp
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;
}
最后实现arp解析函数:xarp_resolve
首先添加错误码XNET_ERR_NONE表示缺少ARP表项
cpp
typedef enum _xnet_err_t
{
XNET_ERR_OK = 0,
XNET_ERR_IO = -1,
XNET_ERR_NONE = -2,
}xnet_err_t;
添加判断两个IP地址整数相同的宏函数
cpp
#define xipaddr_is_equal(addr1, addr2) ((addr1)->addr == (addr2)->addr)
xarp_resolve具体实现:
由于需要返回mac_addr的值,而在ethernet_out中mac_addr是uint8*所以这里mac_addr需要使用二级指针,才能返回解析后的值
cpp
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;
}
最后重新生成解决方案,编译没问题即可

okok,今天的你就到此为止吧,明天还要接着🐺啊!