• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OISF / suricata / 23374838686

21 Mar 2026 07:29AM UTC coverage: 59.341% (-20.0%) from 79.315%
23374838686

Pull #15075

github

web-flow
Merge 90b4e834f into 6587e363a
Pull Request #15075: Stack 8001 v16.4

38 of 70 new or added lines in 10 files covered. (54.29%)

34165 existing lines in 563 files now uncovered.

119621 of 201584 relevant lines covered (59.34%)

650666.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

2.14
/src/util-device.c
1
/* Copyright (C) 2011-2021 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 "conf.h"
20
#include "util-device-private.h"
21
#include "util-ioctl.h"
22
#include "util-misc.h"
23
#include "util-dpdk.h"
24

25
#include "device-storage.h"
26
#include "util-debug.h"
27
#include "util-affinity.h"
28

UNCOV
29
#define MAX_DEVNAME 10
×
30

31
static LiveDevStorageId g_bypass_storage_id = { .id = -1 };
32

33
/**
34
 * \file
35
 *
36
 * \author Eric Leblond <eric@regit.org>
37
 *
38
 *  \brief Utility functions to handle device list
39
 */
40

41
/** private device list */
42
static TAILQ_HEAD(, LiveDevice_) live_devices =
43
    TAILQ_HEAD_INITIALIZER(live_devices);
44

45
typedef struct LiveDeviceName_ {
46
    char *dev; /**< the device (e.g. "eth0") */
47
    TAILQ_ENTRY(LiveDeviceName_) next;
48
} LiveDeviceName;
49

50
/** List of the name of devices
51
 *
52
 * As we don't know the size of the Storage on devices
53
 * before the parsing we need to wait and use this list
54
 * to create later the LiveDevice via LiveDeviceFinalize()
55
 */
56
static TAILQ_HEAD(, LiveDeviceName_) pre_live_devices =
57
    TAILQ_HEAD_INITIALIZER(pre_live_devices);
58

59
typedef struct BypassInfo_ {
60
    SC_ATOMIC_DECLARE(uint64_t, ipv4_hash_count);
61
    SC_ATOMIC_DECLARE(uint64_t, ipv4_fail);
62
    SC_ATOMIC_DECLARE(uint64_t, ipv4_success);
63
    SC_ATOMIC_DECLARE(uint64_t, ipv6_hash_count);
64
    SC_ATOMIC_DECLARE(uint64_t, ipv6_fail);
65
    SC_ATOMIC_DECLARE(uint64_t, ipv6_success);
66
} BypassInfo;
67

68
/** if set to 0 when we don't have real devices */
69
static int live_devices_stats = 1;
70

71

72
static int LiveSafeDeviceName(const char *devname,
73
                              char *newdevname, size_t destlen);
74

75
static int g_live_devices_disable_offloading = 1;
76

77
void LiveSetOffloadDisable(void)
78
{
2✔
79
    g_live_devices_disable_offloading = 1;
2✔
80
}
2✔
81

82
void LiveSetOffloadWarn(void)
83
{
×
84
    g_live_devices_disable_offloading = 0;
×
85
}
×
86

87
int LiveGetOffload(void)
UNCOV
88
{
×
UNCOV
89
    return g_live_devices_disable_offloading;
×
UNCOV
90
}
×
91

92
/**
93
 *  \brief Add a device for monitoring
94
 *
95
 * To be used during option parsing. When a device has
96
 * to be created during runmode init, use LiveRegisterDevice()
97
 *
98
 *  \param dev string with the device name
99
 *
100
 *  \retval 0 on success.
101
 *  \retval -1 on failure.
102
 */
103
int LiveRegisterDeviceName(const char *dev)
UNCOV
104
{
×
UNCOV
105
    LiveDeviceName *pd = NULL;
×
106

UNCOV
107
    pd = SCCalloc(1, sizeof(LiveDeviceName));
×
UNCOV
108
    if (unlikely(pd == NULL)) {
×
109
        return -1;
×
110
    }
×
111

UNCOV
112
    pd->dev = SCStrdup(dev);
×
UNCOV
113
    if (unlikely(pd->dev == NULL)) {
×
114
        SCFree(pd);
×
115
        return -1;
×
116
    }
×
117

UNCOV
118
    TAILQ_INSERT_TAIL(&pre_live_devices, pd, next);
×
119

UNCOV
120
    SCLogDebug("Device \"%s\" registered.", dev);
×
UNCOV
121
    return 0;
×
UNCOV
122
}
×
123

124
/**
125
 *  \brief Add a pcap device for monitoring and create structure
126
 *
127
 *  \param dev string with the device name
128
 *
129
 *  \retval 0 on success.
130
 *  \retval -1 on failure.
131
 */
132
int LiveRegisterDevice(const char *dev)
UNCOV
133
{
×
UNCOV
134
    LiveDevice *pd = NULL;
×
135

UNCOV
136
    pd = SCCalloc(1, sizeof(LiveDevice) + LiveDevStorageSize());
×
UNCOV
137
    if (unlikely(pd == NULL)) {
×
138
        return -1;
×
139
    }
×
140

UNCOV
141
    int id = LiveGetDeviceCount();
×
UNCOV
142
    if (id > UINT16_MAX) {
×
143
        SCFree(pd);
×
144
        return -1;
×
145
    }
×
146

UNCOV
147
    pd->dev = SCStrdup(dev);
×
UNCOV
148
    if (unlikely(pd->dev == NULL)) {
×
149
        SCFree(pd);
×
150
        return -1;
×
151
    }
×
152
    /* create a short version to be used in thread names */
UNCOV
153
    LiveSafeDeviceName(pd->dev, pd->dev_short, sizeof(pd->dev_short));
×
154

UNCOV
155
    SC_ATOMIC_INIT(pd->pkts);
×
UNCOV
156
    SC_ATOMIC_INIT(pd->drop);
×
UNCOV
157
    SC_ATOMIC_INIT(pd->invalid_checksums);
×
UNCOV
158
    pd->id = (uint16_t)id;
×
UNCOV
159
    TAILQ_INSERT_TAIL(&live_devices, pd, next);
×
160

UNCOV
161
    SCLogDebug("Device \"%s\" registered and created.", dev);
×
UNCOV
162
    return 0;
×
UNCOV
163
}
×
164

165
/**
166
 *  \brief Get the number of registered devices
167
 *
168
 *  \retval cnt the number of registered devices
169
 */
170
int LiveGetDeviceCount(void)
UNCOV
171
{
×
UNCOV
172
    int i = 0;
×
UNCOV
173
    LiveDevice *pd;
×
174

UNCOV
175
    TAILQ_FOREACH(pd, &live_devices, next) {
×
UNCOV
176
        i++;
×
UNCOV
177
    }
×
178

UNCOV
179
    return i;
×
UNCOV
180
}
×
181

182
int LiveGetDeviceCountWithoutAssignedThreading(void)
UNCOV
183
{
×
UNCOV
184
    int i = 0;
×
UNCOV
185
    LiveDevice *pd;
×
186

UNCOV
187
    TAILQ_FOREACH (pd, &live_devices, next) {
×
UNCOV
188
        if (GetAffinityTypeForNameAndIface("worker-cpu-set", pd->dev) == NULL) {
×
UNCOV
189
            i++;
×
UNCOV
190
        }
×
UNCOV
191
    }
×
192

UNCOV
193
    return i;
×
UNCOV
194
}
×
195

196
/**
197
 *  \brief Get a pointer to the device name at idx
198
 *
199
 *  \param number idx of the device in our list
200
 *
201
 *  \retval ptr pointer to the string containing the device
202
 *  \retval NULL on error
203
 */
204
const char *LiveGetDeviceName(int number)
UNCOV
205
{
×
UNCOV
206
    int i = 0;
×
UNCOV
207
    LiveDevice *pd;
×
208

UNCOV
209
    TAILQ_FOREACH(pd, &live_devices, next) {
×
UNCOV
210
        if (i == number) {
×
UNCOV
211
            return pd->dev;
×
UNCOV
212
        }
×
213

UNCOV
214
        i++;
×
UNCOV
215
    }
×
216

217
    return NULL;
×
UNCOV
218
}
×
219

220
/** \internal
221
 *  \brief Shorten a device name that is to long
222
 *
223
 *  \param device name from config and destination for modified
224
 *
225
 *  \retval None, is added to destination char *newdevname
226
 */
227
static int LiveSafeDeviceName(const char *devname, char *newdevname, size_t destlen)
UNCOV
228
{
×
UNCOV
229
    const size_t devnamelen = strlen(devname);
×
230

231
    /* If we have to shorten the interface name */
UNCOV
232
    if (devnamelen > MAX_DEVNAME) {
×
233
        /* special mode for DPDK pci addresses */
UNCOV
234
        if (devnamelen >= 5 && strncmp(devname, "0000:", 5) == 0) {
×
235
            strlcpy(newdevname, devname + 5, destlen);
×
236
            return 0;
×
237
        }
×
238

239
        /* IF the dest length is over 10 chars long it will not do any
240
         * good for the shortening. The shortening is done due to the
241
         * max length of pthread names (15 chars) and we use 3 chars
242
         * for the threadname indicator eg. "W#-" and one-two chars for
243
         * the thread number. And if the destination buffer is under
244
         * 6 chars there is no point in shortening it since we must at
245
         * least enter two periods (.) into the string.
246
         */
UNCOV
247
        if ((destlen-1) > 10 || (destlen-1) < 6) {
×
248
            return 1;
×
249
        }
×
250

UNCOV
251
        ShortenString(devname, newdevname, destlen, '~');
×
252

UNCOV
253
        SCLogInfo("%s: shortening device name to %s", devname, newdevname);
×
UNCOV
254
    } else {
×
UNCOV
255
        strlcpy(newdevname, devname, destlen);
×
UNCOV
256
    }
×
UNCOV
257
    return 0;
×
UNCOV
258
}
×
259

260
/**
261
 *  \brief Get a pointer to the device at idx
262
 *
263
 *  \param number idx of the device in our list
264
 *
265
 *  \retval ptr pointer to the string containing the device
266
 *  \retval NULL on error
267
 */
268
LiveDevice *LiveGetDevice(const char *name)
UNCOV
269
{
×
UNCOV
270
    LiveDevice *pd;
×
271

UNCOV
272
    if (name == NULL) {
×
273
        SCLogWarning("Name of device should not be null");
×
274
        return NULL;
×
275
    }
×
276

UNCOV
277
    TAILQ_FOREACH(pd, &live_devices, next) {
×
UNCOV
278
        if (!strcmp(name, pd->dev)) {
×
UNCOV
279
            return pd;
×
UNCOV
280
        }
×
UNCOV
281
    }
×
282

283
    return NULL;
×
UNCOV
284
}
×
285

286
const char *LiveGetShortName(const char *dev)
UNCOV
287
{
×
UNCOV
288
    LiveDevice *live_dev = LiveGetDevice(dev);
×
UNCOV
289
    if (live_dev == NULL)
×
290
        return NULL;
×
UNCOV
291
    return live_dev->dev_short;
×
UNCOV
292
}
×
293

294
int LiveBuildDeviceList(const char *runmode)
UNCOV
295
{
×
UNCOV
296
    return LiveBuildDeviceListCustom(runmode, "interface");
×
UNCOV
297
}
×
298

299
int LiveBuildDeviceListCustom(const char *runmode, const char *itemname)
UNCOV
300
{
×
UNCOV
301
    SCConfNode *base = SCConfGetNode(runmode);
×
UNCOV
302
    SCConfNode *child;
×
UNCOV
303
    int i = 0;
×
304

UNCOV
305
    if (base == NULL)
×
306
        return 0;
×
307

UNCOV
308
    TAILQ_FOREACH(child, &base->head, next) {
×
UNCOV
309
        SCConfNode *subchild;
×
UNCOV
310
        TAILQ_FOREACH(subchild, &child->head, next) {
×
UNCOV
311
            if ((!strcmp(subchild->name, itemname))) {
×
UNCOV
312
                if (!strcmp(subchild->val, "default"))
×
UNCOV
313
                    break;
×
UNCOV
314
                SCLogConfig("Adding %s %s from config file",
×
UNCOV
315
                          itemname, subchild->val);
×
UNCOV
316
                LiveRegisterDeviceName(subchild->val);
×
UNCOV
317
                i++;
×
UNCOV
318
            }
×
UNCOV
319
        }
×
UNCOV
320
    }
×
321

UNCOV
322
    return i;
×
UNCOV
323
}
×
324

325
/** Call this function to disable stat on live devices
326
 *
327
 * This can be useful in the case, this is not a real interface.
328
 */
329
void LiveDeviceHasNoStats(void)
UNCOV
330
{
×
UNCOV
331
    live_devices_stats = 0;
×
UNCOV
332
}
×
333

334
int LiveDeviceListClean(void)
UNCOV
335
{
×
UNCOV
336
    SCEnter();
×
UNCOV
337
    LiveDevice *pd, *tpd;
×
338

339
    /* dpdk: need to close all devices before freeing them. */
UNCOV
340
    TAILQ_FOREACH (pd, &live_devices, next) {
×
UNCOV
341
        DPDKCloseDevice(pd);
×
UNCOV
342
    }
×
UNCOV
343
    TAILQ_FOREACH_SAFE(pd, &live_devices, next, tpd) {
×
UNCOV
344
        if (live_devices_stats) {
×
UNCOV
345
            SCLogNotice("%s: packets: %" PRIu64 ", drops: %" PRIu64
×
UNCOV
346
                        " (%.2f%%), invalid chksum: %" PRIu64,
×
UNCOV
347
                    pd->dev, SC_ATOMIC_GET(pd->pkts), SC_ATOMIC_GET(pd->drop),
×
UNCOV
348
                    SC_ATOMIC_GET(pd->pkts) > 0 ? 100 * ((double)SC_ATOMIC_GET(pd->drop)) /
×
UNCOV
349
                                                          (double)SC_ATOMIC_GET(pd->pkts)
×
UNCOV
350
                                                : 0,
×
UNCOV
351
                    SC_ATOMIC_GET(pd->invalid_checksums));
×
UNCOV
352
        }
×
353

UNCOV
354
        RestoreIfaceOffloading(pd);
×
UNCOV
355
        DPDKFreeDevice(pd);
×
356

UNCOV
357
        if (pd->dev)
×
UNCOV
358
            SCFree(pd->dev);
×
UNCOV
359
        LiveDevFreeStorage(pd);
×
UNCOV
360
        SCFree(pd);
×
UNCOV
361
    }
×
362

UNCOV
363
    SCReturnInt(TM_ECODE_OK);
×
UNCOV
364
}
×
365

366
#ifdef BUILD_UNIX_SOCKET
367
TmEcode LiveDeviceIfaceStat(json_t *cmd, json_t *answer, void *data)
UNCOV
368
{
×
UNCOV
369
    SCEnter();
×
UNCOV
370
    LiveDevice *pd;
×
UNCOV
371
    const char * name = NULL;
×
UNCOV
372
    json_t *jarg = json_object_get(cmd, "iface");
×
UNCOV
373
    if(!json_is_string(jarg)) {
×
374
        json_object_set_new(answer, "message", json_string("Iface is not a string"));
×
375
        SCReturnInt(TM_ECODE_FAILED);
×
376
    }
×
UNCOV
377
    name = json_string_value(jarg);
×
UNCOV
378
    if (name == NULL) {
×
379
        json_object_set_new(answer, "message", json_string("Iface name is NULL"));
×
380
        SCReturnInt(TM_ECODE_FAILED);
×
381
    }
×
382

UNCOV
383
    TAILQ_FOREACH(pd, &live_devices, next) {
×
UNCOV
384
        if (!strcmp(name, pd->dev)) {
×
UNCOV
385
            json_t *jdata = json_object();
×
UNCOV
386
            if (jdata == NULL) {
×
387
                json_object_set_new(answer, "message",
×
388
                        json_string("internal error at json object creation"));
×
389
                SCReturnInt(TM_ECODE_FAILED);
×
390
            }
×
UNCOV
391
            json_object_set_new(jdata, "pkts",
×
UNCOV
392
                                json_integer(SC_ATOMIC_GET(pd->pkts)));
×
UNCOV
393
            json_object_set_new(jdata, "invalid-checksums",
×
UNCOV
394
                                json_integer(SC_ATOMIC_GET(pd->invalid_checksums)));
×
UNCOV
395
            json_object_set_new(jdata, "drop",
×
UNCOV
396
                                json_integer(SC_ATOMIC_GET(pd->drop)));
×
UNCOV
397
            json_object_set_new(jdata, "bypassed",
×
UNCOV
398
                                json_integer(SC_ATOMIC_GET(pd->bypassed)));
×
UNCOV
399
            json_object_set_new(answer, "message", jdata);
×
UNCOV
400
            SCReturnInt(TM_ECODE_OK);
×
UNCOV
401
        }
×
UNCOV
402
    }
×
403
    json_object_set_new(answer, "message", json_string("Iface does not exist"));
×
404
    SCReturnInt(TM_ECODE_FAILED);
×
UNCOV
405
}
×
406

407
TmEcode LiveDeviceIfaceList(json_t *cmd, json_t *answer, void *data)
UNCOV
408
{
×
UNCOV
409
    SCEnter();
×
UNCOV
410
    json_t *jdata;
×
UNCOV
411
    json_t *jarray;
×
UNCOV
412
    LiveDevice *pd;
×
UNCOV
413
    int i = 0;
×
414

UNCOV
415
    jdata = json_object();
×
UNCOV
416
    if (jdata == NULL) {
×
417
        json_object_set_new(answer, "message",
×
418
                            json_string("internal error at json object creation"));
×
419
        return TM_ECODE_FAILED;
×
420
    }
×
UNCOV
421
    jarray = json_array();
×
UNCOV
422
    if (jarray == NULL) {
×
423
        json_object_set_new(answer, "message",
×
424
                            json_string("internal error at json object creation"));
×
425
        return TM_ECODE_FAILED;
×
426
    }
×
UNCOV
427
    TAILQ_FOREACH(pd, &live_devices, next) {
×
UNCOV
428
        json_array_append_new(jarray, json_string(pd->dev));
×
UNCOV
429
        i++;
×
UNCOV
430
    }
×
431

UNCOV
432
    json_object_set_new(jdata, "count", json_integer(i));
×
UNCOV
433
    json_object_set_new(jdata, "ifaces", jarray);
×
UNCOV
434
    json_object_set_new(answer, "message", jdata);
×
UNCOV
435
    SCReturnInt(TM_ECODE_OK);
×
UNCOV
436
}
×
437

438
#endif /* BUILD_UNIX_SOCKET */
439

440
LiveDevice *LiveDeviceForEach(LiveDevice **ldev, LiveDevice **ndev)
441
{
×
442
    if (*ldev == NULL) {
×
443
        *ldev = TAILQ_FIRST(&live_devices);
×
444
        *ndev = TAILQ_NEXT(*ldev, next);
×
445
        return *ldev;
×
446
    } else {
×
447
        *ldev = *ndev;
×
448
        if (*ldev) {
×
449
            *ndev = TAILQ_NEXT(*ldev, next);
×
450
        }
×
451
        return *ldev;
×
452
    }
×
453
    return NULL;
×
454
}
×
455

456
/**
457
 * Create registered devices
458
 *
459
 * This function creates all needed LiveDevice from
460
 * the LiveDeviceName list created via LiveRegisterDevice()
461
 */
462
void LiveDeviceFinalize(void)
463
{
2✔
464
    LiveDeviceName *ld, *pld;
2✔
465
    SCLogDebug("Finalize live device");
2✔
466
    /* Iter on devices and register them */
467
    TAILQ_FOREACH_SAFE(ld, &pre_live_devices, next, pld) {
2✔
UNCOV
468
        if (ld->dev) {
×
UNCOV
469
            LiveRegisterDevice(ld->dev);
×
UNCOV
470
            SCFree(ld->dev);
×
UNCOV
471
        }
×
UNCOV
472
        SCFree(ld);
×
UNCOV
473
    }
×
474
}
2✔
475

476
static void LiveDevExtensionFree(void *x)
477
{
×
478
    if (x)
×
479
        SCFree(x);
×
480
}
×
481

482
/**
483
 * Register bypass stats storage
484
 */
485
void LiveDevRegisterExtension(void)
486
{
×
487
    g_bypass_storage_id = LiveDevStorageRegister("bypass_stats", sizeof(void *),
×
488
                                                 NULL, LiveDevExtensionFree);
×
489
}
×
490

491
/**
492
 * Prepare a LiveDevice so we can set bypass stats
493
 */
494
int LiveDevUseBypass(LiveDevice *dev)
495
{
×
496
    BypassInfo *bpinfo = SCCalloc(1, sizeof(*bpinfo));
×
497
    if (bpinfo == NULL) {
×
498
        SCLogError("Can't allocate bypass info structure");
×
499
        return -1;
×
500
    }
×
501

502
    SC_ATOMIC_INIT(bpinfo->ipv4_hash_count);
×
503
    SC_ATOMIC_INIT(bpinfo->ipv4_hash_count);
×
504

505
    LiveDevSetStorageById(dev, g_bypass_storage_id, bpinfo);
×
506
    return 0;
×
507
}
×
508

509
/**
510
 * Increase number of currently bypassed flows for a protocol family
511
 *
512
 * \param dev pointer to LiveDevice to set stats for
513
 * \param cnt number of flows to add
514
 * \param family AF_INET to set IPv4 count or AF_INET6 to set IPv6 count
515
 */
516
void LiveDevAddBypassStats(LiveDevice *dev, uint64_t cnt, int family)
517
{
×
518
    BypassInfo *bpfdata = LiveDevGetStorageById(dev, g_bypass_storage_id);
×
519
    if (bpfdata) {
×
520
        if (family == AF_INET) {
×
521
            SC_ATOMIC_ADD(bpfdata->ipv4_hash_count, cnt);
×
522
        } else if (family == AF_INET6) {
×
523
            SC_ATOMIC_ADD(bpfdata->ipv6_hash_count, cnt);
×
524
        }
×
525
    }
×
526
}
×
527

528
/**
529
 * Decrease number of currently bypassed flows for a protocol family
530
 *
531
 * \param dev pointer to LiveDevice to set stats for
532
 * \param cnt number of flows to remove
533
 * \param family AF_INET to set IPv4 count or AF_INET6 to set IPv6 count
534
 */
535
void LiveDevSubBypassStats(LiveDevice *dev, uint64_t cnt, int family)
536
{
×
537
    BypassInfo *bpfdata = LiveDevGetStorageById(dev, g_bypass_storage_id);
×
538
    if (bpfdata) {
×
539
        if (family == AF_INET) {
×
540
            SC_ATOMIC_SUB(bpfdata->ipv4_hash_count, cnt);
×
541
        } else if (family == AF_INET6) {
×
542
            SC_ATOMIC_SUB(bpfdata->ipv6_hash_count, cnt);
×
543
        }
×
544
    }
×
545
}
×
546

547
/**
548
 * Increase number of failed captured flows for a protocol family
549
 *
550
 * \param dev pointer to LiveDevice to set stats for
551
 * \param cnt number of flows to add
552
 * \param family AF_INET to set IPv4 count or AF_INET6 to set IPv6 count
553
 */
554
void LiveDevAddBypassFail(LiveDevice *dev, uint64_t cnt, int family)
555
{
×
556
    BypassInfo *bpfdata = LiveDevGetStorageById(dev, g_bypass_storage_id);
×
557
    if (bpfdata) {
×
558
        if (family == AF_INET) {
×
559
            SC_ATOMIC_ADD(bpfdata->ipv4_fail, cnt);
×
560
        } else if (family == AF_INET6) {
×
561
            SC_ATOMIC_ADD(bpfdata->ipv6_fail, cnt);
×
562
        }
×
563
    }
×
564
}
×
565

566
/**
567
 * Increase number of currently successfully bypassed flows for a protocol family
568
 *
569
 * \param dev pointer to LiveDevice to set stats for
570
 * \param cnt number of flows to add
571
 * \param family AF_INET to set IPv4 count or AF_INET6 to set IPv6 count
572
 */
573
void LiveDevAddBypassSuccess(LiveDevice *dev, uint64_t cnt, int family)
574
{
×
575
    BypassInfo *bpfdata = LiveDevGetStorageById(dev, g_bypass_storage_id);
×
576
    if (bpfdata) {
×
577
        if (family == AF_INET) {
×
578
            SC_ATOMIC_ADD(bpfdata->ipv4_success, cnt);
×
579
        } else if (family == AF_INET6) {
×
580
            SC_ATOMIC_ADD(bpfdata->ipv6_success, cnt);
×
581
        }
×
582
    }
×
583
}
×
584

585
#ifdef BUILD_UNIX_SOCKET
586
TmEcode LiveDeviceGetBypassedStats(json_t *cmd, json_t *answer, void *data)
UNCOV
587
{
×
UNCOV
588
    if (g_bypass_storage_id.id < 0) {
×
UNCOV
589
        json_object_set_new(answer, "message", json_string("Bypass not enabled"));
×
UNCOV
590
        SCReturnInt(TM_ECODE_FAILED);
×
UNCOV
591
    }
×
592
    LiveDevice *ldev = NULL, *ndev = NULL;
×
593
    json_t *ifaces = NULL;
×
594
    while(LiveDeviceForEach(&ldev, &ndev)) {
×
595
        BypassInfo *bpinfo = LiveDevGetStorageById(ldev, g_bypass_storage_id);
×
596
        if (bpinfo) {
×
597
            uint64_t ipv4_hash_count = SC_ATOMIC_GET(bpinfo->ipv4_hash_count);
×
598
            uint64_t ipv6_hash_count = SC_ATOMIC_GET(bpinfo->ipv6_hash_count);
×
599
            uint64_t ipv4_success = SC_ATOMIC_GET(bpinfo->ipv4_success);
×
600
            uint64_t ipv4_fail = SC_ATOMIC_GET(bpinfo->ipv4_fail);
×
601
            uint64_t ipv6_success = SC_ATOMIC_GET(bpinfo->ipv6_success);
×
602
            uint64_t ipv6_fail = SC_ATOMIC_GET(bpinfo->ipv6_fail);
×
603
            json_t *iface = json_object();
×
604
            if (ifaces == NULL) {
×
605
                ifaces = json_object();
×
606
                if (ifaces == NULL) {
×
607
                    json_object_set_new(answer, "message",
×
608
                            json_string("internal error at json object creation"));
×
609
                    return TM_ECODE_FAILED;
×
610
                }
×
611
            }
×
612
            json_object_set_new(iface, "ipv4_maps_count", json_integer(ipv4_hash_count));
×
613
            json_object_set_new(iface, "ipv4_success", json_integer(ipv4_success));
×
614
            json_object_set_new(iface, "ipv4_fail", json_integer(ipv4_fail));
×
615
            json_object_set_new(iface, "ipv6_maps_count", json_integer(ipv6_hash_count));
×
616
            json_object_set_new(iface, "ipv6_success", json_integer(ipv6_success));
×
617
            json_object_set_new(iface, "ipv6_fail", json_integer(ipv6_fail));
×
618
            json_object_set_new(ifaces, ldev->dev, iface);
×
619
        }
×
620
    }
×
621
    if (ifaces) {
×
622
        json_object_set_new(answer, "message", ifaces);
×
623
        SCReturnInt(TM_ECODE_OK);
×
624
    }
×
625

626
    json_object_set_new(answer, "message",
×
627
                        json_string("No interface using bypass"));
×
628
    SCReturnInt(TM_ECODE_FAILED);
×
629
}
×
630
#endif
631

632
uint64_t LiveDevicePktsGet(LiveDevice *dev)
633
{
×
634
    return SC_ATOMIC_GET(dev->pkts);
×
635
}
×
636

637
void LiveDevicePktsIncr(LiveDevice *dev)
638
{
×
639
    (void)SC_ATOMIC_ADD(dev->pkts, 1);
×
640
}
×
641

642
void LiveDevicePktsAdd(LiveDevice *dev, uint64_t n)
643
{
×
644
    (void)SC_ATOMIC_ADD(dev->pkts, n);
×
645
}
×
646

647
void LiveDeviceDropAdd(LiveDevice *dev, uint64_t n)
648
{
×
649
    (void)SC_ATOMIC_ADD(dev->drop, n);
×
650
}
×
651

652
void LiveDeviceBypassedAdd(LiveDevice *dev, uint64_t n)
653
{
×
654
    (void)SC_ATOMIC_ADD(dev->bypassed, n);
×
655
}
×
656

657
uint64_t LiveDeviceInvalidChecksumsGet(LiveDevice *dev)
658
{
×
659
    return SC_ATOMIC_GET(dev->invalid_checksums);
660
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc