VPP网络监控利器:sFlow插件详解(二)
在之前的文章《Learning VPP: 简单网络流量监控插件sFlow Plugins (1)》中,我们详细介绍了sFlow插件的基本实现和相关配置。令人振奋的是,此插件已经被正式合并到VPP的25.2版本中。现在,我们将基于这一进展,搭建相应的环境来深入学习如何使用sFlow进行网络流量监控。
sFlow VPP架构概览
为了尽可能减少代码量并降低可能影响VPP数据平面稳定性的概率,整个解决方案被精心设计为三个独立的部分。每个部分都有其独特的风险和性能特点,这种划分不仅有助于简化开发和维护工作,还能够提高系统的整体稳定性与安全性。
- sFlow工作节点
负责从VPP的数据包转发路径中按一定比例(例如1/N)采样数据包,并进行初步处理。该节点会复制输入接口索引(inIfIndex)以及以太网帧的前几个字节,然后将这些信息添加到一个有边界的FIFO队列中。当队列满时,新来的样本会被丢弃,并增加一个计数器来标记这种情况。这种方法不仅能帮助监控数据平面是否出现拥堵,还能确保各VPP工作线程能公平地向代理传递样本。由于直接操作在数据转发路径上,因此需要特别注意避免引入可能导致性能下降或不稳定性的复杂逻辑。
- sFlow主进程
运行于主线程(main核)上,负责处理来自各个工作线程的样本数据,并定期(默认每20秒,可配置)收集启用了sFlow功能接口的相关统计信息。它通过周期性抓取接口计数器信息并通过Netlink消息发送给内核,将后续处理任务从数据平面移开,从而减少对实时数据处理的影响,确保系统性能和稳定性。这种设计不仅降低了复杂度,还允许灵活调整监控频率以适应不同的需求。
- Host sFlow守护程序(hsflowd)
hsflowd作为vpp的外部组件,订阅来自vpp的Netlink消息并处理由vpp生成的样本和计数器数据。借助Neil实现的mod_vpp模块(host sflow开源库新增的组件),hsflowd能够获取接口名称、ifIndex及计数器统计数据,并通过Netlink USERSOCK消息与PSAMPLE一起发送这些信息。作为一个成熟且经过广泛测试的实现,hsflowd支持多种硬件和软件定义网络环境,确保高效处理大量数据而不影响VPP的数据平面性能,从而避免成为系统瓶颈。这种设计使得hsflowd既能独立于VPP运行,又能高效地完成复杂的流量监控任务。
Netlink 是一种用于在内核和用户空间之间传递信息的特殊套接字协议。它支持多种子系统,包括路由、网络接口状态变化等。USERSOCK是Netlink的一个类型,专门用于用户定义的消息传递。USERSOCK允许用户空间应用程序定义自己的Netlink消息格式,并通过Netlink套接字与内核或其他用户空间程序进行通信。PSAMPLE 是Linux内核中的一个模块,专门用于数据包采样。它允许用户空间应用程序从内核中获取数据包样本,而不需要处理所有经过网络接口的数据包。PSAMPLE允许你从指定的网络接口中抽取一部分数据包进行分析,而不是处理所有的数据包。这有助于减少需要处理的数据量,同时仍然能够提供对网络流量的洞察。
接下来,我们将通过源码编译并安装两个软件:host-sflow(即hsflowd)和sflowtool。其中,host-sflow用于采集sFlow报文,而sflowtool则用于分析这些报文。
代码语言:txt复制#1、下载hsflowd源代码
git clone .git
#2、编译,默认情况下不会生成mod-vpp模块,需要指定feature
make FEATURES="VPP"
#3、安装hsflowd进程
make install
#1、下载sflowtool源代码
.git
#2、编译并安装
./boot.sh
./configure
make install
在编译 host-sflow(即 hsflowd)时,需设置 feature 属性为 vpp,以便生成针对vpp sflow插件所需的三个模块。具体包括:
- mod_vpp:专门为 vpp 设计,使 hsflowd 能够获取接口名称、ifIndex 及计数器统计数据。
- mod_dropmon:用于丢包报文的采集。
- mod_psample:提供报文采样的功能。
通过这种方式,编译后的 hsflowd 能够与 VPP 无缝集成,高效地进行流量监控和分析。下面显示安装之后文件存储路径。
代码语言:txt复制root@learningvpp:/etc/hsflowd# tree
.
└── modules
├── mod_dnssd.so
├── mod_dropmon.so #
├── mod_json.so
├── mod_psample.so
└── mod_vpp.so #新增的mod_vpp.so库
2 directories, 5 files
root@learningvpp:/etc/hsflowd# ls ../hsflowd.conf
../hsflowd.conf #hsflowd 配置文件
sflowtool工具路径
sflowtool: /usr/local/bin/sflowtool
接下来,我们将启动VPP进程,创建一个名为tap0的接口,并配置相应的IP地址。具体来说,内核中的TAP接口将被分配IP地址192.168.10.2,而VPP中的tap0接口将被分配IP地址192.168.10.1。创建一个veth虚拟接口对,一段加入netns dataplane命令空间,一端在内核。组网及配置如下:
hsflowd 配置文件 /etc/hsflowd.conf配置如下:
代码语言:txt复制sflow {
collector { ip=192.168.1.2 namespace=dataplane }
psample { group=1 }
vpp { osIndex=off }
}
在vpp上配置sflow功能之前,需要内核加载psample模块,否则会导致psample接口信息发送失败。
代码语言:txt复制modprobe psample
root@learningvpp:plugins/sflow# lsmod | grep psample
psample 16384 0
vpp上配置采样率及采样报文长度及接口tap0上使能sflow功能。
代码语言:txt复制sflow sampling-rate 20
sflow polling-interval 20
sflow header-bytes 128
sflow enable tap0
使用sflowtool工具来查询采样数据
代码语言:txt复制root@learningvpp:~# ip netns exec dataplane sflowtool -J
{
"datagramSourceIP":"192.168.1.2",
"datagramSize":"164",
"unixSecondsUTC":"1742264531",
"unixSecondsUTC_uS":"615566",
"localtime":"2025-03-18T10:22:11+0800",
"datagramVersion":"5",
"agentSubId":"100000",
"agent":"10.3.8.2",
"packetSequenceNo":"3141",
"sysUpTime":"64509017",
"samplesInPacket":"1",
"samples":[{
"sampleType_tag":"0:4",
"sampleType":"COUNTERSSAMPLE",
"sampleSequenceNo":"361",
"sourceId":"0:1",
"elements":[{
"counterBlock_tag":"0:1005",
"ifName":"tap0"
},
{
"counterBlock_tag":"0:1",
"ifIndex":"1",
"networkType":"6",
"ifSpeed":"0",
"ifDirection":"1",
"ifStatus":"3",
"ifInOctets":"695646",
"ifInUcastPkts":"7221",
"ifInMulticastPkts":"0",
"ifInBroadcastPkts":"0",
"ifInDiscards":"0",
"ifInErrors":"0",
"ifInUnknownProtos":"0",
"ifOutOctets":"695436",
"ifOutUcastPkts":"7218",
"ifOutMulticastPkts":"0",
"ifOutBroadcastPkts":"0",
"ifOutDiscards":"3",
"ifOutErrors":"0",
"ifPromiscuousMode":"0"
}
]
}
]
}
其中有统计tap0接口报文数量,在vpp查询了一下,统计信息几乎一致。
代码语言:txt复制DBGvpp# show interface
Name Idx State MTU Counter Count
tap0 1 up 9000 rx packets 689
rx bytes 65966
tx packets 675
tx bytes 64862
drops 14
ip4 653
ip6 13
下面是在vpp设置trace抓包,查询基本转发流程:
代码语言:txt复制:20:24:704755: virtio-input
virtio: hw_if_index 1 next-index 11 vring 0 len 98
hdr: flags 0x00 gso_type 0x00 hdr_len 0 gso_size 0 csum_start 0 csum_offset 0 num_buffers 1
00:20:24:704776: sflow
SFLOW: sw_if_index 1, next index 0
src 02:fe:ab:05:fb:cf -> dst 02:fe:6f:a6:2a:55
00:20:24:704784: ethernet-input
IP4: 02:fe:ab:05:fb:cf -> 02:fe:6f:a6:2a:55
00:20:24:704793: ip4-input
ICMP: 192.168.10.2 -> 192.168.10.1
tos 0x00, ttl 64, length 84, checksum 0x2edd dscp CS0 ecn NON_ECN
fragment id 0x7678, flags DONT_FRAGMENT
ICMP echo_request checksum 0xb31f id 53992
00:20:24:704802: ip4-lookup
fib 0 dpo-idx 7 flow hash: 0x00000000
ICMP: 192.168.10.2 -> 192.168.10.1
tos 0x00, ttl 64, length 84, checksum 0x2edd dscp CS0 ecn NON_ECN
fragment id 0x7678, flags DONT_FRAGMENT
ICMP echo_request checksum 0xb31f id 53992
00:20:24:704812: ip4-receive
fib:0 adj:7 flow:0x00000000
ICMP: 192.168.10.2 -> 192.168.10.1
tos 0x00, ttl 64, length 84, checksum 0x2edd dscp CS0 ecn NON_ECN
fragment id 0x7678, flags DONT_FRAGMENT
ICMP echo_request checksum 0xb31f id 53992
00:20:24:704815: ip4-icmp-input
ICMP: 192.168.10.2 -> 192.168.10.1
tos 0x00, ttl 64, length 84, checksum 0x2edd dscp CS0 ecn NON_ECN
fragment id 0x7678, flags DONT_FRAGMENT
ICMP echo_request checksum 0xb31f id 53992
00:20:24:704817: ip4-icmp-echo-request
ICMP: 192.168.10.2 -> 192.168.10.1
tos 0x00, ttl 64, length 84, checksum 0x2edd dscp CS0 ecn NON_ECN
fragment id 0x7678, flags DONT_FRAGMENT
ICMP echo_request checksum 0xb31f id 53992
00:20:24:704825: ip4-load-balance
fib 0 dpo-idx 2 flow hash: 0x00000000
ICMP: 192.168.10.1 -> 192.168.10.2
tos 0x00, ttl 64, length 84, checksum 0x5ec4 dscp CS0 ecn NON_ECN
fragment id 0x4691, flags DONT_FRAGMENT
ICMP echo_reply checksum 0xbb1f id 53992
00:20:24:704827: ip4-rewrite
tx_sw_if_index 1 dpo-idx 2 : ipv4 via 192.168.10.2 tap0: mtu:9000 next:3 flags:[] 02feab05fbcf02fe6fa62a550800 flow hash: 0x00000000
00000000: 02feab05fbcf02fe6fa62a550800450000544691400040015ec4c0a80a01c0a8
00000020: 0a020000bb1fd2e801fededad86700000000efe30a00000000001011
00:20:24:704830: tap0-output
tap0 flags 0x02180005
IP4: 02:fe:6f:a6:2a:55 -> 02:fe:ab:05:fb:cf
ICMP: 192.168.10.1 -> 192.168.10.2
tos 0x00, ttl 64, length 84, checksum 0x5ec4 dscp CS0 ecn NON_ECN
fragment id 0x4691, flags DONT_FRAGMENT
ICMP echo_reply checksum 0xbb1f id 53992
00:20:24:704837: tap0-tx
buffer 0x9f2a5: current data 0, length 98, buffer-pool 0, ref-count 1, trace handle 0x1000000
local l2-hdr-offset 0 l3-hdr-offset 14
hdr-sz 0 l2-hdr-offset 0 l3-hdr-offset 14 l4-hdr-offset 0 l4-hdr-sz 0
IP4: 02:fe:6f:a6:2a:55 -> 02:fe:ab:05:fb:cf
ICMP: 192.168.10.1 -> 192.168.10.2
tos 0x00, ttl 64, length 84, checksum 0x5ec4 dscp CS0 ecn NON_ECN
fragment id 0x4691, flags DONT_FRAGMENT
ICMP echo_reply checksum 0xbb1f id 53992
至此,我们已经构建了sFlow的基本配置框架,但具体实现细节仍需进一步深入研究代码。该sFlow插件架构被设计为能够支持高达100Gbps的监控需求,非常适合需要高带宽监控的产品应用。此插件已在FOSDEM 2025网络开发室会议上正式发布。如果您对此感兴趣,可以通过参考资料【1】获取更多信息。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。原始发表:2025-03-18,如有侵权请联系 cloudcommunity@tencent 删除网络插件监控接口数据参考资料: 1、/ 2、/
发布者:admin,转转请注明出处:http://www.yc00.com/web/1748216633a4749340.html
评论列表(0条)