Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
adb427a
dpdk: minor refactoring in error handling and variable declaration
May 25, 2023
a9b2f79
dpdk: refactor i40e RSS hash function
May 25, 2023
540df3b
dpdk: separate i40e prestop actions from DPKD 19.11
Jun 2, 2023
2feece6
dpdk: add debug dump of RX offload capabilities
May 25, 2023
bb2760d
dpdk: add device name querying function
May 31, 2023
fee79ff
dpdk: add linker flag for DPDK Bond library
May 25, 2023
c4b0c28
dpdk: add support for DPDK Bond PMD
May 25, 2023
11c3aa8
doc: add DPDK Bond PMD docs
May 30, 2023
f346b3f
debug: fix list-x command line options with debug
catenacyber May 23, 2023
6350736
http2: avoid quadratic complexity in headers
catenacyber May 31, 2023
9dc68ac
json/schema: Add additional VLAN layer stat
jlucovsky Aug 5, 2022
0d2268d
decode/vlan: Decode upto 3 layers of VLAN
jlucovsky Aug 7, 2022
0ff403f
decode/vlan: Remove unused macros/functions
jlucovsky Aug 27, 2022
a4ade05
general/typo: Correct misc. typos
jlucovsky Aug 27, 2022
92884b9
device: limit device id to uint16_t
catenacyber Apr 28, 2022
cc305da
flow: make FlowGetExistingFlowFromHash static
catenacyber Apr 28, 2022
7e725c6
flow: optionally use livedev for hash
catenacyber Apr 28, 2022
000eb91
smb: fix wrong data offset when wct = 12
b1tg May 22, 2023
abc76e2
smb: fix data padding logic in writeAndX parser
b1tg May 29, 2023
82803d1
http: complete multipart data on open
catenacyber May 17, 2023
9afb16b
output/smtp: remove unused function parameters
catenacyber May 11, 2023
0fb75f0
output/dns: remove unused function parameters
catenacyber May 11, 2023
210ca32
output/ftp: remove unused function parameters
catenacyber May 11, 2023
09d364b
output/krb5: remove unused function parameters
catenacyber Jun 5, 2023
24c2702
output/mqtt: remove unused function parameters
catenacyber Jun 5, 2023
0ec0d8d
output/rfb: remove unused function parameters
catenacyber Jun 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1384,6 +1384,7 @@
])

# DPDK support
enable_dpdk_bond_pmd="no"
AC_ARG_ENABLE(dpdk,
AS_HELP_STRING([--enable-dpdk], [Enable DPDK support [default=no]]),
[enable_dpdk=$enableval],[enable_dpdk=no])
Expand Down Expand Up @@ -1415,6 +1416,23 @@
fi
CFLAGS="${CFLAGS} `pkg-config --cflags libdpdk`"
LIBS="${LIBS} -Wl,-R,`pkg-config --libs-only-L libdpdk | cut -c 3-` -lnuma `pkg-config --libs libdpdk`"

if test ! -z "$(ldconfig -p | grep librte_net_bond)"; then
AC_DEFINE([HAVE_DPDK_BOND],[1],(DPDK Bond PMD support enabled))
enable_dpdk_bond_pmd="yes"
LIBS="${LIBS} -lrte_net_bond" # 20.11+
elif test ! -z "$(ldconfig -p | grep librte_pmd_bond)"; then
AC_DEFINE([HAVE_DPDK_BOND],[1],(DPDK Bond PMD support enabled))
enable_dpdk_bond_pmd="yes"
LIBS="${LIBS} -lrte_pmd_bond"
else
echo
echo " WARNING: DPDK Bond PMD was not found on your system, "
echo " you will be unable to use DPDK Bond PMD."
echo " You can try to \"sudo ldconfig\" and reconfigure again"
echo " or compile and install DPDK with Bond support enabled."
echo
fi
])

# Netmap support
Expand Down Expand Up @@ -2629,6 +2647,7 @@ SURICATA_BUILD_CONF="Suricata Configuration:
Profiling rules enabled: ${enable_profiling_rules}

Plugin support (experimental): ${plugin_support}
DPDK Bond PMD: ${enable_dpdk_bond_pmd}

Development settings:
Coccinelle / spatch: ${enable_coccinelle}
Expand Down
97 changes: 97 additions & 0 deletions doc/userguide/capture-hardware/dpdk.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
.. _dpdk:

DPDK
====

Introduction
-------------

The Data Plane Development Kit (DPDK) is a set of libraries and drivers that
enhance and speed up packet processing in the data plane. Its primary use is to
provide faster packet processing by bypassing the kernel network stack, which
can provide significant performance improvements. For detailed instructions on
how to setup DPDK, please refer to :doc:`../configuration/suricata-yaml` to
learn more about the basic setup for DPDK.
The following sections contain examples of how to set up DPDK and Suricata for
more obscure use-cases.

Bond interface
--------------

Link Bonding Poll Mode Driver (Bond PMD), is a software
mechanism provided by the Data Plane Development Kit (DPDK) for aggregating
multiple physical network interfaces into a single logical interface.
Bonding can be e.g. used to:

* deliver bidirectional flows of tapped interfaces to the same worker,
* establish redundancy by monitoring multiple links,
* improve network performance by load-balancing traffic across multiple links.

Bond PMD is essentially a virtual driver that manipulates with multiple
physical network interfaces. It can operate in multiple modes as described
in the `DPDK docs
<https://doc.dpdk.org/guides/prog_guide/link_bonding_poll_mode_drv_lib.html>`_
The individual bonding modes can accustom user needs.
DPDK Bond PMD has a requirement that the aggregated interfaces must be
the same device types - e.g. both physical ports run on mlx5 PMD.
Bond PMD supports multiple queues and therefore can work in workers runmode.
It should have no effect on traffic distribution of the individual ports and
flows should be distributed by physical ports according to the RSS
configuration the same way as if they would be configured independently.

As an example of Bond PMD, we can setup Suricata to monitor 2 interfaces
that receive TAP traffic from optical interfaces. This means that Suricata
receive one direction of the communication on one interface and the other
direction is received on the other interface.

::

...
dpdk:
eal-params:
proc-type: primary
vdev: 'net_bonding0,mode=0,slave=0000:04:00.0,slave=0000:04:00.1'

# DPDK capture support
# RX queues (and TX queues in IPS mode) are assigned to cores in 1:1 ratio
interfaces:
- interface: net_bonding0 # PCIe address of the NIC port
# Threading: possible values are either "auto" or number of threads
# - auto takes all cores
# in IPS mode it is required to specify the number of cores and the
# numbers on both interfaces must match
threads: 4
...

In the DPDK part of suricata.yaml we have added a new parameter to the
eal-params section for virtual devices - `vdev`.
DPDK Environment Abstraction Layer (EAL) can initialize some virtual devices
during the initialization of EAL.
In this case, EAL creates a new device of type `net_bonding`. Suffix of
`net_bonding` signifies the name of the interface (in this case the zero).
Extra arguments are passed after the device name, such as the bonding mode
(`mode=0`). This is the round-robin mode as is described in the DPDK
documentation of Bond PMD.
Members (slaves) of the `net_bonding0` interface are appended after
the bonding mode parameter.

When the device is specified within EAL parameters, it can be used within
Suricata `interfaces` list. Note that the list doesn't contain PCIe addresses
of the physical ports but instead the `net_bonding0` interface.
Threading section is also adjusted according to the items in the interfaces
list by enablign set-cpu-affinity and listing CPUs that should be used in
management and worker CPU set.

::

...
threading:
set-cpu-affinity: yes
cpu-affinity:
- management-cpu-set:
cpu: [ 0 ] # include only these CPUs in affinity settings
- receive-cpu-set:
cpu: [ 0 ] # include only these CPUs in affinity settings
- worker-cpu-set:
cpu: [ 2,4,6,8 ]
...
1 change: 1 addition & 0 deletions doc/userguide/capture-hardware/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ Using Capture Hardware
ebpf-xdp
netmap
af-xdp
dpdk
3 changes: 3 additions & 0 deletions etc/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4204,6 +4204,9 @@
"vlan_qinq": {
"type": "integer"
},
"vlan_qinqinq": {
"type": "integer"
},
"vntag": {
"type": "integer"
},
Expand Down
8 changes: 5 additions & 3 deletions rust/src/http2/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,13 +456,15 @@ fn http2_parse_headers_block_literal_incindex<'a>(
} else {
dyn_headers.table.push(headcopy);
}
let mut toremove = 0;
while dyn_headers.current_size > dyn_headers.max_size
&& !dyn_headers.table.is_empty()
&& toremove < dyn_headers.table.len()
{
dyn_headers.current_size -=
32 + dyn_headers.table[0].name.len() + dyn_headers.table[0].value.len();
dyn_headers.table.remove(0);
32 + dyn_headers.table[toremove].name.len() + dyn_headers.table[toremove].value.len();
toremove += 1;
}
dyn_headers.table.drain(0..toremove);
}
return Ok((r, head));
}
Expand Down
4 changes: 2 additions & 2 deletions rust/src/krb/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
// written by Pierre Chifflier <chifflier@wzdftpd.net>

use crate::jsonbuilder::{JsonBuilder, JsonError};
use crate::krb::krb5::{KRB5State,KRB5Transaction,test_weak_encryption};
use crate::krb::krb5::{KRB5Transaction,test_weak_encryption};

fn krb5_log_response(jsb: &mut JsonBuilder, tx: &mut KRB5Transaction) -> Result<(), JsonError>
{
Expand Down Expand Up @@ -68,7 +68,7 @@ fn krb5_log_response(jsb: &mut JsonBuilder, tx: &mut KRB5Transaction) -> Result<
}

#[no_mangle]
pub extern "C" fn rs_krb5_log_json_response(jsb: &mut JsonBuilder, _state: &mut KRB5State, tx: &mut KRB5Transaction) -> bool
pub extern "C" fn rs_krb5_log_json_response(jsb: &mut JsonBuilder, tx: &mut KRB5Transaction) -> bool
{
krb5_log_response(jsb, tx).is_ok()
}
4 changes: 2 additions & 2 deletions rust/src/mqtt/logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

// written by Sascha Steinbiss <sascha@steinbiss.name>

use super::mqtt::{MQTTState, MQTTTransaction};
use super::mqtt::MQTTTransaction;
use crate::jsonbuilder::{JsonBuilder, JsonError};
use crate::mqtt::mqtt_message::{MQTTOperation, MQTTSubscribeTopicData};
use crate::mqtt::parser::FixedHeader;
Expand Down Expand Up @@ -298,7 +298,7 @@ fn log_mqtt(tx: &MQTTTransaction, flags: u32, js: &mut JsonBuilder) -> Result<()

#[no_mangle]
pub unsafe extern "C" fn rs_mqtt_logger_log(
_state: &mut MQTTState, tx: *mut std::os::raw::c_void, flags: u32, js: &mut JsonBuilder,
tx: *mut std::os::raw::c_void, flags: u32, js: &mut JsonBuilder,
) -> bool {
let tx = cast_pointer!(tx, MQTTTransaction);
log_mqtt(tx, flags, js).is_ok()
Expand Down
5 changes: 2 additions & 3 deletions rust/src/rfb/logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

use std;
use std::fmt::Write;
use super::rfb::{RFBState, RFBTransaction};
use super::rfb::RFBTransaction;
use crate::jsonbuilder::{JsonBuilder, JsonError};

fn log_rfb(tx: &RFBTransaction, js: &mut JsonBuilder) -> Result<(), JsonError> {
Expand Down Expand Up @@ -113,8 +113,7 @@ fn log_rfb(tx: &RFBTransaction, js: &mut JsonBuilder) -> Result<(), JsonError> {
}

#[no_mangle]
pub unsafe extern "C" fn rs_rfb_logger_log(_state: &mut RFBState,
tx: *mut std::os::raw::c_void,
pub unsafe extern "C" fn rs_rfb_logger_log(tx: *mut std::os::raw::c_void,
js: &mut JsonBuilder) -> bool {
let tx = cast_pointer!(tx, RFBTransaction);
log_rfb(tx, js).is_ok()
Expand Down
33 changes: 26 additions & 7 deletions rust/src/smb/smb1_records.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ use crate::smb::smb::*;
use crate::smb::smb_records::*;
use nom7::bytes::streaming::{tag, take};
use nom7::combinator::{complete, cond, peek, rest, verify};
use nom7::error::{make_error, ErrorKind};
use nom7::Err;
use nom7::multi::many1;
use nom7::number::streaming::{le_u8, le_u16, le_u32, le_u64};
use nom7::IResult;
Expand Down Expand Up @@ -94,6 +96,7 @@ pub fn parse_smb1_write_request_record(i: &[u8]) -> IResult<&[u8], Smb1WriteRequ
}

pub fn parse_smb1_write_andx_request_record(i : &[u8], andx_offset: usize) -> IResult<&[u8], Smb1WriteRequestRecord> {
let origin_i = i;
let ax = andx_offset as u16;
let (i, wct) = le_u8(i)?;
let (i, _andx_command) = le_u8(i)?;
Expand All @@ -106,16 +109,19 @@ pub fn parse_smb1_write_andx_request_record(i : &[u8], andx_offset: usize) -> IR
let (i, _remaining) = le_u16(i)?;
let (i, data_len_high) = le_u16(i)?;
let (i, data_len_low) = le_u16(i)?;
let data_len = ((data_len_high as u32) << 16)|(data_len_low as u32);
let (i, data_offset) = le_u16(i)?;
if data_offset < 0x3c || data_offset < ax{
return Err(Err::Error(make_error(i, ErrorKind::LengthValue)));
}
let (i, high_offset) = cond(wct == 14, le_u32)(i)?;
let (i, bcc) = le_u16(i)?;
//spec [MS-CIFS].pdf says always take one byte padding
let (i, _padding) = cond(bcc > data_len_low, |b| take(bcc - data_len_low)(b))(i)?; // TODO figure out how this works with data_len_high
let (i, _padding_evasion) = cond(data_offset > ax+4+2*(wct as u16), |b| take(data_offset - (ax+4+2*(wct as u16)))(b))(i)?;
let (i, file_data) = rest(i)?;
let (_i, _bcc) = le_u16(i)?;
let (i, _padding_data) = take(data_offset-ax)(origin_i)?;
let (i, file_data) = take(std::cmp::min(data_len, i.len() as u32))(i)?;

let record = Smb1WriteRequestRecord {
offset: high_offset.map(|ho| (ho as u64) << 32 | offset as u64).unwrap_or(0),
len: ((data_len_high as u32) << 16)|(data_len_low as u32),
offset: ((high_offset.unwrap_or(0) as u64) << 32) | offset as u64,
len: data_len,
fid,
data: file_data,
};
Expand Down Expand Up @@ -862,3 +868,16 @@ pub fn parse_smb_record(i: &[u8]) -> IResult<&[u8], SmbRecord> {
};
Ok((i, record))
}

#[test]
fn test_parse_smb1_write_andx_request_record_origin() {
let data = hex::decode("0eff000000014000000000ff00000008001400000014003f000000000014004142434445464748494a4b4c4d4e4f5051520a0a").unwrap();
let result = parse_smb1_write_andx_request_record(&data, SMB1_HEADER_SIZE);
assert!(result.is_ok());
let record = result.unwrap().1;
assert_eq!(record.offset, 0);
assert_eq!(record.len, 20);
assert_eq!(record.fid, &[0x01, 0x40]);
assert_eq!(record.data.len(), 20);
assert_eq!(record.data, b"ABCDEFGHIJKLMNOPQR\n\n");
}
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ noinst_HEADERS = \
util-dpdk-i40e.h \
util-dpdk-ice.h \
util-dpdk-ixgbe.h \
util-dpdk-bonding.h \
util-ebpf.h \
util-enum.h \
util-error.h \
Expand Down Expand Up @@ -1127,6 +1128,7 @@ libsuricata_c_a_SOURCES = \
util-dpdk-i40e.c \
util-dpdk-ice.c \
util-dpdk-ixgbe.c \
util-dpdk-bonding.c \
util-ebpf.c \
util-enum.c \
util-error.c \
Expand Down
10 changes: 10 additions & 0 deletions src/app-layer-htp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1604,6 +1604,16 @@ static int HtpRequestBodyHandleMultipart(HtpState *hstate, HtpTxUserData *htud,

if (filedata_len >= (uint32_t)(expected_boundary_len + 2)) {
filedata_len -= (expected_boundary_len + 2 - 1);
// take as much as we can until start of boundary
for (size_t nb = 0; nb < (size_t)expected_boundary_len + 1; nb++) {
if (filedata[filedata_len] == '\r') {
if (nb == expected_boundary_len ||
filedata[filedata_len + 1] == '\n') {
break;
}
}
filedata_len++;
}
SCLogDebug("opening file with partial data");
} else {
filedata = NULL;
Expand Down
2 changes: 1 addition & 1 deletion src/decode-erspan.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ int DecodeERSPAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t
}

if (vlan_id > 0) {
if (p->vlan_idx >= 2) {
if (p->vlan_idx > VLAN_MAX_LAYER_IDX) {
ENGINE_SET_EVENT(p,ERSPAN_TOO_MANY_VLAN_LAYERS);
return TM_ECODE_FAILED;
}
Expand Down
16 changes: 4 additions & 12 deletions src/decode-vlan.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2007-2021 Open Information Security Foundation
/* Copyright (C) 2007-2022 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
Expand Down Expand Up @@ -62,6 +62,8 @@ int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
StatsIncr(tv, dtv->counter_vlan);
else if (p->vlan_idx == 1)
StatsIncr(tv, dtv->counter_vlan_qinq);
else if (p->vlan_idx == 2)
StatsIncr(tv, dtv->counter_vlan_qinqinq);

if(len < VLAN_HEADER_LEN) {
ENGINE_SET_INVALID_EVENT(p, VLAN_HEADER_TOO_SMALL);
Expand All @@ -70,7 +72,7 @@ int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
if (!PacketIncreaseCheckLayers(p)) {
return TM_ECODE_FAILED;
}
if (p->vlan_idx >= 2) {
if (p->vlan_idx > VLAN_MAX_LAYER_IDX) {
ENGINE_SET_EVENT(p,VLAN_HEADER_TOO_MANY_LAYERS);
return TM_ECODE_FAILED;
}
Expand All @@ -93,16 +95,6 @@ int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
return TM_ECODE_OK;
}

uint16_t DecodeVLANGetId(const Packet *p, uint8_t layer)
{
if (unlikely(layer > 1))
return 0;
if (p->vlan_idx > layer) {
return p->vlan_id[layer];
}
return 0;
}

typedef struct IEEE8021ahHdr_ {
uint32_t flags;
uint8_t c_destination[6];
Expand Down
10 changes: 5 additions & 5 deletions src/decode-vlan.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2007-2010 Open Information Security Foundation
/* Copyright (C) 2007-2022 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
Expand Down Expand Up @@ -36,10 +36,6 @@ uint16_t DecodeVLANGetId(const struct Packet_ *, uint8_t layer);
#define GET_VLAN_ID(vlanh) ((uint16_t)(SCNtohs((vlanh)->vlan_cfi) & 0x0FFF))
#define GET_VLAN_PROTO(vlanh) ((SCNtohs((vlanh)->protocol)))

/* return vlan id in host byte order */
#define VLAN_GET_ID1(p) DecodeVLANGetId((p), 0)
#define VLAN_GET_ID2(p) DecodeVLANGetId((p), 1)

/** Vlan header struct */
typedef struct VLANHdr_ {
uint16_t vlan_cfi;
Expand All @@ -51,5 +47,9 @@ typedef struct VLANHdr_ {

void DecodeVLANRegisterTests(void);

/** VLAN max encapsulation layer count/index */
#define VLAN_MAX_LAYERS 3
#define VLAN_MAX_LAYER_IDX (VLAN_MAX_LAYERS - 1)

#endif /* __DECODE_VLAN_H__ */

Loading