All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] lsns: add netnsid column
@ 2017-11-15  2:59 Masatake YAMATO
  2017-11-15  2:59 ` [PATCH 2/2] lsns: add a case for testing " Masatake YAMATO
  2017-11-15 11:09 ` [PATCH 1/2] lsns: add " Karel Zak
  0 siblings, 2 replies; 9+ messages in thread
From: Masatake YAMATO @ 2017-11-15  2:59 UTC (permalink / raw)
  To: util-linux; +Cc: yamato

Linux network subsystem assigns an unique integer to a network
namespace.

  term0# ip netns add UTIL-LINUX-LSNS-TEST-NS
  term0# ip netns list
  UTIL-LINUX-LSNS-TEST-NS
  term0# ip link add name lsns-vetha type veth peer name lsns-vethb
  term0 # ip link set lsns-vethb netns UTIL-LINUX-LSNS-TEST-NS
  term0# ip netns list
  UTIL-LINUX-LSNS-TEST-NS (id: 0)
  term0# ip link show dev lsns-vetha
  230: lsns-vetha@if229: <BROADCAST,MULTICAST> mtu 1500 qdisc noop ...
         link/ether 3e:27:68:ba:b3:95 brd ff:ff:ff:ff:ff:ff link-netnsid 0
In this example 0 is assigned to UTIL-LINUX-LSNS-TEST-NS net namespace.
The name, UTIL-LINUX-LSNS-TEST-NS, and it semantics is given and defined
by iproute2 in userland; and nothing to do with util-linux.

However, the id, 0, is managed in linux kernel. If lsns can show
the ids, it helps users understand the state of network namespaces.

This commit adds NETNSID column to the output.

Here is an example of session:

  term0# ip netns exec UTIL-LINUX-LSNS-TEST-NS cat

  (Open another terminal)

  term1# ./lsns --type net
          NS TYPE NPROCS   PID USER     NETNSID COMMAND
  4026531993 net     383     1 root  unassigned /usr/lib/systemd/...
  4026532433 net       1  1219 rtkit unassigned /usr/libexec/rtkit-daemon
  4026532562 net       1 18201 root           0 cat

0 is shown as NETNSID for the cat process.

For the initial name space, "unassigned" is printed.
For the namespaces other type than net, "n/a" is printed.
If an error occurred during getting the id, "n/a" is printed.

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
---
 configure.ac     |   1 +
 sys-utils/lsns.c | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 189 insertions(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index eebe92259..b2ad5ea98 100644
--- a/configure.ac
+++ b/configure.ac
@@ -223,6 +223,7 @@ AC_CHECK_HEADERS([ \
 	linux/tiocl.h \
 	linux/version.h \
 	linux/securebits.h \
+	linux/net_namespace.h \
 	locale.h \
 	mntent.h \
 	net/if.h \
diff --git a/sys-utils/lsns.c b/sys-utils/lsns.c
index 1fb0b87f3..6252d09fe 100644
--- a/sys-utils/lsns.c
+++ b/sys-utils/lsns.c
@@ -29,6 +29,14 @@
 #include <wchar.h>
 #include <libsmartcols.h>
 
+#ifdef HAVE_LINUX_NET_NAMESPACE_H
+#include <stdbool.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/net_namespace.h>
+#endif
+
 #include "pathnames.h"
 #include "nls.h"
 #include "xalloc.h"
@@ -52,6 +60,8 @@ UL_DEBUG_DEFINE_MASKNAMES(lsns) = UL_DEBUG_EMPTY_MASKNAMES;
 #define LSNS_DEBUG_NS		(1 << 3)
 #define LSNS_DEBUG_ALL		0xFFFF
 
+#define LSNS_NETNS_UNUSABLE -2
+
 #define DBG(m, x)       __UL_DBG(lsns, LSNS_DEBUG_, m, x)
 #define ON_DBG(m, x)    __UL_DBG_CALL(lsns, LSNS_DEBUG_, m, x)
 
@@ -67,7 +77,8 @@ enum {
 	COL_PPID,
 	COL_COMMAND,
 	COL_UID,
-	COL_USER
+	COL_USER,
+	COL_NETNSID
 };
 
 /* column names */
@@ -88,7 +99,8 @@ static const struct colinfo infos[] = {
 	[COL_PPID]    = { "PPID",    5, SCOLS_FL_RIGHT, N_("PPID of the PID") },
 	[COL_COMMAND] = { "COMMAND", 0, SCOLS_FL_TRUNC, N_("command line of the PID")},
 	[COL_UID]     = { "UID",     0, SCOLS_FL_RIGHT, N_("UID of the PID")},
-	[COL_USER]    = { "USER",    0, 0, N_("username of the PID")}
+	[COL_USER]    = { "USER",    0, 0, N_("username of the PID")},
+	[COL_NETNSID] = { "NETNSID", 0, SCOLS_FL_RIGHT, N_("Net namespace ID")}
 };
 
 static int columns[ARRAY_SIZE(infos) * 2];
@@ -118,6 +130,7 @@ struct lsns_namespace {
 	ino_t id;
 	int type;			/* LSNS_* */
 	int nprocs;
+	int netnsid;
 
 	struct lsns_process *proc;
 
@@ -139,6 +152,8 @@ struct lsns_process {
 
 	struct libscols_line *outline;
 	struct lsns_process *parent;
+
+	int netnsid;
 };
 
 struct lsns {
@@ -158,6 +173,16 @@ struct lsns {
 		     no_headings: 1;
 };
 
+struct netnsid_cache {
+	ino_t ino;
+	int   id;
+	struct list_head netnsids;
+};
+
+static struct list_head netnsids_cache;
+
+static int netlink_fd = -1;
+
 static void lsns_init_debug(void)
 {
 	__UL_INIT_DEBUG(lsns, LSNS_DEBUG_, 0, LSNS_DEBUG);
@@ -242,6 +267,137 @@ error:
 	return rc;
 }
 
+#ifdef HAVE_LINUX_NET_NAMESPACE_H
+static bool netnsid_cache_find(ino_t netino, int *netnsid)
+{
+	struct list_head *p;
+
+	list_for_each(p, &netnsids_cache) {
+		struct netnsid_cache *e = list_entry(p,
+						     struct netnsid_cache,
+						     netnsids);
+		if (e->ino == netino) {
+			*netnsid = e->id;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static void netnsid_cache_add(ino_t netino, int netnsid)
+{
+	struct netnsid_cache *e;
+
+	e = xcalloc(1, sizeof(*e));
+	e->ino = netino;
+	e->id  = netnsid;
+	INIT_LIST_HEAD(&e->netnsids);
+	list_add(&e->netnsids, &netnsids_cache);
+}
+
+static int get_netnsid_via_netlink_send_request(int target_fd)
+{
+	unsigned char req[NLMSG_SPACE(sizeof(struct rtgenmsg))
+			  + RTA_SPACE(sizeof(int32_t))];
+
+	struct nlmsghdr *nlh = (struct nlmsghdr *)req;
+	struct rtgenmsg *rt = NLMSG_DATA(req);
+	struct rtattr *rta = (struct rtattr *)
+		(req + NLMSG_SPACE(sizeof(struct rtgenmsg)));
+	int32_t *fd = RTA_DATA(rta);
+
+	nlh->nlmsg_len = sizeof(req);
+	nlh->nlmsg_flags = NLM_F_REQUEST;
+	nlh->nlmsg_type = RTM_GETNSID;
+	rt->rtgen_family = AF_UNSPEC;
+	rta->rta_type = NETNSA_FD;
+	rta->rta_len = RTA_SPACE(sizeof(int32_t));
+	*fd = target_fd;
+
+	if (send(netlink_fd, req, sizeof(req), 0) < 0)
+		return -1;
+	return 0;
+}
+
+static int get_netnsid_via_netlink_recv_response(int *netnsid)
+{
+	unsigned char res[NLMSG_SPACE(sizeof(struct rtgenmsg))
+			  + ((RTA_SPACE(sizeof(int32_t))
+			      < RTA_SPACE(sizeof(struct nlmsgerr)))
+			     ? RTA_SPACE(sizeof(struct nlmsgerr))
+			     : RTA_SPACE(sizeof(int32_t)))];
+	int reslen, rtalen;
+
+	struct nlmsghdr *nlh;
+	struct rtattr *rta;
+
+	reslen = recv(netlink_fd, res, sizeof(res), 0);
+	if (reslen < 0)
+		return -1;
+
+	nlh = (struct nlmsghdr *)res;
+	if (!(NLMSG_OK(nlh, reslen)
+	      && nlh->nlmsg_type == RTM_NEWNSID))
+		return -1;
+
+	rtalen = NLMSG_PAYLOAD(nlh, sizeof(struct rtgenmsg));
+	rta = (struct rtattr *)(res + NLMSG_SPACE(sizeof(struct rtgenmsg)));
+	if (!(RTA_OK(rta, rtalen)
+	      && rta->rta_type == NETNSA_NSID))
+		return -1;
+
+	*netnsid = *(int *)RTA_DATA(rta);
+
+	return 0;
+}
+
+static int get_netnsid_via_netlink(int dir, const char *path)
+{
+	int netnsid;
+	int target_fd;
+
+	if (netlink_fd < 0)
+		return LSNS_NETNS_UNUSABLE;
+
+	target_fd = openat(dir, path, O_RDONLY);
+	if (target_fd < 0)
+		return LSNS_NETNS_UNUSABLE;
+
+	if (get_netnsid_via_netlink_send_request(target_fd) < 0) {
+		netnsid = LSNS_NETNS_UNUSABLE;
+		goto out;
+	}
+
+	if (get_netnsid_via_netlink_recv_response(&netnsid) < 0) {
+		netnsid = LSNS_NETNS_UNUSABLE;
+		goto out;
+	}
+
+ out:
+	close(target_fd);
+	return netnsid;
+}
+
+static int get_netnsid(int dir, ino_t netino)
+{
+	int netnsid;
+
+	if (!netnsid_cache_find(netino, &netnsid)) {
+		netnsid = get_netnsid_via_netlink(dir, "ns/net");
+		netnsid_cache_add(netino, netnsid);
+	}
+
+	return netnsid;
+}
+#else
+static int get_netnsid(int dir __attribute__((__unused__)),
+		       ino_t netino __attribute__((__unused__)))
+{
+	return LSNS_NETNS_UNUSABLE;
+}
+#endif /* HAVE_LINUX_NET_NAMESPACE_H */
+
 static int read_process(struct lsns *ls, pid_t pid)
 {
 	struct lsns_process *p = NULL;
@@ -264,6 +420,7 @@ static int read_process(struct lsns *ls, pid_t pid)
 		rc = -ENOMEM;
 		goto done;
 	}
+	p->netnsid = LSNS_NETNS_UNUSABLE;
 
 	if (fstat(dirfd(dir), &st) == 0) {
 		p->uid = st.st_uid;
@@ -293,6 +450,8 @@ static int read_process(struct lsns *ls, pid_t pid)
 		rc = get_ns_ino(dirfd(dir), ns_names[i], &p->ns_ids[i]);
 		if (rc && rc != -EACCES && rc != -ENOENT)
 			goto done;
+		if (i == LSNS_ID_NET)
+			p->netnsid = get_netnsid(dirfd(dir), p->ns_ids[i]);
 		rc = 0;
 	}
 
@@ -413,6 +572,18 @@ static int cmp_namespaces(struct list_head *a, struct list_head *b,
 	return cmp_numbers(xa->id, xb->id);
 }
 
+static int netnsid_xasputs(char **str, int netnsid)
+{
+	if (netnsid >= 0)
+		return xasprintf(&str, "%d", netnsid);
+#ifdef NETNSA_NSID_NOT_ASSIGNED
+	else if (netnsid == NETNSA_NSID_NOT_ASSIGNED)
+		return xasprintf(&str, "%s", "unassigned");
+#endif
+	else
+		return xasprintf(&str, "%s", "n/a");
+}
+
 static int read_namespaces(struct lsns *ls)
 {
 	struct list_head *p;
@@ -490,6 +661,11 @@ static void add_scols_line(struct lsns *ls, struct libscols_table *table,
 		case COL_USER:
 			xasprintf(&str, "%s", get_id(uid_cache, proc->uid)->name);
 			break;
+		case COL_NETNSID:
+			if (ns->type == LSNS_ID_NET)
+				netnsid_xasputs(&str, proc->netnsid);
+			else
+				xasprintf(&str, "n/a");
 		default:
 			break;
 		}
@@ -675,6 +851,7 @@ int main(int argc, char *argv[])
 
 	INIT_LIST_HEAD(&ls.processes);
 	INIT_LIST_HEAD(&ls.namespaces);
+	INIT_LIST_HEAD(&netnsids_cache);
 
 	while ((c = getopt_long(argc, argv,
 				"Jlp:o:nruhVt:", long_opts, NULL)) != -1) {
@@ -748,6 +925,7 @@ int main(int argc, char *argv[])
 		columns[ncolumns++] = COL_NPROCS;
 		columns[ncolumns++] = COL_PID;
 		columns[ncolumns++] = COL_USER;
+		columns[ncolumns++] = COL_NETNSID;
 		columns[ncolumns++] = COL_COMMAND;
 	}
 
@@ -761,6 +939,12 @@ int main(int argc, char *argv[])
 	if (!uid_cache)
 		err(EXIT_FAILURE, _("failed to allocate UID cache"));
 
+#ifdef HAVE_LINUX_NET_NAMESPACE_H
+	netlink_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+#endif
+	if (netlink_fd < 0)
+		netlink_fd = -errno;
+
 	r = read_processes(&ls);
 	if (!r)
 		r = read_namespaces(&ls);
@@ -775,6 +959,8 @@ int main(int argc, char *argv[])
 			r = show_namespaces(&ls);
 	}
 
+	if (netlink_fd >= 0)
+		close(netlink_fd);
 	free_idcache(uid_cache);
 	return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
-- 
2.13.6


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/2] lsns: add a case for testing netnsid column
  2017-11-15  2:59 [PATCH 1/2] lsns: add netnsid column Masatake YAMATO
@ 2017-11-15  2:59 ` Masatake YAMATO
  2017-11-15 11:09 ` [PATCH 1/2] lsns: add " Karel Zak
  1 sibling, 0 replies; 9+ messages in thread
From: Masatake YAMATO @ 2017-11-15  2:59 UTC (permalink / raw)
  To: util-linux; +Cc: yamato

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
---
 tests/commands.sh           |  1 +
 tests/expected/lsns/netnsid |  1 +
 tests/ts/lsns/netnsid       | 65 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 67 insertions(+)
 create mode 100644 tests/expected/lsns/netnsid
 create mode 100644 tests/ts/lsns/netnsid

diff --git a/tests/commands.sh b/tests/commands.sh
index 655344102..502935ede 100644
--- a/tests/commands.sh
+++ b/tests/commands.sh
@@ -74,6 +74,7 @@ TS_CMD_LOSETUP=${TS_CMD_LOSETUP:-"$top_builddir/losetup"}
 TS_CMD_LSBLK=${TS_CMD_LSBLK-"$top_builddir/lsblk"}
 TS_CMD_LSCPU=${TS_CMD_LSCPU-"$top_builddir/lscpu"}
 TS_CMD_LSMEM=${TS_CMD_LSMEM-"$top_builddir/lsmem"}
+TS_CMD_LSNS=${TS_CMD_LSNS-"$top_builddir/lsns"}
 TS_CMD_MCOOKIE=${TS_CMD_MCOOKIE-"$top_builddir/mcookie"}
 TS_CMD_MKCRAMFS=${TS_CMD_MKCRAMFS:-"$top_builddir/mkfs.cramfs"}
 TS_CMD_MKMINIX=${TS_CMD_MKMINIX:-"$top_builddir/mkfs.minix"}
diff --git a/tests/expected/lsns/netnsid b/tests/expected/lsns/netnsid
new file mode 100644
index 000000000..573541ac9
--- /dev/null
+++ b/tests/expected/lsns/netnsid
@@ -0,0 +1 @@
+0
diff --git a/tests/ts/lsns/netnsid b/tests/ts/lsns/netnsid
new file mode 100644
index 000000000..ad93dd49c
--- /dev/null
+++ b/tests/ts/lsns/netnsid
@@ -0,0 +1,65 @@
+#!/bin/bash
+#
+# Copyright (C) 2017 Masatake YAMATO <yamato@redhat.com>
+#
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="compare NETNSID reported by lsns and that by ip-link"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_CMD_LSNS"
+
+ts_skip_nonroot
+
+ts_cd "$TS_OUTDIR"
+
+vetha=lsns-vetha
+vethb=lsns-vethb
+NS=UTIL-LINUX-LSNS-TEST-NS
+FIFO=$TS_OUTDIR/UTIL-LINUX-LSNS-TEST-FIFO
+NULL=/dev/null
+
+ip netns delete $NS 2> $NULL || :
+ip link delete  $vetha 2> $NULL || :
+
+rm -f $FIFO
+mkfifo $FIFO
+
+if ip netns add $NS &&
+	ip link add name $vetha type veth peer name $vethb &&
+	ip link set $vethb netns $NS; then
+    ip netns exec $NS dd if=$FIFO bs=1 count=2 of=$NULL 2> $NULL &
+    PID=$!
+fi
+{
+    dd if=/dev/zero bs=1 count=1 2> $NULL
+    {
+	ip -o link show dev $vetha > $NULL
+	IP_ID=$(ip -o link show dev $vetha | sed -ne 's/.* *link-netnsid *\([0-9]*\)/\1/p')
+	LSNS_ID=$($TS_CMD_LSNS -n -o NETNSID --type net --task $PID | { read VAL; echo $VAL; } )
+    }
+    dd if=/dev/zero bs=1 count=1 2> $NULL
+} > $FIFO
+
+rm $FIFO
+ip link delete $vetha
+ip netns delete $NS
+
+test "$IP_ID" = "$LSNS_ID"
+echo $? >> $TS_OUTPUT
+
+ts_finalize
-- 
2.13.6


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] lsns: add netnsid column
  2017-11-15  2:59 [PATCH 1/2] lsns: add netnsid column Masatake YAMATO
  2017-11-15  2:59 ` [PATCH 2/2] lsns: add a case for testing " Masatake YAMATO
@ 2017-11-15 11:09 ` Karel Zak
  2017-11-15 18:24   ` Masatake YAMATO
  1 sibling, 1 reply; 9+ messages in thread
From: Karel Zak @ 2017-11-15 11:09 UTC (permalink / raw)
  To: Masatake YAMATO; +Cc: util-linux

On Wed, Nov 15, 2017 at 11:59:18AM +0900, Masatake YAMATO wrote:
> Linux network subsystem assigns an unique integer to a network
> namespace.
> 
>   term0# ip netns add UTIL-LINUX-LSNS-TEST-NS
>   term0# ip netns list
>   UTIL-LINUX-LSNS-TEST-NS
>   term0# ip link add name lsns-vetha type veth peer name lsns-vethb
>   term0 # ip link set lsns-vethb netns UTIL-LINUX-LSNS-TEST-NS
>   term0# ip netns list
>   UTIL-LINUX-LSNS-TEST-NS (id: 0)
>   term0# ip link show dev lsns-vetha
>   230: lsns-vetha@if229: <BROADCAST,MULTICAST> mtu 1500 qdisc noop ...
>          link/ether 3e:27:68:ba:b3:95 brd ff:ff:ff:ff:ff:ff link-netnsid 0
> In this example 0 is assigned to UTIL-LINUX-LSNS-TEST-NS net namespace.
> The name, UTIL-LINUX-LSNS-TEST-NS, and it semantics is given and defined
> by iproute2 in userland; and nothing to do with util-linux.
> 
> However, the id, 0, is managed in linux kernel. If lsns can show
> the ids, it helps users understand the state of network namespaces.

Where iproute2 stores the logical name of the namespace (e.g.
UTIL-LINUX-LSNS-TEST-NS)? Cannot we read it? :-)

> +static int netnsid_xasputs(char **str, int netnsid)
> +{
> +	if (netnsid >= 0)
> +		return xasprintf(&str, "%d", netnsid);
> +#ifdef NETNSA_NSID_NOT_ASSIGNED
> +	else if (netnsid == NETNSA_NSID_NOT_ASSIGNED)
> +		return xasprintf(&str, "%s", "unassigned");
> +#endif
> +	else
> +		return xasprintf(&str, "%s", "n/a");

 We usually use blank space rather than n/a if data are not available.
 In this case "return NULL;" is good enough.

> +#ifdef HAVE_LINUX_NET_NAMESPACE_H
> +	netlink_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
> +#endif
> +	if (netlink_fd < 0)
> +		netlink_fd = -errno;

 I guess this if() is unnecessary. The rest of the code check for
 netlink_fd < 0.
         
 It would be also nice to call socket() only if NETNSID column is wanted.

 What about to add NETNSID collumn to the default output only if "--type net"
 specified on lsns command line?

 I'm ready to do all the changes (you don't have to resend the patch).

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] lsns: add netnsid column
  2017-11-15 11:09 ` [PATCH 1/2] lsns: add " Karel Zak
@ 2017-11-15 18:24   ` Masatake YAMATO
  2017-11-21 11:16     ` Karel Zak
  0 siblings, 1 reply; 9+ messages in thread
From: Masatake YAMATO @ 2017-11-15 18:24 UTC (permalink / raw)
  To: kzak; +Cc: util-linux

On Wed, 15 Nov 2017 12:09:22 +0100, Karel Zak <kzak@redhat.com> wrote:
> On Wed, Nov 15, 2017 at 11:59:18AM +0900, Masatake YAMATO wrote:
>> Linux network subsystem assigns an unique integer to a network
>> namespace.
>> 
>>   term0# ip netns add UTIL-LINUX-LSNS-TEST-NS
>>   term0# ip netns list
>>   UTIL-LINUX-LSNS-TEST-NS
>>   term0# ip link add name lsns-vetha type veth peer name lsns-vethb
>>   term0 # ip link set lsns-vethb netns UTIL-LINUX-LSNS-TEST-NS
>>   term0# ip netns list
>>   UTIL-LINUX-LSNS-TEST-NS (id: 0)
>>   term0# ip link show dev lsns-vetha
>>   230: lsns-vetha@if229: <BROADCAST,MULTICAST> mtu 1500 qdisc noop ...
>>          link/ether 3e:27:68:ba:b3:95 brd ff:ff:ff:ff:ff:ff link-netnsid 0
>> In this example 0 is assigned to UTIL-LINUX-LSNS-TEST-NS net namespace.
>> The name, UTIL-LINUX-LSNS-TEST-NS, and it semantics is given and defined
>> by iproute2 in userland; and nothing to do with util-linux.
>> 
>> However, the id, 0, is managed in linux kernel. If lsns can show
>> the ids, it helps users understand the state of network namespaces.
> 
> Where iproute2 stores the logical name of the namespace (e.g.
> UTIL-LINUX-LSNS-TEST-NS)? Cannot we read it? :-)

I found I don't understand the mechanism of namespace well
enough to answer this question. So I made study.

Before studying I thought logical name of the namespace is
just iproute2 local hack. iproute2 stores the name to a
file under /var/run/netns with using "bind mount".
Though iproute2 is very popular software, I thought a low level
program like lsns should rely on and utilize only kernel to get
runtime information. I assumed making a mount point under
/var/run/netns was just private rule of iproute2.

After I studied I found it is not just iproute2 and
net namespace private things.

nsfs provides kernel level interface for logical name:

    commit 0226f4923f6c9b40cfa1c1c1b19a6ac6b3924ead
    Author: Al Viro <viro@zeniv.linux.org.uk>
    Date:   Tue Dec 6 12:21:54 2011 -0500

	vfs: take /proc/*/mounts and friends to fs/proc_namespace.c

	rationale: that stuff is far tighter bound to fs/namespace.c than to
	the guts of procfs proper.

	Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

[yamato@master]~/var/util-linux% cat /proc/self/mountinfo  | grep nsfs
247 240 0:3 net:[4026532562] /run/netns/UTIL-LINUX-LSNS-TEST-NS rw shared:190 - nsfs nsfs rw,seclabel
270 26 0:3 net:[4026532562] /run/netns/UTIL-LINUX-LSNS-TEST-NS rw shared:190 - nsfs nsfs rw,seclabel

By parsing this file (with libmount), we can say
/run/netns/UTIL-LINUX-LSNS-TEST-NS is the logical name for
net:[4026532562] either the mount point is created by ip command or
not.

"ip link show" still uses netnsid, so I think my patch still makes
sense. However, as you wrote, making a column for logical name,
is more useful. It is not limited to net namespace.

A namespace can have more than one logical names.
I wonder how to print them in a column.

>> +static int netnsid_xasputs(char **str, int netnsid)
>> +{
>> +	if (netnsid >= 0)
>> +		return xasprintf(&str, "%d", netnsid);
>> +#ifdef NETNSA_NSID_NOT_ASSIGNED
>> +	else if (netnsid == NETNSA_NSID_NOT_ASSIGNED)
>> +		return xasprintf(&str, "%s", "unassigned");
>> +#endif
>> +	else
>> +		return xasprintf(&str, "%s", "n/a");
> 
>  We usually use blank space rather than n/a if data are not available.
>  In this case "return NULL;" is good enough.
> 
>> +#ifdef HAVE_LINUX_NET_NAMESPACE_H
>> +	netlink_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
>> +#endif
>> +	if (netlink_fd < 0)
>> +		netlink_fd = -errno;
> 
>  I guess this if() is unnecessary. The rest of the code check for
>  netlink_fd < 0.
>          
>  It would be also nice to call socket() only if NETNSID column is wanted.
> 
>  What about to add NETNSID collumn to the default output only if "--type net"
>  specified on lsns command line?

I think it is good idea.

Masatake YAMATO

>  I'm ready to do all the changes (you don't have to resend the patch).
> 
>     Karel
> 
> -- 
>  Karel Zak  <kzak@redhat.com>
>  http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] lsns: add netnsid column
  2017-11-15 18:24   ` Masatake YAMATO
@ 2017-11-21 11:16     ` Karel Zak
  2017-11-21 11:36       ` Masatake YAMATO
  0 siblings, 1 reply; 9+ messages in thread
From: Karel Zak @ 2017-11-21 11:16 UTC (permalink / raw)
  To: Masatake YAMATO; +Cc: util-linux

On Thu, Nov 16, 2017 at 03:24:39AM +0900, Masatake YAMATO wrote:
> By parsing this file (with libmount), we can say
> /run/netns/UTIL-LINUX-LSNS-TEST-NS is the logical name for
> net:[4026532562] either the mount point is created by ip command or
> not.

Nice. Yes, all you need is:

   tab = mnt_new_table_from_file(_PATH_PROC_MOUNTINFO);

.. see for example sys-utils/fstrim.c, and mnt_fs_get_fstype() and
mnt_fs_get_source().

> "ip link show" still uses netnsid, so I think my patch still makes
> sense. However, as you wrote, making a column for logical name,
> is more useful. It is not limited to net namespace.
> 
> A namespace can have more than one logical names.
> I wonder how to print them in a column.

libsmart supports multi-line cells:

 * use SCOLS_FL_WRAP for the column

 * set wrap function, for example in lsns.c: init_scols_table():

      cl =  scols_table_new_column(tab, col->name, col->whint, flags)
 
      if (flags & SCOLS_FL_WRAP) {
                scols_column_set_wrapfunc(cl,
                                scols_wrapnl_chunksize,
                                scols_wrapnl_nextchunk,
                                NULL);
                scols_column_set_safechars(cl, "\n");
      }


 * and in add_scols_line() where you compose output add to the table
   string where namespace names are separated by '\n', e.g. "aaa\nbbb"


This feature should be probably disabled for --raw, maybe add --nowrap
and in this case use "," as separator and remove SCOLS_FL_WRAP for the
column in init_scols_table().

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] lsns: add netnsid column
  2017-11-21 11:16     ` Karel Zak
@ 2017-11-21 11:36       ` Masatake YAMATO
  2017-11-22  9:06         ` Karel Zak
  0 siblings, 1 reply; 9+ messages in thread
From: Masatake YAMATO @ 2017-11-21 11:36 UTC (permalink / raw)
  To: kzak; +Cc: util-linux

So, my biggest question is "should I send an updated version of patch?" :-)

You wrote in https://marc.info/?l=util-linux-ng&m=151074416720085&w=2:
>  I'm ready to do all the changes (you don't have to resend the patch).

I think you may have improved version of code.
I would like to start from it for reflecting the new comments (if I should do).

Masatake YAMATO


> On Thu, Nov 16, 2017 at 03:24:39AM +0900, Masatake YAMATO wrote:
>> By parsing this file (with libmount), we can say
>> /run/netns/UTIL-LINUX-LSNS-TEST-NS is the logical name for
>> net:[4026532562] either the mount point is created by ip command or
>> not.
> 
> Nice. Yes, all you need is:
> 
>    tab = mnt_new_table_from_file(_PATH_PROC_MOUNTINFO);
> 
> .. see for example sys-utils/fstrim.c, and mnt_fs_get_fstype() and
> mnt_fs_get_source().
> 
>> "ip link show" still uses netnsid, so I think my patch still makes
>> sense. However, as you wrote, making a column for logical name,
>> is more useful. It is not limited to net namespace.
>> 
>> A namespace can have more than one logical names.
>> I wonder how to print them in a column.
> 
> libsmart supports multi-line cells:
> 
>  * use SCOLS_FL_WRAP for the column
> 
>  * set wrap function, for example in lsns.c: init_scols_table():
> 
>       cl =  scols_table_new_column(tab, col->name, col->whint, flags)
>  
>       if (flags & SCOLS_FL_WRAP) {
>                 scols_column_set_wrapfunc(cl,
>                                 scols_wrapnl_chunksize,
>                                 scols_wrapnl_nextchunk,
>                                 NULL);
>                 scols_column_set_safechars(cl, "\n");
>       }
> 
> 
>  * and in add_scols_line() where you compose output add to the table
>    string where namespace names are separated by '\n', e.g. "aaa\nbbb"
> 
> 
> This feature should be probably disabled for --raw, maybe add --nowrap
> and in this case use "," as separator and remove SCOLS_FL_WRAP for the
> column in init_scols_table().
> 
>     Karel
> 
> -- 
>  Karel Zak  <kzak@redhat.com>
>  http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] lsns: add netnsid column
  2017-11-21 11:36       ` Masatake YAMATO
@ 2017-11-22  9:06         ` Karel Zak
  2017-11-23 17:01           ` Masatake YAMATO
  0 siblings, 1 reply; 9+ messages in thread
From: Karel Zak @ 2017-11-22  9:06 UTC (permalink / raw)
  To: Masatake YAMATO; +Cc: util-linux

On Tue, Nov 21, 2017 at 08:36:33PM +0900, Masatake YAMATO wrote:
> So, my biggest question is "should I send an updated version of patch?" :-)
> 
> You wrote in https://marc.info/?l=util-linux-ng&m=151074416720085&w=2:
> >  I'm ready to do all the changes (you don't have to resend the patch).
> 
> I think you may have improved version of code.
> I would like to start from it for reflecting the new comments (if I should do).

I do not have any changes yet ;-) So, you can start, or if you're busy
with something else I can do that.

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] lsns: add netnsid column
  2017-11-22  9:06         ` Karel Zak
@ 2017-11-23 17:01           ` Masatake YAMATO
  2017-11-24  9:28             ` Karel Zak
  0 siblings, 1 reply; 9+ messages in thread
From: Masatake YAMATO @ 2017-11-23 17:01 UTC (permalink / raw)
  To: kzak; +Cc: util-linux

Hi,

> I do not have any changes yet ;-) So, you can start, or if you're busy
> with something else I can do that.

It works:

# ./lsns --type=net
        NS TYPE NPROCS   PID USER     NETNSID NSFS           COMMAND
4026531993 net     405     1 root  unassigned                /usr/lib/systemd/systemd --switched-root --system --deserialize 25
4026532433 net       1  1515 rtkit unassigned                /usr/libexec/rtkit-daemon
4026532579 net       1 10432 root  unassigned /run/netns/QWE bash
                                              /tmp/RTY

> This feature should be probably disabled for --raw, maybe add --nowrap
> and in this case use "," as separator and remove SCOLS_FL_WRAP for the
> column in init_scols_table().

It seems that nsfs is still not so popular.
So I think enabling the column only when --type net is given, as
you suggested about netnsid.

I would like to make clarify what you meant.

If both --raw and -o NSFS are given, what I should do?
Hidden NSFS anyway? or Use ',' as separator instead of '\n'?

Masatake YAMATO

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] lsns: add netnsid column
  2017-11-23 17:01           ` Masatake YAMATO
@ 2017-11-24  9:28             ` Karel Zak
  0 siblings, 0 replies; 9+ messages in thread
From: Karel Zak @ 2017-11-24  9:28 UTC (permalink / raw)
  To: Masatake YAMATO; +Cc: util-linux

On Fri, Nov 24, 2017 at 02:01:28AM +0900, Masatake YAMATO wrote:
> Hi,
> 
> > I do not have any changes yet ;-) So, you can start, or if you're busy
> > with something else I can do that.
> 
> It works:

Cool!

> # ./lsns --type=net
>         NS TYPE NPROCS   PID USER     NETNSID NSFS           COMMAND
> 4026531993 net     405     1 root  unassigned                /usr/lib/systemd/systemd --switched-root --system --deserialize 25
> 4026532433 net       1  1515 rtkit unassigned                /usr/libexec/rtkit-daemon
> 4026532579 net       1 10432 root  unassigned /run/netns/QWE bash
>                                               /tmp/RTY
> 
> > This feature should be probably disabled for --raw, maybe add --nowrap
> > and in this case use "," as separator and remove SCOLS_FL_WRAP for the
> > column in init_scols_table().
> 
> It seems that nsfs is still not so popular.
> So I think enabling the column only when --type net is given, as
> you suggested about netnsid.

Yes.

> I would like to make clarify what you meant.
> 
> If both --raw and -o NSFS are given, what I should do?
> Hidden NSFS anyway? or Use ',' as separator instead of '\n'?
 
I prefer ',' as separator and add to the man page a note that NSFS
uses multi-line cells (to DESCRIPTION where we already have soemthing
about --output).

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2017-11-24  9:28 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-15  2:59 [PATCH 1/2] lsns: add netnsid column Masatake YAMATO
2017-11-15  2:59 ` [PATCH 2/2] lsns: add a case for testing " Masatake YAMATO
2017-11-15 11:09 ` [PATCH 1/2] lsns: add " Karel Zak
2017-11-15 18:24   ` Masatake YAMATO
2017-11-21 11:16     ` Karel Zak
2017-11-21 11:36       ` Masatake YAMATO
2017-11-22  9:06         ` Karel Zak
2017-11-23 17:01           ` Masatake YAMATO
2017-11-24  9:28             ` Karel Zak

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.