tools: tcptop: Get command name from BPF code. (#3760)

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>
diff --git a/tools/tcptop.py b/tools/tcptop.py
index 76c91af..c8bde8f 100755
--- a/tools/tcptop.py
+++ b/tools/tcptop.py
@@ -90,6 +90,7 @@
 
 struct ipv4_key_t {
     u32 pid;
+    char name[TASK_COMM_LEN];
     u32 saddr;
     u32 daddr;
     u16 lport;
@@ -102,6 +103,7 @@
     unsigned __int128 saddr;
     unsigned __int128 daddr;
     u32 pid;
+    char name[TASK_COMM_LEN];
     u16 lport;
     u16 dport;
     u64 __pad__;
@@ -125,6 +127,7 @@
     
     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 @@
 
     } 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 @@
     
     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 @@
 
     } 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 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_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 @@
                                               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 @@
                                               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)))