You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@skywalking.apache.org by li...@apache.org on 2022/08/05 01:29:45 UTC
[skywalking-rover] branch main updated: Support BoringSSL in Envoy (#44)
This is an automated email from the ASF dual-hosted git repository.
liuhan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-rover.git
The following commit(s) were added to refs/heads/main by this push:
new 6d6f622 Support BoringSSL in Envoy (#44)
6d6f622 is described below
commit 6d6f62210717464e5170c92e3c99c2900ffe10c0
Author: mrproliu <74...@qq.com>
AuthorDate: Fri Aug 5 09:29:42 2022 +0800
Support BoringSSL in Envoy (#44)
---
CHANGES.md | 2 +-
bpf/profiling/network/netmonitor.c | 6 +++++
bpf/profiling/network/openssl.c | 16 ++++----------
bpf/profiling/network/openssl.h | 8 -------
bpf/profiling/network/sock_stats.h | 11 ++++++++-
docs/en/setup/configuration/profiling.md | 23 +++++++++++++++++--
pkg/profiling/task/network/context.go | 6 +++++
pkg/profiling/task/network/runner.go | 9 ++++----
pkg/profiling/task/network/ssl.go | 38 ++++++++++++++++++++++++++++++++
9 files changed, 90 insertions(+), 29 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index 8c74a6b..5213e78 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -7,7 +7,7 @@ Release Notes.
#### Features
* Support `NETWORK` Profiling.
* Let the logger as a configurable module.
-* Support analyze the data of OpenSSL library in `NETWORK` Profiling.
+* Support analyze the data of OpenSSL, BoringSSL library in `NETWORK` Profiling.
#### Bug Fixes
* Fixed reading process paths incorrect when running as a container.
diff --git a/bpf/profiling/network/netmonitor.c b/bpf/profiling/network/netmonitor.c
index b7262fc..c929b22 100644
--- a/bpf/profiling/network/netmonitor.c
+++ b/bpf/profiling/network/netmonitor.c
@@ -307,6 +307,12 @@ static __always_inline void process_write_data(struct pt_regs *ctx, __u64 id, st
if (family_should_trace(conn->socket_family) == false) {
return;
}
+ // process the ssl request if the fd not found
+ struct sock_data_args_t *ssl_data_args = bpf_map_lookup_elem(&openssl_sock_data_args, &id);
+ if (ssl_data_args != NULL && ssl_data_args->fd == 0) {
+ ssl_data_args->fd = args->fd;
+ conn->ssl = true;
+ }
// if connect event is not sent
if (conn->connect_event_send == false) {
diff --git a/bpf/profiling/network/openssl.c b/bpf/profiling/network/openssl.c
index 3bd81ed..124c34d 100644
--- a/bpf/profiling/network/openssl.c
+++ b/bpf/profiling/network/openssl.c
@@ -39,14 +39,14 @@ static int get_fd_symaddr(__u32 tgid, bool read, void* ssl) {
}
static int get_fd(uint32_t tgid, bool read, void* ssl) {
- int fd = -1;
+ int fd = 0;
fd = get_fd_symaddr(tgid, read, ssl);
if (fd > 2) {
return fd;
}
- return -1;
+ return 0;
}
SEC("uprobe/ssl_write")
@@ -56,10 +56,6 @@ int openssl_write(struct pt_regs* ctx) {
void* ssl = (void*)PT_REGS_PARM1(ctx);
__u32 fd = get_fd(tgid, false, ssl);
- bpf_printk("ssl_write fd: %d\n", fd);
- if (fd < 0) {
- return 0;
- }
char* buf = (char*)PT_REGS_PARM2(ctx);
struct sock_data_args_t data_args = {};
@@ -75,7 +71,7 @@ SEC("uretprobe/ssl_write")
int openssl_write_ret(struct pt_regs* ctx) {
__u64 id = bpf_get_current_pid_tgid();
struct sock_data_args_t *args = bpf_map_lookup_elem(&openssl_sock_data_args, &id);
- if (args) {
+ if (args && args->fd > 0) {
process_openssl_data(ctx, id, SOCK_DATA_DIRECTION_EGRESS, args, SOCKET_OPTS_TYPE_SSL_WRITE);
}
bpf_map_delete_elem(&openssl_sock_data_args, &id);
@@ -89,10 +85,6 @@ int openssl_read(struct pt_regs* ctx) {
void* ssl = (void*)PT_REGS_PARM1(ctx);
__u32 fd = get_fd(tgid, true, ssl);
- bpf_printk("ssl_read fd: %d\n", fd);
- if (fd < 0) {
- return 0;
- }
char* buf = (char*)PT_REGS_PARM2(ctx);
struct sock_data_args_t data_args = {};
@@ -108,7 +100,7 @@ SEC("uretprobe/ssl_read")
int openssl_read_ret(struct pt_regs* ctx) {
__u64 id = bpf_get_current_pid_tgid();
struct sock_data_args_t *args = bpf_map_lookup_elem(&openssl_sock_data_args, &id);
- if (args) {
+ if (args && args->fd > 0) {
process_openssl_data(ctx, id, SOCK_DATA_DIRECTION_INGRESS, args, SOCKET_OPTS_TYPE_SSL_READ);
}
bpf_map_delete_elem(&openssl_sock_data_args, &id);
diff --git a/bpf/profiling/network/openssl.h b/bpf/profiling/network/openssl.h
index 11536be..61e8425 100644
--- a/bpf/profiling/network/openssl.h
+++ b/bpf/profiling/network/openssl.h
@@ -33,11 +33,3 @@ static __inline struct openssl_fd_symaddr* get_openssl_fd_symaddr(__u32 tgid) {
struct openssl_fd_symaddr *addr = bpf_map_lookup_elem(&openssl_fd_symaddr_finder, &tgid);
return addr;
}
-
-// openssl read or write
-struct {
- __uint(type, BPF_MAP_TYPE_HASH);
- __uint(max_entries, 10000);
- __type(key, __u64);
- __type(value, struct sock_data_args_t);
-} openssl_sock_data_args SEC(".maps");
\ No newline at end of file
diff --git a/bpf/profiling/network/sock_stats.h b/bpf/profiling/network/sock_stats.h
index 018bc69..f3fde47 100644
--- a/bpf/profiling/network/sock_stats.h
+++ b/bpf/profiling/network/sock_stats.h
@@ -56,6 +56,7 @@ struct active_connection_t {
// for protocol analyze
__u32 protocol;
+ __u32 fix;
__u64 prev_count;
char prev_buf[4];
__u32 prepend_length_header;
@@ -245,4 +246,12 @@ struct socket_exception_operation_event_t {
};
struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
-} socket_exception_operation_event_queue SEC(".maps");
\ No newline at end of file
+} socket_exception_operation_event_queue SEC(".maps");
+
+// openssl read or write
+struct {
+ __uint(type, BPF_MAP_TYPE_HASH);
+ __uint(max_entries, 10000);
+ __type(key, __u64);
+ __type(value, struct sock_data_args_t);
+} openssl_sock_data_args SEC(".maps");
\ No newline at end of file
diff --git a/docs/en/setup/configuration/profiling.md b/docs/en/setup/configuration/profiling.md
index 1a3db98..0e3ba42 100644
--- a/docs/en/setup/configuration/profiling.md
+++ b/docs/en/setup/configuration/profiling.md
@@ -9,17 +9,36 @@ and send the snapshot to the backend server.
|------|---------|-----------------|-------------|
| profiling.active | true | ROVER_PROFILING_ACTIVE | Is active the process profiling. |
| profiling.check_interval | 10s | ROVER_PROFILING_CHECK_INTERVAL | Check the profiling task interval. |
-| profiling.flush_interval | 5s | Combine existing profiling data and report to the backend interval |
+| profiling.flush_interval | 5s | Combine existing profiling data and report to the backend interval. |
+| task.on_cpu.dump_period | 9ms | The on CPU profiling thread stack dump period. |
+| task.network.report_interval | 2s | The interval of send network profiling metrics to the backend. |
+| task.network.meter_prefix | rover_net_p | The prefix of network profiling metrics name. |
## Profiling Type
-All the profiling tasks are using the [Linux Official Function](https://man7.org/linux/man-pages/man2/perf_event_open.2.html) to open perf event,
+All the profiling tasks are using the [Linux Official Function](https://man7.org/linux/man-pages/man2/perf_event_open.2.html) and `kprobe` or `uprobe` to open perf event,
and attach the eBPF Program to dump stacks.
### On CPU
On CPU Profiling task is using `PERF_COUNT_SW_CPU_CLOCK` to profiling the process with the CPU clock.
+### Off CPU
+
+Off CPU Profiling task is attach the `finish_task_switch` in `krobe` to profiling the process.
+
+### Network
+
+Network Profiling task is intercept IO-related syscall and `urprobe` in process to identify the network traffic and generate the metrics.
+Also, the following protocol are supported for analyzing using OpenSSL library, BoringSSL library or plaintext:
+
+1. HTTP
+2. MySQL
+3. CQL(The Cassandra Query Language)
+4. MongoDB
+5. Kafka
+6. DNS
+
## Configuration
| Name | Default | Environment Key | Description |
diff --git a/pkg/profiling/task/network/context.go b/pkg/profiling/task/network/context.go
index cba0ce2..644d220 100644
--- a/pkg/profiling/task/network/context.go
+++ b/pkg/profiling/task/network/context.go
@@ -282,6 +282,7 @@ type ActiveConnectionInBPF struct {
// Protocol analyze context
Protocol ConnectionProtocol
+ Fix uint32
ProtocolPrevCount uint64
ProtocolPrevBuf [4]byte
ProtocolPrependHeader uint32
@@ -325,6 +326,11 @@ func (c *Context) fillConnectionMetrics(ccs []*ConnectionContext) {
continue
}
+ if log.Enable(logrus.DebugLevel) {
+ marshal, _ := json.Marshal(activeConnection)
+ log.Debugf("found the active connection, conid: %d, data: %s", cc.ConnectionID, string(marshal))
+ }
+
if cc.Role == ConnectionRoleUnknown && activeConnection.Role != ConnectionRoleUnknown {
cc.Role = activeConnection.Role
}
diff --git a/pkg/profiling/task/network/runner.go b/pkg/profiling/task/network/runner.go
index 7581ade..7b00c19 100644
--- a/pkg/profiling/task/network/runner.go
+++ b/pkg/profiling/task/network/runner.go
@@ -107,6 +107,7 @@ func (r *Runner) Start(ctx context.Context, processes []api.ProcessInterface) er
r.bpfContext.StartSocketAddressParser(r.ctx)
// sock opts
+ r.linker.AddSysCall("close", objs.SysClose, objs.SysCloseRet)
r.linker.AddSysCall("connect", objs.SysConnect, objs.SysConnectRet)
r.linker.AddSysCall("accept", objs.SysAccept, objs.SysAcceptRet)
r.linker.AddSysCall("accept4", objs.SysAccept, objs.SysAcceptRet)
@@ -136,9 +137,6 @@ func (r *Runner) Start(ctx context.Context, processes []api.ProcessInterface) er
r.linker.AddLink(link.Kprobe, objs.TcpRetransmit, "tcp_retransmit_skb")
r.linker.AddLink(link.Kprobe, objs.TcpDrop, "tcp_drop")
- // close socket
- r.linker.AddSysCall("close", objs.SysClose, objs.SysCloseRet)
-
if err := r.linker.HasError(); err != nil {
_ = r.linker.Close()
return err
@@ -178,9 +176,10 @@ func (r *Runner) flushMetrics() error {
if log.Enable(logrus.DebugLevel) {
for _, con := range connections {
- log.Debugf("found connection: %d, %s relation: %s:%d(%d) -> %s:%d, read: %d bytes/%d, write: %d bytes/%d",
+ log.Debugf("found connection: %d, %s relation: %s:%d(%d) -> %s:%d, protocol: %s, is_ssl: %t, read: %d bytes/%d, write: %d bytes/%d",
con.ConnectionID, con.Role.String(),
- con.LocalIP, con.LocalPort, con.LocalPid, con.RemoteIP, con.RemotePort, con.WriteCounter.Cur.Bytes, con.WriteCounter.Cur.Count,
+ con.LocalIP, con.LocalPort, con.LocalPid, con.RemoteIP, con.RemotePort,
+ con.Protocol.String(), con.IsSSL, con.WriteCounter.Cur.Bytes, con.WriteCounter.Cur.Count,
con.ReadCounter.Cur.Bytes, con.ReadCounter.Cur.Count)
}
}
diff --git a/pkg/profiling/task/network/ssl.go b/pkg/profiling/task/network/ssl.go
index a69782b..aac49bf 100644
--- a/pkg/profiling/task/network/ssl.go
+++ b/pkg/profiling/task/network/ssl.go
@@ -50,6 +50,11 @@ func addSSLProcess(pid int, bpf *bpfObjects, linker *Linker) error {
return err1
}
+ // envoy with boring ssl
+ if err1 := processEnvoyProcess(pid, bpf, linker, modules); err1 != nil {
+ return err1
+ }
+
return nil
}
@@ -90,6 +95,39 @@ func processOpenSSLProcess(pid int, bpf *bpfObjects, linker *Linker, modules []*
return linker.HasError()
}
+func processEnvoyProcess(pid int, bpf *bpfObjects, linker *Linker, modules []*profiling.Module) error {
+ moduleName := "/envoy"
+ processModules, err := findProcessModules(modules, moduleName)
+ if err != nil {
+ return err
+ }
+ envoyModule := processModules[moduleName]
+ if envoyModule == nil {
+ return nil
+ }
+ var readSymbol, writeSymbol bool
+ for _, sym := range envoyModule.Symbols {
+ if sym.Name == "SSL_read" {
+ readSymbol = true
+ } else if sym.Name == "SSL_write" {
+ writeSymbol = true
+ }
+ }
+ if !readSymbol || !writeSymbol {
+ log.Debugf("found the envoy process, but the ssl read or write symbol not exists, so ignore. read: %t, write: %t",
+ readSymbol, writeSymbol)
+ return nil
+ }
+
+ log.Debugf("found current module is envoy, so attach to the SSL read and write")
+
+ // attach the linker
+ libSSLLinker := linker.OpenUProbeExeFile(envoyModule.Path)
+ libSSLLinker.AddLink("SSL_write", bpf.OpensslWrite, bpf.OpensslWriteRet, pid)
+ libSSLLinker.AddLink("SSL_read", bpf.OpensslRead, bpf.OpensslReadRet, pid)
+ return linker.HasError()
+}
+
func findProcessModules(modules []*profiling.Module, moduleNames ...string) (map[string]*profiling.Module, error) {
result := make(map[string]*profiling.Module)
for _, mod := range modules {