1 /* 2 * Copyright (C) 2017-2021 THL A29 Limited, a Tencent company. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 */ 26 27 #include <sys/time.h> 28 #include <unistd.h> 29 #include <errno.h> 30 31 #include "ff_dpdk_pcap.h" 32 #define FILE_PATH_LEN 64 33 #define PCAP_FILE_NUM 10 34 35 struct pcap_file_header { 36 uint32_t magic; 37 u_short version_major; 38 u_short version_minor; 39 int32_t thiszone; /* gmt to local correction */ 40 uint32_t sigfigs; /* accuracy of timestamps */ 41 uint32_t snaplen; /* max length saved portion of each pkt */ 42 uint32_t linktype; /* data link type (LINKTYPE_*) */ 43 }; 44 45 struct pcap_pkthdr { 46 uint32_t sec; /* time stamp */ 47 uint32_t usec; /* struct timeval time_t, in linux64: 8*2=16, in cap: 4 */ 48 uint32_t caplen; /* length of portion present */ 49 uint32_t len; /* length this packet (off wire) */ 50 }; 51 52 static __thread FILE* g_pcap_fp = NULL; 53 static __thread uint32_t seq = 0; 54 static __thread uint32_t g_flen = 0; 55 56 int ff_enable_pcap(const char* dump_path, uint16_t snap_len) 57 { 58 char pcap_f_path[FILE_PATH_LEN] = {0}; 59 60 snprintf(pcap_f_path, FILE_PATH_LEN, "%s/cpu%d_%d.pcap", dump_path==NULL?".":dump_path, rte_lcore_id(), seq); 61 g_pcap_fp = fopen(pcap_f_path, "w+"); 62 if (g_pcap_fp == NULL) { 63 rte_exit(EXIT_FAILURE, "Cannot open pcap dump path: %s, errno %d.\n", pcap_f_path, errno); 64 return -1; 65 } 66 g_flen = 0; 67 68 struct pcap_file_header pcap_file_hdr; 69 void* file_hdr = &pcap_file_hdr; 70 71 pcap_file_hdr.magic = 0xA1B2C3D4; 72 pcap_file_hdr.version_major = 0x0002; 73 pcap_file_hdr.version_minor = 0x0004; 74 pcap_file_hdr.thiszone = 0x00000000; 75 pcap_file_hdr.sigfigs = 0x00000000; 76 pcap_file_hdr.snaplen = snap_len; //0x0000FFFF; //65535 77 pcap_file_hdr.linktype = 0x00000001; //DLT_EN10MB, Ethernet (10Mb) 78 79 fwrite(file_hdr, sizeof(struct pcap_file_header), 1, g_pcap_fp); 80 g_flen += sizeof(struct pcap_file_header); 81 82 return 0; 83 } 84 85 int 86 ff_dump_packets(const char* dump_path, struct rte_mbuf* pkt, uint16_t snap_len, uint32_t f_maxlen) 87 { 88 unsigned int out_len = 0, wr_len = 0; 89 struct pcap_pkthdr pcap_hdr; 90 void* hdr = &pcap_hdr; 91 struct timeval ts; 92 char pcap_f_path[FILE_PATH_LEN] = {0}; 93 94 if (g_pcap_fp == NULL) { 95 return -1; 96 } 97 snap_len = pkt->pkt_len < snap_len ? pkt->pkt_len : snap_len; 98 gettimeofday(&ts, NULL); 99 pcap_hdr.sec = ts.tv_sec; 100 pcap_hdr.usec = ts.tv_usec; 101 pcap_hdr.caplen = snap_len; 102 pcap_hdr.len = pkt->pkt_len; 103 fwrite(hdr, sizeof(struct pcap_pkthdr), 1, g_pcap_fp); 104 g_flen += sizeof(struct pcap_pkthdr); 105 106 while(pkt != NULL && out_len <= snap_len) { 107 wr_len = snap_len - out_len; 108 wr_len = wr_len > pkt->data_len ? pkt->data_len : wr_len ; 109 fwrite(rte_pktmbuf_mtod(pkt, char*), wr_len, 1, g_pcap_fp); 110 out_len += wr_len; 111 pkt = pkt->next; 112 } 113 g_flen += out_len; 114 115 if ( g_flen >= f_maxlen ){ 116 fclose(g_pcap_fp); 117 if ( ++seq >= PCAP_FILE_NUM ) 118 seq = 0; 119 120 ff_enable_pcap(dump_path, snap_len); 121 } 122 123 return 0; 124 } 125 126