废除 tfe-kmod, tfe 直接与 kni 通信

* 新增 enable_kni_v3=1 配置项
	* develop_build_release 分支关闭 ASAN 检测
	* 修正根据 CMSG 恢复 TCP 链接时没有正确填写 TCP 时间戳启用选项的问题
This commit is contained in:
luwenpeng
2021-03-08 17:33:17 +08:00
parent 1c37ae746d
commit 1fe60d2428
21 changed files with 1387 additions and 25 deletions

245
common/src/tfe_pkt_util.cpp Normal file
View File

@@ -0,0 +1,245 @@
#include <string.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <linux/tcp.h>
#include <tfe_utils.h>
#include <tfe_pkt_util.h>
// always success
void tfe_pkt_parse_ipv4_header(const void *a_packet, struct pkt_info *pktinfo)
{
pktinfo->addr_type = ADDR_TYPE_IPV4;
pktinfo->iphdr.v4 = (struct iphdr *)a_packet;
pktinfo->iphdr_len = pktinfo->iphdr.v4->ihl * 4;
pktinfo->ip_totlen = ntohs(pktinfo->iphdr.v4->tot_len);
pktinfo->tcphdr = (struct tcphdr *)((char *)pktinfo->iphdr.v4 + pktinfo->iphdr_len);
pktinfo->tcphdr_len = pktinfo->tcphdr->doff * 4;
pktinfo->data = (char *)pktinfo->tcphdr + pktinfo->tcphdr_len;
pktinfo->data_len = pktinfo->ip_totlen - pktinfo->iphdr_len - pktinfo->tcphdr_len;
pktinfo->parse_failed = 0;
}
// check pktinfo->parse_failed for status
void tfe_pkt_parse_ipv6_header(const void *a_packet, struct pkt_info *pktinfo)
{
pktinfo->addr_type = ADDR_TYPE_IPV6;
pktinfo->iphdr.v6 = (struct ip6_hdr *)a_packet;
pktinfo->ip_totlen = ntohs(pktinfo->iphdr.v6->ip6_ctlun.ip6_un1.ip6_un1_plen) + sizeof(struct ip6_hdr);
uint8_t next_hdr_type = pktinfo->iphdr.v6->ip6_ctlun.ip6_un1.ip6_un1_nxt;
char *next_hdr_ptr = (char *)pktinfo->iphdr.v6 + sizeof(struct ip6_hdr);
int skip_len = 0;
while (1)
{
switch(next_hdr_type)
{
case IPPROTO_TCP:
//parse tcphdr
pktinfo->iphdr_len = next_hdr_ptr - (char *)a_packet;
pktinfo->tcphdr = (struct tcphdr *)next_hdr_ptr;
pktinfo->tcphdr_len = pktinfo->tcphdr->doff * 4;
pktinfo->data = (char *)pktinfo->tcphdr + pktinfo->tcphdr_len;
pktinfo->data_len = pktinfo->ip_totlen - pktinfo->iphdr_len - pktinfo->tcphdr_len;
pktinfo->parse_failed = 0;
return;
case IPPROTO_HOPOPTS: /* fall through */
case IPPROTO_ROUTING: /* fall through */
case IPPROTO_AH: /* fall through */
case IPPROTO_DSTOPTS: /* fall through */
skip_len = (*(next_hdr_ptr + 1)) * 8 + 8;
next_hdr_type = *next_hdr_ptr;
next_hdr_ptr += skip_len;
break;
case IPPROTO_NONE: /* fall through */
default:
pktinfo->parse_failed = 1;
return;
}
}
}
uint16_t tfe_pkt_checksum_ip(const void *buf, size_t hdr_len)
{
unsigned long sum = 0;
const uint16_t *ip1;
ip1 = (const uint16_t *)buf;
while (hdr_len > 1)
{
sum += *ip1++;
if (sum & 0x80000000)
{
sum = (sum & 0xFFFF) + (sum >> 16);
}
hdr_len -= 2;
}
while (sum >> 16)
{
sum = (sum & 0xFFFF) + (sum >> 16);
}
return (~sum);
}
uint16_t tfe_pkt_checksum_tcp_v4(const void *_buf, size_t len, in_addr_t src_addr, in_addr_t dest_addr)
{
const uint16_t *buf = (u_int16_t *)_buf;
uint16_t *ip_src = (uint16_t *)&src_addr;
uint16_t *ip_dst = (uint16_t *)&dest_addr;
uint32_t sum;
size_t length = len;
// Calculate the sum
sum = 0;
while (len > 1)
{
sum += *buf++;
if (sum & 0x80000000)
{
sum = (sum & 0xFFFF) + (sum >> 16);
}
len -= 2;
}
if (len & 1)
{
// Add the padding if the packet lenght is odd
sum += *((uint8_t *)buf);
}
// Add the pseudo-header
sum += *(ip_src++);
sum += *ip_src;
sum += *(ip_dst++);
sum += *ip_dst;
sum += htons(IPPROTO_TCP);
sum += htons(length);
// Add the carries
while (sum >> 16)
{
sum = (sum & 0xFFFF) + (sum >> 16);
}
// Return the one's complement of sum
return ((uint16_t)(~sum));
}
uint16_t tfe_pkt_checksum_tcp_v6(const void *_buf, size_t len, struct in6_addr src_addr, struct in6_addr dest_addr)
{
const uint16_t *buf = (u_int16_t *)_buf;
uint16_t *ip_src = (uint16_t *)&src_addr;
uint16_t *ip_dst = (uint16_t *)&dest_addr;
uint32_t sum;
size_t length = len;
int i = 0;
// Calculate the sum
sum = 0;
while (len > 1)
{
sum += *buf++;
if (sum & 0x80000000)
{
sum = (sum & 0xFFFF) + (sum >> 16);
}
len -= 2;
}
if (len & 1)
{
// Add the padding if the packet lenght is odd
sum += *((uint8_t *)buf);
}
// Add the pseudo-header
for (i = 0; i < 8; i++)
{
sum += *ip_src;
ip_src++;
}
for ( i = 0; i < 8; i++)
{
sum += *ip_dst;
ip_dst++;
}
sum += htons(IPPROTO_TCP);
sum += htons(length);
// Add the carries
while (sum >> 16)
{
sum = (sum & 0xFFFF) + (sum >> 16);
}
// Return the one's complement of sum
return ((uint16_t)(~sum));
}
/*
* 目的:在 IP 的 Payload ${data} 中查找指定的 tcp ${option}。
*
* 已知:
* 1.所有的 tcp options 所占的存储空间的长度为 ${optlen}
* 2.${out_opt_buff} 输出缓冲区的最大长度为 ${out_opt_buff_size}
*
* 返回值:
* 1.若找到指定的 tcp ${option} 则返回 1并将该 tcp ${option} 对应的值拷贝到 ${out_opt_buff} 中,并将拷贝的值所占的存储空间记录到 ${out_optlen} 中
* 2.若未找到指定的 tcp ${option} 则返回 0
*/
int tfe_pkt_find_tcp_option(uint8_t option, char *data, unsigned int opts_total_len, uint8_t *out_opt_len, char *out_opt_buff, unsigned int out_opt_buff_size)
{
const uint8_t *op;
unsigned int i;
if (!opts_total_len)
return 0;
op = (uint8_t *)(data + sizeof(struct tcphdr));
for (i = 0; i < opts_total_len;)
{
uint8_t __optlen;
uint8_t __valuelen;
if (op[i] == option)
{
if (op[i] < 2)
{
*out_opt_len = 0;
return 1;
}
__optlen = op[i + 1];
if (__optlen <= 2)
{
TFE_LOG_ERROR(g_default_logger, "failed at parse tcp options, tcp option length must be larger than 2, but the value is %u", __optlen);
return 0;
}
__valuelen = __optlen - 2;
if (__valuelen > out_opt_buff_size)
{
TFE_LOG_ERROR(g_default_logger, "failed at parse tcp options, tcp option length is larger than input buffer");
return 0;
}
*out_opt_len = __valuelen;
memcpy(out_opt_buff, &op[i + 2], __valuelen);
return 1;
}
if (op[i] < 2)
i++;
else
i += op[i + 1] ?: 1;
}
return 0;
}