diff --git a/src/mesa_pkt_dump.h b/src/mesa_pkt_dump.h index 7dedb4b..28b8d6b 100644 --- a/src/mesa_pkt_dump.h +++ b/src/mesa_pkt_dump.h @@ -1,46 +1,54 @@ -#ifndef _MESA_PKT_DUMP_H_ -#define _MESA_PKT_DUMP_H_ 1 - -#define MESA_PKT_DUM_H_VER (20181115) - - -/* - 用于DPDK-3.0, PFRING模式下, 驱动独占网卡时, 通过平台实时捕包. -*/ - -#define PKT_DUMP_HDR_MAGIC (0x44554D50) /* 'MESA' */ - -enum pkt_dump_opt_t{ - PKT_DUMP_OPT_RCV_PORT, - PKT_DUMP_OPT_BPF_FILTER, - PKT_DUMP_OPT_DATA_OFFSET, - PKT_DUMP_OPT_THREAD_INDEX, - PKT_DUMP_OPT_ACK, /* sapp返回给tcpdump_mesa的ack包 */ - PKT_DUMP_OPT_PERCEPTIVE, /* 明察秋毫模式, 可以发现丢包数量 */ - PKT_DUMP_OPT_GREEDY_SEEK, /* 偏移到最内层IP, 便于隧道模式下查找BUG */ -}; - -/* 网络序, 便于以后在其他系统如ARM, PowerPC, MIPS上移植 */ -struct pkt_dump_opt{ - unsigned short opt_type; - unsigned short opt_len; - /* actual opt value */ -}__attribute__((packed, aligned(1))); - -/* 启动捕包前的握手信息, 网络序, 便于以后在其他系统如ARM, PowerPC, MIPS上移植 */ -struct pkt_dump_handshake{ - unsigned int magic; /* 固定为0x44554D50, 'DUMP' */ - unsigned int version; /* 用于判定双方的版本号, 一般为数字20170106等 */ - unsigned int opt_num; /* 后续选项的数量, 如本端接收端口号, BPF过滤条件, 捕包offset值等等 */ -}__attribute__((packed, aligned(1))); - - -struct perceptive_info{ - unsigned char thread_id; - unsigned char pad; - unsigned int pkt_seq; /* 从0开始累计, 如果seq有空洞, 说明传输过程中丢了多少包 */ -}__attribute__((packed, aligned(1))); - - -#endif - +#ifndef _MESA_PKT_DUMP_H_ +#define _MESA_PKT_DUMP_H_ 1 + +#define MESA_PKT_DUM_H_VER (20201102) + +/* + 用于DPDK-3.0, PFRING模式下, 驱动独占网卡时, 通过平台实时捕包. +*/ + +#define PKT_DUMP_HDR_MAGIC (0x44554D50) + +/* 支持按Bit位或 */ +enum _pkt_classify{ + PKT_CLASSIFY_IN = 0x01, /* DMAC ascii码值: I */ + PKT_CLASSIFY_FORWARD = 0x02, /* DMAC ascii码值: F */ + PKT_CLASSIFY_INJECT = 0x04, /* DMAC ascii码值: J */ + PKT_CLASSIFY_DROP = 0x08, /* DMAC ascii码值: D */ + PKT_CLASSIFY_ERROR = 0x10, /* DMAC ascii码值: E */ +}; + +enum pkt_dump_opt_t{ + PKT_DUMP_OPT_RCV_PORT, + PKT_DUMP_OPT_BPF_FILTER, + PKT_DUMP_OPT_DATA_OFFSET, + PKT_DUMP_OPT_THREAD_INDEX, + PKT_DUMP_OPT_ACK, /* sapp返回给tcpdump_mesa的ack包 */ + PKT_DUMP_OPT_PERCEPTIVE, /* 明察秋毫模式, 可以发现丢包数量 */ + PKT_DUMP_OPT_GREEDY_SEEK, /* 偏移到最内层IP, 便于隧道模式下查找BUG */ + PKT_DUMP_OPT_CLASSIFY, /* short类型, 捕包来源分类, 定义详见 enum _pkt_classify, 如果没有指定此参数, 默认值为PKT_CLASSIFY_IN */ + PKT_DUMP_OPT_CLASSIFY_WATERMARK, /* char类型, 0或1, 捕包来源水印,将类型值存入dmac,此参数会修改输出的原始包, 慎用, 默认关闭 */ +}; + +/* 网络序, 便于以后在其他系统如ARM, PowerPC, MIPS上移植 */ +struct pkt_dump_opt{ + unsigned short opt_type; + unsigned short opt_len; + /* actual opt value */ +}__attribute__((packed, aligned(1))); + +/* 启动捕包前的握手信息, 网络序, 便于以后在其他系统如ARM, PowerPC, MIPS上移植 */ +struct pkt_dump_handshake{ + unsigned int magic; /* 固定为0x44554D50, 'DUMP' */ + unsigned int version; /* 用于判定双方的版本号, 一般为数字20170106等 */ + unsigned int opt_num; /* 后续选项的数量, 如本端接收端口号, BPF过滤条件, 捕包offset值等等 */ +}__attribute__((packed, aligned(1))); + +struct perceptive_info{ + unsigned char thread_id; + unsigned char pad; + unsigned int pkt_seq; /* 从0开始累计, 如果seq有空洞, 说明传输过程中丢了多少包 */ +}__attribute__((packed, aligned(1))); + +#endif + diff --git a/src/tcpdump.c b/src/tcpdump.c index d244e92..2ead29e 100644 --- a/src/tcpdump.c +++ b/src/tcpdump.c @@ -55,6 +55,8 @@ static int dump_to_file_flag = 0; /* 鏄惁鏈-w 鍙傛暟, 鍘熸湁鏍囧噯鐨刉FileNam static int has_device_flag = 0; /* 鏄惁鏈-i, -r鍙傛暟, 鍘熸湁鏍囧噯鐨刣evice鍙橀噺鏄痬ain()鐨勫眬閮ㄥ彉閲, 涓嶆柟渚夸娇鐢, 浣跨敤姝ゅ彉閲忚〃绀烘槸鍚︿粠鏌愪釜缃戝崱鎹曞寘 */ static int has_bpf_filter_flag = 0; /* 鏄惁鏈夋纭殑BPF杩囨护鏉′欢 */ extern int treat_vlan_as_mac_in_mac_sw; +static short pkt_classify_flag = 0; +static char pkt_classify_watermark_sw = 0; #endif @@ -532,6 +534,8 @@ show_devices_and_exit (void) #if MESA_DUMP #define OPTION_VLAN_AS_MAC_IN_MAC 131 /* 鐭弬鏁颁笉澶熺敤浜, 澧炲姞闀垮弬鏁 */ +#define OPTION_PKT_CLASSIFY 132 /* 澧炲姞闀垮弬鏁板寘绫诲瀷锛屽畾涔夎PKT_DUMP_OPT_CLASSIFY */ +#define OPTION_PKT_CLASSIFY_WATERMARK 133 /* PKT_DUMP_OPT_CLASSIFY_WATERMARK */ #endif static const struct option longopts[] = { @@ -575,6 +579,8 @@ static const struct option longopts[] = { { "version", no_argument, NULL, OPTION_VERSION }, #if MESA_DUMP { "vlan-as-mac-in-mac", no_argument, NULL, OPTION_VLAN_AS_MAC_IN_MAC }, + { "classify", required_argument, NULL, OPTION_PKT_CLASSIFY }, + { "enable_classify_watermark", no_argument, NULL, OPTION_PKT_CLASSIFY_WATERMARK }, #endif { NULL, 0, NULL, 0 } }; @@ -1058,6 +1064,16 @@ static int MESA_dump_start(unsigned short udp_rcv_port, unsigned short sapp_cmd_ opt_num++; } + if(pkt_classify_flag != 0) + { + opt_num++; + } + + if(pkt_classify_watermark_sw != 0) + { + opt_num++; + } + /************** pkt handshake *************/ pkt_hdr.magic = htonl(PKT_DUMP_HDR_MAGIC); pkt_hdr.version = htonl(20180119); /* 涔嬪墠sapp瀵20180119鐗堟湰鍋氫簡涓ユ牸鏍¢獙, 姝ゅ鍚戝悗鍏煎, 鍏堝浐瀹氱敤姝ゅ, 浠ュ悗鏇存柊sapp鍚, 涓嶅啀鏍¢獙鐗堟湰 */ @@ -1155,6 +1171,36 @@ static int MESA_dump_start(unsigned short udp_rcv_port, unsigned short sapp_cmd_ } } + /************** pkt classify *************/ + if(pkt_classify_flag != 0){ + short t = pkt_classify_flag; + opt.opt_type = htons(PKT_DUMP_OPT_CLASSIFY); + opt.opt_len = htons(sizeof(short)); + ret = write(tcp_cmd_fd, &opt, sizeof(opt)); + if (ret < 0) + { + printf("connection down!\n"); + exit(1); + } + t = htons(t); + ret = write(tcp_cmd_fd, &t, sizeof(short)); + if (ret < 0) + { + printf("connection down!\n"); + exit(1); + } + } + /************** pkt classify watermark*************/ + if(pkt_classify_watermark_sw != 0){ + opt.opt_type = htons(PKT_DUMP_OPT_CLASSIFY_WATERMARK); + opt.opt_len = 0; + ret = write(tcp_cmd_fd, &opt, sizeof(opt)); + if(ret < 0){ + printf("connection down!\n"); + exit(1); + } + } + /********** after send opt, start recv sapp ACK *******/ if(pkt_dump_recv_ack(tcp_cmd_fd) < 0){ printf("connection down!\n"); @@ -1312,6 +1358,42 @@ done: return; } + + + +static short get_pkt_classify_optarg(const char *optarg) +{ + char *p_arg = strdup(optarg); + short pkt_classify_flag = 0; + char *section, *save_ptr; + section = strtok_r(p_arg, "|", &save_ptr); + if(section == NULL) + { + section = p_arg; + } + do { + if (strcasecmp(section, "in") == 0) + pkt_classify_flag |= PKT_CLASSIFY_IN; + else if (strcasecmp(section, "forward") == 0) + pkt_classify_flag |= PKT_CLASSIFY_FORWARD; + else if (strcasecmp(section, "inject") == 0) + pkt_classify_flag |= PKT_CLASSIFY_INJECT; + else if (strcasecmp(section, "drop") == 0) + pkt_classify_flag |= PKT_CLASSIFY_DROP; + else if (strcasecmp(section, "error") == 0) + pkt_classify_flag |= PKT_CLASSIFY_ERROR; + else + { + return 0; + } + + } + while((section=strtok_r(NULL, "|", &save_ptr))); + + free(p_arg); + return pkt_classify_flag; +} + #endif static struct bpf_program fcode; /* lijia modify, 鍋氫负鍏ㄥ眬鍙橀噺, 鍏朵粬鍑芥暟涓皟鐢 */ @@ -1845,6 +1927,16 @@ main(int argc, char **argv) case OPTION_VLAN_AS_MAC_IN_MAC: treat_vlan_as_mac_in_mac_sw = 1; break; + case OPTION_PKT_CLASSIFY: + pkt_classify_flag = get_pkt_classify_optarg(optarg); + if(pkt_classify_flag == 0) + { + error("unknown classify `%s', must be in|forward|inject|drop|error", optarg); + } + break; + case OPTION_PKT_CLASSIFY_WATERMARK: + pkt_classify_watermark_sw = 1; + break; #endif default: @@ -3243,6 +3335,10 @@ print_usage(void) "\t\t[ -P port ] to assign sapp recv command port.\n"); (void)fprintf(stderr, "\t\t[ --vlan-as-mac-in-mac ] force VLAN to be analysed as MAC-IN-MAC format.\n"); + (void)fprintf(stderr, +"\t\t[ --classify in|forward|inject|drop|error ]. specify packet capture classifier by direction and operation\n"); + (void)fprintf(stderr, +"\t\t[ --enable_classify_watermark ]. enable record classify type in src mac address\n"); #endif } /*