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
ff_enable_pcap(const char * dump_path,uint16_t snap_len)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
ff_dump_packets(const char * dump_path,struct rte_mbuf * pkt,uint16_t snap_len,uint32_t f_maxlen)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