tools: tcptop: Get command name from BPF code. (#3760)
authoreiffel-fl <flaniel@linux.microsoft.com>
Sat, 18 Dec 2021 18:21:13 +0000 (19:21 +0100)
committerGitHub <noreply@github.com>
Sat, 18 Dec 2021 18:21:13 +0000 (10:21 -0800)
Before this commit, command name was taken from PID using /proc/PID/comm.
But this method was not reliable as it does not work all the time.
So, this commit takes command name from BPF code using bpf_get_current_comm()
helper like it is done for biotop.

Signed-off-by: Francis Laniel <flaniel@linux.microsoft.com>
tools/tcptop.py

index 76c91affd8955c9174bc99b7ef8619f1bc2de212..c8bde8f61d148da2760de6509fe5156019fd2494 100755 (executable)
@@ -90,6 +90,7 @@ bpf_text = """
 
 struct ipv4_key_t {
     u32 pid;
+    char name[TASK_COMM_LEN];
     u32 saddr;
     u32 daddr;
     u16 lport;
@@ -102,6 +103,7 @@ struct ipv6_key_t {
     unsigned __int128 saddr;
     unsigned __int128 daddr;
     u32 pid;
+    char name[TASK_COMM_LEN];
     u16 lport;
     u16 dport;
     u64 __pad__;
@@ -125,6 +127,7 @@ int kprobe__tcp_sendmsg(struct pt_regs *ctx, struct sock *sk,
     
     if (family == AF_INET) {
         struct ipv4_key_t ipv4_key = {.pid = pid};
+        bpf_get_current_comm(&ipv4_key.name, sizeof(ipv4_key.name));
         ipv4_key.saddr = sk->__sk_common.skc_rcv_saddr;
         ipv4_key.daddr = sk->__sk_common.skc_daddr;
         ipv4_key.lport = sk->__sk_common.skc_num;
@@ -134,6 +137,7 @@ int kprobe__tcp_sendmsg(struct pt_regs *ctx, struct sock *sk,
 
     } else if (family == AF_INET6) {
         struct ipv6_key_t ipv6_key = {.pid = pid};
+        bpf_get_current_comm(&ipv6_key.name, sizeof(ipv6_key.name));
         bpf_probe_read_kernel(&ipv6_key.saddr, sizeof(ipv6_key.saddr),
             &sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
         bpf_probe_read_kernel(&ipv6_key.daddr, sizeof(ipv6_key.daddr),
@@ -173,6 +177,7 @@ int kprobe__tcp_cleanup_rbuf(struct pt_regs *ctx, struct sock *sk, int copied)
     
     if (family == AF_INET) {
         struct ipv4_key_t ipv4_key = {.pid = pid};
+        bpf_get_current_comm(&ipv4_key.name, sizeof(ipv4_key.name));
         ipv4_key.saddr = sk->__sk_common.skc_rcv_saddr;
         ipv4_key.daddr = sk->__sk_common.skc_daddr;
         ipv4_key.lport = sk->__sk_common.skc_num;
@@ -182,6 +187,7 @@ int kprobe__tcp_cleanup_rbuf(struct pt_regs *ctx, struct sock *sk, int copied)
 
     } else if (family == AF_INET6) {
         struct ipv6_key_t ipv6_key = {.pid = pid};
+        bpf_get_current_comm(&ipv6_key.name, sizeof(ipv6_key.name));
         bpf_probe_read_kernel(&ipv6_key.saddr, sizeof(ipv6_key.saddr),
             &sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
         bpf_probe_read_kernel(&ipv6_key.daddr, sizeof(ipv6_key.daddr),
@@ -216,17 +222,11 @@ if debug or args.ebpf:
     if args.ebpf:
         exit()
 
-TCPSessionKey = namedtuple('TCPSession', ['pid', 'laddr', 'lport', 'daddr', 'dport'])
-
-def pid_to_comm(pid):
-    try:
-        comm = open("/proc/%d/comm" % pid, "r").read().rstrip()
-        return comm
-    except IOError:
-        return str(pid)
+TCPSessionKey = namedtuple('TCPSession', ['pid', 'name', 'laddr', 'lport', 'daddr', 'dport'])
 
 def get_ipv4_session_key(k):
     return TCPSessionKey(pid=k.pid,
+                         name=k.name,
                          laddr=inet_ntop(AF_INET, pack("I", k.saddr)),
                          lport=k.lport,
                          daddr=inet_ntop(AF_INET, pack("I", k.daddr)),
@@ -234,6 +234,7 @@ def get_ipv4_session_key(k):
 
 def get_ipv6_session_key(k):
     return TCPSessionKey(pid=k.pid,
+                         name=k.name,
                          laddr=inet_ntop(AF_INET6, k.saddr),
                          lport=k.lport,
                          daddr=inet_ntop(AF_INET6, k.daddr),
@@ -288,7 +289,7 @@ while i != args.count and not exiting:
                                               key=lambda kv: sum(kv[1]),
                                               reverse=True):
         print("%-6d %-12.12s %-21s %-21s %6d %6d" % (k.pid,
-            pid_to_comm(k.pid),
+            k.name,
             k.laddr + ":" + str(k.lport),
             k.daddr + ":" + str(k.dport),
             int(recv_bytes / 1024), int(send_bytes / 1024)))
@@ -315,7 +316,7 @@ while i != args.count and not exiting:
                                               key=lambda kv: sum(kv[1]),
                                               reverse=True):
         print("%-6d %-12.12s %-32s %-32s %6d %6d" % (k.pid,
-            pid_to_comm(k.pid),
+            k.name,
             k.laddr + ":" + str(k.lport),
             k.daddr + ":" + str(k.dport),
             int(recv_bytes / 1024), int(send_bytes / 1024)))