* [PATCH iproute2] ss: add -P/--process-age option to display process runtime
@ 2026-09-15 18:35 Harshith Hari
2026-09-15 20:44 ` Stephen Hemminger
0 siblings, 1 reply; 2+ messages in thread
From: Harshith Hari @ 2026-09-15 18:35 UTC (permalink / raw)
To: netdev; +Cc: stephen, Harshith Hari
Add a new option (-P/--process-age) to display process uptime/age
alongside process info inside socket user context output.
Signed-off-by: Harshith Hari <harshithhari000111@gmail.com>
---
man/man8/ss.8 | 3 +
misc/ss.c | 456 ++++++++++++++++++++++++++++++--------------------
2 files changed, 282 insertions(+), 177 deletions(-)
diff --git a/man/man8/ss.8 b/man/man8/ss.8
index b0629b82..5f345c21 100644
--- a/man/man8/ss.8
+++ b/man/man8/ss.8
@@ -163,6 +163,9 @@ the number of packets dropped before they are de-multiplexed into the socket
.TP
\.B \-P, \-\-process\-age
Show process age/runtime alongside process socket information.
+.TP
+\.B \-P, \-\-process\-age
+Show process age/runtime alongside process socket information.
Show processes using sockets.
.TP
.B \-T, \-\-threads
diff --git a/misc/ss.c b/misc/ss.c
index 6c32455d..66fb1fee 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -56,58 +56,58 @@ static int show_process_age;
static void print_process_age(pid_t pid)
{
-char path[64];
-FILE *f;
-unsigned long long starttime;
-double uptime = 0.0;
-long clock_ticks = sysconf(_SC_CLK_TCK);
-
-f = fopen("/proc/uptime", "r");
-if (!f)
-return;
-
-if (fscanf(f, "%lf", &uptime) != 1) {
-fclose(f);
-return;
-}
-fclose(f);
+ char path[64];
+ FILE *f;
+ unsigned long long starttime;
+ double uptime = 0.0;
+ long clock_ticks = sysconf(_SC_CLK_TCK);
+
+ f = fopen("/proc/uptime", "r");
+ if (!f)
+ return;
-snprintf(path, sizeof(path), "/proc/%d/stat", pid);
-f = fopen(path, "r");
-if (!f)
-return;
+ if (fscanf(f, "%lf", &uptime) != 1) {
+ fclose(f);
+ return;
+ }
+ fclose(f);
-char buf[1024];
+ snprintf(path, sizeof(path), "/proc/%d/stat", pid);
+ f = fopen(path, "r");
+ if (!f)
+ return;
-if (fgets(buf, sizeof(buf), f)) {
-char *ptr = strrchr(buf, ')');
+ char buf[1024];
-if (ptr) {
-int field = 3;
+ if (fgets(buf, sizeof(buf), f)) {
+ char *ptr = strrchr(buf, ')');
-ptr++;
-while (*ptr && field < 22) {
-if (*ptr == ' ')
-field++;
-ptr++;
-}
-if (sscanf(ptr, "%llu", &starttime) == 1) {
-double process_secs = uptime - ((double)starttime / clock_ticks);
-long secs = (long)process_secs;
-long hours = secs / 3600;
-long mins = (secs % 3600) / 60;
-long s = secs % 60;
+ if (ptr) {
+ int field = 3;
-if (hours > 0)
-out(",age=%ldh%ldm", hours, mins);
-else if (mins > 0)
-out(",age=%ldm%lds", mins, s);
-else
-out(",age=%lds", s);
-}
-}
-}
-fclose(f);
+ ptr++;
+ while (*ptr && field < 22) {
+ if (*ptr == ' ')
+ field++;
+ ptr++;
+ }
+ if (sscanf(ptr, "%llu", &starttime) == 1) {
+ double process_secs = uptime - ((double)starttime / clock_ticks);
+ long secs = (long)process_secs;
+ long hours = secs / 3600;
+ long mins = (secs % 3600) / 60;
+ long s = secs % 60;
+
+ if (hours > 0)
+ out(",age=%ldh%ldm", hours, mins);
+ else if (mins > 0)
+ out(",age=%ldm%lds", mins, s);
+ else
+ out(",age=%lds", s);
+ }
+ }
+ }
+ fclose(f);
}
@@ -115,57 +115,58 @@ static int show_process_age;
static void print_process_age(pid_t pid)
{
-char path[64];
-FILE *f;
-unsigned long long starttime;
-double uptime = 0.0;
-long clock_ticks = sysconf(_SC_CLK_TCK);
+ char path[64];
+ FILE *f;
+ unsigned long long starttime;
+ double uptime = 0.0;
+ long clock_ticks = sysconf(_SC_CLK_TCK);
-f = fopen("/proc/uptime", "r");
-if (!f)
-return;
-if (fscanf(f, "%lf", &uptime) != 1) {
-fclose(f);
-return;
-}
-fclose(f);
+ f = fopen("/proc/uptime", "r");
+ if (!f)
+ return;
-snprintf(path, sizeof(path), "/proc/%d/stat", pid);
-f = fopen(path, "r");
-if (!f)
-return;
+ if (fscanf(f, "%lf", &uptime) != 1) {
+ fclose(f);
+ return;
+ }
+ fclose(f);
-char buf[1024];
+ snprintf(path, sizeof(path), "/proc/%d/stat", pid);
+ f = fopen(path, "r");
+ if (!f)
+ return;
-if (fgets(buf, sizeof(buf), f)) {
-char *ptr = strrchr(buf, ')');
+ char buf[1024];
-if (ptr) {
-int field = 3;
+ if (fgets(buf, sizeof(buf), f)) {
+ char *ptr = strrchr(buf, ')');
-ptr++;
-while (*ptr && field < 22) {
-if (*ptr == ' ')
-field++;
-ptr++;
-}
-if (sscanf(ptr, "%llu", &starttime) == 1) {
-double process_secs = uptime - ((double)starttime / clock_ticks);
-long secs = (long)process_secs;
-long hours = secs / 3600;
-long mins = (secs % 3600) / 60;
-long s = secs % 60;
+ if (ptr) {
+ int field = 3;
-if (hours > 0)
-out(",age=%ldh%ldm", hours, mins);
-else if (mins > 0)
-out(",age=%ldm%lds", mins, s);
-else
-out(",age=%lds", s);
-}
-}
-}
-fclose(f);
+ ptr++;
+ while (*ptr && field < 22) {
+ if (*ptr == ' ')
+ field++;
+ ptr++;
+ }
+ if (sscanf(ptr, "%llu", &starttime) == 1) {
+ double process_secs = uptime - ((double)starttime / clock_ticks);
+ long secs = (long)process_secs;
+ long hours = secs / 3600;
+ long mins = (secs % 3600) / 60;
+ long s = secs % 60;
+
+ if (hours > 0)
+ out(",age=%ldh%ldm", hours, mins);
+ else if (mins > 0)
+ out(",age=%ldm%lds", mins, s);
+ else
+ out(",age=%lds", s);
+ }
+ }
+ }
+ fclose(f);
}
@@ -892,12 +893,12 @@ static int find_entry(unsigned int ino, char **buf, int type)
show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
@@ -1088,12 +1089,12 @@ static const char *unix_netid_name(int type)
show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
@@ -1114,12 +1115,12 @@ static const char *proto_name(int protocol)
show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
@@ -1147,12 +1148,12 @@ static const char *vsock_netid_name(int type)
show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
@@ -1172,12 +1173,12 @@ static const char *tipc_netid_name(int type)
show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
@@ -1656,12 +1657,12 @@ static void sock_state_print(struct sockstat *s)
show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
@@ -2037,12 +2038,12 @@ static int run_ssfilter(struct ssfilter *f, struct sockstat *s)
show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
@@ -2174,12 +2175,12 @@ static int ssfilter_bytecompile(struct ssfilter *f, char **bytecode)
show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
@@ -2727,42 +2728,76 @@ static void proc_ctx_print(struct sockstat *s)
if (find_entry(s->ino, &buf,
(show_proc_ctx & show_sock_ctx) ?
PROC_SOCK_CTX : PROC_CTX) > 0) {
- out(" users:(%s)", buf);
+ if (show_process_age) {
+ char *ptr_p = buf;
+
+ out(" users:(");
+ while (*ptr_p) {
+ char *pid_ptr = strstr(ptr_p, "pid=");
+
+ if (pid_ptr) {
+ char *close_paren = strchr(pid_ptr, ')');
+
+ if (close_paren) {
+ out("%.*s",
+ (int)(close_paren - ptr_p),
+ ptr_p);
+ pid_t pid = atoi(pid_ptr + 4);
+
+ if (pid > 0)
+ print_process_age(pid);
+ out(")");
+ ptr_p = close_paren + 1;
+ } else {
+ out("%s", ptr_p);
+ break;
+ }
+ } else {
+ out("%s", ptr_p);
+ break;
+ }
+ }
+ out(")");
+ } else {
+ out(" users:(%s)", buf);
+ }
free(buf);
}
} else if (show_processes || show_threads) {
if (find_entry(s->ino, &buf, USERS) > 0) {
if (show_process_age) {
-char *p = buf;
-
-out(" users:(");
-while (*p) {
-char *pid_ptr = strstr(p, "pid=");
-
-if (pid_ptr) {
-char *close_paren = strchr(pid_ptr, ')');
-
-if (close_paren) {
-out("%.*s", (int)(close_paren - p), p);
-pid_t pid = atoi(pid_ptr + 4);
-
-if (pid > 0)
-print_process_age(pid);
-out(")");
-p = close_paren + 1;
-} else {
-out("%s", p);
-break;
-}
-} else {
-out("%s", p);
-break;
-}
-}
-out(")");
-} else {
-out(" users:(%s)", buf);
-}
+ char *ptr_p = buf;
+
+ out(" users:(");
+ while (*ptr_p) {
+ char *pid_ptr = strstr(ptr_p, "pid=");
+
+ if (pid_ptr) {
+ char *close_paren = strchr(pid_ptr, ')');
+
+ if (close_paren) {
+ out("%.*s",
+ (int)(close_paren - ptr_p),
+ ptr_p);
+ pid_t pid = atoi(pid_ptr + 4);
+
+ if (pid > 0)
+ print_process_age(pid);
+ out(")");
+ ptr_p = close_paren + 1;
+ } else {
+ out("%s", ptr_p);
+ break;
+ }
+ } else {
+ out("%s", ptr_p);
+ break;
+ }
+ }
+ out(")");
+ } else {
+ out(" users:(%s)", buf);
+ }
free(buf);
}
} else {
@@ -3245,12 +3280,12 @@ static void tcp_tls_version(struct rtattr *attr)
show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
@@ -3279,12 +3314,12 @@ static void tcp_tls_cipher(struct rtattr *attr)
show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
@@ -3310,12 +3345,12 @@ static void tcp_tls_conf(const char *name, struct rtattr *attr)
show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
@@ -3673,12 +3708,12 @@ static const char *format_host_sa(struct sockaddr_storage *sa)
show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
@@ -5831,12 +5866,12 @@ static int generic_show_sock(struct nlmsghdr *nlh, void *arg)
show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
@@ -6217,10 +6252,69 @@ wrong_state:
#define OPT_BPF_MAPS 263
#define OPT_BPF_MAP_ID 264
+static int show_process_age;
+
+static void print_process_age(pid_t pid)
+{
+ char path[64];
+ FILE *f;
+ unsigned long long starttime;
+ double uptime = 0.0;
+ long clock_ticks = sysconf(_SC_CLK_TCK);
+
+ f = fopen("/proc/uptime", "r");
+ if (!f)
+ return;
+
+ if (fscanf(f, "%lf", &uptime) != 1) {
+ fclose(f);
+ return;
+ }
+ fclose(f);
+
+ snprintf(path, sizeof(path), "/proc/%d/stat", pid);
+ f = fopen(path, "r");
+ if (!f)
+ return;
+
+ char buf[1024];
+
+ if (fgets(buf, sizeof(buf), f)) {
+ char *ptr = strrchr(buf, ')');
+
+ if (ptr) {
+ int field = 3;
+
+ ptr++;
+ while (*ptr && field < 22) {
+ if (*ptr == ' ')
+ field++;
+ ptr++;
+ }
+ if (sscanf(ptr, "%llu", &starttime) == 1) {
+ double process_secs = uptime - ((double)starttime / clock_ticks);
+ long secs = (long)process_secs;
+ long hours = secs / 3600;
+ long mins = (secs % 3600) / 60;
+ long s = secs % 60;
+
+ if (hours > 0)
+ out(",age=%ldh%ldm", hours, mins);
+ else if (mins > 0)
+ out(",age=%ldm%lds", mins, s);
+ else
+ out(",age=%lds", s);
+ }
+ }
+ }
+ fclose(f);
+}
+
static const struct option long_opts[] = {
{ "process-age", no_argument, NULL, 'P' },
{ "process-age", no_argument, NULL, 'P' },
{ "process-age", no_argument, NULL, 'P' },
+ { "process-age", no_argument, NULL, 'P' },
{ "numeric", 0, 0, 'n' },
{ "resolve", 0, 0, 'r' },
{ "options", 0, 0, 'o' },
@@ -6283,20 +6377,28 @@ int main(int argc, char *argv[])
int ch;
int state_filter = 0;
+ case 'P':
+ show_process_age = 1;
+ show_processes = 1;
+ break;
while ((ch = getopt_long(argc, argv,
"halBetuwxnro460spTbEf:mMiA:D:F:vVzZN:KHQSOPPP",
long_opts, NULL)) != EOF) {
switch (ch) {
+ case 'P':
+ show_process_age = 1;
+ show_processes = 1;
+ break;
case \'P\':
show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
- case 'P':
- show_process_age = 1;
+ case 'P':
+ show_process_age = 1;
show_processes = 1;
break;
--
2.43.7
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH iproute2] ss: add -P/--process-age option to display process runtime
2026-09-15 18:35 [PATCH iproute2] ss: add -P/--process-age option to display process runtime Harshith Hari
@ 2026-09-15 20:44 ` Stephen Hemminger
0 siblings, 0 replies; 2+ messages in thread
From: Stephen Hemminger @ 2026-09-15 20:44 UTC (permalink / raw)
To: Harshith Hari; +Cc: netdev
On Wed, 16 Sep 2026 00:05:22 +0530
Harshith Hari <harshithhari000111@gmail.com> wrote:
> Add a new option (-P/--process-age) to display process uptime/age
> alongside process info inside socket user context output.
>
> Signed-off-by: Harshith Hari <harshithhari000111@gmail.com>
> ---
Your mailing method is mangling whitespace and the patch will not apply cleanly
to the current iproute2 tree. Suggest fixing your settings and use git send-email.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-09-15 20:44 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-15 18:35 [PATCH iproute2] ss: add -P/--process-age option to display process runtime Harshith Hari
2026-09-15 20:44 ` Stephen Hemminger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox