ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest)
分片函数
/* Save original offset / tmp = lwip_ntohs(IPH_OFFSET(iphdr)); ofo = tmp & IP_OFFMASK; / already fragmented? if so, the last fragment we create must have MF, too */ mf_set = tmp & IP_MF; 保存分片标志
/* Set new offset and MF flag / tmp = (IP_OFFMASK & (ofo)); if (!last || mf_set) { / the last fragment has MF set if the input frame had it */ tmp = tmp | IP_MF; } 如果这个ip包已经是分片 那么所有的分片都要置1 如果这个是一个分片包但是 确实最后一个 ,那么它的分片的最后一个置0 表示这个分片的结束
const u16_t nfb = (u16_t)((netif->mtu - IP_HLEN) / 8); fragsize = LWIP_MIN(left, (u16_t)(nfb * 8)); 可见ip头中的13bit offset 是以8bytes为单位,记录的是这个ip包的数据相对 被分片的ip包 的偏移
if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) { struct pbuf * ip4_reass(struct pbuf *p)
判断包是分片包就调用ip4_reass 将包组装起来
reassdatagrams 将需要组装的不同id分片包 使用链表连接起来,然后遍历找到这个分片包所属的链表项 或者新创建一个加入链表。
找到之后调用 /* find the right place to insert this pbuf / / @todo: trim pbufs if fragments are overlapping */ valid = ip_reass_chain_frag_into_datagram_and_validate(ipr, p, is_last); if (valid == IP_REASS_VALIDATE_PBUF_DROPPED) { goto nullreturn_ipr; } 将其放入所在包项 然后函数内检查当前id的分片包是否收完
如果收完 就将修复所有pbuf然后将整个包返回给ip4_input
/* chain together the pbufs contained within the reass_data list. */
while (r != NULL) {
iprh = (struct ip_reass_helper *)r->payload;
/* hide the ip header for every succeeding fragment */
pbuf_remove_header(r, IP_HLEN);
pbuf_cat(p, r);
r = iprh->next_pbuf;
}
/* find the previous entry in the linked list */
if (ipr == reassdatagrams) {
ipr_prev = NULL;
} else {
for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) {
if (ipr_prev->next == ipr) {
break;
}
}
}
这一段就是将真个包pbuf链上的phuf进行指针移动即将payload加上iphdr大小一般20字节
|