Skip to content

Commit 8926b0d

Browse files
committed
feat: support icmp close type
1 parent 51488c1 commit 8926b0d

File tree

10 files changed

+263
-46
lines changed

10 files changed

+263
-46
lines changed

agent/src/collector/quadruple_generator.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,19 @@ impl QuadrupleGenerator {
986986
| CloseType::TcpFin
987987
| CloseType::Unknown
988988
| CloseType::TcpFinClientRst
989+
| CloseType::IcmpOtherTimeout
990+
| CloseType::IcmpAddressMaskTimeout
991+
| CloseType::IcmpDestinationUnreachable
992+
| CloseType::IcmpEchoTimeout
993+
| CloseType::IcmpInformationTimeout
994+
| CloseType::IcmpNeighborTimeout
995+
| CloseType::IcmpNormal
996+
| CloseType::IcmpPacketTooBig
997+
| CloseType::IcmpParameterProblem
998+
| CloseType::IcmpRouterTimeout
999+
| CloseType::IcmpSourceQuench
1000+
| CloseType::IcmpTimeExceeded
1001+
| CloseType::IcmpTimestampTimeout
9891002
| CloseType::Max => (),
9901003
}
9911004
}

agent/src/common/flow.rs

Lines changed: 75 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,35 @@ const COUNTER_FLOW_ID_MASK: u64 = 0x00FFFFFF;
6262
#[repr(u8)]
6363
pub enum CloseType {
6464
Unknown = 0,
65-
TcpFin = 1, // 1: 正常结束
66-
TcpServerRst = 2, // 2: 传输-服务端重置
67-
Timeout = 3, // 3: 连接超时
68-
ForcedReport = 5, // 5: 周期性上报
69-
ClientSynRepeat = 7, // 7: 建连-客户端SYN结束
70-
ServerHalfClose = 8, // 8: 断连-服务端半关
71-
TcpClientRst = 9, // 9: 传输-客户端重置
72-
ServerSynAckRepeat = 10, // 10: 建连-服务端SYN结束
73-
ClientHalfClose = 11, // 11: 断连-客户端半关
74-
ClientSourcePortReuse = 13, // 13: 建连-客户端端口复用
75-
ServerReset = 15, // 15: 建连-服务端直接重置
76-
ServerQueueLack = 17, // 17: 传输-服务端队列溢出
77-
ClientEstablishReset = 18, // 18: 建连-客户端其他重置
78-
ServerEstablishReset = 19, // 19: 建连-服务端其他重置
79-
TcpFinClientRst = 20, // 20: 正常结束-客户端重置
80-
Max = 21,
65+
TcpFin = 1, // 1: 正常结束
66+
TcpServerRst = 2, // 2: 传输-服务端重置
67+
Timeout = 3, // 3: 连接超时
68+
ForcedReport = 5, // 5: 周期性上报
69+
ClientSynRepeat = 7, // 7: 建连-客户端SYN结束
70+
ServerHalfClose = 8, // 8: 断连-服务端半关
71+
TcpClientRst = 9, // 9: 传输-客户端重置
72+
ServerSynAckRepeat = 10, // 10: 建连-服务端SYN结束
73+
ClientHalfClose = 11, // 11: 断连-客户端半关
74+
ClientSourcePortReuse = 13, // 13: 建连-客户端端口复用
75+
ServerReset = 15, // 15: 建连-服务端直接重置
76+
ServerQueueLack = 17, // 17: 传输-服务端队列溢出
77+
ClientEstablishReset = 18, // 18: 建连-客户端其他重置
78+
ServerEstablishReset = 19, // 19: 建连-服务端其他重置
79+
TcpFinClientRst = 20, // 20: 正常结束-客户端重置
80+
IcmpNormal = 21, // 21: ICMP-正常结束
81+
IcmpAddressMaskTimeout = 22, // 22: ICMP-地址掩码超时
82+
IcmpDestinationUnreachable = 23, // 23: ICMP-目标不可达
83+
IcmpEchoTimeout = 24, // 24: ICMP-PING超时
84+
IcmpInformationTimeout = 25, // 25: ICMP-信息超时
85+
IcmpParameterProblem = 26, // 26: ICMP-参数问题
86+
IcmpRouterTimeout = 27, // 27: ICMP-路由器超时
87+
IcmpSourceQuench = 28, // 28: ICMP-源站抑制
88+
IcmpTimeExceeded = 29, // 29: ICMP-TTL溢出
89+
IcmpTimestampTimeout = 30, // 30: ICMP-时间戳超时
90+
IcmpNeighborTimeout = 31, // 31: ICMP-邻居发现超时
91+
IcmpPacketTooBig = 32, // 32: ICMP-Packet过大
92+
IcmpOtherTimeout = 33, // 33: ICMP-未知超时
93+
Max = 34,
8194
}
8295

8396
impl CloseType {
@@ -97,6 +110,18 @@ impl CloseType {
97110
|| self == CloseType::ServerReset
98111
|| self == CloseType::ServerQueueLack
99112
|| self == CloseType::ServerEstablishReset
113+
|| self == CloseType::IcmpAddressMaskTimeout
114+
|| self == CloseType::IcmpEchoTimeout
115+
|| self == CloseType::IcmpInformationTimeout
116+
|| self == CloseType::IcmpRouterTimeout
117+
|| self == CloseType::IcmpTimestampTimeout
118+
|| self == CloseType::IcmpNeighborTimeout
119+
|| self == CloseType::IcmpPacketTooBig
120+
|| self == CloseType::IcmpTimeExceeded
121+
|| self == CloseType::IcmpSourceQuench
122+
|| self == CloseType::IcmpDestinationUnreachable
123+
|| self == CloseType::IcmpParameterProblem
124+
|| self == CloseType::IcmpOtherTimeout
100125
}
101126
}
102127

@@ -1070,7 +1095,40 @@ impl Flow {
10701095
FlowState::Exception => CloseType::Unknown,
10711096
FlowState::Opening1 => CloseType::ClientSynRepeat,
10721097
FlowState::Opening2 => CloseType::ServerSynAckRepeat,
1073-
FlowState::Established => CloseType::Timeout,
1098+
FlowState::IcmpAddressMaskReply => CloseType::IcmpNormal,
1099+
FlowState::IcmpAddressMaskRequest => CloseType::IcmpAddressMaskTimeout,
1100+
FlowState::IcmpEchoReply => CloseType::IcmpNormal,
1101+
FlowState::IcmpEchoRequest => CloseType::IcmpEchoTimeout,
1102+
FlowState::IcmpDestinationUnreachable => CloseType::IcmpDestinationUnreachable,
1103+
FlowState::IcmpInformationReply => CloseType::IcmpNormal,
1104+
FlowState::IcmpInformationRequest => CloseType::IcmpInformationTimeout,
1105+
FlowState::IcmpNeighborAdvert => CloseType::IcmpNormal,
1106+
FlowState::IcmpNeighborSolicit => CloseType::IcmpNeighborTimeout,
1107+
FlowState::IcmpPacketTooBig => CloseType::IcmpPacketTooBig,
1108+
FlowState::IcmpParameterProblem => CloseType::IcmpParameterProblem,
1109+
FlowState::IcmpRedirectMessage => CloseType::IcmpNormal,
1110+
FlowState::IcmpRouterAdvertisement => CloseType::IcmpNormal,
1111+
FlowState::IcmpRouterSolicitation => CloseType::IcmpRouterTimeout,
1112+
FlowState::IcmpSourceQuench => CloseType::IcmpSourceQuench,
1113+
FlowState::IcmpTimeExceeded => CloseType::IcmpTimeExceeded,
1114+
FlowState::IcmpTimestamp => CloseType::IcmpTimestampTimeout,
1115+
FlowState::IcmpTimestampReply => CloseType::IcmpNormal,
1116+
FlowState::IcmpTraceroute => CloseType::IcmpNormal,
1117+
FlowState::Established => {
1118+
if self.flow_key.proto == IpProtocol::ICMPV4
1119+
|| self.flow_key.proto == IpProtocol::ICMPV6
1120+
{
1121+
if self.flow_metrics_peers[0].total_packet_count
1122+
!= self.flow_metrics_peers[1].total_packet_count
1123+
{
1124+
CloseType::IcmpOtherTimeout
1125+
} else {
1126+
CloseType::IcmpNormal
1127+
}
1128+
} else {
1129+
CloseType::Timeout
1130+
}
1131+
}
10741132
FlowState::ClosingTx1 => CloseType::ServerHalfClose,
10751133
FlowState::ClosingRx1 => CloseType::ClientHalfClose,
10761134
FlowState::ClosingTx2 | FlowState::ClosingRx2 | FlowState::Closed => CloseType::TcpFin,

agent/src/flow_generator/flow_config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub const TIMEOUT_OTHERS: Timestamp = Timestamp::from_secs(5);
2626
pub const TIMEOUT_ESTABLISHED: Timestamp = Timestamp::from_secs(300);
2727
pub const TIMEOUT_CLOSING: Timestamp = Timestamp::from_secs(35);
2828
pub const TIMEOUT_OPENING_RST: Timestamp = Timestamp::from_secs(1);
29+
pub const TIMEOUT_ICMP: Timestamp = Timestamp::from_secs(5);
2930

3031
pub struct TcpTimeout {
3132
pub established: Timestamp,
@@ -55,6 +56,7 @@ pub struct FlowTimeout {
5556
pub closed_fin: Timestamp,
5657
pub single_direction: Timestamp,
5758
pub opening_rst: Timestamp,
59+
pub icmp_timeout: Timestamp,
5860

5961
pub min: Timestamp,
6062
pub max: Timestamp, // time window
@@ -71,6 +73,8 @@ impl From<TcpTimeout> for FlowTimeout {
7173
closed_fin: Timestamp::from_secs(2),
7274
single_direction: t.others,
7375
opening_rst: t.opening_rst,
76+
icmp_timeout: TIMEOUT_ICMP,
77+
7478
min: Timestamp::from_secs(0),
7579
max: Timestamp::from_secs(0),
7680
};

agent/src/flow_generator/flow_map.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,12 @@ impl FlowMap {
915915
) -> bool {
916916
self.update_flow(config, node, meta_packet);
917917
let peers = &node.tagged_flow.flow.flow_metrics_peers;
918-
if peers[FLOW_METRICS_PEER_SRC].packet_count > 0
918+
if node.tagged_flow.flow.flow_key.proto == IpProtocol::ICMPV4
919+
|| node.tagged_flow.flow.flow_key.proto == IpProtocol::ICMPV6
920+
{
921+
node.timeout = config.flow.flow_timeout.icmp_timeout;
922+
node.set_icmp_flow_state(meta_packet);
923+
} else if peers[FLOW_METRICS_PEER_SRC].packet_count > 0
919924
&& peers[FLOW_METRICS_PEER_DST].packet_count > 0
920925
{
921926
node.timeout = config.flow.flow_timeout.established_rst;
@@ -1732,9 +1737,15 @@ impl FlowMap {
17321737
meta_packet.flow_id = node.tagged_flow.flow.flow_id;
17331738
meta_packet.second_in_minute =
17341739
(node.tagged_flow.flow.start_time.as_secs() % SECONDS_IN_MINUTE) as u8;
1735-
node.flow_state = FlowState::Established;
1736-
// opening timeout
1737-
node.timeout = config.flow.flow_timeout.opening;
1740+
if meta_packet.lookup_key.proto == IpProtocol::ICMPV4
1741+
|| meta_packet.lookup_key.proto == IpProtocol::ICMPV6
1742+
{
1743+
node.set_icmp_flow_state(meta_packet);
1744+
node.timeout = config.flow.flow_timeout.icmp_timeout;
1745+
} else {
1746+
node.flow_state = FlowState::Established;
1747+
node.timeout = config.flow.flow_timeout.opening;
1748+
}
17381749
if let Some(meta_flow_log) = node.meta_flow_log.as_mut() {
17391750
let _ = meta_flow_log.parse_l3(meta_packet);
17401751
}
@@ -3087,6 +3098,7 @@ mod tests {
30873098
exception: Timestamp::from_secs(5),
30883099
closed_fin: Timestamp::ZERO,
30893100
single_direction: Timestamp::from_millis(10),
3101+
icmp_timeout: Timestamp::from_secs(5),
30903102
max: Timestamp::from_secs(300),
30913103
min: Timestamp::ZERO,
30923104
}),

agent/src/flow_generator/flow_node.rs

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,23 @@
1616

1717
use std::{net::IpAddr, sync::Arc};
1818

19+
use pnet::packet::{
20+
icmp::{IcmpType, IcmpTypes},
21+
icmpv6::{Icmpv6Type, Icmpv6Types},
22+
};
23+
1924
use super::{perf::FlowLog, FlowState, FLOW_METRICS_PEER_DST, FLOW_METRICS_PEER_SRC};
2025
use crate::common::{
2126
decapsulate::TunnelType,
2227
endpoint::EndpointDataPov,
2328
enums::{EthernetType, TapType, TcpFlags},
2429
flow::{FlowMetricsPeer, L7PerfStats, PacketDirection, SignalSource, TcpPerfStats},
2530
lookup_key::LookupKey,
26-
meta_packet::MetaPacket,
31+
meta_packet::{MetaPacket, ProtocolData},
2732
tagged_flow::TaggedFlow,
2833
TapPort, Timestamp,
2934
};
30-
use public::{proto::common::TridentType, utils::net::MacAddr};
35+
use public::{enums::IpProtocol, proto::common::TridentType, utils::net::MacAddr};
3136

3237
use npb_pcap_policy::PolicyData;
3338
use packet_sequence_block::PacketSequenceBlock;
@@ -145,6 +150,65 @@ pub struct FlowNode {
145150
}
146151

147152
impl FlowNode {
153+
pub(super) fn set_icmpv4_flow_state(&mut self, meta_packet: &MetaPacket) {
154+
let ProtocolData::IcmpData(icmp_data) = &meta_packet.protocol_data else {
155+
return;
156+
};
157+
let icmp_type = IcmpType::new(icmp_data.icmp_type);
158+
match icmp_type {
159+
IcmpTypes::AddressMaskReply => self.flow_state = FlowState::IcmpAddressMaskReply,
160+
IcmpTypes::AddressMaskRequest => self.flow_state = FlowState::IcmpAddressMaskRequest,
161+
IcmpTypes::DestinationUnreachable => {
162+
self.flow_state = FlowState::IcmpDestinationUnreachable
163+
}
164+
IcmpTypes::EchoReply => self.flow_state = FlowState::IcmpEchoReply,
165+
IcmpTypes::EchoRequest => self.flow_state = FlowState::IcmpEchoRequest,
166+
IcmpTypes::InformationReply => self.flow_state = FlowState::IcmpInformationReply,
167+
IcmpTypes::InformationRequest => self.flow_state = FlowState::IcmpInformationRequest,
168+
IcmpTypes::ParameterProblem => self.flow_state = FlowState::IcmpParameterProblem,
169+
IcmpTypes::RedirectMessage => self.flow_state = FlowState::IcmpRedirectMessage,
170+
IcmpTypes::RouterAdvertisement => self.flow_state = FlowState::IcmpRouterAdvertisement,
171+
IcmpTypes::RouterSolicitation => self.flow_state = FlowState::IcmpRouterSolicitation,
172+
IcmpTypes::SourceQuench => self.flow_state = FlowState::IcmpSourceQuench,
173+
IcmpTypes::TimeExceeded => self.flow_state = FlowState::IcmpTimeExceeded,
174+
IcmpTypes::Timestamp => self.flow_state = FlowState::IcmpTimestamp,
175+
IcmpTypes::TimestampReply => self.flow_state = FlowState::IcmpTimestampReply,
176+
IcmpTypes::Traceroute => self.flow_state = FlowState::IcmpTraceroute,
177+
_ => self.flow_state = FlowState::Established,
178+
}
179+
}
180+
181+
pub(super) fn set_icmpv6_flow_state(&mut self, meta_packet: &MetaPacket) {
182+
let ProtocolData::IcmpData(icmp_data) = &meta_packet.protocol_data else {
183+
return;
184+
};
185+
let icmp_type = Icmpv6Type::new(icmp_data.icmp_type);
186+
match icmp_type {
187+
Icmpv6Types::DestinationUnreachable => {
188+
self.flow_state = FlowState::IcmpDestinationUnreachable
189+
}
190+
Icmpv6Types::EchoReply => self.flow_state = FlowState::IcmpEchoReply,
191+
Icmpv6Types::EchoRequest => self.flow_state = FlowState::IcmpEchoRequest,
192+
Icmpv6Types::NeighborAdvert => self.flow_state = FlowState::IcmpNeighborAdvert,
193+
Icmpv6Types::NeighborSolicit => self.flow_state = FlowState::IcmpNeighborSolicit,
194+
Icmpv6Types::PacketTooBig => self.flow_state = FlowState::IcmpPacketTooBig,
195+
Icmpv6Types::ParameterProblem => self.flow_state = FlowState::IcmpParameterProblem,
196+
Icmpv6Types::Redirect => self.flow_state = FlowState::IcmpRedirectMessage,
197+
Icmpv6Types::RouterAdvert => self.flow_state = FlowState::IcmpRouterAdvertisement,
198+
Icmpv6Types::RouterSolicit => self.flow_state = FlowState::IcmpRouterSolicitation,
199+
Icmpv6Types::TimeExceeded => self.flow_state = FlowState::IcmpTimeExceeded,
200+
_ => self.flow_state = FlowState::Established,
201+
}
202+
}
203+
204+
pub(super) fn set_icmp_flow_state(&mut self, meta_packet: &MetaPacket) {
205+
match meta_packet.lookup_key.proto {
206+
IpProtocol::ICMPV4 => self.set_icmpv4_flow_state(meta_packet),
207+
IpProtocol::ICMPV6 => self.set_icmpv6_flow_state(meta_packet),
208+
_ => unreachable!(),
209+
}
210+
}
211+
148212
pub(super) fn reset_flow_stat_info(&mut self) {
149213
self.policy_in_tick = [false; 2];
150214
self.packet_in_tick = false;

agent/src/flow_generator/flow_state.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,26 @@ pub enum FlowState {
4444
EstablishReset,
4545
OpeningRst,
4646

47+
IcmpAddressMaskReply,
48+
IcmpAddressMaskRequest,
49+
IcmpDestinationUnreachable,
50+
IcmpEchoReply,
51+
IcmpEchoRequest,
52+
IcmpInformationReply,
53+
IcmpInformationRequest,
54+
IcmpParameterProblem,
55+
IcmpRedirectMessage,
56+
IcmpRouterAdvertisement,
57+
IcmpRouterSolicitation,
58+
IcmpSourceQuench,
59+
IcmpTimeExceeded,
60+
IcmpTimestamp,
61+
IcmpTimestampReply,
62+
IcmpTraceroute,
63+
IcmpNeighborAdvert,
64+
IcmpNeighborSolicit,
65+
IcmpPacketTooBig,
66+
4767
Max,
4868
}
4969

server/ingester/flow_log/log_data/l4_flow_log.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -858,11 +858,11 @@ func (k *KnowledgeGraph) FillL4(f *pb.Flow, isIPv6 bool, platformData *grpc.Plat
858858

859859
func getStatus(t datatype.CloseType, p layers.IPProtocol) datatype.LogMessageStatus {
860860
if t == datatype.CloseTypeTCPFin || t == datatype.CloseTypeForcedReport || t == datatype.CloseTypeTCPFinClientRst ||
861-
(p != layers.IPProtocolTCP && t == datatype.CloseTypeTimeout) {
861+
(p != layers.IPProtocolTCP && t == datatype.CloseTypeTimeout) || t == atatype.CloseTypeIcmpNormal {
862862
return datatype.STATUS_OK
863863
} else if t.IsClientError() {
864864
return datatype.STATUS_CLIENT_ERROR
865-
} else if p == layers.IPProtocolTCP && t.IsServerError() {
865+
} else if (p == layers.IPProtocolTCP || p == layers.IPProtocolICMPv4 || p == layers.IPProtocolICMPv6) && t.IsServerError() {
866866
return datatype.STATUS_SERVER_ERROR
867867
} else {
868868
return datatype.STATUS_NOT_EXIST

0 commit comments

Comments
 (0)