suricata
source-pcap.c
Go to the documentation of this file.
1/* Copyright (C) 2020 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "../suricata-common.h"
19#include "../util-unittest.h"
20
21static uint32_t Upper32(uint64_t value)
22{
23 /* uint64_t -> uint32_t is defined behaviour. It slices lower 32bits. */
24 return value >> 32;
25}
26static uint32_t Lower32(uint64_t value)
27{
28 /* uint64_t -> uint32_t is defined behaviour. It slices lower 32bits. */
29 return value;
30}
31
32/* Structured test data to make it easier on my eyes */
33typedef struct TestData_ {
34 uint64_t last; /* internal 64bit counter to drag along */
35 u_int current; /* 32bit pcap stat */
37
38static int UpdatePcapStatsValue64NoChange01(void)
39{
40 /*
41 * No change in counter values.
42 * Last count is within first 32bit range, i.e. same as pcap_stat range.
43 */
44 TestData data[] = {{.last = 0, .current = 0},
45 {.last = 12345, .current = 12345},
46 {.last = (uint64_t)UINT32_MAX, .current = UINT_MAX}};
47
48 for (size_t i = 0; i < ARRAY_SIZE(data); ++i) {
49 FAIL_IF_NOT(data[i].last == data[i].current);
50
51 UpdatePcapStatsValue64(&data[i].last, data[i].current);
52 FAIL_IF_NOT(data[i].last == data[i].current);
53 }
54
55 PASS;
56}
57
58static int UpdatePcapStatsValue64NoChange02(void)
59{
60 /*
61 * No change in counter values.
62 * Last count is outside 32bits range.
63 */
64 TestData data[] = {{.last = (2ull << 32) + 0, .current = 0},
65 {.last = (3ull << 32) + 12345, .current = 12345},
66 {.last = (3ull << 32) + (uint64_t)UINT32_MAX, .current = UINT_MAX},
67 {.last = UINT64_MAX, .current = UINT_MAX}};
68
69 for (size_t i = 0; i < ARRAY_SIZE(data); ++i) {
70 uint32_t upper = Upper32(data[i].last);
71 FAIL_IF_NOT(Lower32(data[i].last) == data[i].current);
72
73 UpdatePcapStatsValue64(&data[i].last, data[i].current);
74 FAIL_IF_NOT(Lower32(data[i].last) == data[i].current);
75 FAIL_IF_NOT(Upper32(data[i].last) == upper);
76 }
77
78 PASS;
79}
80
81static int UpdatePcapStatsValue64NoOverflow01(void)
82{
83 /*
84 * Non-overflowing counter value is simply taken over in lower 32bits.
85 * Last count is within first 32bit range, i.e. same as pcap_stat range.
86 * Also test edges and simple +1.
87 */
88 TestData data[] = {{.last = 0, .current = 1},
89 {.last = 12345, .current = 34567},
90 {.last = (uint64_t)UINT32_MAX - 1, .current = UINT_MAX}};
91
92 for (size_t i = 0; i < ARRAY_SIZE(data); ++i) {
93 FAIL_IF_NOT(data[i].last < data[i].current);
94
95 UpdatePcapStatsValue64(&data[i].last, data[i].current);
96 FAIL_IF_NOT(data[i].last == data[i].current);
97 }
98
99 PASS;
100}
101
102static int UpdatePcapStatsValue64NoOverflow02(void)
103{
104 /*
105 * Non-overflowing counter value is simply taken over in lower 32bits.
106 * Last count is outside 32bits range.
107 */
108 TestData data[] = {{.last = (2ull << 32) + 0, .current = 1},
109 {.last = (3ull << 32) + 12345, .current = 34567},
110 {.last = UINT64_MAX - 1, .current = UINT_MAX}};
111
112 for (size_t i = 0; i < ARRAY_SIZE(data); ++i) {
113 uint32_t upper = Upper32(data[i].last);
114 FAIL_IF_NOT(Lower32(data[i].last) < data[i].current);
115
116 UpdatePcapStatsValue64(&data[i].last, data[i].current);
117 FAIL_IF_NOT(Lower32(data[i].last) == data[i].current);
118 FAIL_IF_NOT(Upper32(data[i].last) == upper);
119 }
120
121 PASS;
122}
123
124static int UpdatePcapStatsValue64Overflow01(void)
125{
126 /*
127 * Overflowing counter value is simply taken over in lower 32bits.
128 * Last count is within first 32bit range, i.e. same as pcap_stat range.
129 */
130 TestData data[] = {{.last = 1, .current = 0},
131 {.last = 12345, .current = 22}, {.last = 12345, .current = 12344},
132 {.last = (uint64_t)UINT32_MAX, .current = UINT_MAX - 1}};
133
134 for (size_t i = 0; i < ARRAY_SIZE(data); ++i) {
135 FAIL_IF_NOT(data[i].last > data[i].current);
136
137 UpdatePcapStatsValue64(&data[i].last, data[i].current);
138 FAIL_IF_NOT(Lower32(data[i].last) == data[i].current);
139 FAIL_IF_NOT(Upper32(data[i].last) == 1); /* wrap around */
140 }
141
142 PASS;
143}
144
145static int UpdatePcapStatsValue64Overflow02(void)
146{
147 /*
148 * Overflowing counter value is simply taken over in lower 32bits.
149 * Last count is outside 32bits range.
150 */
151 TestData data[] = {{.last = (2ull << 32) + 1, .current = 0},
152 {.last = (3ull << 32) + 12345, .current = 22},
153 {.last = (3ull << 32) + 12345, .current = 12344},
154 {.last = UINT64_MAX, .current = UINT_MAX - 1}};
155
156 for (size_t i = 0; i < ARRAY_SIZE(data); ++i) {
157 uint32_t upper = Upper32(data[i].last);
158 FAIL_IF_NOT(Lower32(data[i].last) > data[i].current);
159
160 UpdatePcapStatsValue64(&data[i].last, data[i].current);
161 FAIL_IF_NOT(Lower32(data[i].last) == data[i].current);
162 FAIL_IF_NOT(Upper32(data[i].last) == upper + 1); /* wrap around */
163 }
164
165 PASS;
166}
167
168static int UpdatePcapStatsValue64Overflow03(void)
169{
170 /*
171 * Overflowing counter value is simply taken over in lower 32bits.
172 * Edge cases where upper32 bit wrap around to 0.
173 */
174 TestData data[] = {{.last = UINT64_MAX, .current = 0},
175 {.last = UINT64_MAX, .current = 3333}};
176
177 for (size_t i = 0; i < ARRAY_SIZE(data); ++i) {
178 FAIL_IF_NOT(Lower32(data[i].last) > data[i].current);
179
180 UpdatePcapStatsValue64(&data[i].last, data[i].current);
181 FAIL_IF_NOT(Lower32(data[i].last) == data[i].current);
182 FAIL_IF_NOT(Upper32(data[i].last) == 0); /* wrap around */
183 }
184
185 PASS;
186}
187
188static int UpdatePcapStats64Assorted01(void)
189{
190 /*
191 * Test that all fields of the struct are correctly updated.
192 *
193 * Full testing of value behaviour is done in UpdatePcapStatsValue64...()
194 * tests.
195 */
196 PcapStats64 last = {.ps_recv = 0, .ps_drop = 1234, .ps_ifdrop = 8765};
197 struct pcap_stat current = {
198 .ps_recv = 12, .ps_drop = 2345, .ps_ifdrop = 9876};
199
200 // test setup sanity check
201 FAIL_IF_NOT(last.ps_recv < current.ps_recv);
202 FAIL_IF_NOT(last.ps_drop < current.ps_drop);
203 FAIL_IF_NOT(last.ps_ifdrop < current.ps_ifdrop);
204
205 UpdatePcapStats64(&last, &current);
206
207 FAIL_IF_NOT(last.ps_recv == current.ps_recv);
208 FAIL_IF_NOT(last.ps_drop == current.ps_drop);
209 FAIL_IF_NOT(last.ps_ifdrop == current.ps_ifdrop);
210
211 PASS;
212}
213
214static void SourcePcapRegisterStatsTests(void)
215{
216 UtRegisterTest("UpdatePcapStatsValue64NoChange01",
217 UpdatePcapStatsValue64NoChange01);
218 UtRegisterTest("UpdatePcapStatsValue64NoChange02",
219 UpdatePcapStatsValue64NoChange02);
220 UtRegisterTest("UpdatePcapStatsValue64NoOverflow01",
221 UpdatePcapStatsValue64NoOverflow01);
222 UtRegisterTest("UpdatePcapStatsValue64NoOverflow02",
223 UpdatePcapStatsValue64NoOverflow02);
224 UtRegisterTest("UpdatePcapStatsValue64Overflow01",
225 UpdatePcapStatsValue64Overflow01);
226 UtRegisterTest("UpdatePcapStatsValue64Overflow02",
227 UpdatePcapStatsValue64Overflow02);
228 UtRegisterTest("UpdatePcapStatsValue64Overflow03",
229 UpdatePcapStatsValue64Overflow03);
230
231 UtRegisterTest("UpdatePcapStats64Assorted01", UpdatePcapStats64Assorted01);
232}
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
64bit pcap stats counters.
Definition source-pcap.c:63
uint64_t ps_recv
Definition source-pcap.c:64
uint64_t ps_drop
Definition source-pcap.c:65
uint64_t ps_ifdrop
Definition source-pcap.c:66
u_int current
Definition source-pcap.c:35
uint64_t last
Definition source-pcap.c:34
#define ARRAY_SIZE(arr)
struct TestData_ TestData