xref: /f-stack/lib/ff_dpdk_pcap.c (revision 4418919f)
1 /*
2  * Copyright (C) 2017 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