🎈perf(tcpdump.c):

优化greedy模式,放弃使用MESA_dump_seek_to_inner拷贝并构造虚拟的MAC头,使用pcap_compile_nopcap构造DLT_RAW类型的bpf,并调用MESA_net_jump_to_layer_greedy找到最内层IP地址直接使用cbpf进行匹配
This commit is contained in:
yangwei
2020-09-25 21:29:54 +08:00
parent dd465b375a
commit 6429a20dd4
2 changed files with 83 additions and 9 deletions

1
.gitignore vendored
View File

@@ -7,3 +7,4 @@ version.c
config.h config.h
config.log config.log
config.status config.status
tcpdump_mesa

View File

@@ -986,7 +986,7 @@ static int pkt_dump_recv_ack(int connfd)
*/ */
static void *detect_sapp_alive_thread(void *arg) static void *detect_sapp_alive_thread(void *arg)
{ {
int tcp_cmd_fd = (int)arg; int tcp_cmd_fd = (int)(long)arg;
int ret; int ret;
char nouse_buf[1500]; char nouse_buf[1500];
@@ -1156,7 +1156,7 @@ static int MESA_dump_start(unsigned short udp_rcv_port, unsigned short sapp_cmd_
exit(1); exit(1);
} }
pthread_create(&pid, NULL, detect_sapp_alive_thread, (void *)tcp_cmd_fd); pthread_create(&pid, NULL, detect_sapp_alive_thread, (void *)(long)tcp_cmd_fd);
return tcp_cmd_fd; return tcp_cmd_fd;
} }
@@ -1272,6 +1272,7 @@ static void MESA_dump(pcap_handler callback, u_char *pcap_userdata, char *filter
/* 如果有-g参数, 且写了-w, 即需要保存原始包到文件, 则不进行seek操作, /* 如果有-g参数, 且写了-w, 即需要保存原始包到文件, 则不进行seek操作,
只是在没有-w 参数时, 让tcpdump能打印出包的信息, 才进行seek操作. 只是在没有-w 参数时, 让tcpdump能打印出包的信息, 才进行seek操作.
*/ */
#if 0
if((greedy_seek_flag != 0) && (dump_to_file_flag == 0)){ if((greedy_seek_flag != 0) && (dump_to_file_flag == 0)){
inner_pkt_len = MESA_dump_seek_to_inner(pkt_buf, pkt_len); inner_pkt_len = MESA_dump_seek_to_inner(pkt_buf, pkt_len);
if(inner_pkt_len < 0){ if(inner_pkt_len < 0){
@@ -1283,6 +1284,10 @@ static void MESA_dump(pcap_handler callback, u_char *pcap_userdata, char *filter
phony_pcap_hdr.caplen = pkt_len; phony_pcap_hdr.caplen = pkt_len;
phony_pcap_hdr.len = pkt_len; phony_pcap_hdr.len = pkt_len;
} }
#else
phony_pcap_hdr.caplen = pkt_len;
phony_pcap_hdr.len = pkt_len;
#endif
gettimeofday(&phony_pcap_hdr.ts, NULL); gettimeofday(&phony_pcap_hdr.ts, NULL);
callback(pcap_userdata, &phony_pcap_hdr, pkt_buf); /* NOTE: 刷屏模式调用print_packet(); 捕包模式调用: dump_packet() */ callback(pcap_userdata, &phony_pcap_hdr, pkt_buf); /* NOTE: 刷屏模式调用print_packet(); 捕包模式调用: dump_packet() */
@@ -1305,7 +1310,6 @@ done:
#endif #endif
static struct bpf_program fcode; /* lijia modify, 做为全局变量, 其他函数中调用 */ static struct bpf_program fcode; /* lijia modify, 做为全局变量, 其他函数中调用 */
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
@@ -2274,6 +2278,15 @@ main(int argc, char **argv)
if (pcap_setfilter(pd, &fcode) < 0) if (pcap_setfilter(pd, &fcode) < 0)
error("%s", pcap_geterr(pd)); error("%s", pcap_geterr(pd));
} }
else
{
pcap_freecode(&fcode);
if(pcap_compile_nopcap(Oflag, DLT_RAW, &fcode, cmdbuf, 0, netmask) < 0){
printf("Compile pcap filter %s error\n", cmdbuf);
return -1;
}
}
#else #else
if (pcap_setfilter(pd, &fcode) < 0) if (pcap_setfilter(pd, &fcode) < 0)
error("%s", pcap_geterr(pd)); error("%s", pcap_geterr(pd));
@@ -2948,20 +2961,45 @@ dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
static void static void
MESA_dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *raw_pkt) MESA_dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *raw_pkt)
{ {
char modify_pkt_buf[2048]; //char modify_pkt_buf[2048];
int inner_pkt_len; int inner_pkt_len;
++packets_captured; ++packets_captured;
++infodelay; ++infodelay;
memcpy(modify_pkt_buf, raw_pkt, h->caplen >= 2048? 2048:h->caplen); //memcpy(modify_pkt_buf, raw_pkt, h->caplen >= 2048? 2048:h->caplen);
inner_pkt_len = MESA_dump_seek_to_inner(modify_pkt_buf, h->caplen); //inner_pkt_len = MESA_dump_seek_to_inner(modify_pkt_buf, h->caplen);
if(inner_pkt_len < 0){ //if(inner_pkt_len < 0){
// return;
//}
struct mesa_ip4_hdr *ip4hdr_greedy;
struct mesa_ip6_hdr *ip6hdr_greedy;
const unsigned char *inner_iphdr = NULL;
ip4hdr_greedy = (struct mesa_ip4_hdr *)MESA_net_jump_to_layer_greedy(raw_pkt, ADDR_TYPE_MAC, __ADDR_TYPE_IP_PAIR_V4);
if(ip4hdr_greedy)
{
inner_iphdr = (const unsigned char *)ip4hdr_greedy;
inner_pkt_len = h->caplen - ((const u_char *)ip4hdr_greedy - raw_pkt) ;
}
else
{
ip6hdr_greedy = (struct mesa_ip6_hdr *)MESA_net_jump_to_layer_greedy(raw_pkt, ADDR_TYPE_MAC, __ADDR_TYPE_IP_PAIR_V6);
if(ip6hdr_greedy)
{
inner_iphdr = (const unsigned char *)ip6hdr_greedy;
inner_pkt_len = h->caplen - ((const u_char *)ip6hdr_greedy - raw_pkt);
}
else
{
return; return;
} }
}
if(has_bpf_filter_flag != 0){ if(has_bpf_filter_flag != 0){
if(0 == bpf_filter(fcode.bf_insns, if(0 == bpf_filter(fcode.bf_insns,
(const unsigned char *)modify_pkt_buf, inner_pkt_len, inner_pkt_len)){ (const unsigned char *)inner_iphdr, inner_pkt_len, inner_pkt_len)){
return; return;
} }
} }
@@ -2999,6 +3037,7 @@ MESA_dump_print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *
{ {
int inner_pkt_len; int inner_pkt_len;
#if 0
/* 此函数仅用于tcpdump屏幕打印, 直接修改pkt原始包, 避免再copy一次, 节约点CPU */ /* 此函数仅用于tcpdump屏幕打印, 直接修改pkt原始包, 避免再copy一次, 节约点CPU */
inner_pkt_len = MESA_dump_seek_to_inner(pkt, h->caplen); inner_pkt_len = MESA_dump_seek_to_inner(pkt, h->caplen);
if(inner_pkt_len < 0){ if(inner_pkt_len < 0){
@@ -3015,7 +3054,41 @@ MESA_dump_print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *
/* 改为新的修改后的数据包长度 */ /* 改为新的修改后的数据包长度 */
((struct pcap_pkthdr *)h)->caplen = (unsigned int)inner_pkt_len; ((struct pcap_pkthdr *)h)->caplen = (unsigned int)inner_pkt_len;
((struct pcap_pkthdr *)h)->len = (unsigned int)inner_pkt_len; ((struct pcap_pkthdr *)h)->len = (unsigned int)inner_pkt_len;
#else
struct mesa_ip4_hdr *ip4hdr_greedy;
struct mesa_ip6_hdr *ip6hdr_greedy;
const unsigned char *inner_iphdr = NULL;
ip4hdr_greedy = (struct mesa_ip4_hdr *)MESA_net_jump_to_layer_greedy(pkt, ADDR_TYPE_MAC, __ADDR_TYPE_IP_PAIR_V4);
if(ip4hdr_greedy)
{
inner_iphdr = (const unsigned char *)ip4hdr_greedy;
inner_pkt_len = h->caplen - ((const unsigned char *)ip4hdr_greedy - pkt);
}
else
{
ip6hdr_greedy = (struct mesa_ip6_hdr *)MESA_net_jump_to_layer_greedy(pkt, ADDR_TYPE_MAC, __ADDR_TYPE_IP_PAIR_V6);
if(ip6hdr_greedy)
{
inner_iphdr = (const unsigned char *)ip6hdr_greedy;
inner_pkt_len = h->caplen - ((const unsigned char *)ip6hdr_greedy - pkt);
}
else
{
return;
}
}
if (has_bpf_filter_flag != 0)
{
if (0 == bpf_filter(fcode.bf_insns,
(const unsigned char *)inner_iphdr, inner_pkt_len, inner_pkt_len))
{
return;
}
}
#endif
print_packet(user, h, pkt); print_packet(user, h, pkt);
} }