I was looking for ways to tcpdump a Kubernetes pod. Each pod creates a virtual interface and it is hard to know which interface belongs to the actual pod. I found a method that helps identify the system-wide interface index. Basically, it is possible to cat /sys/class/net/eth0/iflink inside a container running in the target pod, and it will show the host network interface index. This way you can know the veth that belongs to the pod.

So, it worked but it left me thinking... why can I get system-wide information on the network if I'm supposed to be in a network namespace in the container. So, I shouldn't have access to the system-wide index, I should only see the virtual "namespace" index for the virtual interface.

Is there any explaination to how /sys/class/net/eth0/iflink is related to the network namespaces inside K8s?


1 Answer 1


The iflink value isn't a system-wide value. It's a value valid in the peer network nsid, as displayed for example with all ip link show dev eth0 (since it's a veth interface with its peer in an other network namespace). For the little details, the peer network nsid isn't either a system-wide value but a value valid only in the current network namespace that links the (system-wide) peer network to this (system-wide) network namespace because at some time a related interface was moved across.

Here's an example, using ip netns add and ip netns exec (which also correctly (re)mounts /sys in its own mount namespace to be able to use network entries in /sys).

# ip netns add n1
# ip netns add n2
# ip netns add n3
# ip netns add n4

# ip -n n1 link add name ton2 index 42 type veth peer netns n2 name eth0
# ip -n n3 link add name ton4 index 42 type veth peer netns n4 name eth0

# ip netns exec n2 cat /sys/class/net/eth0/iflink
# ip -n n2 link show dev eth0
2: eth0@if42: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 0e:27:6f:19:05:02 brd ff:ff:ff:ff:ff:ff link-netns n1
# ip netns exec n4 cat /sys/class/net/eth0/iflink
# ip -n n4 link show dev eth0
2: eth0@if42: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether fe:09:53:11:84:d6 brd ff:ff:ff:ff:ff:ff link-netns n3

Both interfaces have a peer link with index value 42, but this doesn't represent the same interface: one value 42 is ton2's index value in netns n1, the other is ton4's index value in netns n3. If modern versions of ip link didn't resolve the link-nsid to the actual names as designated by ip netns add of the peer namespaces, they would both show as link-netnsid 0 below (because that's the only peer network namespace and the link-nsid starts by default at 0 unless set otherwise, in each network namespace), again with 0 not being system-wide.

# stat -f -c %T /run/netns/n1 /run/netns/n3
# stat -c %i /run/netns/n1 /run/netns/n3

The actual system-wide value for the peer is the network namespace + the index. Here that would be 4026533318:42 and 4026533590:42 . But it can be quite challenging to figure out simply this network namespace when it happens to not be the initial network namespace (as in this example) if one doesn't know how it was created (here with ip netns which leaves a mounted reference in /run/netns).

Additional information about this available in this answer I made.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .