18
18
package collector
19
19
20
20
import (
21
+ "context"
21
22
"encoding/binary"
23
+ "fmt"
22
24
"net"
25
+ "os"
26
+
27
+ "github.com/docker/go-units"
23
28
24
29
"github.com/sirupsen/logrus"
25
30
@@ -29,6 +34,7 @@ import (
29
34
"github.com/apache/skywalking-rover/pkg/logger"
30
35
"github.com/apache/skywalking-rover/pkg/module"
31
36
"github.com/apache/skywalking-rover/pkg/tools"
37
+ "github.com/apache/skywalking-rover/pkg/tools/btf"
32
38
"github.com/apache/skywalking-rover/pkg/tools/enums"
33
39
"github.com/apache/skywalking-rover/pkg/tools/ip"
34
40
@@ -43,72 +49,108 @@ var connectLogger = logger.GetLogger("access_log", "collector", "connect")
43
49
var connectCollectInstance = NewConnectCollector ()
44
50
45
51
type ConnectCollector struct {
46
- connTracker * ip. ConnTrack
52
+ eventQueue * btf. EventQueue
47
53
}
48
54
49
55
func NewConnectCollector () * ConnectCollector {
56
+ return & ConnectCollector {}
57
+ }
58
+
59
+ func (c * ConnectCollector ) Start (_ * module.Manager , ctx * common.AccessLogContext ) error {
60
+ perCPUBufferSize , err := units .RAMInBytes (ctx .Config .ConnectionAnalyze .PerCPUBufferSize )
61
+ if err != nil {
62
+ return err
63
+ }
64
+ if int (perCPUBufferSize ) < os .Getpagesize () {
65
+ return fmt .Errorf ("the cpu buffer must bigger than %dB" , os .Getpagesize ())
66
+ }
67
+ if ctx .Config .ConnectionAnalyze .Parallels < 1 {
68
+ return fmt .Errorf ("the parallels cannot be small than 1" )
69
+ }
70
+ if ctx .Config .ConnectionAnalyze .QueueSize < 1 {
71
+ return fmt .Errorf ("the queue size be small than 1" )
72
+ }
50
73
track , err := ip .NewConnTrack ()
51
74
if err != nil {
52
75
connectLogger .Warnf ("cannot create the connection tracker, %v" , err )
53
76
}
54
- return & ConnectCollector {connTracker : track }
55
- }
77
+ c .eventQueue = btf .NewEventQueue (ctx .Config .ConnectionAnalyze .Parallels , ctx .Config .ConnectionAnalyze .QueueSize , func () btf.PartitionContext {
78
+ return newConnectionPartitionContext (ctx , track )
79
+ })
80
+ c .eventQueue .RegisterReceiver (ctx .BPF .SocketConnectionEventQueue , int (perCPUBufferSize ), func () interface {} {
81
+ return & events.SocketConnectEvent {}
82
+ }, func (data interface {}) string {
83
+ return fmt .Sprintf ("%d" , data .(* events.SocketConnectEvent ).ConID )
84
+ })
85
+ c .eventQueue .Start (ctx .RuntimeContext , ctx .BPF .Linker )
56
86
57
- func (c * ConnectCollector ) Start (_ * module.Manager , context * common.AccessLogContext ) error {
58
- context .BPF .AddTracePoint ("syscalls" , "sys_enter_connect" , context .BPF .TracepointEnterConnect )
59
- context .BPF .AddTracePoint ("syscalls" , "sys_exit_connect" , context .BPF .TracepointExitConnect )
60
- context .BPF .AddTracePoint ("syscalls" , "sys_enter_accept" , context .BPF .TracepointEnterAccept )
61
- context .BPF .AddTracePoint ("syscalls" , "sys_exit_accept" , context .BPF .TracepointExitAccept )
62
- context .BPF .AddTracePoint ("syscalls" , "sys_enter_accept4" , context .BPF .TracepointEnterAccept )
63
- context .BPF .AddTracePoint ("syscalls" , "sys_exit_accept4" , context .BPF .TracepointExitAccept )
87
+ ctx .BPF .AddTracePoint ("syscalls" , "sys_enter_connect" , ctx .BPF .TracepointEnterConnect )
88
+ ctx .BPF .AddTracePoint ("syscalls" , "sys_exit_connect" , ctx .BPF .TracepointExitConnect )
89
+ ctx .BPF .AddTracePoint ("syscalls" , "sys_enter_accept" , ctx .BPF .TracepointEnterAccept )
90
+ ctx .BPF .AddTracePoint ("syscalls" , "sys_exit_accept" , ctx .BPF .TracepointExitAccept )
91
+ ctx .BPF .AddTracePoint ("syscalls" , "sys_enter_accept4" , ctx .BPF .TracepointEnterAccept )
92
+ ctx .BPF .AddTracePoint ("syscalls" , "sys_exit_accept4" , ctx .BPF .TracepointExitAccept )
64
93
65
- context .BPF .AddLink (link .Kprobe , map [string ]* ebpf.Program {
66
- "tcp_connect" : context .BPF .TcpConnect ,
94
+ ctx .BPF .AddLink (link .Kprobe , map [string ]* ebpf.Program {
95
+ "tcp_connect" : ctx .BPF .TcpConnect ,
67
96
})
68
- context .BPF .AddLink (link .Kretprobe , map [string ]* ebpf.Program {
69
- "sock_alloc" : context .BPF .SockAllocRet ,
97
+ ctx .BPF .AddLink (link .Kretprobe , map [string ]* ebpf.Program {
98
+ "sock_alloc" : ctx .BPF .SockAllocRet ,
70
99
})
71
- context .BPF .AddLink (link .Kprobe , map [string ]* ebpf.Program {
72
- "ip4_datagram_connect" : context .BPF .Ip4UdpDatagramConnect ,
100
+ ctx .BPF .AddLink (link .Kprobe , map [string ]* ebpf.Program {
101
+ "ip4_datagram_connect" : ctx .BPF .Ip4UdpDatagramConnect ,
73
102
})
74
103
75
- _ = context .BPF .AddLinkOrError (link .Kprobe , map [string ]* ebpf.Program {
76
- "__nf_conntrack_hash_insert" : context .BPF .NfConntrackHashInsert ,
104
+ _ = ctx .BPF .AddLinkOrError (link .Kprobe , map [string ]* ebpf.Program {
105
+ "__nf_conntrack_hash_insert" : ctx .BPF .NfConntrackHashInsert ,
77
106
})
78
- _ = context .BPF .AddLinkOrError (link .Kprobe , map [string ]* ebpf.Program {
79
- "nf_confirm" : context .BPF .NfConfirm ,
107
+ _ = ctx .BPF .AddLinkOrError (link .Kprobe , map [string ]* ebpf.Program {
108
+ "nf_confirm" : ctx .BPF .NfConfirm ,
80
109
})
81
- _ = context .BPF .AddLinkOrError (link .Kprobe , map [string ]* ebpf.Program {
82
- "ctnetlink_fill_info" : context .BPF .NfCtnetlinkFillInfo ,
83
- })
84
-
85
- context .BPF .ReadEventAsync (context .BPF .SocketConnectionEventQueue , func (data interface {}) {
86
- event := data .(* events.SocketConnectEvent )
87
- connectLogger .Debugf ("receive connect event, connection ID: %d, randomID: %d, " +
88
- "pid: %d, fd: %d, role: %s: func: %s, family: %d, success: %d, conntrack exist: %t" ,
89
- event .ConID , event .RandomID , event .PID , event .SocketFD , enums .ConnectionRole (event .Role ), enums .SocketFunctionName (event .FuncName ),
90
- event .SocketFamily , event .ConnectSuccess , event .ConnTrackUpstreamPort != 0 )
91
- socketPair := c .buildSocketFromConnectEvent (event )
92
- if socketPair == nil {
93
- connectLogger .Debugf ("cannot found the socket paire from connect event, connection ID: %d, randomID: %d" ,
94
- event .ConID , event .RandomID )
95
- return
96
- }
97
- connectLogger .Debugf ("build socket pair success, connection ID: %d, randomID: %d, role: %s, local: %s:%d, remote: %s:%d" ,
98
- event .ConID , event .RandomID , socketPair .Role , socketPair .SrcIP , socketPair .SrcPort , socketPair .DestIP , socketPair .DestPort )
99
- context .ConnectionMgr .OnConnectEvent (event , socketPair )
100
- forwarder .SendConnectEvent (context , event , socketPair )
101
- }, func () interface {} {
102
- return & events.SocketConnectEvent {}
110
+ _ = ctx .BPF .AddLinkOrError (link .Kprobe , map [string ]* ebpf.Program {
111
+ "ctnetlink_fill_info" : ctx .BPF .NfCtnetlinkFillInfo ,
103
112
})
104
-
105
113
return nil
106
114
}
107
115
108
116
func (c * ConnectCollector ) Stop () {
109
117
}
110
118
111
- func (c * ConnectCollector ) fixSocketFamilyIfNeed (event * events.SocketConnectEvent , result * ip.SocketPair ) {
119
+ type ConnectionPartitionContext struct {
120
+ context * common.AccessLogContext
121
+ connTracker * ip.ConnTrack
122
+ }
123
+
124
+ func newConnectionPartitionContext (ctx * common.AccessLogContext , connTracker * ip.ConnTrack ) * ConnectionPartitionContext {
125
+ return & ConnectionPartitionContext {
126
+ context : ctx ,
127
+ connTracker : connTracker ,
128
+ }
129
+ }
130
+
131
+ func (c * ConnectionPartitionContext ) Start (ctx context.Context ) {
132
+
133
+ }
134
+
135
+ func (c * ConnectionPartitionContext ) Consume (data interface {}) {
136
+ event := data .(* events.SocketConnectEvent )
137
+ connectLogger .Debugf ("receive connect event, connection ID: %d, randomID: %d, " +
138
+ "pid: %d, fd: %d, role: %s: func: %s, family: %d, success: %d, conntrack exist: %t" ,
139
+ event .ConID , event .RandomID , event .PID , event .SocketFD , enums .ConnectionRole (event .Role ), enums .SocketFunctionName (event .FuncName ),
140
+ event .SocketFamily , event .ConnectSuccess , event .ConnTrackUpstreamPort != 0 )
141
+ socketPair := c .buildSocketFromConnectEvent (event )
142
+ if socketPair == nil {
143
+ connectLogger .Debugf ("cannot found the socket paire from connect event, connection ID: %d, randomID: %d" ,
144
+ event .ConID , event .RandomID )
145
+ return
146
+ }
147
+ connectLogger .Debugf ("build socket pair success, connection ID: %d, randomID: %d, role: %s, local: %s:%d, remote: %s:%d" ,
148
+ event .ConID , event .RandomID , socketPair .Role , socketPair .SrcIP , socketPair .SrcPort , socketPair .DestIP , socketPair .DestPort )
149
+ c .context .ConnectionMgr .OnConnectEvent (event , socketPair )
150
+ forwarder .SendConnectEvent (c .context , event , socketPair )
151
+ }
152
+
153
+ func (c * ConnectionPartitionContext ) fixSocketFamilyIfNeed (event * events.SocketConnectEvent , result * ip.SocketPair ) {
112
154
if result == nil {
113
155
return
114
156
}
@@ -128,7 +170,7 @@ func (c *ConnectCollector) fixSocketFamilyIfNeed(event *events.SocketConnectEven
128
170
}
129
171
}
130
172
131
- func (c * ConnectCollector ) buildSocketFromConnectEvent (event * events.SocketConnectEvent ) * ip.SocketPair {
173
+ func (c * ConnectionPartitionContext ) buildSocketFromConnectEvent (event * events.SocketConnectEvent ) * ip.SocketPair {
132
174
if event .SocketFamily != unix .AF_INET && event .SocketFamily != unix .AF_INET6 && event .SocketFamily != enums .SocketFamilyUnknown {
133
175
// if not ipv4, ipv6 or unknown, ignore
134
176
return nil
@@ -160,7 +202,7 @@ func (c *ConnectCollector) buildSocketFromConnectEvent(event *events.SocketConne
160
202
return pair
161
203
}
162
204
163
- func (c * ConnectCollector ) isOnlyLocalPortEmpty (socketPair * ip.SocketPair ) bool {
205
+ func (c * ConnectionPartitionContext ) isOnlyLocalPortEmpty (socketPair * ip.SocketPair ) bool {
164
206
if socketPair == nil {
165
207
return false
166
208
}
@@ -172,7 +214,7 @@ func (c *ConnectCollector) isOnlyLocalPortEmpty(socketPair *ip.SocketPair) bool
172
214
return socketPair .IsValid ()
173
215
}
174
216
175
- func (c * ConnectCollector ) buildSocketPair (event * events.SocketConnectEvent ) * ip.SocketPair {
217
+ func (c * ConnectionPartitionContext ) buildSocketPair (event * events.SocketConnectEvent ) * ip.SocketPair {
176
218
var result * ip.SocketPair
177
219
haveConnTrack := false
178
220
if event .SocketFamily == unix .AF_INET {
@@ -232,7 +274,7 @@ func (c *ConnectCollector) buildSocketPair(event *events.SocketConnectEvent) *ip
232
274
return result
233
275
}
234
276
235
- func (c * ConnectCollector ) tryToUpdateSocketFromConntrack (event * events.SocketConnectEvent , socket * ip.SocketPair ) {
277
+ func (c * ConnectionPartitionContext ) tryToUpdateSocketFromConntrack (event * events.SocketConnectEvent , socket * ip.SocketPair ) {
236
278
if socket != nil && socket .IsValid () && c .connTracker != nil && ! tools .IsLocalHostAddress (socket .DestIP ) &&
237
279
event .FuncName != enums .SocketFunctionNameAccept { // accept event don't need to update the remote address
238
280
// if no contract and socket data is valid, then trying to get the remote address from the socket
0 commit comments