Skip to content

Commit

Permalink
feat: add promisc to afpacket
Browse files Browse the repository at this point in the history
  • Loading branch information
yuanchaoa authored and rvql committed Jan 6, 2025
1 parent 70645aa commit d34c22c
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 21 deletions.
3 changes: 3 additions & 0 deletions agent/src/config/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,8 @@ pub struct AfPacketTunning {
pub ring_blocks: usize,
pub packet_fanout_count: usize,
pub packet_fanout_mode: u32,
#[serde(rename = "interface_promisc_enabled")]
pub promisc: bool,
}

impl Default for AfPacketTunning {
Expand All @@ -638,6 +640,7 @@ impl Default for AfPacketTunning {
ring_blocks: 128,
packet_fanout_count: 1,
packet_fanout_mode: 0,
promisc: false,
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions agent/src/config/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2660,6 +2660,14 @@ impl ConfigHandler {
tunning.packet_fanout_mode = new_tunning.packet_fanout_mode;
restart_agent = !first_run;
}
if tunning.promisc != new_tunning.promisc {
info!(
"Update inputs.cbpf.af_packet.tunning.interface_promisc_enabled from {:?} to {:?}.",
tunning.promisc, new_tunning.promisc
);
tunning.promisc = new_tunning.promisc;
restart_agent = !first_run;
}
if tunning.ring_blocks != new_tunning.ring_blocks {
info!(
"Update inputs.cbpf.af_packet.tunning.ring_blocks from {:?} to {:?}.",
Expand Down
14 changes: 14 additions & 0 deletions agent/src/dispatcher/base_dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,20 @@ impl BaseDispatcher {
e
);
}

if self.options.lock().unwrap().promisc {
let if_indices = tap_interfaces
.iter()
.map(|i| i.if_index as i32)
.collect::<Vec<i32>>();
if let Err(e) = self.engine.set_promisc(&if_indices) {
warn!(
"set_promisc failed with tap_interfaces count {}: {:?}",
if_indices.len(),
e
);
}
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions agent/src/dispatcher/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,8 @@ pub struct Options {
pub dpdk_ebpf_receiver: Option<Receiver<Box<packet::Packet<'static>>>>,
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fanout_enabled: bool,
#[cfg(any(target_os = "linux", target_os = "android"))]
pub promisc: bool,
}

impl Options {
Expand Down
34 changes: 17 additions & 17 deletions agent/src/dispatcher/recv_engine/af_packet/tpacket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ use std::os::unix::io::{AsRawFd, FromRawFd};
use std::process;

use libc::{
c_int, c_uint, c_void, getsockopt, mmap, munmap, off_t, poll, pollfd, setsockopt, size_t,
sockaddr, sockaddr_ll, socket, socklen_t, write, AF_PACKET, ETH_P_ALL, MAP_LOCKED,
MAP_NORESERVE, MAP_SHARED, POLLERR, POLLIN, PROT_READ, PROT_WRITE, SOL_PACKET, SOL_SOCKET,
SO_ATTACH_FILTER,
c_int, c_uint, c_void, getsockopt, mmap, munmap, off_t, packet_mreq, poll, pollfd, setsockopt,
size_t, sockaddr, sockaddr_ll, socket, socklen_t, write, AF_PACKET, ETH_P_ALL, MAP_LOCKED,
MAP_NORESERVE, MAP_SHARED, PACKET_ADD_MEMBERSHIP, PACKET_MR_PROMISC, POLLERR, POLLIN,
PROT_READ, PROT_WRITE, SOL_PACKET, SOL_SOCKET, SO_ATTACH_FILTER,
};
use log::{info, warn};
use public::error::*;
Expand Down Expand Up @@ -131,19 +131,19 @@ impl Tpacket {
Ok(())
}

// TODO: 这里看起来不需要,golang版本未涉及该配置,后续有需要再添加
#[allow(dead_code)]
fn set_promisc(&self) -> Result<()> {
// 设置混杂模式

//raw_socket.set_flag(IFF_PROMISC as u64)?;

// TODO:
//let mut mreq: packet_mreq = std::mem::zeroed();
//mreq.mr_ifindex = interface.index as i32;
//mreq.mr_type = PACKET_MR_PROMISC as u16;

//raw_socket.setsockopt(SOL_PACKET, PACKET_ADD_MEMBERSHIP, (&mreq as *const packet_mreq) as *const libc::c_void);
pub fn set_promisc(&self, if_indices: &Vec<i32>) -> Result<()> {
for i in if_indices {
let mreq = packet_mreq {
mr_type: PACKET_MR_PROMISC as u16,
mr_ifindex: *i,
mr_alen: 0,
mr_address: [0, 0, 0, 0, 0, 0, 0, 0],
};
let err = self.setsockopt(SOL_PACKET, PACKET_ADD_MEMBERSHIP, mreq);
if err.is_err() {
warn!("Ifindex {} set promisc error: {:?}", i, err);
}
}
Ok(())
}

Expand Down
8 changes: 8 additions & 0 deletions agent/src/dispatcher/recv_engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ impl RecvEngine {
}
}

pub fn set_promisc(&mut self, if_index: &Vec<i32>) -> Result<()> {
match self {
#[cfg(any(target_os = "linux", target_os = "android"))]
Self::AfPacket(e) => e.set_promisc(if_index).map_err(|e| e.into()),
_ => return Ok(()),
}
}

pub fn get_counter_handle(&self) -> Arc<dyn stats::RefCountable> {
match self {
#[cfg(any(target_os = "linux", target_os = "android"))]
Expand Down
2 changes: 2 additions & 0 deletions agent/src/trident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3571,6 +3571,8 @@ fn build_dispatchers(
dpdk_ebpf_receiver,
#[cfg(target_os = "linux")]
fanout_enabled,
#[cfg(any(target_os = "linux", target_os = "android"))]
promisc: user_config.inputs.cbpf.af_packet.tunning.promisc,
..Default::default()
})))
.bpf_options(bpf_options)
Expand Down
33 changes: 32 additions & 1 deletion server/agent_config/README-CH.md
Original file line number Diff line number Diff line change
Expand Up @@ -2448,6 +2448,37 @@ inputs:
- https://github.com/torvalds/linux/blob/afcd48134c58d6af45fb3fdb648f1260b20f2326/include/uapi/linux/if_packet.h#L71
- https://www.stackpath.com/blog/bpf-hook-points-part-1/

##### 开启网卡混杂模式 {#inputs.cbpf.af_packet.tunning.interface_promisc_enabled}

**标签**:

<mark>agent_restart</mark>

**FQCN**:

`inputs.cbpf.af_packet.tunning.interface_promisc_enabled`

**默认值**:
```yaml
inputs:
cbpf:
af_packet:
tunning:
interface_promisc_enabled: false
```

**模式**:
| Key | Value |
| ---- | ---------------------------- |
| Type | bool |

**详细描述**:

如下场景需要开启混杂模式:
- capture_mode 等于 1 或 2
- capture_mode 等于 0 并且无法采集到虚拟机的流量
注意:网卡开启混杂模式后会采集更多的流量导致性能降低。

### 特殊网络 {#inputs.cbpf.special_network}

#### DPDK {#inputs.cbpf.special_network.dpdk}
Expand Down Expand Up @@ -3251,7 +3282,7 @@ Module: i40e

配置样例: `rx_hooks: [ixgbe_recv_pkts, i40e_recv_pkts, virtio_recv_pkts, virtio_recv_mergeable_pkts]`

注意:在当前 DPDK 驱动接口的突发模式下发送和接收数据包时,旧版 Linux 内核(低于 5.2)的 eBPF 指令数量限制为 4096。
注意:在当前 DPDK 驱动接口的突发模式下发送和接收数据包时,旧版 Linux 内核(低于 5.2)的 eBPF 指令数量限制为 4096。
因此,在 DPDK 捕获数据包期间,最多只能捕获 16 个数据包。对于 Linux 5.2 及以上版本的内核,最多可捕获 32 个数
据包(这通常是 DPDK 突发模式的默认值)。对于低于 Linux 5.2 的内核,如果突发大小超过 16,可能会发生数据包丢失。

Expand Down
35 changes: 33 additions & 2 deletions server/agent_config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2505,6 +2505,37 @@ kernel to specify the desired packet distribution algorithm. Refer to:
- https://github.com/torvalds/linux/blob/afcd48134c58d6af45fb3fdb648f1260b20f2326/include/uapi/linux/if_packet.h#L71
- https://www.stackpath.com/blog/bpf-hook-points-part-1/

##### Interface Promisc Enabled {#inputs.cbpf.af_packet.tunning.interface_promisc_enabled}

**Tags**:

<mark>agent_restart</mark>

**FQCN**:

`inputs.cbpf.af_packet.tunning.interface_promisc_enabled`

**Default value**:
```yaml
inputs:
cbpf:
af_packet:
tunning:
interface_promisc_enabled: false
```

**Schema**:
| Key | Value |
| ---- | ---------------------------- |
| Type | bool |

**Description**:

The following scenarios require promiscuous mode to be enabled:
- capture_mode is 1 or 2
- capture_mode is 0 and traffic to the virtual machine cannot be collected
Note: After the NIC is enabled in promiscuous mode, more traffic will be collected, resulting in lower performance

### Special Network {#inputs.cbpf.special_network}

#### DPDK {#inputs.cbpf.special_network.dpdk}
Expand Down Expand Up @@ -3368,8 +3399,8 @@ inputs:
**Description**:

Specify the appropriate packet transmission hook point according to the actual network card driver.
To obtain the driver method and configure the transmission hook point, as well as precautions,
refer to the description of 'rx_hooks'.
To obtain the driver method and configure the transmission hook point, as well as precautions,refer
to the description of 'rx_hooks'.

Example: `tx_hooks: [i40e_xmit_pkts, virtio_xmit_pkts_packed, virtio_xmit_pkts]`

Expand Down
23 changes: 22 additions & 1 deletion server/agent_config/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1693,6 +1693,27 @@ inputs:
# - https://www.stackpath.com/blog/bpf-hook-points-part-1/
# upgrade_from: static_config.packet-fanout-mode
packet_fanout_mode: 0
# type: bool
# name:
# en: Interface Promisc Enabled
# ch: 开启网卡混杂模式
# unit:
# range: []
# enum_options: []
# modification: agent_restart
# ee_feature: false
# description:
# en: |-
# The following scenarios require promiscuous mode to be enabled:
# - capture_mode is 1 or 2
# - capture_mode is 0 and traffic to the virtual machine cannot be collected
# Note: After the NIC is enabled in promiscuous mode, more traffic will be collected, resulting in lower performance
# ch: |-
# 如下场景需要开启混杂模式:
# - capture_mode 等于 1 或 2
# - capture_mode 等于 0 并且无法采集到虚拟机的流量
# 注意:网卡开启混杂模式后会采集更多的流量导致性能降低。
interface_promisc_enabled: false
# type: section
# name:
# en: Special Network
Expand Down Expand Up @@ -2293,7 +2314,7 @@ inputs:
#
# 配置样例: `rx_hooks: [ixgbe_recv_pkts, i40e_recv_pkts, virtio_recv_pkts, virtio_recv_mergeable_pkts]`
#
# 注意:在当前 DPDK 驱动接口的突发模式下发送和接收数据包时,旧版 Linux 内核(低于 5.2)的 eBPF 指令数量限制为 4096。
# 注意:在当前 DPDK 驱动接口的突发模式下发送和接收数据包时,旧版 Linux 内核(低于 5.2)的 eBPF 指令数量限制为 4096。
# 因此,在 DPDK 捕获数据包期间,最多只能捕获 16 个数据包。对于 Linux 5.2 及以上版本的内核,最多可捕获 32 个数
# 据包(这通常是 DPDK 突发模式的默认值)。对于低于 Linux 5.2 的内核,如果突发大小超过 16,可能会发生数据包丢失。
# upgrade_from:
Expand Down

0 comments on commit d34c22c

Please sign in to comment.